Advertisement
DMeville

Untitled

May 26th, 2018
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 47.43 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.                 DMMapCamera.transform.parent.position = camPos;
  384.  
  385.  
  386.                 //setup default rotation
  387.                 Vector3 rot = new Vector3();
  388.                 Quaternion q = DMMapCamera.transform.parent.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.                 DMMapCamera.transform.parent.rotation = q;
  402.            
  403.  
  404.         }
  405.  
  406.         public void Update() {
  407.             if (!started) {
  408.                 Setup();
  409.             }
  410.  
  411.             //following and rotating a target
  412.             if (configs[loadedConfig].objectToFocusOn != null) {
  413.                 //clamp the camera to specific values on a specific axis
  414.                 Vector3 camPos = new Vector3(configs[loadedConfig].objectToFocusOn.position.x, configs[loadedConfig].objectToFocusOn.position.y, configs[loadedConfig].objectToFocusOn.position.z);
  415.                 switch (orientation) {
  416.                     case MapOrientation.XZ:
  417.                         camPos.y = 25f;
  418.                         break;
  419.                     case MapOrientation.XY:
  420.                         camPos.z = -25f;
  421.                         break;
  422.                     case MapOrientation.YZ:
  423.                         camPos.x = 25f;
  424.                         break;
  425.                 }
  426.  
  427.                 DMMapCamera.transform.parent.position = camPos;
  428.                 if (configs[loadedConfig].rotate) {
  429.                     //depending on the MapOrientation rotate a different axis
  430.                     Vector3 rot = new Vector3();
  431.                     Quaternion q = DMMapCamera.transform.rotation;
  432.                     switch (orientation) {
  433.                         case MapOrientation.XZ:
  434.                             rot = new Vector3(90f, configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.y, 0f);
  435.                             break;
  436.                         case MapOrientation.XY:
  437.                             rot = new Vector3(0f, 0f, configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.z);
  438.                             break;
  439.                         case MapOrientation.YZ:
  440.                             rot = new Vector3(0f, 270f, -configs[loadedConfig].objectToFocusOn.transform.rotation.eulerAngles.x);
  441.                             break;
  442.                     }
  443.                     q.eulerAngles = rot;
  444.                     DMMapCamera.transform.parent.rotation = q;
  445.                 }
  446.             }
  447.  
  448.             //set the zoom
  449.             DMMapCamera.orthographicSize = configs[loadedConfig].zoom;
  450.  
  451.             //update opacity
  452.             if (mapImage != null) {
  453.                 mapImage.material.SetFloat("_Opacity", configs[loadedConfig].opacity);
  454.             }
  455.  
  456.             //update background color
  457.             DMMapCamera.backgroundColor = configs[loadedConfig].mapBackgroundColor;
  458.  
  459.             //update icons
  460.             foreach (DMMapIcon i in icons) {
  461.                 i.UpdateIcons();
  462.             }
  463.  
  464.         }
  465.  
  466.         private void InitializeRenderTexture() {
  467.             DMMapDebug("Initializing RenderTexture");
  468.             mainRenderTexture = new RenderTexture(1024, 1024, 24, RenderTextureFormat.ARGB32);
  469.             mainRenderTexture.wrapMode = TextureWrapMode.Clamp;
  470.  
  471.             mainRenderTexture.name = "DMMap_RenderTexture";
  472.             mainRenderTexture.Create();
  473.         }
  474.  
  475.         private void CreateMeshContainer() {
  476.             if (meshContainer == null) {
  477.                 Transform child = this.transform.Find("DMMap Mesh");
  478.                 if (child != null) {
  479.                     meshContainer = child.gameObject;
  480.                 } else {
  481.                     meshContainer = new GameObject("DMMap Mesh");
  482.                     meshContainer.layer = LayerMask.NameToLayer("DMMap");
  483.                     meshContainer.transform.parent = this.transform;
  484.                 }
  485.             }
  486.         }
  487.  
  488.         private void GenerateMeshLayer(int layer = 0) {
  489.             #region Generate
  490.             DMMapDebug("Generating mesh layer [" + layer + "]");
  491.  
  492.             additive = new List<DMMapShape>();
  493.             subtractive = new List<DMMapShape>();
  494.  
  495.             if (shapes.Count <= 0) {
  496.                 DMMapDebug("You can't generate a map with no shapes!");
  497.                 return;
  498.             }
  499.  
  500.             DMMapDebug("Generating map with [" + shapes.Count + "] shapes");
  501.             for (int i = 0; i < shapes.Count; i++) {
  502.                 if (shapes[i].mode == DrawMode.Additive && shapes[i].layer == layer) {
  503.                     additive.Add(shapes[i]);
  504.                 } else if (shapes[i].mode == DrawMode.Subtractive && shapes[i].layer == layer) {
  505.                     subtractive.Add(shapes[i]);
  506.                 }
  507.             }
  508.             if (DebugMessages) {
  509.                 DMMapDebug("Generating map with shapes: Additive [" + additive.Count + "] | Subtractive [" + subtractive.Count + "]");
  510.             }
  511.             if (additive.Count <= 0) {
  512.                 return;
  513.             }
  514.  
  515.  
  516.             Transform child = meshContainer.transform.Find("Mesh_" + layer);
  517.             GameObject meshObject;
  518.             if (child == null) {
  519.                 meshObject = new GameObject("Mesh_" + layer);
  520.             } else {
  521.                 meshObject = child.gameObject;
  522.             }
  523.             meshObject.layer = LayerMask.NameToLayer("DMMap");
  524.             meshObject.transform.parent = meshContainer.transform;
  525.             meshLayers[layer] = meshObject;
  526.  
  527.             switch (orientation) {
  528.                 case MapOrientation.XZ:
  529.                     meshObject.gameObject.transform.localScale = new Vector3(1f, -1f, 1f);
  530.                     meshObject.gameObject.transform.position = new Vector3(0f, 1f * layer, 0f);
  531.                     break;
  532.                 case MapOrientation.XY:
  533.                     meshObject.gameObject.transform.localScale = new Vector3(1f, -1f, 1f);
  534.                     meshObject.gameObject.transform.position = new Vector3(0f, 0f, 1f * layer);
  535.                     meshObject.gameObject.transform.rotation = Quaternion.AngleAxis(-90f, Vector3.right);
  536.  
  537.                     break;
  538.                 case MapOrientation.YZ:
  539.                     meshObject.gameObject.transform.localScale = new Vector3(1f, 1f, 1f);
  540.                     meshObject.gameObject.transform.position = new Vector3(1f*layer, 0f, 0f);
  541.                     meshObject.gameObject.transform.rotation = Quaternion.AngleAxis(90f, Vector3.forward);
  542.  
  543.                     break;
  544.             }
  545.             //Clipping
  546.  
  547.             Clipper c = new Clipper();
  548.             //List<List<IntPoint>> subj = new List<List<IntPoint>>();
  549.             //List<List<IntPoint>> clip = new List<List<IntPoint>>();
  550.             List<List<IntPoint>> solution = new List<List<IntPoint>>();
  551.             PolyTree ptSolution = new PolyTree();
  552.  
  553.             //the last execute needs to get the polytree computed..
  554.             bool hasSubtractive = (subtractive.Count > 0) ? true : false;
  555.  
  556.             if (additive.Count > 0) {
  557.                 c.AddPath(ShapeToCPolygon(additive[0]), PolyType.ptSubject, true);
  558.                 if (additive.Count == 1) {
  559.                     c.Execute(ClipType.ctUnion, ptSolution);
  560.                 }
  561.  
  562.             }
  563.  
  564.             for (int i = 1; i < additive.Count; i++) {
  565.                 if (i == additive.Count - 1 && !hasSubtractive) {
  566.                     c.AddPath(ShapeToCPolygon(additive[i]), PolyType.ptClip, true);
  567.                     c.Execute(ClipType.ctUnion, ptSolution);
  568.                 } else {
  569.                     c.AddPath(ShapeToCPolygon(additive[i]), PolyType.ptClip, true);
  570.                     c.Execute(ClipType.ctUnion, solution);
  571.                     c.Clear();
  572.                     c.AddPaths(solution, PolyType.ptSubject, true);
  573.                 }
  574.             }
  575.  
  576.             if (hasSubtractive) {
  577.                 for (int i = 0; i < subtractive.Count; i++) {
  578.                     if (i == subtractive.Count - 1) {
  579.                         c.AddPath(ShapeToCPolygon(subtractive[i]), PolyType.ptClip, true);
  580.                         c.Execute(ClipType.ctDifference, ptSolution);
  581.                     } else {
  582.                         c.AddPath(ShapeToCPolygon(subtractive[i]), PolyType.ptClip, true);
  583.                         c.Execute(ClipType.ctDifference, solution);
  584.                         c.Clear();
  585.                         c.AddPaths(solution, PolyType.ptSubject, true);
  586.                     }
  587.                 }
  588.             }
  589.             c.Clear();
  590.  
  591.             List<DPolygon> dPolygons = new List<DPolygon>();
  592.             for (int childsCount = 0; childsCount < ptSolution.ChildCount; childsCount++) {
  593.                 PolyTreeToDPolygonList(ptSolution.Childs[childsCount], ref dPolygons);
  594.             }
  595.  
  596.             //Triangulation
  597.             List<DMMTriangleNet.Mesh> tMesh = new List<DMMTriangleNet.Mesh>();
  598.             //List<DMMTriangleNet.Geometry.Polygon> tp = new List<Polygon>();
  599.             for (int i = 0; i < dPolygons.Count; i++) {
  600.                 if (!dPolygons[i].isHole) {
  601.                     DMMTriangleNet.Geometry.Polygon tnPoly = new Polygon();
  602.                     tnPoly.AddContour(dPolygons[i].points, 0, false);
  603.                     for (int j = 0; j < dPolygons[i].holes.Count; j++) {
  604.                         tnPoly.AddContour(dPolygons[i].holes[j].points, 0, true);
  605.                     }
  606.                     DMMTriangleNet.Meshing.GenericMesher gm = new DMMTriangleNet.Meshing.GenericMesher();
  607.                     gm.Triangulate(tnPoly);
  608.                     tMesh.Add((DMMTriangleNet.Mesh)tnPoly.Triangulate());
  609.                 }
  610.             }
  611.  
  612.  
  613.             //Edge normals
  614.             #region Normals
  615.             foreach (DPolygon poly in dPolygons) {
  616.                 for (int i = 0; i < poly.points.Count; i++) {
  617.                     int prev, next = 0;
  618.                     prev = i - 1;
  619.                     next = i + 1;
  620.                     if (prev < 0) {
  621.                         prev = poly.points.Count - 1;
  622.                     }
  623.                     if (next >= poly.points.Count) {
  624.                         next = 0;
  625.                     }
  626.  
  627.                     Vector2 eNormal = CalculateOutwardNormal(poly.points[i], poly.points[prev], poly.points[next]);
  628.                     eNormal.Normalize();
  629.                     poly.edgeNormals.Add(eNormal);
  630.                 }
  631.                 foreach (DPolygon hole in poly.holes) {
  632.                     for (int i = 0; i < hole.points.Count; i++) {
  633.                         int prev, next = 0;
  634.                         prev = i - 1;
  635.                         next = i + 1;
  636.                         if (prev < 0) {
  637.                             prev = hole.points.Count - 1;
  638.                         }
  639.                         if (next >= hole.points.Count) {
  640.                             next = 0;
  641.                         }
  642.  
  643.                         Vector2 eNormal = CalculateOutwardNormal(hole.points[i], hole.points[prev], hole.points[next]);
  644.                         eNormal.Normalize();
  645.                         hole.edgeNormals.Add(eNormal);
  646.                     }
  647.                 }
  648.             }
  649.  
  650.             //vertex normals
  651.             for (int j = 0; j < dPolygons.Count; j++) {
  652.                 DPolygon poly = dPolygons[j];
  653.                 for (int i = 0; i < poly.points.Count; i++) {
  654.                     int prev, next = 0;
  655.                     prev = i - 1;
  656.                     next = i + 1;
  657.                     if (prev < 0) {
  658.                         prev = poly.points.Count - 1;
  659.                     }
  660.                     if (next >= poly.points.Count) {
  661.                         next = 0;
  662.                     }
  663.                     Vector2 sum = poly.edgeNormals[i] + poly.edgeNormals[next];
  664.                     sum.Normalize();
  665.                     poly.vNormals.Add(sum);
  666.                 }
  667.                 foreach (DPolygon hole in poly.holes) {
  668.                     for (int i = 0; i < hole.points.Count; i++) {
  669.                         int prev, next = 0;
  670.                         prev = i - 1;
  671.                         next = i + 1;
  672.                         if (prev < 0) {
  673.                             prev = hole.points.Count - 1;
  674.                         }
  675.                         if (next >= hole.points.Count) {
  676.                             next = 0;
  677.                         }
  678.                         Vector2 sum = hole.edgeNormals[i] + hole.edgeNormals[next];
  679.                         sum.Normalize();
  680.                         hole.vNormals.Add(sum);
  681.                     }
  682.                 }
  683.             }
  684.             #endregion
  685.  
  686.             //Mesh calculation
  687.             List<Vector3> verts = new List<Vector3>();
  688.             List<int> tris = new List<int>();
  689.             //List<Vector2> uvs = new List<Vector2>();
  690.             List<Vector3> normals = new List<Vector3>();
  691.             Mesh mesh = new Mesh();
  692.  
  693.             for (int i = 0; i < dPolygons.Count; i++) {
  694.                 for (int j = 0; j < tMesh[i].Triangles.Count(); j++) {
  695.  
  696.  
  697.                     Vertex p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P0];
  698.                     Vector3 p3 = new Vector3();
  699.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  700.  
  701.                     //switch (orientation) {
  702.                     //    case MapOrientation.XZ:
  703.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  704.                     //        break;
  705.                     //    case MapOrientation.XY:
  706.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  707.                     //        break;
  708.                     //    case MapOrientation.YZ:
  709.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  710.                     //        break;
  711.                     //}
  712.  
  713.  
  714.                     if (verts.Contains(p3)) {
  715.                         int index = verts.IndexOf(p3);
  716.                         tris.Add(index);
  717.                     } else {
  718.                         verts.Add(p3);
  719.                         tris.Add(verts.Count - 1);
  720.                         Vector2 norm = Vector2.zero;
  721.                         if (dPolygons[i].points.Contains(p)) {
  722.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  723.                         } else {
  724.                             foreach (DPolygon hole in dPolygons[i].holes) {
  725.                                 if (hole.points.Contains(p)) {
  726.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  727.                                     break;
  728.                                 }
  729.                             }
  730.                         }
  731.  
  732.                         if (norm == Vector2.zero) {
  733.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  734.                         }
  735.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  736.  
  737.                         //switch (orientation) {
  738.                         //    case MapOrientation.XZ:
  739.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  740.                         //        break;
  741.                         //    case MapOrientation.XY:
  742.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  743.                         //        break;
  744.                         //    case MapOrientation.YZ:
  745.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  746.                         //        break;
  747.                         //}
  748.                     }
  749.  
  750.                     //point 2
  751.  
  752.                     p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P1];
  753.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  754.  
  755.                     //switch (orientation) {
  756.                     //    case MapOrientation.XZ:
  757.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  758.                     //        break;
  759.                     //    case MapOrientation.XY:
  760.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  761.                     //        break;
  762.                     //    case MapOrientation.YZ:
  763.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  764.                     //        break;
  765.                     //}
  766.                     if (verts.Contains(p3)) {
  767.                         int index = verts.IndexOf(p3);
  768.                         tris.Add(index);
  769.                     } else {
  770.                         verts.Add(p3);
  771.                         tris.Add(verts.Count - 1);
  772.                         Vector2 norm = Vector2.zero;
  773.                         if (dPolygons[i].points.Contains(p)) {
  774.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  775.                         } else {
  776.                             foreach (DPolygon hole in dPolygons[i].holes) {
  777.                                 if (hole.points.Contains(p)) {
  778.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  779.                                     break;
  780.                                 }
  781.                             }
  782.                         }
  783.  
  784.                         if (norm == Vector2.zero) {
  785.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  786.                         }
  787.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  788.  
  789.                         //switch (orientation) {
  790.                         //    case MapOrientation.XZ:
  791.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  792.                         //        break;
  793.                         //    case MapOrientation.XY:
  794.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  795.                         //        break;
  796.                         //    case MapOrientation.YZ:
  797.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  798.                         //        break;
  799.                         //}
  800.                     }
  801.  
  802.                     //point 3
  803.                     p = tMesh[i].vertices[tMesh[i].Triangles.ElementAt(j).P2];
  804.                     p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  805.  
  806.                     //switch (orientation) {
  807.                     //    case MapOrientation.XZ:
  808.                     //        p3 = new Vector3((float)p.x / triangulationScale, 0f, (float)p.y / triangulationScale);
  809.                     //        break;
  810.                     //    case MapOrientation.XY:
  811.                     //        p3 = new Vector3((float)p.x / triangulationScale, (float)p.y / triangulationScale, 0f);
  812.                     //        break;
  813.                     //    case MapOrientation.YZ:
  814.                     //        p3 = new Vector3(0f, (float)p.x / triangulationScale, (float)p.y / triangulationScale);
  815.                     //        break;
  816.                     //}
  817.                     if (verts.Contains(p3)) {
  818.  
  819.                         int index = verts.IndexOf(p3);
  820.                         tris.Add(index);
  821.  
  822.                     } else {
  823.                         verts.Add(p3);
  824.                         tris.Add(verts.Count - 1);
  825.                         Vector2 norm = Vector2.zero;
  826.                         if (dPolygons[i].points.Contains(p)) {
  827.                             norm = dPolygons[i].vNormals[dPolygons[i].points.IndexOf(p)];
  828.                         } else {
  829.                             foreach (DPolygon hole in dPolygons[i].holes) {
  830.                                 if (hole.points.Contains(p)) {
  831.                                     norm = hole.vNormals[hole.points.IndexOf(p)];
  832.                                     break;
  833.                                 }
  834.                             }
  835.                         }
  836.  
  837.                         if (norm == Vector2.zero) {
  838.                             Debug.LogWarning("Normal was null... there was a problem finding it...");
  839.                         }
  840.                         normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  841.  
  842.                         //switch (orientation) {
  843.                         //    case MapOrientation.XZ:
  844.                         //        normals.Add(new Vector3(norm.x, yNormalOffset, norm.y));
  845.                         //        break;
  846.                         //    case MapOrientation.XY:
  847.                         //        normals.Add(new Vector3(norm.x, norm.y, -yNormalOffset));
  848.                         //        break;
  849.                         //    case MapOrientation.YZ:
  850.                         //        normals.Add(new Vector3(-yNormalOffset, norm.x, norm.y));
  851.                         //        break;
  852.                         //}
  853.                     }
  854.  
  855.                 }
  856.             }
  857.  
  858.             mesh.vertices = verts.ToArray();
  859.             mesh.normals = normals.ToArray();
  860.             mesh.triangles = tris.ToArray();
  861.  
  862.             MeshFilter mf = meshObject.GetComponent<MeshFilter>();
  863.             if (mf == null) {
  864.                 mf = meshObject.AddComponent<MeshFilter>();
  865.             }
  866.  
  867.             MeshRenderer meshrenderer = meshObject.GetComponent<MeshRenderer>();
  868.             if (meshrenderer == null) {
  869.                 meshrenderer = meshObject.AddComponent<MeshRenderer>();
  870.                 meshrenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  871.                 meshrenderer.receiveShadows = false;
  872.             }
  873.  
  874.            
  875.             meshrenderer.material = defaultMaterial;
  876.             mf.mesh = mesh;
  877.             DMMapDebug("Map Generation Complete: Layer[" + layer + "]");
  878.  
  879.             #endregion
  880.         }
  881.  
  882.         #region MapMeshGen Helper functions
  883.         private Vector2 CalculateOutwardNormal(Vertex _a, Vertex _b, Vertex _c) {
  884.             Vector2 a = new Vector2((float)_a.X, (float)_a.Y);
  885.             Vector2 b = new Vector2((float)_b.X, (float)_b.Y);
  886.             Vector2 c = new Vector2((float)_c.X, (float)_c.Y);
  887.  
  888.             Vector2 AB = b - a;
  889.             Vector2 AC = c - a;
  890.             Vector2 nAB = new Vector2(-AB.y, AB.x);
  891.             float dot = Vector2.Dot(nAB, AC);
  892.  
  893.             if (dot > 0) {
  894.                 return nAB;
  895.             } else {
  896.                 return nAB;
  897.             }
  898.         }
  899.         private void AddPolygonWithHoles2(PolyNode node, ref Polygon p) {
  900.             List<Vertex> contour = new List<Vertex>();
  901.             for (int i = 0; i < node.Contour.Count; i++) {
  902.                 contour.Add(new Vertex((double)node.Contour[i].X, (double)node.Contour[i].Y));
  903.             }
  904.  
  905.             p.AddContour(contour, 0, node.IsHole);
  906.             for (int i = 0; i < node.ChildCount; i++) {
  907.                 AddPolygonWithHoles2(node.Childs[i], ref p);
  908.             }
  909.         }
  910.         private void PolyTreeToDPolygonList(PolyNode node, ref List<DPolygon> dPolygons) {
  911.  
  912.             DPolygon poly = new DPolygon();
  913.             poly.points = new List<Vertex>();
  914.  
  915.             poly.isHole = false;
  916.             if (!node.IsHole) {
  917.                 dPolygons.Add(poly);
  918.             }
  919.  
  920.             for (int i = 0; i < node.Contour.Count; i++) {
  921.                 poly.points.Add(new Vertex((double)node.Contour[i].X, (double)node.Contour[i].Y));
  922.             }
  923.             for (int i = 0; i < node.ChildCount; i++) {
  924.                 if (node.Childs[i].IsHole) {
  925.                     DPolygon hole = new DPolygon();
  926.                     for (int j = 0; j < node.Childs[i].Contour.Count; j++) {
  927.                         hole.points.Add(new Vertex((double)node.Childs[i].Contour[j].X, (double)node.Childs[i].Contour[j].Y));
  928.                     }
  929.                     poly.holes.Add(hole);
  930.                 }
  931.                 PolyTreeToDPolygonList(node.Childs[i], ref dPolygons);
  932.             }
  933.         }
  934.  
  935.         private List<IntPoint> ShapeToCPolygon(DMMapShape shape) {
  936.             List<IntPoint> points = new List<IntPoint>();
  937.             for (int i = 0; i < shape.verts.Count; i++) {
  938.                 switch (orientation) {
  939.                     case MapOrientation.XZ:
  940.                         points.Add(new IntPoint(shape.verts[i].transform.position.x * triangulationScale, shape.verts[i].transform.position.z * triangulationScale));
  941.                         break;
  942.                     case MapOrientation.XY:
  943.                         points.Add(new IntPoint(shape.verts[i].transform.position.x * triangulationScale, shape.verts[i].transform.position.y * triangulationScale));
  944.                         break;
  945.                     case MapOrientation.YZ:
  946.                         points.Add(new IntPoint(shape.verts[i].transform.position.y * triangulationScale, shape.verts[i].transform.position.z * triangulationScale));
  947.                         break;
  948.  
  949.                 }
  950.  
  951.             }
  952.             return points;
  953.         }
  954.         #endregion
  955.  
  956.         private void DrawPolytree(List<DPolygon> plist, bool drawNormals = false) {
  957.             foreach (DPolygon p in plist) {
  958.                 for (int i = 0; i < p.points.Count - 1; i++) {
  959.                     Vector3 p0 = new Vector3();
  960.                     Vector3 p1 = new Vector3();
  961.  
  962.                     switch (orientation) {
  963.                         case MapOrientation.XZ:
  964.                             p0 = new Vector3((float)p.points[i].X, 10f, (float)p.points[i].Y);
  965.                             p1 = new Vector3((float)p.points[i + 1].X, 10f, (float)p.points[i + 1].Y);
  966.                             break;
  967.                         case MapOrientation.XY:
  968.                             p0 = new Vector3((float)p.points[i].X, (float)p.points[i].Y, 10f);
  969.                             p1 = new Vector3((float)p.points[i + 1].X, (float)p.points[i + 1].Y, 10f);
  970.                             break;
  971.  
  972.                         case MapOrientation.YZ:
  973.                             p0 = new Vector3(10f, (float)p.points[i].X, (float)p.points[i].Y);
  974.                             p1 = new Vector3(10f, (float)p.points[i + 1].X, (float)p.points[i + 1].Y);
  975.                             break;
  976.                     }
  977.  
  978.                     Debug.DrawLine(p0, p1, Color.cyan, float.MaxValue);
  979.  
  980.                     //draw edge normals
  981.                     if (drawNormals) {
  982.                         Vector3 dir = new Vector3(p.vNormals[i].x, 0f, p.vNormals[i].y);
  983.                         Debug.DrawRay(p0, dir * 100f, Color.white, float.MaxValue);
  984.                     }
  985.                 }
  986.                 Vector3 p2 = new Vector3();
  987.                 Vector3 p3 = new Vector3();
  988.                 switch (orientation) {
  989.                     case MapOrientation.XZ:
  990.                         p2 = new Vector3((float)p.points[0].X, 10f, (float)p.points[0].Y);
  991.                         p3 = new Vector3((float)p.points[p.points.Count - 1].X, 10f, (float)p.points[p.points.Count - 1].Y);
  992.                         break;
  993.                     case MapOrientation.XY:
  994.                         p2 = new Vector3((float)p.points[0].X, (float)p.points[0].Y, 10f);
  995.                         p3 = new Vector3((float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y, 10f);
  996.                         break;
  997.  
  998.                     case MapOrientation.YZ:
  999.                         p2 = new Vector3(10f, (float)p.points[0].X, (float)p.points[0].Y);
  1000.                         p3 = new Vector3(10f, (float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y);
  1001.                         break;
  1002.                 }
  1003.  
  1004.                 Debug.DrawLine(p2, p3, Color.cyan, float.MaxValue);
  1005.  
  1006.  
  1007.                 if (p.holes != null) {
  1008.                     foreach (DPolygon h in p.holes) {
  1009.                         for (int i = 0; i < h.points.Count - 1; i++) {
  1010.                             Vector3 p0 = new Vector3();
  1011.                             Vector3 p1 = new Vector3();
  1012.                             switch (orientation) {
  1013.                                 case MapOrientation.XZ:
  1014.                                     p0 = new Vector3((float)p.points[i].X, 10f, (float)p.points[i].Y);
  1015.                                     p1 = new Vector3((float)p.points[i + 1].X, 10f, (float)p.points[i + 1].Y);
  1016.                                     break;
  1017.                                 case MapOrientation.XY:
  1018.                                     p0 = new Vector3((float)p.points[i].X, (float)p.points[i].Y, 10f);
  1019.                                     p1 = new Vector3((float)p.points[i + 1].X, (float)p.points[i + 1].Y, 10f);
  1020.                                     break;
  1021.  
  1022.                                 case MapOrientation.YZ:
  1023.                                     p0 = new Vector3(10f, (float)p.points[i].X, (float)p.points[i].Y);
  1024.                                     p1 = new Vector3(10f, (float)p.points[i + 1].X, (float)p.points[i + 1].Y);
  1025.                                     break;
  1026.                             }
  1027.                             Debug.DrawLine(p0, p1, Color.red, float.MaxValue);
  1028.  
  1029.                             if (drawNormals) {
  1030.                                 Vector3 dir = new Vector3(h.vNormals[i].x, 0f, h.vNormals[i].y);
  1031.                                 Debug.DrawRay(p0, dir * 100f, Color.white, float.MaxValue);
  1032.                             }
  1033.  
  1034.                         }
  1035.                         Vector3 p4 = new Vector3();
  1036.                         Vector3 p5 = new Vector3();
  1037.                         switch (orientation) {
  1038.                             case MapOrientation.XZ:
  1039.                                 p4 = new Vector3((float)p.points[0].X, 10f, (float)p.points[0].Y);
  1040.                                 p5 = new Vector3((float)p.points[p.points.Count - 1].X, 10f, (float)p.points[p.points.Count - 1].Y);
  1041.                                 break;
  1042.                             case MapOrientation.XY:
  1043.                                 p4 = new Vector3((float)p.points[0].X, (float)p.points[0].Y, 10f);
  1044.                                 p5 = new Vector3((float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y, 10f);
  1045.                                 break;
  1046.  
  1047.                             case MapOrientation.YZ:
  1048.                                 p4 = new Vector3(10f, (float)p.points[0].X, (float)p.points[0].Y);
  1049.                                 p5 = new Vector3(10f, (float)p.points[p.points.Count - 1].X, (float)p.points[p.points.Count - 1].Y);
  1050.                                 break;
  1051.                         }
  1052.                         Debug.DrawLine(p4, p5, Color.red, float.MaxValue);
  1053.  
  1054.                     }
  1055.                 }
  1056.             }
  1057.         }
  1058.         #endregion
  1059.     }
  1060.  
  1061.     public enum IconScaleMode {
  1062.         ScaleWithZoom,
  1063.         NoScale,
  1064.         DefinedPerIcon
  1065.     }
  1066.  
  1067.     public enum MapOrientation {
  1068.         XZ,
  1069.         XY,
  1070.         YZ,
  1071.     }
  1072. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement