Creating a Vertex Painter in Unity 3D教学视频学习
2015-11-25 17:01
447 查看
这个视频主要介绍了unity编辑器关于EditorWindow、SceneGUI以及点绘制的知识。
EditorWindow的知识很普通,看官方教程就够了。这里不做特别记录。
SceneGUI主要用到了Handles、HandleUtility、GUIUtility这三个类:
1、Handles在教程中用于绘制控制手柄,如下图:
2、HandleUtility在教程中通过HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive))这样的函数,达到绘图时避免误选择对象的效果。如果想要获得View视图中鼠标从屏幕发出的射线的话还可以用这句HandleUtility.GUIPointToWorldRay(MousePos),MousePos是鼠标在View视图屏幕中的位置。
以下贴出核心类Gatu_VTXPainter_Window:
using UnityEngine;
using UnityEditor;
using System.Collections;
public class Gatu_VTXPainter_Window : EditorWindow
{
#region Variable
GUIStyle boxStyle;
public Vector2 MousePos;
public RaycastHit CurHit;
public bool AllowPainting;
public bool IsPainting;
public float BrushSize = 1f;
public float BrushMinSize = 0.01f;
public float BrushMaxSize = 10f;
public float BrushOpacity = 1f;
public float BrushFalloff = 1f;
public bool ChangingBrushValue;
public GameObject curGO;
public GameObject lastGO;
public Mesh curMesh;
public Color ForeBackgourndColor = Color.white;
#endregion
#region MainMethod
public static void LaunchVertexPainter()
{
var win = EditorWindow.GetWindow<Gatu_VTXPainter_Window>(false, "绘图窗口", true);
win.GenerateStyles();
}
void Update()
{
//Debug.Log("update");
if (AllowPainting)
{
Selection.activeGameObject = null;
}
else
{
curGO = null;
curMesh = null;
lastGO = null;
}
if (CurHit.transform != null)
{
//Debug.Log(CurHit.transform.name);
if (CurHit.transform.gameObject != lastGO)
{
curGO = CurHit.transform.gameObject;
curMesh = Gatu_VTXPainter_Utils.GetMesh(curGO);
lastGO = curGO;
if (curGO != null && curMesh != null)
{
Debug.Log(curGO.name + ":" + curMesh.name);
}
}
}
}
void OnEnable()
{
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
void OnDestroy()
{
SceneView.onSceneGUIDelegate -= OnSceneGUI;
}
#endregion
#region GUIMethod
void OnGUI()
{
//Header
GUILayout.Box("Vertex Painter", boxStyle, GUILayout.ExpandWidth(true), GUILayout.Height(60));
//Body
GUILayout.BeginVertical(boxStyle);
GUILayout.Space(10);
{
//GUILayout.BeginHorizontal();
//GUILayout.Button("Button", GUILayout.Height(40));
//GUILayout.Button("Button", GUILayout.Height(40));
//GUILayout.EndHorizontal();
AllowPainting = GUILayout.Toggle(AllowPainting, "Allow Painter", GUI.skin.button, GUILayout.Height(60));
}
GUILayout.Button("Button", GUILayout.Height(40));
GUILayout.Space(5);
ForeBackgourndColor = EditorGUILayout.ColorField("ForeBackgroundColor:", ForeBackgourndColor);
GUILayout.FlexibleSpace();
GUILayout.EndVertical();
//Footer
GUILayout.Box("Box", boxStyle, GUILayout.ExpandWidth(true), GUILayout.Height(60));
//Update and Repainter UI in real time
Repaint();
}
void OnSceneGUI(SceneView sceneView)
{
//Handles.Label( Vector3.up,"Vextex Painter Access!");
/*
Handles.BeginGUI();
GUILayout.BeginArea(new Rect(10, 10, 200, 150), boxStyle);
GUILayout.Button("Button", GUILayout.Height(30));
GUILayout.Button("Button", GUILayout.Height(30));
GUILayout.EndArea();
Handles.EndGUI();
*/
if (AllowPainting)
{
if (CurHit.transform != null)
{
Handles.color = new Color(ForeBackgourndColor.r, ForeBackgourndColor.g, ForeBackgourndColor.b, BrushOpacity);
Handles.DrawSolidDisc(CurHit.point, CurHit.normal, BrushSize);
Handles.color = Color.red;
Handles.DrawWireDisc(CurHit.point, CurHit.normal, BrushSize);
Handles.DrawWireDisc(CurHit.point, CurHit.normal, BrushFalloff);
}
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Ray worldRay = HandleUtility.GUIPointToWorldRay(MousePos);
if (!ChangingBrushValue)
{
if (Physics.Raycast(worldRay, out CurHit, 500f))
{
//Debug.Log("Begein vertex painting here");
if (IsPainting)
PaintVertexColor();
}
}
}
else
{
//HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Native));
}
ProcessInput();
sceneView.Repaint();
}
#endregion
#region Temp Painter Method
void PaintVertexColor()
{
if (curMesh)
{
Vector3[] verts = curMesh.vertices;
Color[] colors = new Color[0];
if (curMesh.colors.Length > 0)
{
colors = curMesh.colors;
}
else
{
colors = new Color[verts.Length];
}
for (int i = 0; i < verts.Length; i++)
{
Vector3 v = curGO.transform.TransformPoint(verts[i]);
float dis = (v - CurHit.point).sqrMagnitude;
if (dis > BrushSize)
continue;
//float falloff = Gatu_VTXPainter_Utils.LinerFalloff(Mathf.Clamp(dis - BrushFalloff, 0, 10), BrushSize - BrushFalloff);
float falloff = Gatu_VTXPainter_Utils.LinerFalloff(dis, BrushSize);
falloff = Mathf.Pow(falloff, BrushFalloff* 3f) * BrushOpacity; //这里是以falloff为变量的幕函数.
//colors[i] = ForeBackgourndColor * falloff * BrushOpacity;
colors[i] = Gatu_VTXPainter_Utils.VtxLerpColor(colors[i],ForeBackgourndColor,falloff) ;
}
curMesh.colors = colors;
}
}
#endregion
#region Utility Method
void ProcessInput()
{
Event e = Event.current;
MousePos = e.mousePosition;
if (e.type == EventType.KeyDown && e.isKey)
{
if (e.keyCode == KeyCode.Y)
{
// Debug.Log("Press Y");
AllowPainting = !AllowPainting;
if (!AllowPainting)
{
Tools.current = Tool.View;
}
else
{
Tools.current = Tool.None;
}
}
if (e.keyCode == KeyCode.Space)
{
// Debug.Log("Press space");
}
}
if (e.type == EventType.MouseDown)
{
if (e.button == 0)
{
//Debug.Log("Left mouse button downs!");
}
if (e.button == 1)
{
//Debug.Log("Right mouse button downs!");
}
if (e.button == 2)
{
// Debug.Log("Middle mouse button downs!");
}
}
if (e.type == EventType.MouseUp)
{
ChangingBrushValue = false;
IsPainting = false;
}
if (AllowPainting)
{
if (e.ty
4000
pe == EventType.MouseDrag && e.button == 0 && e.control && !e.shift)
{
BrushSize += e.delta.x * 0.005f;
BrushSize = Mathf.Clamp(BrushSize, BrushMinSize, BrushMaxSize);
ChangingBrushValue = true;
if (BrushFalloff > BrushSize)
BrushFalloff = BrushSize;
}
if (e.type == EventType.MouseDrag && e.button == 0 && !e.control && e.shift)
{
BrushOpacity += e.delta.x * 0.005f;
BrushOpacity = Mathf.Clamp01(BrushOpacity);
ChangingBrushValue = true;
}
if (e.type == EventType.MouseDrag && e.button == 0 && e.control && e.shift)
{
BrushFalloff += e.delta.x * 0.005f;
BrushFalloff = Mathf.Clamp(BrushFalloff, BrushMinSize, BrushSize);
ChangingBrushValue = true;
}
if (e.type == EventType.MouseDrag && e.button == 0 && !e.control && !e.shift && !e.alt)
{
IsPainting = true;
}
}
}
void GenerateStyles()
{
boxStyle = new GUIStyle();
boxStyle.normal.background = Resources.Load<Texture2D>("Textures/defalt_box_bg");
boxStyle.normal.textColor = Color.white;
boxStyle.border = new RectOffset(4, 4, 4, 4);
boxStyle.margin = new RectOffset(2, 2, 2, 2);
boxStyle.fontSize = 30;
boxStyle.alignment = TextAnchor.MiddleCenter;
}
#endregion
}
EditorWindow的知识很普通,看官方教程就够了。这里不做特别记录。
SceneGUI主要用到了Handles、HandleUtility、GUIUtility这三个类:
1、Handles在教程中用于绘制控制手柄,如下图:
2、HandleUtility在教程中通过HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive))这样的函数,达到绘图时避免误选择对象的效果。如果想要获得View视图中鼠标从屏幕发出的射线的话还可以用这句HandleUtility.GUIPointToWorldRay(MousePos),MousePos是鼠标在View视图屏幕中的位置。
以下贴出核心类Gatu_VTXPainter_Window:
using UnityEngine;
using UnityEditor;
using System.Collections;
public class Gatu_VTXPainter_Window : EditorWindow
{
#region Variable
GUIStyle boxStyle;
public Vector2 MousePos;
public RaycastHit CurHit;
public bool AllowPainting;
public bool IsPainting;
public float BrushSize = 1f;
public float BrushMinSize = 0.01f;
public float BrushMaxSize = 10f;
public float BrushOpacity = 1f;
public float BrushFalloff = 1f;
public bool ChangingBrushValue;
public GameObject curGO;
public GameObject lastGO;
public Mesh curMesh;
public Color ForeBackgourndColor = Color.white;
#endregion
#region MainMethod
public static void LaunchVertexPainter()
{
var win = EditorWindow.GetWindow<Gatu_VTXPainter_Window>(false, "绘图窗口", true);
win.GenerateStyles();
}
void Update()
{
//Debug.Log("update");
if (AllowPainting)
{
Selection.activeGameObject = null;
}
else
{
curGO = null;
curMesh = null;
lastGO = null;
}
if (CurHit.transform != null)
{
//Debug.Log(CurHit.transform.name);
if (CurHit.transform.gameObject != lastGO)
{
curGO = CurHit.transform.gameObject;
curMesh = Gatu_VTXPainter_Utils.GetMesh(curGO);
lastGO = curGO;
if (curGO != null && curMesh != null)
{
Debug.Log(curGO.name + ":" + curMesh.name);
}
}
}
}
void OnEnable()
{
SceneView.onSceneGUIDelegate -= OnSceneGUI;
SceneView.onSceneGUIDelegate += OnSceneGUI;
}
void OnDestroy()
{
SceneView.onSceneGUIDelegate -= OnSceneGUI;
}
#endregion
#region GUIMethod
void OnGUI()
{
//Header
GUILayout.Box("Vertex Painter", boxStyle, GUILayout.ExpandWidth(true), GUILayout.Height(60));
//Body
GUILayout.BeginVertical(boxStyle);
GUILayout.Space(10);
{
//GUILayout.BeginHorizontal();
//GUILayout.Button("Button", GUILayout.Height(40));
//GUILayout.Button("Button", GUILayout.Height(40));
//GUILayout.EndHorizontal();
AllowPainting = GUILayout.Toggle(AllowPainting, "Allow Painter", GUI.skin.button, GUILayout.Height(60));
}
GUILayout.Button("Button", GUILayout.Height(40));
GUILayout.Space(5);
ForeBackgourndColor = EditorGUILayout.ColorField("ForeBackgroundColor:", ForeBackgourndColor);
GUILayout.FlexibleSpace();
GUILayout.EndVertical();
//Footer
GUILayout.Box("Box", boxStyle, GUILayout.ExpandWidth(true), GUILayout.Height(60));
//Update and Repainter UI in real time
Repaint();
}
void OnSceneGUI(SceneView sceneView)
{
//Handles.Label( Vector3.up,"Vextex Painter Access!");
/*
Handles.BeginGUI();
GUILayout.BeginArea(new Rect(10, 10, 200, 150), boxStyle);
GUILayout.Button("Button", GUILayout.Height(30));
GUILayout.Button("Button", GUILayout.Height(30));
GUILayout.EndArea();
Handles.EndGUI();
*/
if (AllowPainting)
{
if (CurHit.transform != null)
{
Handles.color = new Color(ForeBackgourndColor.r, ForeBackgourndColor.g, ForeBackgourndColor.b, BrushOpacity);
Handles.DrawSolidDisc(CurHit.point, CurHit.normal, BrushSize);
Handles.color = Color.red;
Handles.DrawWireDisc(CurHit.point, CurHit.normal, BrushSize);
Handles.DrawWireDisc(CurHit.point, CurHit.normal, BrushFalloff);
}
HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
Ray worldRay = HandleUtility.GUIPointToWorldRay(MousePos);
if (!ChangingBrushValue)
{
if (Physics.Raycast(worldRay, out CurHit, 500f))
{
//Debug.Log("Begein vertex painting here");
if (IsPainting)
PaintVertexColor();
}
}
}
else
{
//HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Native));
}
ProcessInput();
sceneView.Repaint();
}
#endregion
#region Temp Painter Method
void PaintVertexColor()
{
if (curMesh)
{
Vector3[] verts = curMesh.vertices;
Color[] colors = new Color[0];
if (curMesh.colors.Length > 0)
{
colors = curMesh.colors;
}
else
{
colors = new Color[verts.Length];
}
for (int i = 0; i < verts.Length; i++)
{
Vector3 v = curGO.transform.TransformPoint(verts[i]);
float dis = (v - CurHit.point).sqrMagnitude;
if (dis > BrushSize)
continue;
//float falloff = Gatu_VTXPainter_Utils.LinerFalloff(Mathf.Clamp(dis - BrushFalloff, 0, 10), BrushSize - BrushFalloff);
float falloff = Gatu_VTXPainter_Utils.LinerFalloff(dis, BrushSize);
falloff = Mathf.Pow(falloff, BrushFalloff* 3f) * BrushOpacity; //这里是以falloff为变量的幕函数.
//colors[i] = ForeBackgourndColor * falloff * BrushOpacity;
colors[i] = Gatu_VTXPainter_Utils.VtxLerpColor(colors[i],ForeBackgourndColor,falloff) ;
}
curMesh.colors = colors;
}
}
#endregion
#region Utility Method
void ProcessInput()
{
Event e = Event.current;
MousePos = e.mousePosition;
if (e.type == EventType.KeyDown && e.isKey)
{
if (e.keyCode == KeyCode.Y)
{
// Debug.Log("Press Y");
AllowPainting = !AllowPainting;
if (!AllowPainting)
{
Tools.current = Tool.View;
}
else
{
Tools.current = Tool.None;
}
}
if (e.keyCode == KeyCode.Space)
{
// Debug.Log("Press space");
}
}
if (e.type == EventType.MouseDown)
{
if (e.button == 0)
{
//Debug.Log("Left mouse button downs!");
}
if (e.button == 1)
{
//Debug.Log("Right mouse button downs!");
}
if (e.button == 2)
{
// Debug.Log("Middle mouse button downs!");
}
}
if (e.type == EventType.MouseUp)
{
ChangingBrushValue = false;
IsPainting = false;
}
if (AllowPainting)
{
if (e.ty
4000
pe == EventType.MouseDrag && e.button == 0 && e.control && !e.shift)
{
BrushSize += e.delta.x * 0.005f;
BrushSize = Mathf.Clamp(BrushSize, BrushMinSize, BrushMaxSize);
ChangingBrushValue = true;
if (BrushFalloff > BrushSize)
BrushFalloff = BrushSize;
}
if (e.type == EventType.MouseDrag && e.button == 0 && !e.control && e.shift)
{
BrushOpacity += e.delta.x * 0.005f;
BrushOpacity = Mathf.Clamp01(BrushOpacity);
ChangingBrushValue = true;
}
if (e.type == EventType.MouseDrag && e.button == 0 && e.control && e.shift)
{
BrushFalloff += e.delta.x * 0.005f;
BrushFalloff = Mathf.Clamp(BrushFalloff, BrushMinSize, BrushSize);
ChangingBrushValue = true;
}
if (e.type == EventType.MouseDrag && e.button == 0 && !e.control && !e.shift && !e.alt)
{
IsPainting = true;
}
}
}
void GenerateStyles()
{
boxStyle = new GUIStyle();
boxStyle.normal.background = Resources.Load<Texture2D>("Textures/defalt_box_bg");
boxStyle.normal.textColor = Color.white;
boxStyle.border = new RectOffset(4, 4, 4, 4);
boxStyle.margin = new RectOffset(2, 2, 2, 2);
boxStyle.fontSize = 30;
boxStyle.alignment = TextAnchor.MiddleCenter;
}
#endregion
}
相关文章推荐
- PDF编辑工具 Foxit PDF Editor 1.5 Build 2911 下载
- MicroAdobe PDF Editor 6.2 英文正式版附破解补丁 下载
- JavaScript 井字棋人工智能实现代码
- unity实现多点触控代码
- javascript substr和substring用法比较
- 在Unity中实现动画的正反播放代码
- unity实现摄像头跟随
- Leanote集成Ace代码编辑器, 程序员的最爱
- Unity3D上路_01-2D太空射击游戏
- Unity3D上路_02-第一视角射击游戏
- Unity3D上路_03-塔防游戏
- Unity3D上路_04-基础资源介绍
- Unity3D上路_05-网络相关
- [软件资讯]Unity已支持将3D游戏导出成Flash
- Unity 武器拖尾效果
- SCOUNIX-第三讲vi editor
- unity常见问题之20题
- PDF编辑器-Foxit PDF Editor 1.5 破解版下载
- Unity3D动画存储插件
- unity 赛车相机跟随物体移动