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);
        }
Exemple #3
0
        /// <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);
        }