1
This commit is contained in:
@@ -0,0 +1,819 @@
|
||||
#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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92ad6649e3c0a0648bcbc2ec10fd9ffc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user