Exemplo n.º 1
0
        void DrawTextMeshProLabels()
        {
            if (labelsFontTMPro == null)
            {
                ReloadFont();
                if (labelsFontTMPro == null)
                {
                    return;
                }
            }

            float mw = mapWidth;
            float mh = mapHeight;

            if (labelsCurve == null || labelsCurve.Length == 0)
            {
                ComputeLabelsCurve();
            }

            Vector2 center = Misc.Vector2zero;

            for (int countryIndex = 0; countryIndex < _countries.Length; countryIndex++)
            {
                Country country = _countries[countryIndex];
                if (country.hidden || !country.labelVisible || country.mainRegionIndex < 0 || country.mainRegionIndex >= country.regions.Count)
                {
                    continue;
                }

                Region region = country.regions[country.mainRegionIndex];
                if (!ComputeCurvedLabelData(region))
                {
                    continue;
                }

                if (country.labelOffset.x != 0 || country.labelOffset.y != 0)
                {
                    center = country.center + country.labelOffset;
                }
                else
                {
                    FastVector.Average(ref region.curvedLabelInfo.axisStart, ref region.curvedLabelInfo.axisEnd, ref center); // (curvedLabel.axisStart + curvedLabel.axisEnd) * 0.5f;
                }
                center.x *= mw;
                center.y *= mh;

                // Adjusts country name length
                string countryName = country.customLabel != null ? country.customLabel : country.name.ToUpper();
                if (countryName.Length == 0)
                {
                    continue;
                }

                if (countryName.Length > 15)
                {
                    countryName = BreakOneLineString(countryName);
                }

                // add caption
                GameObject  textObj;
                TextMeshPro tm;
                Color       labelColor = country.labelColorOverride ? country.labelColor : _countryLabelsColor;
                if (country.labelTextMeshGO == null)
                {
                    // create base text
                    textObj            = new GameObject(countryName);
                    textObj.hideFlags  = HideFlags.DontSave;
                    textObj.hideFlags |= HideFlags.HideInHierarchy;
                    tm                       = textObj.AddComponent <TextMeshPro>();
                    tm.alignment             = TextAlignmentOptions.Center;
                    tm.enableWordWrapping    = false;
                    country.labelTextMeshPro = tm;
                    country.labelTextMeshGO  = tm.gameObject;
                    textObj.transform.SetParent(textRoot.transform, false);
                    textObj.layer = textRoot.gameObject.layer;
                }
                else
                {
                    tm      = (TextMeshPro)country.labelTextMeshPro;
                    textObj = tm.gameObject;
                    textObj.transform.localPosition = center;
                }
                tm.font  = (TMP_FontAsset)labelsFontTMPro;
                tm.color = labelColor;

                Material fontMat;
                if (_countryLabelsEnableAutomaticFade)
                {
                    // By using fontMaterial we're forcing to instantiate the material which will enable individual colors and alpha
                    fontMat           = tm.fontMaterial;
                    fontMat.hideFlags = HideFlags.DontSave;
                }
                else
                {
                    fontMat = tm.fontSharedMaterial;
                }

                if (_countryLabelsOutlineWidth > 0)
                {
                    fontMat.SetColor("_OutlineColor", _countryLabelsOutlineColor);
                    fontMat.SetFloat("_OutlineWidth", _countryLabelsOutlineWidth);
                    fontMat.EnableKeyword("OUTLINE_ON");
                }
                else
                {
                    fontMat.DisableKeyword("OUTLINE_ON");
                }

                tm.text = countryName;
                textObj.transform.localPosition = center;
                country.labelMeshWidth          = tm.preferredWidth;
                country.labelMeshHeight         = tm.preferredHeight;
                country.labelMeshCenter         = center;

                float meshWidth  = country.labelMeshWidth;
                float meshHeight = country.labelMeshHeight;

                // adjusts scale to fit in region
                Vector2 axis = region.curvedLabelInfo.axisEnd - region.curvedLabelInfo.axisStart;
                float   scale;
                if (country.labelFontSizeOverride)
                {
                    scale = country.labelFontSize;
                }
                else
                {
                    // axisWidth represents the length of the label along the longest axis
                    float axisWidth = new Vector2(axis.x * mw, axis.y * mh).magnitude;
                    // axisAveragedWidth represents the average length of the region (used as a maximum height for the label)
                    float axisAveragedThickness = new Vector2(region.curvedLabelInfo.axisAveragedThickness.x * mw, region.curvedLabelInfo.axisAveragedThickness.y * mh).magnitude;
                    float scaleheight           = axisAveragedThickness / meshHeight;
                    float scaleWidth            = axisWidth / meshWidth;
                    scale = Mathf.Min(scaleWidth, scaleheight);
                    if (meshHeight * scale < _countryLabelsAbsoluteMinimumSize)
                    {
                        scale = _countryLabelsAbsoluteMinimumSize / meshHeight;
                    }
                    scale *= _countryLabelsSize * 2f;
                }

                // apply scale
                textObj.transform.localScale = new Vector3(scale, scale, 1);

                // Apply axis rotation or user defined rotation
                if (country.labelRotation > 0)
                {
                    textObj.transform.localRotation = Quaternion.Euler(0, 0, country.labelRotation);
                }
                else
                {
                    textObj.transform.localRotation = Quaternion.Euler(0, 0, region.curvedLabelInfo.axisAngle);
                }

                if (_countryLabelsCurvature > 0)
                {
                    // Compute fitting curve
                    tm.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated.
                    tm.ForceMeshUpdate();            // Generate the mesh and populate the textInfo with data we can use and manipulate.

                    TMP_TextInfo textInfo       = tm.textInfo;
                    int          characterCount = textInfo.characterCount;

                    float boundsMinX = tm.bounds.min.x;
                    float boundsMaxX = tm.bounds.max.x;
                    // map bounds to axis length
                    float axisLengthWS = new Vector2(axis.x * mw / scale, axis.y * mh / scale).magnitude;
                    float boundsLength = boundsMaxX - boundsMinX;
                    float boundsMid    = (boundsMaxX + boundsMinX) * 0.5f;
                    boundsMinX = boundsMid - (boundsMid - boundsMinX) * axisLengthWS / boundsLength;
                    boundsMaxX = boundsMid + (boundsMaxX - boundsMid) * axisLengthWS / boundsLength;

                    float curveMultiplier = new Vector2(region.curvedLabelInfo.axisMidDisplacement.x * mw / scale, region.curvedLabelInfo.axisMidDisplacement.y * mh / scale).magnitude *_countryLabelsCurvature;
                    // check if axisAveragedThickness is above or below axis
                    Vector2 a   = axis * 0.5f + region.curvedLabelInfo.axisMidDisplacement;
                    float   dot = a.x * -axis.y + a.y * axis.x;
                    if (dot < 0)
                    {
                        curveMultiplier *= -1f;
                    }
                    float boundsWidth = boundsMaxX - boundsMinX;

                    // Get the index of the mesh used by this character.
                    int       materialIndex = textInfo.characterInfo[0].materialReferenceIndex;
                    Vector3[] vertices      = textInfo.meshInfo[materialIndex].vertices;

                    for (int i = 0; i < characterCount; i++)
                    {
                        if (!textInfo.characterInfo[i].isVisible)
                        {
                            continue;
                        }

                        int vertexIndex = textInfo.characterInfo[i].vertexIndex;

                        // Compute the baseline mid point for each character
                        Vector2 offsetToMidBaseline = new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine);
                        if (float.IsNaN(offsetToMidBaseline.x) || float.IsNaN(offsetToMidBaseline.y))
                        {
                            continue;
                            //offsetToMidBaseline.x = offsetToMidBaseline.y = 0;
                        }

                        // Apply offset to adjust our pivot point.
                        vertices[vertexIndex + 0].x -= offsetToMidBaseline.x;
                        vertices[vertexIndex + 0].y -= offsetToMidBaseline.y;
                        vertices[vertexIndex + 1].x -= offsetToMidBaseline.x;
                        vertices[vertexIndex + 1].y -= offsetToMidBaseline.y;
                        vertices[vertexIndex + 2].x -= offsetToMidBaseline.x;
                        vertices[vertexIndex + 2].y -= offsetToMidBaseline.y;
                        vertices[vertexIndex + 3].x -= offsetToMidBaseline.x;
                        vertices[vertexIndex + 3].y -= offsetToMidBaseline.y;

                        // Compute the angle of rotation for each character based on the animation curve
                        float       x0   = (offsetToMidBaseline.x - boundsMinX) / boundsWidth; // Character's position relative to the bounds of the mesh.
                        float       x1   = x0 + 0.01f;
                        const float minT = 0.0f;
                        const float maxT = 0.9999f;
                        if (x0 < minT)
                        {
                            x0 = minT;
                        }
                        else if (x0 > maxT)
                        {
                            x0 = maxT;
                        }
                        int   ix0 = (int)(x0 * labelsCurve.Length);
                        float y0  = labelsCurve[ix0] * curveMultiplier;
                        if (x1 < minT)
                        {
                            x1 = minT;
                        }
                        else if (x1 > maxT)
                        {
                            x1 = maxT;
                        }
                        int   ix1 = (int)(x1 * labelsCurve.Length);
                        float y1  = labelsCurve[ix1] * curveMultiplier;

                        Vector2 tangent = new Vector2(x1 * boundsWidth + boundsMinX - offsetToMidBaseline.x, y1 - y0);
                        dot = Mathf.Acos(tangent.normalized.x) * Mathf.Rad2Deg;
                        float angle = tangent.y > 0 ? dot : 360 - dot;

                        Matrix4x4 matrix = Matrix4x4.TRS(new Vector3(offsetToMidBaseline.x, y0 + offsetToMidBaseline.y, 0), Quaternion.Euler(0, 0, angle), Misc.Vector3one);

                        vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]);
                        vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]);
                        vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]);
                        vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]);
                    }

                    // Upload the mesh with the revised information
                    tm.UpdateVertexData();
                }
                country.labelMeshWidth  = tm.bounds.size.x;
                country.labelMeshHeight = tm.bounds.size.y;

                //																GameObject sphere3 = GameObject.CreatePrimitive (PrimitiveType.Sphere);
                //																sphere3.name = "Axis Middle";
                //																sphere3.transform.SetParent (o.transform, true);
                //																sphere3.transform.localPosition = (curvedLabel.axisStart + curvedLabel.axisEnd) * 0.5f;
                //																sphere3.transform.localScale *= 0.3f;
                //
                //																GameObject sphere4 = GameObject.CreatePrimitive (PrimitiveType.Sphere);
                //																sphere4.name = "avgAxisPoint";
                //																sphere4.transform.SetParent (o.transform, true);
                //																sphere4.transform.localPosition = (curvedLabel.axisStart + curvedLabel.axisEnd) * 0.5f + curvedLabel.axisMidDisplacement;
                //																sphere4.GetComponent<Renderer> ().material.color = Color.red;
                //																sphere4.transform.localScale *= 0.2f;
            }

            StartCoroutine(RepositionTexts());
        }
Exemplo n.º 2
0
        void Start()
        {
            WMSK map = WMSK.instance;

            // ***********************************************************************
            // Adding custom attributes to a country (same for provinces, cities, ...)
            // ***********************************************************************

            Country canada = map.GetCountry("Canada");

            canada.attrib ["Language"]         = "French";                                              // Add language as a custom attribute
            canada.attrib ["ConstitutionDate"] = new DateTime(1867, 7, 1);                              // Add the date of British North America Act, 1867
            canada.attrib ["AreaKm2"]          = 9984670;                                               // Add the land area in km2

            // List example
            List <int> values = new List <int> (10);

            for (int j = 0; j < 10; j++)
            {
                values.Add(j);
            }
            canada.attrib ["List"] = JSONObject.FromArray(values);

            // ******************************************************
            // Obtain attributes and print them out over the console.
            // ******************************************************

            Debug.Log("Language = " + canada.attrib ["Language"]);
            Debug.Log("Constitution Date = " + canada.attrib ["ConstitutionDate"].d);                   // Note the use of .d to force cast the internal number representation to DateTime
            Debug.Log("Area in km2 = " + canada.attrib ["AreaKm2"]);
            Debug.Log("List = " + canada.attrib ["List"]);

            // *********************************************************
            // Now, look up by attribute example using lambda expression
            // *********************************************************

            List <Country> countries = map.GetCountries(
                (attrib) => "French".Equals(attrib ["Language"]) && attrib ["AreaKm2"] > 1000000
                );

            Debug.Log("Matches found = " + countries.Count);
            foreach (Country c in countries)
            {
                Debug.Log("Match: " + c.name);
            }

            // *****************************************************************
            // Export/import individual country attributes in JSON format sample
            // *****************************************************************

            string json = canada.attrib.Print();                // Get raw jSON

            Debug.Log(json);

            canada.attrib = new JSONObject(json);               // Import from raw jSON
            int keyCount = canada.attrib.keys.Count;

            Debug.Log("Imported JSON has " + keyCount + " keys.");
            for (int k = 0; k < keyCount; k++)
            {
                Debug.Log("Key " + (k + 1) + ": " + canada.attrib.keys [k] + " = " + canada.attrib [k]);
            }

            // *****************************************************************
            // Finally, export all countries attributes in one single JSON file
            // *****************************************************************

            string jsonCountries = map.GetCountriesAttributes(true);                    // get the complete json for all countries with attributes

            Debug.Log(jsonCountries);

            canada.attrib = null;
            map.SetCountriesAttributes(jsonCountries);                                                  // parse the jsonCountries string (expects a jSON compliant string) and loads the attributes
            Debug.Log("Canada's attributes restored: Lang = " + canada.attrib ["Language"] + ", Date = " + canada.attrib ["ConstitutionDate"].d + ", Area = " + canada.attrib ["AreaKm2"]);
        }