You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
mapbox-sdk/Unity/Editor/AtlasTemplateGenerator.cs

339 lines
8.8 KiB

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using Mapbox.Unity.MeshGeneration.Data;
using System.IO;
namespace Mapbox.Editor
{
class AtlasTemplateGenerator : EditorWindow
{
[MenuItem("Mapbox/Atlas Template Generator")]
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(AtlasTemplateGenerator));
}
public class PixelRect
{
public int x;
public int y;
public int xx;
public int yy;
}
public string m_saveFileName = "AtlasTemplate";
public Texture2D m_texture;
public AtlasInfo m_atlasInfo;
public Color[] m_colors;
public int m_textureResolution = 2048;
public bool m_generateFacadesTemplate = true;
public bool m_generateRoofsTemplate = false;
private int _drawCount;
private const int _DEFAULT_TEX_SIZE = 2048;
private const int _MIN_TEX_SIZE = 512;
private const int _MAX_TEX_SIZE = 2048;
private const float _cellRatioMargin = 0.01f;
private void Awake()
{
CreateTexture();
}
private void CreateTexture()
{
m_texture = new Texture2D(m_textureResolution, m_textureResolution, TextureFormat.ARGB32, false);
m_texture.filterMode = FilterMode.Point;
}
void OnGUI()
{
GUILayout.Space(20);
GUIStyle titleStyle = new GUIStyle(EditorStyles.label);
titleStyle.fontSize = 32;
titleStyle.normal.textColor = Color.white;
titleStyle.fontStyle = FontStyle.Bold;
titleStyle.stretchWidth = true;
titleStyle.stretchHeight = true;
titleStyle.alignment = TextAnchor.MiddleCenter;
GUILayout.BeginVertical();
EditorGUILayout.LabelField("Mapbox Atlas Template Generator", titleStyle, GUILayout.Height(100));
GUILayout.BeginHorizontal();
GUILayout.BeginVertical(GUILayout.MinWidth(200), GUILayout.MaxWidth(300));
EditorGUI.BeginChangeCheck();
EditorGUI.indentLevel++;
m_atlasInfo = EditorGUILayout.ObjectField("Atlas info:", m_atlasInfo, typeof(AtlasInfo), true) as Mapbox.Unity.MeshGeneration.Data.AtlasInfo;
EditorGUILayout.Space();
m_generateFacadesTemplate = EditorGUILayout.Toggle("Create Facades", m_generateFacadesTemplate);
m_generateRoofsTemplate = EditorGUILayout.Toggle("Create Roofs", m_generateRoofsTemplate);
if (EditorGUI.EndChangeCheck())
{
if (m_atlasInfo != null)
{
int facadeCount = m_generateFacadesTemplate ? m_atlasInfo.Textures.Count : 0;
int roofCount = m_generateRoofsTemplate ? m_atlasInfo.Roofs.Count : 0;
int textureCount = facadeCount + roofCount;
m_colors = new Color[textureCount];
float hueIncrement = (float)1.0f / textureCount;
float hue = 0.0f;
for (int i = 0; i < textureCount; i++)
{
m_colors[i] = Color.HSVToRGB(hue, 1.0f, 1.0f);
hue += hueIncrement;
}
}
else
{
m_colors = new Color[0];
CreateTexture();
}
}
EditorGUI.BeginChangeCheck();
m_textureResolution = Mathf.Clamp(EditorGUILayout.IntField("Texture resolution:", m_textureResolution), _MIN_TEX_SIZE, _MAX_TEX_SIZE);
if (EditorGUI.EndChangeCheck())
{
CreateTexture();
}
EditorGUILayout.Space();
if (m_colors != null)
{
for (int i = 0; i < m_colors.Length; i++)
{
string colorFieldName = string.Format("Color {0}", i);
m_colors[i] = EditorGUILayout.ColorField(colorFieldName, m_colors[i]);
}
}
if (GUILayout.Button("Generate Template"))
{
if (m_atlasInfo == null)
{
EditorUtility.DisplayDialog("Atlas Template Generator", "Error: No AtlasInfo object selected.", "Ok");
return;
}
if (!m_generateFacadesTemplate && !m_generateRoofsTemplate)
{
EditorUtility.DisplayDialog("Atlas Template Generator", "Error: Template generation requires Create Facades and/or Create Roofs to be enabled.", "Ok");
return;
}
GenerateTemplate();
}
EditorGUILayout.Space();
if (GUILayout.Button("Save to file"))
{
SaveTextureAsPNG();
}
EditorGUI.indentLevel--;
GUILayout.EndVertical();
GUIStyle boxStyle = new GUIStyle();
boxStyle.alignment = TextAnchor.UpperLeft;
GUILayout.Box(m_texture, boxStyle, GUILayout.Width(300), GUILayout.Height(300), GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.Space(20);
}
private int GetPixelCoorFromAtlasRatio(float ratio)
{
return (int)(m_textureResolution * ratio);
}
private PixelRect ConvertUVRectToPixelRect(Rect atlasRect)
{
PixelRect pixelRect = new PixelRect();
pixelRect.x = GetPixelCoorFromAtlasRatio(atlasRect.x);
pixelRect.y = GetPixelCoorFromAtlasRatio(atlasRect.y);
pixelRect.xx = GetPixelCoorFromAtlasRatio(atlasRect.x + atlasRect.width);
pixelRect.yy = GetPixelCoorFromAtlasRatio(atlasRect.y + atlasRect.height);
return pixelRect;
}
private void DrawRect(PixelRect pr, Color color)
{
for (int i = pr.x; i < pr.xx; i++)
{
for (int j = pr.y; j < pr.yy; j++)
{
m_texture.SetPixel(i, j, color);
}
}
}
private void DrawWatermark(int x, int y)
{
m_texture.SetPixel(x, y, Color.black);
m_texture.SetPixel(x + 3, y, Color.black);
m_texture.SetPixel(x, y + 3, Color.black);
m_texture.SetPixel(x + 3, y + 3, Color.black);
m_texture.SetPixel(x + 1, y + 1, Color.black);
m_texture.SetPixel(x + 2, y + 1, Color.black);
m_texture.SetPixel(x + 1, y + 2, Color.black);
m_texture.SetPixel(x + 2, y + 2, Color.black);
}
private void DrawCornerWatermarks(PixelRect pr)
{
DrawWatermark(pr.x, pr.y);
DrawWatermark(pr.xx - 4, pr.y);
DrawWatermark(pr.x, pr.yy - 4);
DrawWatermark(pr.xx - 4, pr.yy - 4);
}
private void DrawDebugCross(PixelRect pr)
{
int centerX = (pr.x + pr.xx) / 2;
int centerY = (pr.y + pr.yy) / 2;
m_texture.SetPixel(centerX, centerY, Color.black);
for (int x = pr.x; x < pr.xx; x++)
{
m_texture.SetPixel(x, centerY, Color.black);
m_texture.SetPixel(x, centerY - 1, Color.black);
m_texture.SetPixel(x, centerY + 1, Color.black);
}
for (int y = pr.y; y < pr.yy; y++)
{
m_texture.SetPixel(centerX, y, Color.black);
m_texture.SetPixel(centerX - 1, y, Color.black);
m_texture.SetPixel(centerX + 1, y, Color.black);
}
}
private void DrawAtlasEntityData(List<AtlasEntity> aeList)
{
for (int i = 0; i < aeList.Count; i++)
{
AtlasEntity ae = aeList[i];
Rect baseRect = ae.TextureRect;
float topRatio = ae.TopSectionRatio * baseRect.height;
float bottomRatio = ae.BottomSectionRatio * baseRect.height;
float middleRatio = baseRect.height - (topRatio + bottomRatio);
Rect groundFloorRect = new Rect(baseRect.x, baseRect.y, baseRect.width, bottomRatio);
Rect topFloorRect = new Rect(baseRect.x, baseRect.y + baseRect.height - topRatio, baseRect.width, topRatio);
PixelRect basePixelRect = ConvertUVRectToPixelRect(baseRect);
PixelRect groundFloorPixelRect = ConvertUVRectToPixelRect(groundFloorRect);
PixelRect topFloorPixelRect = ConvertUVRectToPixelRect(topFloorRect);
Color color = m_colors[_drawCount];
Color colorLight = (color + Color.white) / 2;
Color colorDark = (color + Color.black) / 2;
DrawRect(basePixelRect, color);
DrawRect(groundFloorPixelRect, colorLight);
DrawRect(topFloorPixelRect, colorDark);
DrawDebugCross(groundFloorPixelRect);
DrawDebugCross(topFloorPixelRect);
int numColumns = (int)ae.ColumnCount;
int numMidFloors = ae.MidFloorCount;
float colWidth = baseRect.width / numColumns;
float floorHeight = middleRatio / numMidFloors;
float midFloorBase = baseRect.y + bottomRatio;
float mrgn = _cellRatioMargin;
float halfMrgn = mrgn / 2;
for (int j = 0; j < numMidFloors; j++)
{
float floorStart = midFloorBase + (floorHeight * j);
for (int k = 0; k < numColumns; k++)
{
float columnStart = baseRect.x + (colWidth * k);
Rect cellRect = new Rect(columnStart + halfMrgn, floorStart + halfMrgn, colWidth - mrgn, floorHeight - mrgn);
PixelRect cellPixelRect = ConvertUVRectToPixelRect(cellRect);
DrawRect(cellPixelRect, Color.white);
DrawDebugCross(cellPixelRect);
}
}
DrawCornerWatermarks(groundFloorPixelRect);
DrawCornerWatermarks(topFloorPixelRect);
_drawCount++;
}
}
public void GenerateTemplate()
{
_drawCount = 0;
if (m_generateFacadesTemplate)
{
DrawAtlasEntityData(m_atlasInfo.Textures);
}
if (m_generateRoofsTemplate)
{
DrawAtlasEntityData(m_atlasInfo.Roofs);
}
m_texture.Apply();
}
public void SaveTextureAsPNG()
{
var path = EditorUtility.SaveFilePanel("Save texture as PNG", "Assets", "AtlasTemplate.png", "png");
if (path.Length == 0)
{
return;
}
byte[] pngData = m_texture.EncodeToPNG();
if (pngData != null)
{
File.WriteAllBytes(path, pngData);
Debug.Log(pngData.Length / 1024 + "Kb was saved as: " + path);
AssetDatabase.Refresh();
}
}
}
}