void CountrySubstractCountryEnclaves(int countryIndex, Region region, Poly2Tri.Polygon poly) { List <Region> negativeRegions = new List <Region> (); int countryCount = _countriesOrderedBySize.Count; for (int ops = 0; ops < countryCount; ops++) { int op = _countriesOrderedBySize [ops]; if (op == countryIndex) { continue; } Country opCountry = _countries [op]; Region opCountryRegion = opCountry.regions [opCountry.mainRegionIndex]; if (opCountryRegion.points.Length >= 5 && opCountry.mainRegion.rect2DArea < region.rect2DArea && opCountryRegion.rect2D.Overlaps(region.rect2D, true)) { if (region.Contains(opCountryRegion)) // just check main region of province for speed purposes { negativeRegions.Add(opCountryRegion.Clone()); } } } // Collapse negative regions in big holes for (int nr = 0; nr < negativeRegions.Count - 1; nr++) { for (int nr2 = nr + 1; nr2 < negativeRegions.Count; nr2++) { if (negativeRegions [nr].Intersects(negativeRegions [nr2])) { Clipper clipper = new Clipper(); int control = negativeRegions [nr].points.Length; clipper.AddPath(negativeRegions [nr], PolyType.ptSubject); clipper.AddPath(negativeRegions [nr2], PolyType.ptClip); clipper.Execute(ClipType.ctUnion); negativeRegions.RemoveAt(nr2); nr = -1; break; } } } // Substract holes for (int r = 0; r < negativeRegions.Count; r++) { Poly2Tri.Polygon polyHole = new Poly2Tri.Polygon(negativeRegions [r].points); poly.AddHole(polyHole); } }
GameObject GenerateCountryRegionSurface(int countryIndex, int regionIndex, Material material, Vector2 textureScale, Vector2 textureOffset, float textureRotation) { if (countryIndex < 0 || countryIndex >= _countries.Length) { return(null); } Country country = _countries [countryIndex]; Region region = country.regions [regionIndex]; if (region.points.Length < 3) { return(null); } Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.points); // Extracts enclaves from main region if (_enableEnclaves && regionIndex == country.mainRegionIndex) { // Remove negative provinces if (_showProvinces) { CountrySubstractProvinceEnclaves(countryIndex, region, poly); } else { CountrySubstractCountryEnclaves(countryIndex, region, poly); } } P2T.Triangulate(poly); // Prepare surface cache entry and deletes older surface if exists int cacheIndex = GetCacheIndexForCountryRegion(countryIndex, regionIndex); string id = cacheIndex.ToString(); // Creates surface mesh GameObject surf = Drawing.CreateSurface(id, poly, material, region.rect2D, textureScale, textureOffset, textureRotation, disposalManager); ParentObjectToRegion(id, COUNTRY_SURFACES_ROOT_NAME, surf); surfaces [cacheIndex] = surf; return(surf); }
/// <summary> /// Creates an extruded version of a given region /// </summary> /// <returns>The generate extrude game object.</returns> /// <param name="name">Name.</param> /// <param name="extrusionAmount">Size of the extrusion.</param> /// <param name="region">Region.</param> /// <param name="material">Material.</param> /// <param name="textureScale">Texture scale.</param> /// <param name="textureOffset">Texture offset.</param> /// <param name="textureRotation">Texture rotation.</param> public GameObject RegionGenerateExtrudeGameObject(string name, Region region, float extrusionAmount, Material topMaterial, Material sideMaterial, Vector2 textureScale, Vector2 textureOffset, float textureRotation, bool useRegionRect = true) { if (region == null || region.points.Length < 3) { return(null); } Rect rect = useRegionRect ? region.rect2D : new Rect(0.5f, 0.5f, 1f, 1f); GameObject go = new GameObject(name); go.transform.SetParent(transform, false); Poly2Tri.Polygon poly = new Poly2Tri.Polygon(region.points); P2T.Triangulate(poly); // Creates surface mesh GameObject surf = Drawing.CreateSurface("RegionTop", poly, topMaterial, rect, textureScale, textureOffset, textureRotation, null); surf.transform.SetParent(go.transform, false); surf.transform.localPosition = new Vector3(0, 0, -extrusionAmount); // Create side band int pointCount = region.points.Length; Vector3[] vertices = new Vector3[pointCount * 2]; int[] indices = new int[pointCount * 6]; int vi = 0, ii = -1; for (int k = 0; k < pointCount; k++, vi += 2) { vertices[vi] = region.points[k]; vertices[vi].z = -extrusionAmount; vertices[vi + 1] = vertices[vi]; vertices[vi + 1].z = 0; if (k == pointCount - 1) { indices[++ii] = vi + 1; indices[++ii] = vi; indices[++ii] = 1; indices[++ii] = vi + 1; indices[++ii] = 1; indices[++ii] = 0; } else { indices[++ii] = vi; indices[++ii] = vi + 1; indices[++ii] = vi + 2; indices[++ii] = vi + 1; indices[++ii] = vi + 3; indices[++ii] = vi + 2; } } GameObject band = new GameObject("RegionBand"); band.transform.SetParent(go.transform, false); Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = indices; mesh.RecalculateNormals(); MeshFilter mf = band.AddComponent <MeshFilter>(); mf.mesh = mesh; MeshRenderer mr = band.AddComponent <MeshRenderer>(); mr.sharedMaterial = sideMaterial; if (region.entity.allowHighlight && (region.entity is Country && _enableCountryHighlight || region.entity is Province && _enableProvinceHighlight)) { ExtrudedRegionInteraction interaction = go.AddComponent <ExtrudedRegionInteraction>(); interaction.map = this; interaction.region = region; interaction.topMaterial = topMaterial; interaction.sideMaterial = sideMaterial; interaction.highlightColor = region.entity is Country ? _fillColor : _provincesFillColor; } return(go); }
void ProvinceSubstractProvinceEnclaves(int provinceIndex, Region region, Poly2Tri.Polygon poly) { List <Region> negativeRegions = new List <Region> (); for (int oc = 0; oc < _countries.Length; oc++) { Country ocCountry = _countries [oc]; if (ocCountry.hidden || ocCountry.provinces == null) { continue; } Region mainCountryRegion = ocCountry.regions [ocCountry.mainRegionIndex]; if (!mainCountryRegion.rect2D.Overlaps(region.rect2D)) { continue; } for (int op = 0; op < ocCountry.provinces.Length; op++) { Province opProvince = ocCountry.provinces [op]; if (opProvince == provinces [provinceIndex]) { continue; } if (opProvince.regions == null) { ReadProvincePackedString(opProvince); } if (opProvince.regions == null) { continue; } if (opProvince.regionsRect2D.Overlaps(region.rect2D, true)) { Region oProvRegion = opProvince.regions [opProvince.mainRegionIndex]; if (region.Contains(oProvRegion)) // just check main region of province for speed purposes { negativeRegions.Add(oProvRegion.Clone()); } } } } // Collapse negative regions in big holes for (int nr = 0; nr < negativeRegions.Count - 1; nr++) { for (int nr2 = nr + 1; nr2 < negativeRegions.Count; nr2++) { if (negativeRegions [nr].Intersects(negativeRegions [nr2])) { Clipper clipper = new Clipper(); int control = negativeRegions [nr].points.Length; clipper.AddPath(negativeRegions [nr], PolyType.ptSubject); clipper.AddPath(negativeRegions [nr2], PolyType.ptClip); clipper.Execute(ClipType.ctUnion); negativeRegions.RemoveAt(nr2); nr = -1; break; } } } // Substract holes int negativeRegionsCount = negativeRegions.Count; for (int r = 0; r < negativeRegionsCount; r++) { int pointCount = negativeRegions [r].points.Length; Vector2[] pp = new Vector2[pointCount]; for (int p = 0; p < pointCount; p++) { Vector2 point = negativeRegions [r].points [p]; Vector2 midPoint = negativeRegions [r].center; pp [p] = point + (midPoint - point) * 0.0001f; // prevents Poly2Tri issues when enclave boarders are to near from region borders } Poly2Tri.Polygon polyHole = new Poly2Tri.Polygon(pp); poly.AddHole(polyHole); } }
/// <summary> /// Highlights the province region specified. Returns the generated highlight surface gameObject. /// Internally used by the Map UI and the Editor component, but you can use it as well to temporarily mark a country region. /// </summary> /// <param name="refreshGeometry">Pass true only if you're sure you want to force refresh the geometry of the highlight (for instance, if the frontiers data has changed). If you're unsure, pass false.</param> public GameObject HighlightProvinceRegion(int provinceIndex, int regionIndex, bool refreshGeometry) { if (!refreshGeometry && _provinceHighlightedIndex == provinceIndex && _provinceRegionHighlightedIndex == regionIndex) { return(provinceRegionHighlightedObj); } if (provinceRegionHighlightedObj != null) { HideProvinceRegionHighlight(); } if (provinceIndex < 0 || provinceIndex >= provinces.Length || provinces [provinceIndex].regions == null || regionIndex < 0 || regionIndex >= provinces [provinceIndex].regions.Count) { return(null); } if (OnProvinceHighlight != null) { bool allowHighlight = true; OnProvinceHighlight(provinceIndex, regionIndex, ref allowHighlight); if (!allowHighlight) { return(null); } } int cacheIndex = GetCacheIndexForProvinceRegion(provinceIndex, regionIndex); GameObject obj; bool existsInCache = surfaces.TryGetValue(cacheIndex, out obj); if (refreshGeometry && existsInCache) { surfaces.Remove(cacheIndex); DestroyImmediate(obj); existsInCache = false; } bool doHighlight = true; if (_highlightMaxScreenAreaSize < 1f) { // Check screen area size Region region = provinces [provinceIndex].regions [regionIndex]; doHighlight = CheckScreenAreaSizeOfRegion(region); } if (doHighlight) { if (_enableProvinceHighlight && _provinces [provinceIndex].allowHighlight && _countries [_provinces [provinceIndex].countryIndex].allowProvincesHighlight) { if (existsInCache) { provinceRegionHighlightedObj = surfaces [cacheIndex]; if (provinceRegionHighlightedObj == null) { surfaces.Remove(cacheIndex); } else { if (!provinceRegionHighlightedObj.activeSelf) { provinceRegionHighlightedObj.SetActive(true); } Renderer[] rr = provinceRegionHighlightedObj.GetComponentsInChildren <Renderer> (true); for (int k = 0; k < rr.Length; k++) { if (rr [k].sharedMaterial != hudMatProvince && rr [k].sharedMaterial != outlineMatSimple) { rr [k].enabled = true; rr [k].sharedMaterial = hudMatProvince; } } } } else { provinceRegionHighlightedObj = GenerateProvinceRegionSurface(provinceIndex, regionIndex, hudMatProvince); // Add rest of regions? if (_highlightAllProvinceRegions) { Province province = provinces [provinceIndex]; for (int r = 0; r < province.regions.Count; r++) { if (r != regionIndex) { Region otherRegion = province.regions [r]; // Triangulate to get the polygon vertex indices Poly2Tri.Polygon poly = new Poly2Tri.Polygon(otherRegion.points); P2T.Triangulate(poly); GameObject otherSurf = Drawing.CreateSurface(provinceRegionHighlightedObj.name, poly, hudMatProvince, otherRegion.rect2D, Misc.Vector2zero, Misc.Vector2zero, 0, disposalManager); otherSurf.transform.SetParent(provinceRegionHighlightedObj.transform, false); otherSurf.transform.localPosition = Misc.Vector3zero; otherSurf.transform.localRotation = Quaternion.Euler(Misc.Vector3zero); otherSurf.layer = gameObject.layer; } } } } } else { provinceRegionHighlightedObj = null; } } _provinceHighlighted = provinces [provinceIndex]; _provinceHighlightedIndex = provinceIndex; _provinceRegionHighlighted = _provinceHighlighted.regions [regionIndex]; _provinceRegionHighlightedIndex = regionIndex; return(provinceRegionHighlightedObj); }