void DrawUnityStandardTextLabels() { ResetDefaultCountryLabelOffset(); if (meshRects == null) { meshRects = new List <MeshRect>(_countries.Length); } else { meshRects.Clear(); } float mw = mapWidth; float mh = mapHeight; 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; } Vector2 center = new Vector2(country.center.x * mapWidth, country.center.y * mh) + country.labelOffset; center += GetDefaultCountryLabelOffset(countryIndex); Region region = country.regions[country.mainRegionIndex]; // Adjusts country name length string countryName = country.customLabel != null ? country.customLabel : country.name.ToUpper(); bool introducedCarriageReturn = false; if (countryName.Length > 15) { countryName = BreakOneLineString(countryName); introducedCarriageReturn = true; } // add caption GameObject textObj; TextMesh tm; Renderer tmRenderer; TextMesh tmShadow = null; if (country.labelTextMeshGO == null) { Color labelColor = country.labelColorOverride ? country.labelColor : _countryLabelsColor; Font customFont = country.labelFontOverride ?? labelsFont; if ((object)customFont == null) { continue; } Material customLabelShadowMaterial = country.labelFontShadowMaterial ?? labelsShadowMaterial; tm = Drawing.CreateText(countryName, null, center, customFont, labelColor, _showLabelsShadow, customLabelShadowMaterial, _countryLabelsShadowColor, out tmShadow); textObj = tm.gameObject; country.labelTextMesh = tm; country.labelTextMeshGO = tm.gameObject; tmRenderer = textObj.GetComponent <Renderer>(); Bounds bounds = tmRenderer.bounds; country.labelMeshWidth = bounds.size.x; country.labelMeshHeight = bounds.size.y; country.labelMeshCenter = center; textObj.transform.SetParent(textRoot.transform, false); textObj.transform.localPosition = center; textObj.layer = textRoot.gameObject.layer; if (_showLabelsShadow) { country.labelShadowTextMesh = tmShadow; //textObj.transform.Find ("shadow").GetComponent<TextMesh> (); country.labelShadowTextMesh.gameObject.layer = textObj.layer; } } else { tm = country.labelTextMesh; textObj = tm.gameObject; textObj.transform.localPosition = center; tmRenderer = textObj.GetComponent <Renderer>(); } float meshWidth = country.labelMeshWidth; float meshHeight = country.labelMeshHeight; // adjusts caption Rect rect = new Rect(region.rect2D.xMin * mw, region.rect2D.yMin * mh, region.rect2D.width * mw, region.rect2D.height * mh); float absoluteHeight; if (country.labelRotation > 0) { textObj.transform.localRotation = Quaternion.Euler(0, 0, country.labelRotation); absoluteHeight = Mathf.Min(rect.height * _countryLabelsSize, rect.width); } else if (rect.height > rect.width * 1.45f) { float angle; if (rect.height > rect.width * 1.5f) { angle = 90; } else { angle = Mathf.Atan2(rect.height, rect.width) * Mathf.Rad2Deg; } textObj.transform.localRotation = Quaternion.Euler(0, 0, angle); absoluteHeight = Mathf.Min(rect.width * _countryLabelsSize, rect.height); } else { absoluteHeight = Mathf.Min(rect.height * _countryLabelsSize, rect.width); } // adjusts scale to fit width in rect float adjustedMeshHeight = introducedCarriageReturn ? meshHeight * 0.5f : meshHeight; float scale = absoluteHeight / adjustedMeshHeight; if (country.labelFontSizeOverride) { scale = country.labelFontSize; } else { float desiredWidth = meshWidth * scale; if (desiredWidth > rect.width) { scale = rect.width / meshWidth; } if (adjustedMeshHeight * scale < _countryLabelsAbsoluteMinimumSize) { scale = _countryLabelsAbsoluteMinimumSize / adjustedMeshHeight; } } // stretchs out the caption float displayedMeshWidth = meshWidth * scale; float displayedMeshHeight = meshHeight * scale; string wideName; int times = Mathf.FloorToInt(rect.width * 0.45f / (meshWidth * scale)); if (times > 10) { times = 10; } if (times > 0) { StringBuilder sb = new StringBuilder(); string spaces = new string(' ', times * 2); for (int c = 0; c < countryName.Length; c++) { sb.Append(countryName[c]); if (c < countryName.Length - 1) { sb.Append(spaces); } } wideName = sb.ToString(); } else { wideName = countryName; } if (tm.text.Length != wideName.Length) { tm.text = wideName; displayedMeshWidth = tmRenderer.bounds.size.x * scale; displayedMeshHeight = tmRenderer.bounds.size.y * scale; if (_showLabelsShadow) { tmShadow.text = wideName; } } // apply scale textObj.transform.localScale = new Vector3(scale, scale, 1); // Save mesh rect for overlapping checking if (country.labelOffset == Misc.Vector2zero) { float xMin = center.x - displayedMeshWidth * 0.5f; float yMin = center.y - displayedMeshHeight * 0.5f; float xMax = xMin + displayedMeshWidth; float yMax = yMin + displayedMeshHeight; MeshRect mr = new MeshRect(countryIndex, new Vector4(xMin, yMin, xMax, yMax)); meshRects.Add(mr); } } // Simple-fast overlapping checking int cont = 0; bool needsResort = true; int meshRectsCount = meshRects.Count; while (needsResort && ++cont < 10) { meshRects.Sort(overlapComparer); needsResort = false; for (int c = 1; c < meshRectsCount; c++) { Vector4 r1 = meshRects[c].rect; for (int prevc = c - 1; prevc >= 0; prevc--) { Vector4 r2 = meshRects[prevc].rect; bool overlaps = !(r2.x > r1.z || r2.z <r1.x || r2.y> r1.w || r2.w < r1.y); if (overlaps) { needsResort = true; int thisCountryIndex = meshRects[c].entityIndex; Country country = _countries[thisCountryIndex]; GameObject thisLabel = country.labelTextMeshGO; // displaces this label float offsety = r1.w - r2.y; offsety = Mathf.Min(country.regions[country.mainRegionIndex].rect2D.height * mh * 0.35f, offsety); thisLabel.transform.localPosition = new Vector3(country.labelMeshCenter.x, country.labelMeshCenter.y - offsety, thisLabel.transform.localPosition.z); float width = r1.z - r1.x; float height = r1.w - r1.y; float xMin = thisLabel.transform.localPosition.x - width * 0.5f; float yMin = thisLabel.transform.localPosition.y - height * 0.5f; float xMax = xMin + width; float yMax = yMin + height; r1 = new Vector4(xMin, yMin, xMax, yMax); meshRects[c].rect = r1; } } } } }