Advertisement
DMeville

Untitled

May 26th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 47.63 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Text;
  8. using ClipperLib;
  9. using DMMTriangleNet.Geometry;
  10. using UnityEngine.UI;
  11.  
  12. namespace DMM {
  13.     public class DMMap : MonoBehaviour {
  14.         #region Private Variables
  15.         [HideInInspector]
  16.         public List<DMMapShape> shapes = new List<DMMapShape>();
  17.         [HideInInspector]
  18.         public List<DMMapIcon> icons = new List<DMMapIcon>();
  19.         private List<DMMapShape> additive = new List<DMMapShape>();
  20.         private List<DMMapShape> subtractive = new List<DMMapShape>();
  21.         private float yNormalOffset = 0.1f;
  22.         private GameObject meshContainer;
  23.         private GameObject[] meshLayers;
  24.         [HideInInspector]
  25.         public static DMMap instance {
  26.             get {
  27.                 if (_instance == null) {
  28.                     _instance = (DMMap)FindObjectOfType(typeof(DMMap));
  29.                 }
  30.                 return _instance;
  31.             }
  32.             set {
  33.                 _instance = value;
  34.             }
  35.         }
  36.         private static DMMap _instance = null;
  37.         [HideInInspector]
  38.         public RenderTexture mainRenderTexture;
  39.         private bool started = false;
  40.         private bool initialized = false;
  41.         #endregion
  42.  
  43.         /// <summary>
  44.         /// Toggle this off to disable all debug messages.
  45.         /// </summary>
  46.         public bool DebugMessages = true;
  47.  
  48.         [Header("Required Objects ")]
  49.         // These 5 objects should be set by default.  If they are not please see the docs on how to fix this! (or reimport the DMMap package!)
  50.  
  51.         /// <summary>
  52.         /// The material used for the generated meshes.  This Should be set to the material found in DMMap/Materials/2DPolygonOutline
  53.         /// </summary>
  54.         public Material defaultMaterial;
  55.  
  56.         /// <summary>
  57.         /// The camera used to render the minimap.  This should be set to the Camera object found on the DMMap prefab "DMMapCamera"
  58.         /// DMMap > DMMapCamera
  59.         /// </summary>
  60.         public Camera DMMapCamera;
  61.  
  62.  
  63.         /// <summary>
  64.         /// The canvas object used by DMMap.
  65.         /// </summary>
  66.         public Canvas canvas;
  67.  
  68.         /// <summary>
  69.         /// The container that all created icons are added to
  70.         /// </summary>
  71.         public GameObject iconContainer;
  72.  
  73.         /// <summary>
  74.         /// The image to use for displaying the rendered minimap.  This should be set to the RawImage found on the DMMap Prefab.
  75.         /// DMMap > Canvas > Map
  76.         /// </summary>
  77.         public RawImage mapImage;
  78.  
  79.         /// <summary>
  80.         /// The image to use for displaying the overlay of the minimap.  This should be set to the RawImage found on the DMMap Prefab.
  81.         /// DMMap > Canvas > Overlay
  82.         /// </summary>
  83.         public RawImage overlayImage;
  84.  
  85.         [Header("Map Options")]
  86.         /// <summary>
  87.         /// If true, map mesh generation will start automatically as the scene loads.
  88.         /// Otherwise, if you want to use map meshes, you must either
  89.         ///  - Call DMMap.instance.Generate() yourself, at some point
  90.         ///  - Click the "Generate Map Mesh" button on the DMMap Component while in edit mode, which effectively precaches the meshes.
  91.         /// </summary>
  92.         public bool generateOnStart = true;
  93.  
  94.         /// <summary>
  95.         /// This value is used when generating the map meshes, higher values mean more precise generation.
  96.         /// This is because the clipping library uses int values for the points so we lose precision.
  97.         /// A triangulationScale of 100 gives us 2 decimal points of precision, which is in most cases more than enough.
  98.         /// </summary>
  99.         public float triangulationScale = 100f;
  100.  
  101.         //
  102.         public bool useCustomOrientation = false;
  103.         //public Vector3 cameraOrientation = new Vector3(0, 1f, 0f); //default for top down, change this to any angle for something like orthographic
  104.         //public float cameraOffset = 25f; //how far from the target (or 0,0,0) in the camraOrientation direction should the camera be placed?
  105.  
  106.         /// <summary>
  107.         /// The orientation of the map.  Note that the map is always rendered facing the POSITIVE direction
  108.         /// ie; using MapOrientation.XZ, the map will be rendered facing the +Y direction.
  109.         /// </summary>
  110.         public MapOrientation orientation = MapOrientation.XZ;
  111.  
  112.        
  113.         /// <summary>
  114.         /// This is the currently loaded config, which is set when calling DMMap.instance.LoadConfig(int).
  115.         /// This is also the config which is loaded at startup.
  116.         /// </summary>
  117.         public int loadedConfig = 0;
  118.  
  119.         /// <summary>
  120.         /// This is the list of configs used to set up different layouts of the same map.
  121.         /// For example, you could create just one config and use that as your minimap.
  122.         /// Or you could create two: One for a minimap and another for a fullscreen map, and toggle bettween them.
  123.         /// The DMMapConfig class also holds all the useful properties that define the look and feel of the map (colors, zooms, etc)
  124.         /// You can also change the properties on the config values to update the values in real time.
  125.         /// ie; DMMap.instance.configs[loadedConfig].zoom += 10f; will increase the zoom.
  126.         /// For a working example at this load any of the demo projects found in DMMap/Demo and take a look at the DMMapUIControls script (DMMap/Demos/DemoAssets/DMMapUIControls.cs)
  127.         /// </summary>
  128.         public List<DMMapConfig> configs = new List<DMMapConfig>();
  129.  
  130.         /// <summary>
  131.         /// Loads a DMMapConfig and loads all the data into the current layout of the map
  132.         /// </summary>
  133.         /// <param name="config">The config to load</param>
  134.         public void LoadConfig(int config) {
  135.             if (config < 0 || config >= configs.Count) Debug.LogError(string.Format("[DMMap] - Error: Can not load config {0}, config missing", config));
  136.             loadedConfig = config;
  137.             configs[config].Apply();
  138.         }
  139.  
  140.         /// <summary>
  141.         /// Loads a DMMapConfig and loads all the data into the current layout of the map
  142.         /// </summary>
  143.         /// <param name="config">The config to load</param>
  144.         public void LoadConfig(string config) {
  145.             for (int i = 0; i < configs.Count; i++) {
  146.                 if (configs[i].name == config) {
  147.                     configs[i].Apply();
  148.                     return;
  149.                 }
  150.             }
  151.             Debug.LogError(string.Format("[DMMap] - Error: Can not load config {0}, no config with that name", config));
  152.         }
  153.         /// <summary>
  154.         /// Sets the current active layer, turning off all layers except for one.
  155.         /// Using this function you can easily create multi-layer maps, and only show the map of the layer you are on.
  156.         /// </summary>
  157.         /// <param name="layer"> The layer to set as active.</param>
  158.         public void SetActiveLayer(int layer) {
  159.             DisableAllLayers();
  160.             if (layer >= 0 && layer < meshLayers.Length) {
  161.                 if (meshLayers[layer] != null) {
  162.                     meshLayers[layer].SetActive(true);
  163.                 }
  164.             }
  165.             for (int i = 0; i < icons.Count; i++) {
  166.                 if (icons[i].layer == -1 || icons[i].layer == layer) {
  167.                     icons[i].gameObject.SetActive(true);
  168.                 }
  169.             }
  170.         }
  171.         /// <summary>
  172.         /// Disables all layers, resulting in no map layers being rendered.
  173.         /// </summary>
  174.         public void DisableAllLayers() {
  175.             if (meshLayers.Length == 0) {
  176.                 return;
  177.             }
  178.             for (int i = 0; i < meshLayers.Length; i++) {
  179.                 if (meshLayers[i] != null) {
  180.                     meshLayers[i].SetActive(false);
  181.                 }
  182.             }
  183.             for (int i = 0; i < icons.Count; i++) {
  184.                 icons[i].gameObject.SetActive(false);
  185.             }
  186.         }
  187.  
  188.         /// <summary>
  189.         /// Begins the generation of the map layers.  Can be called at runtime, or in the editor by clicking the "Generate Map Mesh" button on the DMMap Component
  190.         /// </summary>
  191.         public void Generate() {
  192.             CreateMeshContainer();
  193.             int highestLayer = 0;
  194.             DMMapShape[] sha = GameObject.FindObjectsOfType<DMMapShape>();
  195.             shapes = new List<DMMapShape>();
  196.             for (int i = 0; i < sha.Length; i++) {
  197.                 shapes.Add(sha[i]);
  198.             }
  199.  
  200.             for (int i = 0; i < shapes.Count; i++) {
  201.                 if (shapes[i].layer > highestLayer) {
  202.                     highestLayer = shapes[i].layer;
  203.                 }
  204.             }
  205.  
  206.             meshLayers = new GameObject[highestLayer + 1];
  207.             for (int i = 0; i < meshLayers.Length; i++) {
  208.                 GenerateMeshLayer(i);
  209.             }
  210.         }
  211.  
  212.         /// <summary>
  213.         /// Transforms an icon worldposition to UI space so that it aligns with the Map UI component
  214.         /// </summary>
  215.         /// <param name="worldPoint"></param>
  216.         /// <returns></returns>
  217.         public Vector3 WorldtoUI(Vector3 worldPoint) {
  218.             Vector3 camera = DMMapCamera.WorldToViewportPoint(worldPoint);
  219.             camera = camera - new Vector3(0.5f, 0.5f, 0f);
  220.  
  221.             RectTransform imageRT = mapImage.GetComponent<RectTransform>();
  222.  
  223.             Vector3 scale = new Vector3(imageRT.rect.width, imageRT.rect.height, 0f);
  224.             Vector3 r = new Vector3(camera.x * scale.x, camera.y * scale.y, camera.z * scale.z);
  225.  
  226.             return r;
  227.         }
  228.         /// <summary>
  229.         /// Transforms an icon UI position to world-position
  230.         /// </summary>
  231.         /// <param name="screenPoint"></param> Usually Input.mouse.position
  232.         /// <returns></returns>
  233.         public Vector3 UIToWorld(Vector3 screenPoint) {
  234.             RectTransform imageRT = mapImage.GetComponent<RectTransform>();
  235.             //Debug.Log("screen point: " + screenPoint);
  236.             //Debug.Log("UI center: " + imageRT.transform.position);
  237.  
  238.             Vector3 mapViewportPosition = new Vector3((screenPoint.x - imageRT.transform.position.x) / (imageRT.rect.width * canvas.scaleFactor),
  239.                                                               (screenPoint.y - imageRT.transform.position.y) / (imageRT.rect.height * canvas.scaleFactor), 0f);
  240.             Vector3 offset = new Vector3(0.5f, 0.5f, 0f);
  241.             mapViewportPosition = mapViewportPosition + offset;
  242.             Vector3 worldPoint = DMMap.instance.DMMapCamera.ViewportToWorldPoint(mapViewportPosition);
  243.             return worldPoint;
  244.         }
  245.  
  246.         /// <summary>
  247.         /// Creates an instance of a gameobject at the world-position represented on the minimap.
  248.         /// </summary>
  249.         /// <param name="waypoint"></param> The gameobject you wish to instantiate (which has a DMMapIcon component.
  250.         /// Using a gameobject here allows you to create a visual representation of the waypoint in your game (like a beam of light?)
  251.         /// <param name="screenPoint"></param> the screen point of where you want to create the waypoint.  Usually Input.mousePosition.
  252.         /// We convert this internally to the proper map-image coordinate space.
  253.         /// <returns></returns>
  254.         public bool CreateWaypoint(GameObject waypoint, Vector3 screenPoint) {
  255.             Vector3 worldPoint = UIToWorld(screenPoint);
  256.             RectTransform imageRT = mapImage.GetComponent<RectTransform>();
  257.  
  258.            if (Mathf.Abs(screenPoint.x - imageRT.transform.position.x) < (imageRT.rect.width * canvas.scaleFactor) / 2f &&
  259.                Mathf.Abs(screenPoint.y - imageRT.transform.position.y) < (imageRT.rect.height * canvas.scaleFactor) / 2f) {
  260.                    ((GameObject)Instantiate(waypoint)).transform.position = worldPoint;
  261.                return true;
  262.            } else {
  263.                //waypoint creation failed because we didn't click within the map bounds
  264.                return false;
  265.            }
  266.         }
  267.  
  268.         /// -----------------------------------------------------
  269.         /// ----------- INTERNAL STUFF BELOW --------------------
  270.         /// -----------------------------------------------------
  271.         /// -----------------------------------------------------
  272.         /// The stuff below is internal stuff you shouldn't have to worry about.
  273.         /// It's *mostly* undocumenated, but feel free to poke around if you want! :D
  274.  
  275.         #region INTERNAL_STUFF
  276.  
  277.         public void UpdateMeshMaterials() {
  278.             if (meshLayers == null) return;
  279.  
  280.             //lazy
  281.             for (int i = 0; i < meshLayers.Length; i++) {
  282.                 try {
  283.                     meshLayers[i].GetComponent<Renderer>().material = configs[loadedConfig].meshLayerMaterial[i];
  284.                 }
  285.                 catch {
  286.                     try {
  287.                         meshLayers[i].GetComponent<Renderer>().material = defaultMaterial;
  288.                     }
  289.                     catch {
  290.                     }
  291.                 }
  292.             }
  293.         }
  294.  
  295.         public void DMMapDebug(string msg) {
  296.             if (DebugMessages) {
  297.                 Debug.Log("[DMMap] - " + msg);
  298.             }
  299.         }
  300.         public void Awake() {
  301.             shapes = new List<DMMapShape>();
  302.             icons = new List<DMMapIcon>();
  303.             DMMap.instance = this;
  304.  
  305.             //if (LayerMask.NameToLayer("DMMap") == -1) {
  306.             //    Debug.LogError("[DMMap] - Layer is missing.  See the readme.txt");
  307.             //}
  308.         }
  309.         public void Start() {
  310.  
  311.             Initialize();
  312.         }
  313.  
  314.         public void Initialize() {
  315.             if (!initialized) {
  316.                 initialized = true;
  317.                 Setup();
  318.             }
  319.         }
  320.  
  321.         private void Setup() {
  322.             if (configs.Count <= 0) Debug.LogError("[DMMap] - Error:  Need at least one config to load!");
  323.             LayerMask layer = LayerMask.NameToLayer("DMMap");
  324.             if (layer.value == -1) Debug.LogError("DMMap Layer was not found.  Please follow the instructions in the Readme.txt to set up a DMMap layer!");
  325.             DMMapCamera.cullingMask = 1 << layer.value;
  326.  
  327.             started = true;
  328.             LoadConfig(loadedConfig);
  329.  
  330.             this.gameObject.layer = LayerMask.NameToLayer("DMMap");
  331.             DMMapCamera.gameObject.layer = LayerMask.NameToLayer("DMMap");
  332.  
  333.             SetupCamera();
  334.  
  335.             if (generateOnStart) {
  336.                 Generate();
  337.             } else {
  338.                 int highestLayer = 0;
  339.                 for (int i = 0; i < shapes.Count; i++) {
  340.                     if (shapes[i].layer > highestLayer) {
  341.                         highestLayer = shapes[i].layer;
  342.                     }
  343.                 }
  344.                 meshLayers = new GameObject[highestLayer + 1];
  345.                 Transform m_container = this.transform.Find("DMMap Mesh");
  346.                 Transform child;
  347.                 if (m_container != null) {
  348.                     for (int i = 0; i < meshLayers.Length; i++) {
  349.                         child = m_container.Find("Mesh_" + i);
  350.                         if (child != null) {
  351.                             meshLayers[i] = child.gameObject;
  352.                         }
  353.                     }
  354.                 }
  355.             }
  356.  
  357.             UpdateMeshMaterials();
  358.  
  359.         }
  360.  
  361.         private void SetupCamera() {
  362.             InitializeRenderTexture();
  363.             DMMapCamera.targetTexture = mainRenderTexture;
  364.             mapImage.texture = mainRenderTexture;
  365.             mapImage.material.SetTexture("_MainTex", DMMapCamera.targetTexture);
  366.             DMMapCamera.backgroundColor = configs[loadedConfig].mapBackgroundColor;
  367.             DMMapCamera.orthographicSize = configs[loadedConfig].zoom;
  368.  
  369.             //setup default position
  370.  
  371.                 Vector3 camPos = Vector3.zero;
  372.                 switch(orientation) {
  373.                     case MapOrientation.XZ:
  374.                         camPos.y = 25f;
  375.                         break;
  376.                     case MapOrientation.XY:
  377.                         camPos.z = -25f;
  378.                         break;
  379.                     case MapOrientation.YZ:
  380.                         camPos.x = 25f;
  381.                         break;
  382.                 }
  383.                 GetCameraTarget().position = camPos;
  384.  
  385.  
  386.                 //setup default rotation
  387.                 Vector3 rot = new Vector3();
  388.                 Quaternion q = GetCameraTarget().rotation;
  389.                 switch(orientation) {
  390.                     case MapOrientation.XZ:
  391.                         rot = new Vector3(90f, 0f, 0f);
  392.                         break;
  393.                     case MapOrientation.XY:
  394.                         rot = new Vector3(0f, 0f, 0f);
  395.                         break;
  396.                     case MapOrientation.YZ:
  397.                         rot = new Vector3(0f, 270f, 0f);
  398.                         break;
  399.                 }
  400.                 q.eulerAngles = rot;
  401.                 GetCameraTarget().rotation = q;
  402.            
  403.  
  404.         }
  405.  
  406.         //if using custom orientation returns cam.parent, otherwise returns cam
  407.         public Transform GetCameraTarget() {
  408.             if(useCustomOrientation) return DMMapCamera.transform.parent;
  409.             else return DMMapCamera.transform;
  410.         }
  411.  
  412.         public void Update() {
  413.             if (!started) {
  414.                 Setup();
  415.             }
  416.  
  417.             //following and rotating a target
  418.             if (configs[loadedConfig].objectToFocusOn != null) {
  419.                 //clamp the camera to specific values on a specific axis
  420.                 Vector3 camPos = new Vector3(configs[loadedConfig].objectToFocusOn.position.x, configs[loadedConfig].objectToFocusOn.position.y, configs[loadedConfig].objectToFocusOn.position.z);
  421.                 switch (orientation) {
  422.                     case MapOrientation.XZ:
  423.                         camPos.y = 25f;
  424.                         break;
  425.                     case MapOrientation.XY:
  426.                         camPos.z = -25f;
  427.                         break;
  428.                     case MapOrientation.YZ:
  429.                         camPos.x = 25f;
  430.                         break;
  431.                 }
  432.  
  433.                 GetCameraTarget().position = camPos;
  434.                 if (configs[loadedConfig].rotate) {
  435.                     //depending on the MapOrientation rotate a different axis
  436.                     Vector3 rot = new Vector3();
  437.                     Quaternion q = DMMapCamera.transform.rotation;
  438.                     switch (orientation) {
  439.                         case MapOrientation.XZ:
  440.                             rot = new Vector3(90f, configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.y, 0f);
  441.                             break;
  442.                         case MapOrientation.XY:
  443.                             rot = new Vector3(0f, 0f, configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.z);
  444.                             break;
  445.                         case MapOrientation.YZ:
  446.                             rot = new Vector3(0f, 270f, -configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.x);
  447.                             break;
  448.                     }
  449.                     q.eulerAngles = rot;
  450.                     GetCameraTarget().rotation = q;
  451.                 }
  452.             }
  453.  
  454.             //set the zoom
  455.             DMMapCamera.orthographicSize = configs[loadedConfig].zoom;
  456.  
  457.             //update opacity
  458.             if (mapImage != null) {
  459.                 mapImage.material.SetFloat("_Opacity", configs[loadedConfig].opacity);
  460.             }
  461.  
  462.             //update background color
  463.             DMMapCamera.backgroundColor = configs[loadedConfig].mapBackgroundColor;
  464.  
  465.             //update icons
  466.             foreach (DMMapIcon i in icons) {
  467.                 i.UpdateIcons();
  468.             }
  469.  
  470.         }
  471.  
  472.         private void InitializeRenderTexture() {
  473.             DMMapDebug("Initializing RenderTexture");
  474.             mainRenderTexture = new RenderTexture(1024, 1024, 24, RenderTextureFormat.ARGB32);
  475.             mainRenderTexture.wrapMode = TextureWrapMode.Clamp;
  476.  
  477.             mainRenderTexture.name = "DMMap_RenderTexture";
  478.             mainRenderTexture.Create();
  479.         }
  480.  
  481.         private void CreateMeshContainer() {
  482.             if (meshContainer == null) {
  483.                 Transform child = this.transform.Find("DMMap Mesh");
  484.                 if (child != null) {
  485.                     meshContainer = child.gameObject;
  486.                 } else {
  487.                     meshContainer = new GameObject("DMMap Mesh");
  488.                     meshContainer.layer = LayerMask.NameToLayer("DMMap");
  489.                     meshContainer.transform.parent = this.transform;
  490.                 }
  491.             }
  492.         }
  493.  
  494.         private void GenerateMeshLayer(int layer = 0) {
  495.             #region Generate
  496.             DMMapDebug("Generating mesh layer [" + layer + "]");
  497.  
  498.             additive = new List<DMMapShape>();
  499.             subtractive = new List<DMMapShape>();
  500.  
  501.             if (shapes.Count <= 0) {
  502.                 DMMapDebug("You can't generate a map with no shapes!");
  503.                 return;
  504.             }
  505.  
  506.             DMMapDebug("Generating map with [" + shapes.Count + "] shapes");
  507.             for (int i = 0; i < shapes.Count; i++) {
  508.                 if (shapes[i].mode == DrawMode.Additive && shapes[i].layer == layer) {
  509.                     additive.Add(shapes[i]);
  510.                 } else if (shapes[i].mode == DrawMode.Subtractive && shapes[i].layer == layer) {
  511.                     subtractive.Add(shapes[i]);
  512.                 }
  513.             }
  514.             if (DebugMessages) {
  515.                 DMMapDebug("Generating map with shapes: Additive [" + additive.Count + "] | Subtractive [" + subtractive.Count + "]");
  516.             }
  517.             if (additive.Count <= 0) {
  518.                 return;
  519.             }
  520.  
  521.  
  522.             Transform child = meshContainer.transform.Find("Mesh_" + layer);
  523.             GameObject meshObject;
  524.             if (child == null) {
  525.                 meshObject = new GameObject("Mesh_" + layer);
  526.             } else {
  527.                 meshObject = child.gameObject;
  528.             }
  529.             meshObject.layer = LayerMask.NameToLayer("DMMap");
  530.             meshObject.transform.parent = meshContainer.transform;
  531.             meshLayers[layer] = meshObject;
  532.  
  533.             switch (orientation) {
  534.                 case MapOrientation.XZ:
  535.                     meshObject.gameObject.transform.localScale = new Vector3(1f, -1f, 1f);
  536.                     meshObject.gameObject.transform.position = new Vector3(0f, 1f * layer, 0f);
  537.                     break;
  538.                 case MapOrientation.XY:
  539.                     meshObject.gameObject.transform.localScale = new Vector3(1f, -1f, 1f);
  540.                     meshObject.gameObject.transform.position = new Vector3(0f, 0f, 1f * layer);
  541.                     meshObject.gameObject.transform.rotation = Quaternion.AngleAxis(-90f, Vector3.right);
  542.  
  543.                     break;
  544.                 case MapOrientation.YZ:
  545.                     meshObject.gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
  546.                     meshObject.gameObject.transform.position = new Vector3(1f*layer, 0f, 0f);
  547.                     meshObject.gameObject.transform.rotation = Quaternion.AngleAxis(90f, Vector3.forward);
  548.  
  549.                     break;
  550.             }
  551.             //Clipping
  552.  
  553.             Clipper c = new Clipper();
  554.             //List<List<IntPoint>> subj = new List<List<IntPoint>>();
  555.             //List<List<IntPoint>> clip = new List<List<IntPoint>>();
  556.             List<List<IntPoint>> solution = new List<List<IntPoint>>();
  557.             PolyTree ptSolution = new PolyTree();
  558.  
  559.             //the last execute needs to get the polytree computed..
  560.             bool hasSubtractive = (subtractive.Count > 0) ? true : false;
  561.  
  562.             if (additive.Count > 0) {
  563.                 c.AddPath(ShapeToCPolygon(additive[0]), PolyType.ptSubject, true);
  564.                 if (additive.Count == 1) {
  565.                     c.Execute(ClipType.ctUnion, ptSolution);
  566.                 }
  567.  
  568.             }
  569.  
  570.             for (int i = 1; i < additive.Count; i++) {
  571.                 if (i == additive.Count - 1 && !hasSubtractive) {
  572.                     c.AddPath(ShapeToCPolygon(additive[i]), PolyType.ptClip, true);
  573.                     c.Execute(ClipType.ctUnion, ptSolution);
  574.                 } else {
  575.                     c.AddPath(ShapeToCPolygon(additive[i]), PolyType.ptClip, true);
  576.                     c.Execute(ClipType.ctUnion, solution);
  577.                     c.Clear();
  578.                     c.AddPaths(solution, PolyType.ptSubject, true);
  579.                 }
  580.             }
  581.  
  582.             if (hasSubtractive) {
  583.                 for (int i = 0; i < subtractive.Count; i++) {
  584.                     if (i == subtractive.Count - 1) {
  585.                         c.AddPath(ShapeToCPolygon(subtractive[i]), PolyType.ptClip, true);
  586.                         c.Execute(ClipType.ctDifference, ptSolution);
  587.                     } else {
  588.                         c.AddPath(ShapeToCPolygon(subtractive[i]), PolyType.ptClip, true);
  589.                         c.Execute(ClipType.ctDifference, solution);
  590.                         c.Clear();
  591.                         c.AddPaths(solution, PolyType.ptSubject, true);
  592.                     }
  593.                 }
  594.             }
  595.             c.Clear();
  596.  
  597.             List<DPolygon> dPolygons = new List<DPolygon>();
  598.             for (int childsCount = 0; childsCount < ptSolution.ChildCount; childsCount++) {
  599.                 PolyTreeToDPolygonList(ptSolution.Childs[childsCount], ref dPolygons);
  600.             }
  601.  
  602.             //Triangulation
  603.             List<DMMTriangleNet.Mesh> tMesh = new List<DMMTriangleNet.Mesh>();
  604.             //List<DMMTriangleNet.Geometry.Polygon> tp = new List<Polygon>();
  605.             for (int i = 0; i < dPolygons.Count; i++) {
  606.                 if (!dPolygons[i].isHole) {
  607.                     DMMTriangleNet.Geometry.Polygon tnPoly = new Polygon();
  608.                     tnPoly.AddContour(dPolygons[i].points, 0, false);
  609.                     for (int j = 0; j < dPolygons[i].holes.Count; j++) {
  610.                         tnPoly.AddContour(dPolygons[i].holes[j].points, 0, true);
  611.                     }
  612.                     DMMTriangleNet.Meshing.GenericMesher gm = new DMMTriangleNet.Meshing.GenericMesher();
  613.                     gm.Triangulate(tnPoly);
  614.                     tMesh.Add((DMMTriangleNet.Mesh)tnPoly.Triangulate());
  615.                 }
  616.             }
  617.  
  618.  
  619.             //Edge normals
  620.             #region Normals
  621.             foreach (DPolygon poly in dPolygons) {
  622.                 for (int i = 0; i < poly.points.Count; i++) {
  623.                     int prev, next = 0;
  624.                     prev = i - 1;
  625.                     next = i + 1;
  626.                     if (prev < 0) {
  627.                         prev = poly.points.Count - 1;
  628.                     }
  629.                     if (next >= poly.points.Count) {
  630.                         next = 0;
  631.                     }
  632.  
  633.                     Vector2 eNormal = CalculateOutwardNormal(poly.points[i], poly.points[prev], poly.points[next]);
  634.                     eNormal.Normalize();
  635.                     poly.edgeNormals.Add(eNormal);
  636.                 }
  637.                 foreach (DPolygon hole in poly.holes) {
  638.                     for (int i = 0; i < hole.points.Count; i++) {
  639.                         int prev, next = 0;
  640.                         prev = i - 1;
  641.                         next = i + 1;
  642.                         if (prev < 0) {
  643.                             prev = hole.points.Count - 1;
  644.                         }
  645.                         if (next >= hole.points.Count) {
  646.                             next = 0;
  647.                         }
  648.  
  649.                         Vector2 eNormal = CalculateOutwardNormal(hole.points[i], hole.points[prev], hole.points[next]);
  650.                         eNormal.Normalize();
  651.                         hole.edgeNormals.Add(eNormal);
  652.                     }
  653.                 }
  654.             }
  655.  
  656.             //vertex normals
  657.             for (int j = 0; j < dPolygons.Count; j++) {
  658.                 DPolygon poly = dPolygons[j];
  659.                 for (int i = 0; i < poly.points.Count; i++) {
  660.                     int prev, next = 0;
  661.                     prev = i - 1;
  662.                     next = i + 1;
  663.                     if (prev < 0) {
  664.                         prev = poly.points.Count - 1;
  665.                     }
  666.                     if (next >= poly.points.Count) {
  667.                         next = 0;
  668.                     }
  669.                     Vector2 sum = poly.edgeNormals[i] + poly.edgeNormals[next];
  670.                     sum.Normalize();
  671.                     poly.vNormals.Add(sum);
  672.                 }
  673.                 foreach (DPolygon hole in poly.holes) {
  674.                     for (int i = 0; i < hole.points.Count; i++) {
  675.                         int prev, next = 0;
  676.                         prev = i - 1;
  677.                         next = i + 1;
  678.                         if (prev < 0) {
  679.                             prev = hole.points.Count - 1;
  680.                         }
  681.                         if (next >= hole.points.Count) {
  682.                             next = 0;
  683.                         }
  684.                         Vector2 sum = hole.edgeNormals[i] + hole.edgeNormals[next];
  685.                         sum.Normalize();
  686.                         hole.vNormals.Add(sum);
  687.                     }
  688.                 }
  689.             }
  690.             #endregion
  691.  
  692.             //Mesh calculation
  693.             List<Vector3> verts = new List<Vector3>();
  694.             List<int> tris = new List<int>();
  695.             //List<Vector2> uvs = new List<Vector2>();
  696.             List<Vector3> normals = new List<Vector3>();
  697.             Mesh mesh = new Mesh();
  698.  
  699.             for (int i = 0; i < dPolygons.Count; i++) {
  700.                 for (int j = 0; j < tMesh[i].Triangles.Count(); j++) {
  701.  
  702.  
  703.                     Vertex p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P0];
  704.                     Vector3 p3 = new Vector3();
  705.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  706.  
  707.                     //switch (orientation) {
  708.                     //    case MapOrientation.XZ:
  709.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  710.                     //        break;
  711.                     //    case MapOrientation.XY:
  712.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  713.                     //        break;
  714.                     //    case MapOrientation.YZ:
  715.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  716.                     //        break;
  717.                     //}
  718.  
  719.  
  720.                     if (verts.Contains(p3)) {
  721.                         int index = verts.IndexOf(p3);
  722.                         tris.Add(index);
  723.                     } else {
  724.                         verts.Add(p3);
  725.                         tris.Add(verts.Count - 1);
  726.                         Vector2 norm = Vector2.zero;
  727.                         if (dPolygons[i].points.Contains(p)) {
  728.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  729.                         } else {
  730.                             foreach (DPolygon hole in dPolygons[i].holes) {
  731.                                 if (hole.points.Contains(p)) {
  732.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  733.                                     break;
  734.                                 }
  735.                             }
  736.                         }
  737.  
  738.                         if (norm == Vector2.zero) {
  739.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  740.                         }
  741.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  742.  
  743.                         //switch (orientation) {
  744.                         //    case MapOrientation.XZ:
  745.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  746.                         //        break;
  747.                         //    case MapOrientation.XY:
  748.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  749.                         //        break;
  750.                         //    case MapOrientation.YZ:
  751.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  752.                         //        break;
  753.                         //}
  754.                     }
  755.  
  756.                     //point 2
  757.  
  758.                     p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P1];
  759.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  760.  
  761.                     //switch (orientation) {
  762.                     //    case MapOrientation.XZ:
  763.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  764.                     //        break;
  765.                     //    case MapOrientation.XY:
  766.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  767.                     //        break;
  768.                     //    case MapOrientation.YZ:
  769.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  770.                     //        break;
  771.                     //}
  772.                     if (verts.Contains(p3)) {
  773.                         int index = verts.IndexOf(p3);
  774.                         tris.Add(index);
  775.                     } else {
  776.                         verts.Add(p3);
  777.                         tris.Add(verts.Count - 1);
  778.                         Vector2 norm = Vector2.zero;
  779.                         if (dPolygons[i].points.Contains(p)) {
  780.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  781.                         } else {
  782.                             foreach (DPolygon hole in dPolygons[i].holes) {
  783.                                 if (hole.points.Contains(p)) {
  784.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  785.                                     break;
  786.                                 }
  787.                             }
  788.                         }
  789.  
  790.                         if (norm == Vector2.zero) {
  791.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  792.                         }
  793.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  794.  
  795.                         //switch (orientation) {
  796.                         //    case MapOrientation.XZ:
  797.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  798.                         //        break;
  799.                         //    case MapOrientation.XY:
  800.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  801.                         //        break;
  802.                         //    case MapOrientation.YZ:
  803.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  804.                         //        break;
  805.                         //}
  806.                     }
  807.  
  808.                     //point 3
  809.                     p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P2];
  810.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  811.  
  812.                     //switch (orientation) {
  813.                     //    case MapOrientation.XZ:
  814.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  815.                     //        break;
  816.                     //    case MapOrientation.XY:
  817.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  818.                     //        break;
  819.                     //    case MapOrientation.YZ:
  820.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  821.                     //        break;
  822.                     //}
  823.                     if (verts.Contains(p3)) {
  824.  
  825.                         int index = verts.IndexOf(p3);
  826.                         tris.Add(index);
  827.  
  828.                     } else {
  829.                         verts.Add(p3);
  830.                         tris.Add(verts.Count - 1);
  831.                         Vector2 norm = Vector2.zero;
  832.                         if (dPolygons[i].points.Contains(p)) {
  833.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  834.                         } else {
  835.                             foreach (DPolygon hole in dPolygons[i].holes) {
  836.                                 if (hole.points.Contains(p)) {
  837.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  838.                                     break;
  839.                                 }
  840.                             }
  841.                         }
  842.  
  843.                         if (norm == Vector2.zero) {
  844.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  845.                         }
  846.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  847.  
  848.                         //switch (orientation) {
  849.                         //    case MapOrientation.XZ:
  850.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  851.                         //        break;
  852.                         //    case MapOrientation.XY:
  853.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  854.                         //        break;
  855.                         //    case MapOrientation.YZ:
  856.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  857.                         //        break;
  858.                         //}
  859.                     }
  860.  
  861.                 }
  862.             }
  863.  
  864.             mesh.vertices = verts.ToArray();
  865.             mesh.normals = normals.ToArray();
  866.             mesh.triangles = tris.ToArray();
  867.  
  868.             MeshFilter mf = meshObject.GetComponent<MeshFilter>();
  869.             if (mf == null) {
  870.                 mf = meshObject.AddComponent<MeshFilter>();
  871.             }
  872.  
  873.             MeshRenderer meshrenderer = meshObject.GetComponent<MeshRenderer>();
  874.             if (meshrenderer == null) {
  875.                 meshrenderer = meshObject.AddComponent<MeshRenderer>();
  876.                 meshrenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  877.                 meshrenderer.receiveShadows = false;
  878.             }
  879.  
  880.            
  881.             meshrenderer.material = defaultMaterial;
  882.             mf.mesh = mesh;
  883.             DMMapDebug("Map Generation Complete: Layer[" + layer + "]");
  884.  
  885.             #endregion
  886.         }
  887.  
  888.         #region MapMeshGen Helper functions
  889.         private Vector2 CalculateOutwardNormal(Vertex _a, Vertex _b, Vertex _c) {
  890.             Vector2 a = new Vector2((float)_a.X, (float)_a.Y);
  891.             Vector2 b = new Vector2((float)_b.X, (float)_b.Y);
  892.             Vector2 c = new Vector2((float)_c.X, (float)_c.Y);
  893.  
  894.             Vector2 AB = b - a;
  895.             Vector2 AC = c - a;
  896.             Vector2 nAB = new Vector2(-AB.y, AB.x);
  897.             float dot = Vector2.Dot(nAB, AC);
  898.  
  899.             if (dot > 0) {
  900.                 return nAB;
  901.             } else {
  902.                 return nAB;
  903.             }
  904.         }
  905.         private void AddPolygonWithHoles2(PolyNode node, ref Polygon p) {
  906.             List<Vertex> contour = new List<Vertex>();
  907.             for (int i = 0; i < node.Contour.Count; i++) {
  908.                 contour.Add(new Vertex((double)node.Contour[i].X, (double)node.Contour[i].Y));
  909.             }
  910.  
  911.             p.AddContour(contour, 0, node.IsHole);
  912.             for (int i = 0; i < node.ChildCount; i++) {
  913.                 AddPolygonWithHoles2(node.Childs[i], ref p);
  914.             }
  915.         }
  916.         private void PolyTreeToDPolygonList(PolyNode node, ref List<DPolygon> dPolygons) {
  917.  
  918.             DPolygon poly = new DPolygon();
  919.             poly.points = new List<Vertex>();
  920.  
  921.             poly.isHole = false;
  922.             if (!node.IsHole) {
  923.                 dPolygons.Add(poly);
  924.             }
  925.  
  926.             for (int i = 0; i < node.Contour.Count; i++) {
  927.                 poly.points.Add(new Vertex((double)node.Contour[i].X, (double)node.Contour[i].Y));
  928.             }
  929.             for (int i = 0; i < node.ChildCount; i++) {
  930.                 if (node.Childs[i].IsHole) {
  931.                     DPolygon hole = new DPolygon();
  932.                     for (int j = 0; j < node.Childs[i].Contour.Count; j++) {
  933.                         hole.points.Add(new Vertex((double)node.Childs[i].Contour[j].X, (double)node.Childs[i].Contour[j].Y));
  934.                     }
  935.                     poly.holes.Add(hole);
  936.                 }
  937.                 PolyTreeToDPolygonList(node.Childs[i], ref dPolygons);
  938.             }
  939.         }
  940.  
  941.         private List<IntPoint> ShapeToCPolygon(DMMapShape shape) {
  942.             List<IntPoint> points = new List<IntPoint>();
  943.             for (int i = 0; i < shape.verts.Count; i++) {
  944.                 switch (orientation) {
  945.                     case MapOrientation.XZ:
  946.                         points.Add(new IntPoint(shape.verts[i].transform.position.x * triangulationScale, shape.verts[i].transform.position.z * triangulationScale));
  947.                         break;
  948.                     case MapOrientation.XY:
  949.                         points.Add(new IntPoint(shape.verts[i].transform.position.x * triangulationScale, shape.verts[i].transform.position.y * triangulationScale));
  950.                         break;
  951.                     case MapOrientation.YZ:
  952.                         points.Add(new IntPoint(shape.verts[i].transform.position.y * triangulationScale, shape.verts[i].transform.position.z * triangulationScale));
  953.                         break;
  954.  
  955.                 }
  956.  
  957.             }
  958.             return points;
  959.         }
  960.         #endregion
  961.  
  962.         private void DrawPolytree(List<DPolygon> plist, bool drawNormals = false) {
  963.             foreach (DPolygon p in plist) {
  964.                 for (int i = 0; i < p.points.Count - 1; i++) {
  965.                     Vector3 p0 = new Vector3();
  966.                     Vector3 p1 = new Vector3();
  967.  
  968.                     switch (orientation) {
  969.                         case MapOrientation.XZ:
  970.                             p0 = new Vector3((float)p.points[i].X, 10f, (float)p.points[i].Y);
  971.                             p1 = new Vector3((float)p.points[i + 1].X, 10f, (float)p.points[i + 1].Y);
  972.                             break;
  973.                         case MapOrientation.XY:
  974.                             p0 = new Vector3((float)p.points[i].X, (float)p.points[i].Y, 10f);
  975.                             p1 = new Vector3((float)p.points[i + 1].X, (float)p.points[i + 1].Y, 10f);
  976.                             break;
  977.  
  978.                         case MapOrientation.YZ:
  979.                             p0 = new Vector3(10f, (float)p.points[i].X, (float)p.points[i].Y);
  980.                             p1 = new Vector3(10f, (float)p.points[i + 1].X, (float)p.points[i + 1].Y);
  981.                             break;
  982.                     }
  983.  
  984.                     Debug.DrawLine(p0, p1, Color.cyan, float.MaxValue);
  985.  
  986.                     //draw edge normals
  987.                     if (drawNormals) {
  988.                         Vector3 dir = new Vector3(p.vNormals[i].x, 0f, p.vNormals[i].y);
  989.                         Debug.DrawRay(p0, dir * 100f, Color.white, float.MaxValue);
  990.                     }
  991.                 }
  992.                 Vector3 p2 = new Vector3();
  993.                 Vector3 p3 = new Vector3();
  994.                 switch (orientation) {
  995.                     case MapOrientation.XZ:
  996.                         p2 = new Vector3((float)p.points[0].X, 10f, (float)p.points[0].Y);
  997.                         p3 = new Vector3((float)p.points[p.points.Count - 1].X, 10f, (float)p.points[p.points.Count - 1].Y);
  998.                         break;
  999.                     case MapOrientation.XY:
  1000.                         p2 = new Vector3((float)p.points[0].X, (float)p.points[0].Y, 10f);
  1001.                         p3 = new Vector3((float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y, 10f);
  1002.                         break;
  1003.  
  1004.                     case MapOrientation.YZ:
  1005.                         p2 = new Vector3(10f, (float)p.points[0].X, (float)p.points[0].Y);
  1006.                         p3 = new Vector3(10f, (float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y);
  1007.                         break;
  1008.                 }
  1009.  
  1010.                 Debug.DrawLine(p2, p3, Color.cyan, float.MaxValue);
  1011.  
  1012.  
  1013.                 if (p.holes != null) {
  1014.                     foreach (DPolygon h in p.holes) {
  1015.                         for (int i = 0; i < h.points.Count - 1; i++) {
  1016.                             Vector3 p0 = new Vector3();
  1017.                             Vector3 p1 = new Vector3();
  1018.                             switch (orientation) {
  1019.                                 case MapOrientation.XZ:
  1020.                                     p0 = new Vector3((float)p.points[i].X, 10f, (float)p.points[i].Y);
  1021.                                     p1 = new Vector3((float)p.points[i + 1].X, 10f, (float)p.points[i + 1].Y);
  1022.                                     break;
  1023.                                 case MapOrientation.XY:
  1024.                                     p0 = new Vector3((float)p.points[i].X, (float)p.points[i].Y, 10f);
  1025.                                     p1 = new Vector3((float)p.points[i + 1].X, (float)p.points[i + 1].Y, 10f);
  1026.                                     break;
  1027.  
  1028.                                 case MapOrientation.YZ:
  1029.                                     p0 = new Vector3(10f, (float)p.points[i].X, (float)p.points[i].Y);
  1030.                                     p1 = new Vector3(10f, (float)p.points[i + 1].X, (float)p.points[i + 1].Y);
  1031.                                     break;
  1032.                             }
  1033.                             Debug.DrawLine(p0, p1, Color.red, float.MaxValue);
  1034.  
  1035.                             if (drawNormals) {
  1036.                                 Vector3 dir = new Vector3(h.vNormals[i].x, 0f, h.vNormals[i].y);
  1037.                                 Debug.DrawRay(p0, dir * 100f, Color.white, float.MaxValue);
  1038.                             }
  1039.  
  1040.                         }
  1041.                         Vector3 p4 = new Vector3();
  1042.                         Vector3 p5 = new Vector3();
  1043.                         switch (orientation) {
  1044.                             case MapOrientation.XZ:
  1045.                                 p4 = new Vector3((float)p.points[0].X, 10f, (float)p.points[0].Y);
  1046.                                 p5 = new Vector3((float)p.points[p.points.Count - 1].X, 10f, (float)p.points[p.points.Count - 1].Y);
  1047.                                 break;
  1048.                             case MapOrientation.XY:
  1049.                                 p4 = new Vector3((float)p.points[0].X, (float)p.points[0].Y, 10f);
  1050.                                 p5 = new Vector3((float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y, 10f);
  1051.                                 break;
  1052.  
  1053.                             case MapOrientation.YZ:
  1054.                                 p4 = new Vector3(10f, (float)p.points[0].X, (float)p.points[0].Y);
  1055.                                 p5 = new Vector3(10f, (float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y);
  1056.                                 break;
  1057.                         }
  1058.                         Debug.DrawLine(p4, p5, Color.red, float.MaxValue);
  1059.  
  1060.                     }
  1061.                 }
  1062.             }
  1063.         }
  1064.         #endregion
  1065.     }
  1066.  
  1067.     public enum IconScaleMode {
  1068.         ScaleWithZoom,
  1069.         NoScale,
  1070.         DefinedPerIcon
  1071.     }
  1072.  
  1073.     public enum MapOrientation {
  1074.         XZ,
  1075.         XY,
  1076.         YZ,
  1077.     }
  1078. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement