BITFALL/Assets/Polaris - Low Poly Ecosystem/Polaris - Low Poly Terrain .../Editor/Scripts/BillboardTool/GBillboardEditor.cs

820 lines
35 KiB
C#

#if GRIFFIN
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Pinwheel.Griffin.BillboardTool
{
public class GBillboardEditor : GTwoPaneWindowWindow
{
private int previewPadding = 10;
private bool alphaBlend = true;
private GBillboardRenderMode mode;
private GameObject target;
private int row = 4;
private int column = 4;
private int cellSize = 256;
private Vector3 cameraOffset = new Vector3(0, 0, 5);
private float cameraSize = 1;
private Material atlasMaterial;
private Material normalMaterial;
private string srcTextureProps = "_MainTex";
private string desTextureProps = "_MainTex";
private string srcColorProps = "_Color";
private string desColorProps = "_Color";
private int cellIndex = 0;
private List<Vector2> vertices = new List<Vector2>(new Vector2[] { new Vector2(0.01f, 0.01f), new Vector2(0.01f, 0.99f), new Vector2(0.99f, 0.99f), new Vector2(0.99f, 0.01f) });
private int selectedVertexIndex = -1;
private float vertexClickDistance = 10;
private ushort[] tris = new ushort[0];
private float bottom = 0;
private float width = 1;
private float height = 2;
private string saveFolder;
private const int MAX_VERTICES = 10;
private int[] rowColumnValues = new int[] { 1, 2, 4, 8, 16 };
private string[] rowColumnLabels = new string[] { "1", "2", "4", "8", "16" };
private int[] cellSizeValues = new int[] { 128, 256, 512 };
private string[] cellSizeLabels = new string[] { "128", "256", "512" };
private RenderTexture previewRt;
private const string ATLAS_INSTRUCTION =
"Preview billboard atlas. Image order from bottom-left to top-right.";
private const string NORMAL_INSTRUCTION =
"Preview billboard normal map. Image order from bottom-left to top-right";
private const string FLIPBOOK_INSTRUCTION =
"Preview billboard transition and edit billboard mesh.\n" +
" - Use Scrollwheel to iterate images.\n" +
" - Use Left Mouse to edit vertex position.\n" +
" - Use Ctrl & Left Mouse to remove vertex.\n" +
" - Use Shift & Left Mouse to add vertex.\n" +
"For best rendering performance, billboard mesh is limited at maximum 10 vertices.";
private const string KEY_BILLBOARDEDITOR = "billboardeditor";
private const string KEY_MODE = "mode";
private const string KEY_PREFAB = "prefab";
private const string KEY_ROW = "row";
private const string KEY_COLUMN = "column";
private const string KEY_CELLSIZE = "cellsize";
private const string KEY_CAM_X = "camx";
private const string KEY_CAM_Y = "camy";
private const string KEY_CAM_Z = "camz";
private const string KEY_CAM_SIZE = "camsize";
private const string KEY_ATLAS_MAT = "atlasmat";
private const string KEY_NORMAL_MAT = "normalmat";
private const string KEY_SRC_TEX_PROPS = "srctex";
private const string KEY_DES_TEX_PROPS = "destex";
private const string KEY_SRC_COLOR_PROPS = "srccolor";
private const string KEY_DES_COLOR_PROPS = "descolor";
private const string KEY_BOTTOM = "bottom";
private const string KEY_WIDTH = "width";
private const string KEY_HEIGHT = "height";
private const string KEY_ALPHA_BLEND = "alphablend";
private const string KEY_SAVE_FOLDER = "save-folder";
private List<string> srcColorSuggestion;
private List<string> SrcColorSuggestion
{
get
{
if (srcColorSuggestion == null)
{
srcColorSuggestion = new List<string>();
}
return srcColorSuggestion;
}
}
private List<string> srcTextureSuggestion;
private List<string> SrcTextureSuggestion
{
get
{
if (srcTextureSuggestion == null)
{
srcTextureSuggestion = new List<string>();
}
return srcTextureSuggestion;
}
}
public static void ShowWindow()
{
GBillboardEditor window = EditorWindow.GetWindow<GBillboardEditor>();
window.titleContent = new GUIContent("Billboard");
window.minSize = new Vector2(400, 300);
window.Show();
}
private void OnEnable()
{
LoadPrefs();
wantsMouseMove = true;
tris = GBillboardCreator.Triangulate(vertices.ToArray());
RenderPreview();
RefreshMaterialPropsSuggestions();
}
private void OnDisable()
{
SavePrefs();
}
private void SavePrefs()
{
EditorPrefs.SetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_MODE), (int)mode);
if (target != null)
{
string assetPath = AssetDatabase.GetAssetPath(target);
if (!string.IsNullOrEmpty(assetPath))
{
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_PREFAB), assetPath);
}
}
EditorPrefs.SetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_ROW), row);
EditorPrefs.SetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_COLUMN), column);
EditorPrefs.SetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CELLSIZE), cellSize);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_X), cameraOffset.x);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_Y), cameraOffset.y);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_Z), cameraOffset.z);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_SIZE), cameraSize);
if (atlasMaterial != null)
{
string assetPath = AssetDatabase.GetAssetPath(atlasMaterial);
if (!string.IsNullOrEmpty(assetPath))
{
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_ATLAS_MAT), assetPath);
}
}
if (normalMaterial != null)
{
string assetPath = AssetDatabase.GetAssetPath(normalMaterial);
if (!string.IsNullOrEmpty(assetPath))
{
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_NORMAL_MAT), assetPath);
}
}
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SRC_COLOR_PROPS), srcColorProps);
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_DES_COLOR_PROPS), desColorProps);
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SRC_TEX_PROPS), srcTextureProps);
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_DES_TEX_PROPS), desTextureProps);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_WIDTH), width);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_HEIGHT), height);
EditorPrefs.SetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_BOTTOM), bottom);
EditorPrefs.SetBool(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_ALPHA_BLEND), alphaBlend);
EditorPrefs.SetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SAVE_FOLDER), saveFolder);
}
private void LoadPrefs()
{
mode = (GBillboardRenderMode)EditorPrefs.GetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_MODE), 0);
string targetAssetPath = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_PREFAB), string.Empty);
target = AssetDatabase.LoadAssetAtPath<GameObject>(targetAssetPath);
row = EditorPrefs.GetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_ROW), 4);
column = EditorPrefs.GetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_COLUMN), 4);
cellSize = EditorPrefs.GetInt(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CELLSIZE), 256);
float camX = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_X), 0);
float camY = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_Y), -2);
float camZ = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_Z), 0);
cameraOffset = new Vector3(camX, camY, camZ);
cameraSize = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_CAM_SIZE), 2);
atlasMaterial = GEditorSettings.Instance.billboardTools.atlasMaterial;
normalMaterial = GEditorSettings.Instance.billboardTools.normalMaterial;
srcColorProps = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SRC_COLOR_PROPS), "_Color");
desColorProps = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_DES_COLOR_PROPS), "_Color");
srcTextureProps = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SRC_TEX_PROPS), "_MainTex");
desTextureProps = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_DES_TEX_PROPS), "_MainTex");
width = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_WIDTH), 1);
height = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_HEIGHT), 2);
bottom = EditorPrefs.GetFloat(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_BOTTOM), 0.2f);
alphaBlend = EditorPrefs.GetBool(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_ALPHA_BLEND), true);
saveFolder = EditorPrefs.GetString(GEditorCommon.GetProjectRelatedEditorPrefsKey(KEY_BILLBOARDEDITOR, KEY_SAVE_FOLDER), "Assets/");
}
protected override void OnToolbarGUI(Rect r)
{
base.OnToolbarGUI(r);
List<string> buttonLabels = new List<string>()
{
"Atlas",
"Normal",
"Flipbook",
"",
"A"
};
List<Rect> buttonRects = EditorGUIUtility.GetFlowLayoutedRects(r, EditorStyles.toolbarButton, 0, 0, buttonLabels);
for (int i = 0; i < 3; ++i)
{
if (GUI.Button(buttonRects[i], buttonLabels[i], EditorStyles.toolbarButton))
{
mode = (GBillboardRenderMode)i;
RenderPreview();
}
if (i == (int)mode)
{
Color highlightColor = EditorGUIUtility.isProSkin ? new Color(1, 1, 1, 0.1f) : new Color(1, 1, 1, 0.3f);
EditorGUI.DrawRect(buttonRects[i], highlightColor);
}
}
if (GUI.Button(buttonRects[4], buttonLabels[4], EditorStyles.toolbarButton))
{
alphaBlend = !alphaBlend;
}
if (alphaBlend)
{
Color highlightColor = EditorGUIUtility.isProSkin ? new Color(1, 1, 1, 0.1f) : new Color(1, 1, 1, 0.3f);
EditorGUI.DrawRect(buttonRects[4], highlightColor);
}
Rect saveButtonRect = new Rect(
r.max.x - 100 - 2,
r.min.y,
100,
r.height);
if (GUI.Button(saveButtonRect, "Save", EditorStyles.toolbarButton))
{
SaveAssets();
}
}
private GBillboardCreatorArgs ConstructArgs()
{
GBillboardCreatorArgs args = new GBillboardCreatorArgs();
args.Mode = mode;
args.Target = target;
args.Row = row;
args.Column = column;
args.CellSize = cellSize;
args.CameraOffset = cameraOffset;
args.CameraSize = cameraSize;
args.AtlasMaterial = atlasMaterial;
args.NormalMaterial = normalMaterial;
args.SrcColorProps = srcColorProps;
//args.DesColorProps = desColorProps;
args.DesColorProps = "_Color";
args.SrcTextureProps = srcTextureProps;
//args.DesTextureProps = desTextureProps;
args.DesTextureProps = "_MainTex";
args.CellIndex = cellIndex % (args.Row * args.Column);
args.Vertices = vertices.ToArray();
args.Width = width;
args.Height = height;
args.Bottom = bottom;
return args;
}
private void CopyArgs(GBillboardCreatorArgs args)
{
mode = args.Mode;
target = args.Target;
row = args.Row;
column = args.Column;
cellSize = args.CellSize;
cameraOffset = args.CameraOffset;
cameraSize = args.CameraSize;
atlasMaterial = args.AtlasMaterial;
normalMaterial = args.NormalMaterial;
srcColorProps = args.SrcColorProps;
desColorProps = args.DesColorProps;
srcTextureProps = args.SrcTextureProps;
desTextureProps = args.DesTextureProps;
cellIndex = args.CellIndex;
vertices = new List<Vector2>(args.Vertices);
width = args.Width;
height = args.Height;
bottom = args.Bottom;
tris = GBillboardCreator.Triangulate(vertices.ToArray());
}
protected override void OnLeftPaneGUI(Rect r)
{
base.OnLeftPaneGUI(r);
Rect previewRect = new Rect();
int size = Mathf.FloorToInt(Mathf.Min(LeftPaneRect.width, LeftPaneRect.height) - 2 * previewPadding);
previewRect.size = new Vector2(size, size);
previewRect.center = LeftPaneRect.center;
if (previewRt != null)
{
if (alphaBlend)
EditorGUI.DrawTextureTransparent(previewRect, previewRt, ScaleMode.ScaleToFit);
else
EditorGUI.DrawPreviewTexture(previewRect, previewRt, null, ScaleMode.ScaleToFit);
}
else
{
EditorGUI.DrawRect(previewRect, Color.black);
}
if (Event.current != null &&
Event.current.isScrollWheel &&
previewRect.Contains(Event.current.mousePosition) &&
mode == GBillboardRenderMode.Flipbook)
{
cellIndex += (int)(Event.current.delta.y / 2f);
if (cellIndex < 0)
cellIndex = row * column - 1;
if (cellIndex >= row * column)
cellIndex = 0;
RenderPreview();
}
if (mode == GBillboardRenderMode.Flipbook)
{
DrawBottomLine(previewRect);
DrawTriangles(previewRect);
DrawVertices(previewRect);
Rect pageRect = new Rect(
previewRect.min.x, previewRect.max.y - 20,
previewRect.width, 20);
EditorGUI.DropShadowLabel(pageRect, string.Format("{0}/{1}", cellIndex + 1, row * column), GEditorCommon.CenteredWhiteLabel);
}
}
private void DrawTriangles(Rect previewRect)
{
if (tris == null)
return;
if (tris.Length % 3 != 0)
{
Debug.Log("Invalid tris array!");
return;
}
int trisCount = tris.Length / 3;
for (int i = 0; i < trisCount; ++i)
{
Vector2 v0 = vertices[tris[i * 3 + 0]];
Vector2 v1 = vertices[tris[i * 3 + 1]];
Vector2 v2 = vertices[tris[i * 3 + 2]];
v0 = GUtilities.FlipY(v0);
v1 = GUtilities.FlipY(v1);
v2 = GUtilities.FlipY(v2);
Vector2 p0 = Rect.NormalizedToPoint(previewRect, v0);
Vector2 p1 = Rect.NormalizedToPoint(previewRect, v1);
Vector2 p2 = Rect.NormalizedToPoint(previewRect, v2);
GEditorCommon.DrawLine(p0, p1, Color.green);
GEditorCommon.DrawLine(p1, p2, Color.green);
GEditorCommon.DrawLine(p2, p0, Color.green);
}
}
private void DrawVertices(Rect previewRect)
{
if (vertices == null)
{
vertices = new List<Vector2>();
tris = new ushort[0];
}
for (int i = 0; i < vertices.Count; ++i)
{
HandleEditingVertices(previewRect, i);
}
HandleAddVertex(previewRect);
}
private void DrawBottomLine(Rect previewRect)
{
float h = bottom / (bottom - height);
h = 1 - h;
Vector2 p0 = Rect.NormalizedToPoint(previewRect, new Vector2(0, h));
Vector2 p1 = Rect.NormalizedToPoint(previewRect, new Vector2(1, h));
GEditorCommon.DrawLine(p0, p1, Color.red);
}
private void HandleEditingVertices(Rect previewRect, int vertIndex)
{
if (vertIndex >= vertices.Count)
return;
if (Event.current == null)
return;
Event e = Event.current;
Vector2 uv = vertices[vertIndex];
Vector2 point = Rect.NormalizedToPoint(previewRect, GUtilities.FlipY(uv));
if (e.type == EventType.MouseDown)
{
selectedVertexIndex = -1;
float d = Vector2.Distance(e.mousePosition, point);
if (d <= vertexClickDistance)
{
if (e.button == 0 && !e.control)
{
selectedVertexIndex = vertIndex;
e.Use();
}
else if (e.button == 0 && e.control)
{
vertices.RemoveAt(vertIndex);
tris = GBillboardCreator.Triangulate(vertices.ToArray());
e.Use();
}
}
}
else if (e.type == EventType.MouseDrag)
{
if (selectedVertexIndex == vertIndex)
{
point = e.mousePosition;
uv = Rect.PointToNormalized(previewRect, point);
uv.Set(Mathf.Clamp01(uv.x), Mathf.Clamp01(uv.y));
vertices[vertIndex] = GUtilities.FlipY(uv);
tris = GBillboardCreator.Triangulate(vertices.ToArray());
e.Use();
}
}
Color handleColor = selectedVertexIndex == vertIndex ? Color.yellow : Color.green;
float handleSize = 6;
Rect handleRect = new Rect();
handleRect.size = Vector2.one * handleSize;
handleRect.center = point;
EditorGUI.DrawRect(handleRect, handleColor);
}
private void HandleAddVertex(Rect previewRect)
{
if (vertices.Count >= MAX_VERTICES)
return;
if (Event.current == null)
return;
Event e = Event.current;
if (e.type == EventType.MouseDown && e.shift)
{
if (!previewRect.Contains(e.mousePosition))
return;
Vector2 uv = Rect.PointToNormalized(previewRect, e.mousePosition);
vertices.Add(GUtilities.FlipY(uv));
selectedVertexIndex = vertices.Count - 1;
tris = GBillboardCreator.Triangulate(vertices.ToArray());
e.Use();
}
}
protected override void OnRightPaneScrollViewGUI()
{
base.OnRightPaneScrollViewGUI();
EditorGUI.BeginChangeCheck();
float labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = 120;
DrawInstruction();
DrawTargetSettings();
DrawCameraSettings();
DrawAtlasSettings();
DrawMaterialSettings();
if (mode == GBillboardRenderMode.Flipbook)
{
DrawMeshSettings();
}
DrawUtilities();
EditorGUIUtility.labelWidth = labelWidth;
if (EditorGUI.EndChangeCheck())
{
RenderPreview();
}
}
private void DrawInstruction()
{
string label = "Instruction";
string id = "billboardeditor-instruction";
GEditorCommon.Foldout(label, false, id, () =>
{
string instruction =
mode == GBillboardRenderMode.Atlas ? ATLAS_INSTRUCTION :
mode == GBillboardRenderMode.Normal ? NORMAL_INSTRUCTION :
mode == GBillboardRenderMode.Flipbook ? FLIPBOOK_INSTRUCTION :
string.Empty;
EditorGUILayout.LabelField(instruction, GEditorCommon.WordWrapItalicLabel);
});
}
private void DrawTargetSettings()
{
string label = "Target";
string id = "billboardeditor-target";
GEditorCommon.Foldout(label, false, id, () =>
{
EditorGUI.BeginChangeCheck();
target = EditorGUILayout.ObjectField("Prefab", target, typeof(GameObject), true) as GameObject;
if (EditorGUI.EndChangeCheck())
{
GBillboardCreatorArgs args = GBillboardCreator.FitCameraToTarget(ConstructArgs());
CopyArgs(args);
RefreshMaterialPropsSuggestions();
}
});
}
private void DrawCameraSettings()
{
string label = "Camera";
string id = "billboardeditor-camera";
GEditorCommon.Foldout(label, false, id, () =>
{
EditorGUIUtility.wideMode = true;
cameraOffset = EditorGUILayout.Vector3Field("Offset", cameraOffset);
EditorGUIUtility.wideMode = false;
cameraSize = EditorGUILayout.FloatField("Size", cameraSize);
cameraSize = Mathf.Max(0, cameraSize);
});
}
private void DrawAtlasSettings()
{
string label = "Atlas";
string id = "billboardeditor-atlas";
GEditorCommon.Foldout(label, false, id, () =>
{
row = EditorGUILayout.IntPopup("Row", row, rowColumnLabels, rowColumnValues);
column = EditorGUILayout.IntPopup("Column", column, rowColumnLabels, rowColumnValues);
cellSize = EditorGUILayout.IntPopup("Cell Size", cellSize, cellSizeLabels, cellSizeValues);
EditorGUILayout.LabelField("Resolution: ", string.Format("{0} x {1}", column * cellSize, row * cellSize));
});
}
private void DrawMaterialSettings()
{
string label = "Materials";
string id = "billboardeditor-materials";
GEditorCommon.Foldout(label, false, id, () =>
{
GUI.enabled = false;
atlasMaterial = EditorGUILayout.ObjectField("Atlas Material", atlasMaterial, typeof(Material), false) as Material;
normalMaterial = EditorGUILayout.ObjectField("Normal Material", normalMaterial, typeof(Material), false) as Material;
GUI.enabled = true;
EditorGUILayout.BeginHorizontal();
srcColorProps = EditorGUILayout.TextField("Source Color", srcColorProps);
if (GUILayout.Button(GEditorCommon.contextIconText, EditorStyles.label, GUILayout.Width(14)))
{
GenericMenu menu = new GenericMenu();
if (SrcColorSuggestion.Count > 0)
{
menu.AddDisabledItem(new GUIContent("Suggestion"));
menu.AddSeparator(null);
for (int i = 0; i < SrcColorSuggestion.Count; ++i)
{
string s = SrcColorSuggestion[i];
menu.AddItem(
new GUIContent(s),
false,
() => { srcColorProps = s; RenderPreview(); });
}
}
else
{
menu.AddDisabledItem(new GUIContent("No suitable property found!"));
}
menu.ShowAsContext();
}
EditorGUILayout.EndHorizontal();
//desColorProps = EditorGUILayout.TextField("Des Color", desColorProps);
EditorGUILayout.BeginHorizontal();
srcTextureProps = EditorGUILayout.TextField("Source Texture", srcTextureProps);
if (GUILayout.Button(GEditorCommon.contextIconText, EditorStyles.label, GUILayout.Width(14)))
{
GenericMenu menu = new GenericMenu();
if (SrcTextureSuggestion.Count > 0)
{
menu.AddDisabledItem(new GUIContent("Suggestion"));
menu.AddSeparator(null);
for (int i = 0; i < SrcTextureSuggestion.Count; ++i)
{
string s = SrcTextureSuggestion[i];
menu.AddItem(
new GUIContent(s),
false,
() => { srcTextureProps = s; RenderPreview(); });
}
}
else
{
menu.AddDisabledItem(new GUIContent("No suitable property found!"));
}
menu.ShowAsContext();
}
EditorGUILayout.EndHorizontal();
//desTextureProps = EditorGUILayout.TextField("Des Texture", desTextureProps);
});
}
private void RenderPreview()
{
GBillboardCreatorArgs args = ConstructArgs();
GBillboardCreator.PrepareRenderTexture(ref previewRt, args);
GBillboardCreator.RenderPreview(previewRt, args);
}
private void DrawMeshSettings()
{
string label = "Mesh";
string id = "billboardeditor-mesh";
GEditorCommon.Foldout(label, false, id, () =>
{
int trisCount = tris.Length / 3;
EditorGUILayout.LabelField("Triangles", trisCount.ToString());
EditorGUILayout.LabelField("Vertices", vertices.Count.ToString());
EditorGUI.indentLevel += 1;
for (int i = 0; i < vertices.Count; ++i)
{
Vector2 v = vertices[i];
EditorGUIUtility.wideMode = true;
v = EditorGUILayout.Vector2Field("Vertex " + i, v);
EditorGUIUtility.wideMode = false;
v.Set(Mathf.Clamp01(v.x), Mathf.Clamp01(v.y));
vertices[i] = v;
}
EditorGUI.indentLevel -= 1;
width = EditorGUILayout.FloatField("Width", width);
width = Mathf.Max(0, width);
height = EditorGUILayout.FloatField("Height", height);
height = Mathf.Max(0, height);
bottom = EditorGUILayout.FloatField("Bottom", bottom);
bottom = Mathf.Min(bottom, 0);
});
}
private void DrawUtilities()
{
string label = "Utilites";
string id = "billboardeditor-utilities";
GEditorCommon.Foldout(label, false, id, () =>
{
Rect fitButtonRect = EditorGUILayout.GetControlRect();
if (GUI.Button(fitButtonRect, "Fit Camera"))
{
GBillboardCreatorArgs args = GBillboardCreator.FitCameraToTarget(ConstructArgs());
CopyArgs(args);
}
});
}
private void SaveAssets()
{
if (string.IsNullOrEmpty(saveFolder))
{
saveFolder = "Assets/";
}
string folder = EditorUtility.OpenFolderPanel("Select Folder", saveFolder, "");
if (string.IsNullOrEmpty(folder))
return;
try
{
saveFolder = folder;
EditorUtility.DisplayProgressBar("Saving", "Saving assets...", 1f);
GBillboardCreatorArgs args = ConstructArgs();
BillboardAsset billboard = GBillboardCreator.CreateBillboardAsset(args);
Texture2D atlas = GBillboardCreator.RenderAtlas(args);
Texture2D normal = GBillboardCreator.RenderNormal(args);
string billboardPath = Path.Combine(FileUtil.GetProjectRelativePath(saveFolder), billboard.name + ".asset");
BillboardAsset billboardAsset = AssetDatabase.LoadAssetAtPath<BillboardAsset>(billboardPath);
if (billboardAsset == null)
{
AssetDatabase.CreateAsset(billboard, billboardPath);
billboardAsset = billboard;
}
else
{
billboardAsset.SetVertices(billboard.GetVertices());
billboardAsset.SetIndices(billboard.GetIndices());
billboardAsset.SetImageTexCoords(billboard.GetImageTexCoords());
billboardAsset.width = billboard.width;
billboardAsset.height = billboard.height;
billboardAsset.bottom = billboard.bottom;
billboardAsset.name = billboard.name;
}
string atlasPath = Path.Combine(FileUtil.GetProjectRelativePath(saveFolder), atlas.name + ".png");
byte[] atlasData = atlas.EncodeToPNG();
File.WriteAllBytes(atlasPath, atlasData);
GUtilities.DestroyObject(atlas);
string normalPath = Path.Combine(FileUtil.GetProjectRelativePath(saveFolder), normal.name + ".png");
byte[] normalData = normal.EncodeToPNG();
File.WriteAllBytes(normalPath, normalData);
GUtilities.DestroyObject(normal);
AssetDatabase.Refresh();
TextureImporter atlasImporter = AssetImporter.GetAtPath(atlasPath) as TextureImporter;
atlasImporter.wrapMode = TextureWrapMode.Clamp;
atlasImporter.alphaIsTransparency = true;
atlasImporter.SaveAndReimport();
atlas = AssetDatabase.LoadAssetAtPath<Texture2D>(atlasPath);
TextureImporter normalImporter = AssetImporter.GetAtPath(normalPath) as TextureImporter;
normalImporter.textureType = TextureImporterType.NormalMap;
normalImporter.wrapMode = TextureWrapMode.Clamp;
normalImporter.SaveAndReimport();
normal = AssetDatabase.LoadAssetAtPath<Texture2D>(normalPath);
Material mat = null;
if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Universal)
{
mat = Object.Instantiate(GRuntimeSettings.Instance.foliageRendering.urpTreeBillboardMaterial);
}
else
{
mat = Object.Instantiate(GRuntimeSettings.Instance.foliageRendering.treeBillboardMaterial);
}
if (mat != null)
{
if (mat.HasProperty("_MainTex"))
{
mat.SetTexture("_MainTex", atlas);
}
if (mat.HasProperty("_BumpMap"))
{
mat.SetTexture("_BumpMap", normal);
}
mat.name = args.Target.name + "_BillboardMaterial";
string matPath = Path.Combine(FileUtil.GetProjectRelativePath(saveFolder), mat.name + ".mat");
AssetDatabase.CreateAsset(mat, matPath);
billboardAsset.material = mat;
}
AssetDatabase.Refresh();
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
EditorUtility.ClearProgressBar();
}
private void RefreshMaterialPropsSuggestions()
{
if (target == null)
{
SrcColorSuggestion.Clear();
SrcColorSuggestion.Add("_Color");
SrcTextureSuggestion.Clear();
SrcTextureSuggestion.Add("_MainTex");
}
else
{
HashSet<Shader> shaders = new HashSet<Shader>();
MeshRenderer[] mrs = target.GetComponentsInChildren<MeshRenderer>();
for (int i = 0; i < mrs.Length; ++i)
{
Material[] mats = mrs[i].sharedMaterials;
for (int j = 0; j < mats.Length; ++j)
{
shaders.Add(mats[j].shader);
}
}
HashSet<string> colorProps = new HashSet<string>();
colorProps.Add("_Color");
HashSet<string> textureProps = new HashSet<string>();
textureProps.Add("_MainTex");
IEnumerator<Shader> shaderIterator = shaders.GetEnumerator();
while (shaderIterator.MoveNext())
{
colorProps.UnionWith(GShaderParser.GetProperties(shaderIterator.Current, "Color"));
textureProps.UnionWith(GShaderParser.GetProperties(shaderIterator.Current, "2D"));
}
SrcColorSuggestion.Clear();
SrcColorSuggestion.AddRange(colorProps);
SrcTextureSuggestion.Clear();
SrcTextureSuggestion.AddRange(textureProps);
}
}
}
}
#endif