永州市开发建设投资有限公司网站青岛网站制作
news/
2025/10/9 3:02:48/
文章来源:
永州市开发建设投资有限公司网站,青岛网站制作,品牌做网站公司,wordpress 付费下载插件大家好#xff0c;我是阿赵。 之前分享过怎样通过MaxScript在3DsMax里面修改模型的顶点色。不过由于很多时候顶点色的编辑需要根据在游戏引擎里面的实际情况和shader的情况来动态调整#xff0c;所以如果能在引擎里面直接修改模型的顶点色#xff0c;将会方便很多。于是…大家好我是阿赵。 之前分享过怎样通过MaxScript在3DsMax里面修改模型的顶点色。不过由于很多时候顶点色的编辑需要根据在游戏引擎里面的实际情况和shader的情况来动态调整所以如果能在引擎里面直接修改模型的顶点色将会方便很多。于是我写了下面这个在Unity引擎里面修改模型顶点色的工具。
一、功能介绍
1、模型选择和网格生成
这是工具的界面选择一个或者多个带有网格模型的GameObject点击开始编辑
如果选择的网格模型是属于不能编辑的类型比如unity自带网格fbx里面的网格工具会提示生成可编辑网格
工具将会把网格模型复制一份保存成asset格式的资源文件。
2、笔刷功能
开始编辑之后把鼠标放在模型上会出现笔刷笔刷的大小、衰减、强度等可以调节
其中笔刷的半径可以用快捷键”[“和”]”控制衰减可以用快捷键”-”和””来控制
3、顶点色显示
为了能在使用工具的过程中知道绘制的效果所以有必要把顶点色给显示出来。
不过如果模型默认有颜色可能会导致刷的过程比较难看得清楚所以也可以进入线框模式看
如果模型的顶点很多那么显示顶点也会比较耗时表现就是在刷颜色的时候有点卡所以也提供了一个显示模式是指显示笔刷覆盖范围的点
为了便于观察单个通道的当前值所以在单个通道模式下可以选择单色显示或者是黑白显示这样看起来会更加直观
4、刷颜色 调一下强度其实就是笔刷的透明度就可以在模型上面刷顶点颜色了。如果是刷所有通道可以直接选择颜色。如果是单个通道可以选择是增加或者减少该通道的颜色。 这里加入了权重模式的选项。所谓的权重模式是保证RGBA4个通道的颜色值加起来等于1如果增加某个通道的颜色就会相应的减少其他几个通道的颜色。在用顶点色做某些混合功能的时候这个权重模式会比较的有用。
二、技术点
1、判断笔刷位置 本来很简单的一件事情鼠标在屏幕位置发射射线求和模型网格的碰撞点就可以了。不过如果用Physics.Raycast方法是需要模型网格上有碰撞体才能检测到的。而在这个工具的环境下我需要的是没有碰撞体也能检测得到网格模型的碰撞点。 其实这个方法是Unity自带了的:
bool HandleUtility.IntersectRayMesh(Ray ray,Mesh mesh,Matrix4x4 matrix,out RaycastHit hit)可惜的是这个方法Unity居然是隐藏的并没有暴露出来给我们用。所以只能使用反射的手段去调用
private bool IntersectRayMesh(Ray ray,Mesh sharedMesh,Matrix4x4 matrix,out RaycastHit hit)
{System.Type type typeof(HandleUtility);System.Reflection.MethodInfo method type.GetMethod(IntersectRayMesh, (BindingFlags.Static | BindingFlags.NonPublic));RaycastHit tempHit new RaycastHit();object[] objArr new object[4];objArr[0] ray;objArr[1] sharedMesh;objArr[2] matrix;objArr[3] null;bool isSuccess (bool)method.Invoke(null,objArr);hit (RaycastHit)objArr[3]; return isSuccess;
}2、锁定操作
在刷顶点色的时候我们肯定不希望鼠标还有原来的操作行为比如框选、位移旋转之类的操作所以需要对操作进行锁定 通过这个方法来锁定鼠标操作 HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); 然后记录一下当前使用的工具,并把当前工具置为None。这样就不会出现移动的坐标轴之类了记录当前使用的工具是为了退出编辑的时候可以还原。
LastTool Tools.current;
Tools.current Tool.None;3、绘制笔刷和顶点
在Scene视图里面绘制图形需要添加duringSceneGui 处理
SceneView.duringSceneGui OnSceneGUI;
void OnSceneGUI(SceneView sceneView)
{
}然后绘制的命令都写在OnSceneGUI里面。 这里主要用到了3个命令 绘制线条
Handles.DrawLine绘制圆盘
Handles.DrawWireDisc绘制点
Handles.DotHandleCap然后改变绘制颜色是用
Handles.color4、在不影响mesh本身的情况下修改颜色
如果只是为了改变mesh的顶点色那么直接修改Mesh.colors就可以了不过这个毕竟只是一个编辑的过程我们也有可能撤销修改甚至直接不保存这次的修改。所以不能直接修改Mesh.colors。 我这里是使用了一个数据类MeshEditData来记录了每个mesh上面的所有顶点颜色然后在刷顶点色的过程中只是改变这个MeshEditData对象里面的颜色。等确定保存的时候才把color数据写入mesh。
5、撤回操作
Unity本身是自带了Undo的操作的按道理只需要调用Undo相关的方法就可以实现撤回操作了。 不过不论是Undo.RecordObject还是Undo.RecordObjects都需要传入Object作为参数也就是Unity的对象。而我记录的是自定义对象并不是Object所以不能直接这么用。 于是可以这样操作 通过注册undoRedoPerformed 方法来自定义撤回的时候执行的方法 Undo.undoRedoPerformed this.OnUndo; 在每次笔刷开始刷之前也就是鼠标左键点下的时候记录一下当前所有网格的颜色值并存到一个数组里面。 然后在OnUndo方法里面检查回撤的数组如果有就把数组最后入栈的颜色值取出并赋值给当前的数据。 值得注意的有2点 1.undoRedoPerformed 方法不论是ctrlz还是ctrly都会执行的 2.undoRedoPerformed 方法是需要前面有操作才会记录堆栈如果我们一直在Scene视图刷颜色他只会记录一次操作所以也只能回退一次这里需要每次绘制完一笔之后也就是鼠标左键抬起的时候手动调用一下Undo.RegisterCompleteObjectUndo方法
三、工具源码
总共3个c#脚本
using System.Collections;
using System.Collections.Generic;using UnityEngine;
using UnityEditor;
using System.IO;
using System.Reflection;namespace azhao.tools.VertexColorPainer
{public enum BrushChannelType{ALL 0,RED 1,GREEN 2,BLUE 3,ALPHA 4}public enum SetColorMode{ADD 0,WEIGHT 1}public enum OperatorType{ADD 0,REDUCE 1}public class VertexColorPainerWin : EditorWindow{static private VertexColorPainerWin _instance;public static VertexColorPainerWin Instance{get{if (_instance null){_instance (VertexColorPainerWin)EditorWindow.GetWindow(typeof(VertexColorPainerWin));_instance.titleContent new GUIContent(顶点颜色刷);_instance.maxSize _instance.minSize new Vector2(600, 600);}return _instance;}}[MenuItem(Tools/顶点颜色刷)]static void ShowWin(){VertexColorPainerWin.Instance.Show();}#region 生命周期// Start is called before the first frame updatevoid Start(){}private void OnEnable(){SceneView.duringSceneGui OnSceneGUI;Undo.undoRedoPerformed - this.OnUndo;Undo.undoRedoPerformed this.OnUndo;}private void OnDisable(){SceneView.duringSceneGui - OnSceneGUI;Undo.undoRedoPerformed - this.OnUndo;Tools.current LastTool;}void OnDestroy(){SceneView.duringSceneGui - this.OnSceneGUI;Undo.undoRedoPerformed - this.OnUndo;}// Update is called once per framevoid Update(){}#endregionTool LastTool Tool.None;private bool isEditMode false;private ListGameObject meshObjList;ListMeshEditData meshEditList;private string val ;private float brushSize 0.5f;private float brushFalloff 1;private Color brushColor Color.white;private bool isShowPointColor false;private string[] channelSelectStr new string[] { 所有通道, R通道, G通道, B通道, A通道 };private int channelSelectIndex 0;private string[] showPointStr new string[] { 不显示, 笔刷范围显示, 全部显示 };private int showPointIndex 0;private string[] showColorType new string[] { 原色, 单色,黑白 };private int showColorIndex 0;string[] drawTypeStr new string[] { 颜色叠加, 权重模式 };int drawTypeIndex 0;string[] drawAddTypeStr new string[] { 增加, 减少 };int drawAddTypeIndex 0;private float brushSizeScale 0.01f;private float brushAlpha 1;private bool isPaint false;void OnGUI(){ShowHelp();ShowSelectobj();if(isEditMode){if(HasSelectObj() false){CleanMeshList();isEditMode false;}ShowObjInfo();ShowTitle();ShowCtrl();ShowContent();}}#region 说明private bool isShowHelp true;private void ShowHelp(){if(GUILayout.Button(来自阿赵的使用说明,GUILayout.Height(40))){isShowHelp !isShowHelp;}if(isShowHelp false){return;}GUILayout.Label(1、在场景中想编辑的模型点击开始编辑);GUILayout.Label(2、如果模型中的网格不可编辑会生成课编辑网格路径在Assets/meshes/);GUILayout.Label(3、根据情况选择刷所有通道颜色还是单个通道颜色);GUILayout.Label(4、可以选择叠加模式或者权重模式);GUILayout.Label(\t叠加模式是直接绘制指定颜色);GUILayout.Label(\t权重模式是保证RGBA通道加起来等于1);GUILayout.Label(5、绘制不合适可以按CtrlZ撤回);}#endregion#region 物体选择编辑private bool HasSelectObj(){if(meshEditList null||meshEditList.Count0){return false;}if(meshObjList null||meshObjList.Count0){return false;}for(int i 0;imeshObjList.Count;i){if(meshObjList[i]null){return false;}}return true;}private void ShowSelectobj(){ShowLine(编辑模型顶点色工具);if (isEditMode true){if (GUILayout.Button(保存编辑, GUILayout.Width(600), GUILayout.Height(40))){SaveMeshes(); }if (GUILayout.Button(退出编辑,GUILayout.Width(600),GUILayout.Height(40))){OnEditEnd();}}else{if (GUILayout.Button(开始编辑, GUILayout.Width(600), GUILayout.Height(40))){OnEditBegin();}}}private void OnEditEnd(){Tools.current LastTool;if (HasEditableMesh()){if(ShowSelectTips(是否保存网格?, 保存, 退出)){SaveMeshes();}isEditMode false;}}private bool HasEditableMesh(){if(meshEditList ! null meshEditList.Count0){return true;}return false;}private void OnEditBegin(){LastTool Tools.current;Tools.current Tool.None;meshObjList new ListGameObject();meshEditList new ListMeshEditData();GameObject[] gos Selection.gameObjects;if(gos!null){for(int i 0;igos.Length;i){Transform[] trs gos[i].GetComponentsInChildrenTransform();for(int j 0;jtrs.Length;j){if (trs[j].gameObject.activeSelf true){if (meshObjList.IndexOf(trs[j].gameObject) 0){meshObjList.Add(trs[j].gameObject);}}}}}if(meshObjList null||meshObjList.Count0){ShowTips(没有可以编辑的模型请用鼠标选中场景中的模型);return;}if(CheckMeshCanEdit()true){isEditMode true;}}private void CleanMeshList(){meshEditList null;}private bool CheckMeshCanEdit(int count 0){count;if(count3){return false;}if(meshObjList null){return false;}meshEditList new ListMeshEditData();for(int i 0;imeshObjList.Count;i){if(meshObjList[i].activeSelf false){continue;}MeshEditData data new MeshEditData(meshObjList[i]);if(data.mesh!null){meshEditList.Add(data);}}if(HasEditableMesh()false){
;CleanMeshList();ShowTips(选择的物体里面没有可以编辑的网格模型);return false;}bool hasOrigMesh false;if(meshEditList ! null meshEditList.Count0){for(int i 0;i meshEditList.Count;i){Mesh mesh meshEditList[i].mesh;string path AssetDatabase.GetAssetPath(mesh);if(path.EndsWith(.asset)false){hasOrigMesh true;break;}}}if(hasOrigMesh true){ if (ShowSelectTips(当前模型里面有不可以直接编辑的网格是否生成可编辑的网格?, 生成, 取消编辑)){bool successCreate CreateCopyMeshAsset();if(successCreate false){CleanMeshList();return false;}else{CleanMeshList();return CheckMeshCanEdit(count);}}else{CleanMeshList();return false;}}else{return true;}}private void SaveMeshes(){if (meshEditList ! null meshEditList.Count 0){for (int i 0; i meshEditList.Count; i){meshEditList[i].SaveMesh();}}AssetDatabase.SaveAssets();AssetDatabase.Refresh();}#endregion#region 笔刷操作编辑private void ShowObjInfo(){GUILayout.Label(当前编辑的对象:, GUILayout.Width(120));if(meshEditList ! null meshEditList.Count0){for(int i 0;i meshEditList.Count;i){EditorGUILayout.ObjectField(meshEditList[i].gameObject, typeof(Object), true, GUILayout.Width(200));}}}private void ShowCtrl(){GUILayout.BeginHorizontal();GUILayout.Label(是否显示顶点色, GUILayout.Width(120));//isShowPointColor EditorGUILayout.Toggle(isShowPointColor, GUILayout.Width(40));showPointIndex GUILayout.SelectionGrid(showPointIndex, showPointStr, 4, GUILayout.Width(500));GUILayout.EndHorizontal();if(showPointIndex0 channelSelectIndex0){GUILayout.BeginHorizontal();GUILayout.Label(显示颜色类型:, GUILayout.Width(120));showColorIndex GUILayout.SelectionGrid(showColorIndex, showColorType, 3, GUILayout.Width(300)); GUILayout.EndHorizontal();}GUILayout.BeginHorizontal();GUILayout.Label(半径:, GUILayout.Width(80));brushSize EditorGUILayout.Slider(brushSize, 0.1f, 2, GUILayout.Width(400));if(brushSize0.1f){brushSize 0.1f;}if(brushSize2){brushSize 10;}GUILayout.EndHorizontal();GUILayout.BeginHorizontal();GUILayout.Label(衰减:, GUILayout.Width(80));brushFalloff EditorGUILayout.Slider(brushFalloff, 0, 1, GUILayout.Width(200));if(brushFalloff0){brushFalloff 0;}if(brushFalloff1){brushFalloff 1;}GUILayout.EndHorizontal();GUILayout.BeginHorizontal();GUILayout.Label(强度:, GUILayout.Width(80));brushAlpha EditorGUILayout.Slider(brushAlpha, 0.1f, 1, GUILayout.Width(200));GUILayout.EndHorizontal();}private void ShowTitle(){channelSelectIndex GUILayout.SelectionGrid(channelSelectIndex, channelSelectStr, 5, GUILayout.Width(500));}private void ShowContent(){if(channelSelectIndex (int)BrushChannelType.ALL){ShowAllColorCtrl();}else{ShowOneChannelColorCtrl();}}private void ShowAllColorCtrl(){GUILayout.BeginHorizontal();GUILayout.Label(笔刷颜色:, GUILayout.Width(100));brushColor EditorGUILayout.ColorField(brushColor, GUILayout.Width(100));GUILayout.EndHorizontal();}private void ShowOneChannelColorCtrl(){GUILayout.BeginHorizontal();GUILayout.Label(绘制模式, GUILayout.Width(100));drawTypeIndex GUILayout.SelectionGrid(drawTypeIndex, drawTypeStr, 2, GUILayout.Width(200));GUILayout.EndHorizontal();GUILayout.BeginHorizontal();GUILayout.Label(颜色叠加, GUILayout.Width(100));drawAddTypeIndex GUILayout.SelectionGrid(drawAddTypeIndex, drawAddTypeStr, 2, GUILayout.Width(200));GUILayout.EndHorizontal();}#endregion#region 显示顶点色private void ShowPointColorFunc(){if(meshEditList ! null meshEditList.Count0){for (int i 0; i meshEditList.Count; i){ShowOneMeshPointColor(meshEditList[i]);}}}private void ShowPointColorFunc(Vector3 center,Vector3 normal){if (meshEditList ! null meshEditList.Count 0){for (int i 0; i meshEditList.Count; i){ShowOneMeshPointColor(meshEditList[i], center,normal);}}}private void ShowOneMeshPointColor(MeshEditData data){ShowOneMeshPointColor(data, Vector3.zero, Vector3.zero,false);}private void ShowOneMeshPointColor(MeshEditData data, Vector3 center,Vector3 normal,bool needCheckDistance true){Vector3[] verts data.mesh.vertices;float r (brushSize brushSize * brushFalloff);r r * r;//Debug.Log(mesh.vertices.Length , mesh.colors.Length);Handles.zTest UnityEngine.Rendering.CompareFunction.LessEqual;for (int j 0; j verts.Length; j){Vector3 pos data.transform.TransformPoint(verts[j]);if (needCheckDistancetrue){ float tempR (pos.x - center.x) * (pos.x - center.x) (pos.y - center.y) * (pos.y - center.y) (pos.z - center.z) * (pos.z - center.z);if (tempR r){continue;}}if (data.colors.Length j){if (channelSelectIndex (int)BrushChannelType.ALL||showColorIndex 0){Handles.color data.colors[j];}else{if (channelSelectIndex (int)BrushChannelType.RED){if (showColorIndex 1){Handles.color new Color(data.colors[j].r, 0, 0, 1);}else if (showColorIndex 2){Handles.color new Color(data.colors[j].r, data.colors[j].r, data.colors[j].r, 1);}}else if (channelSelectIndex (int)BrushChannelType.GREEN){if (showColorIndex 1){Handles.color new Color(0, data.colors[j].g, 0, 1);}else if (showColorIndex 2){Handles.color new Color(data.colors[j].g, data.colors[j].g, data.colors[j].g, 1);}}else if (channelSelectIndex (int)BrushChannelType.BLUE){if (showColorIndex 1){Handles.color new Color(0, 0, data.colors[j].b, 1);}else if (showColorIndex 2){Handles.color new Color(data.colors[j].b, data.colors[j].b, data.colors[j].b, 1);}}else if (channelSelectIndex (int)BrushChannelType.ALPHA){Handles.color new Color(data.colors[j].a, data.colors[j].a, data.colors[j].a, 1);}}}Handles.DotHandleCap(0, pos, Quaternion.identity, HandleUtility.GetHandleSize(pos) * 0.03f, EventType.Repaint);}}#endregion#region 绘制顶点色private void PaintPointColor(Vector3 center, Vector3 normal){if (meshEditList ! null meshEditList.Count 0){for (int i 0; i meshEditList.Count; i){PaintOneMeshPoint(meshEditList[i], center, normal);}}}private void PaintOneMeshPoint(MeshEditData data, Vector3 center, Vector3 normal){Vector3[] verts data.mesh.vertices;float r (brushSize brushSize * brushFalloff);r r * r;//Debug.Log(mesh.vertices.Length , mesh.colors.Length);Handles.zTest UnityEngine.Rendering.CompareFunction.LessEqual;for (int j 0; j verts.Length; j){Vector3 pos data.transform.TransformPoint(verts[j]);float tempR (pos.x - center.x) * (pos.x - center.x) (pos.y - center.y) * (pos.y - center.y) (pos.z - center.z) * (pos.z - center.z);if (tempR r){continue;}float falloff 1;if(brushFalloff0){falloff Vector3.Distance(pos, center) - brushSize / (brushSize brushSize * brushFalloff*0.1f);falloff 1 - falloff;if(falloff0){falloff 0;}if(falloff1){falloff 1;}}if(channelSelectIndex (int)BrushChannelType.ALL){data.DrawVertexColor(j, brushColor, falloff* brushAlpha * Time.deltaTime);}else{data.DrawVertexChannelColor(j, channelSelectIndex, drawTypeIndex, drawAddTypeIndex, falloff* brushAlpha * Time.deltaTime*0.1f);}}}#endregionvoid OnSceneGUI(SceneView sceneView){if (isEditMode false){return;}HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));if (meshObjList null){return;}if (HasEditableMesh() false){return;}Event e Event.current;if (e.isKey){//Debug.Log(e.keyCode);if (e.keyCode KeyCode.RightBracket){brushSize brushSizeScale;if (brushSize 2){brushSize 2;}}else if (e.keyCode KeyCode.LeftBracket){brushSize - brushSizeScale;if (brushSize 0.1f){brushSize 0.1f;}}else if (e.keyCode KeyCode.Minus){brushFalloff - 0.1f;if (brushFalloff 0){brushFalloff 0;}}else if (e.keyCode KeyCode.Equals){brushFalloff 0.1f;if (brushFalloff 1){brushFalloff 1;}}}if (e.rawType EventType.MouseDown e.button 0){AddToUndo();isPaint true;}if (e.rawType EventType.MouseUp e.button 0){isPaint false;}Vector3 mousePos e.mousePosition;Camera camera SceneView.currentDrawingSceneView.camera;float mult 1;
#if UNITY_5_4_OR_NEWERmult EditorGUIUtility.pixelsPerPoint;
#endifmousePos.y camera.pixelHeight - mousePos.y * mult;mousePos.x * mult;//Vector3 fakePoint mousePos;//fakePoint.z 20;//Vector3 point sceneView.camera.ScreenToWorldPoint(fakePoint);float minDis 99999;bool isHit false;Vector3 center Vector3.zero;Vector3 normal Vector3.zero;Ray ray camera.ScreenPointToRay(mousePos);float num 1000;if (meshEditList ! null meshEditList.Count 0){for (int i 0; i meshEditList.Count; i){Mesh sharedMesh meshEditList[i].mesh;RaycastHit hit;bool hasHit IntersectRayMesh(ray, sharedMesh, meshEditList[i].transform.localToWorldMatrix, out hit);if (hasHit false || hit.distance num){continue;}isHit true;if (hit.distance minDis){center hit.point;normal hit.normal;minDis hit.distance;}}}if (isHit true){Color tempColor;if (channelSelectIndex (int)BrushChannelType.RED){tempColor Color.red;}else if (channelSelectIndex (int)BrushChannelType.GREEN){tempColor Color.green;}else if (channelSelectIndex (int)BrushChannelType.BLUE){tempColor Color.blue;}else if (channelSelectIndex (int)BrushChannelType.ALPHA){tempColor Color.gray;}else{tempColor brushColor;}DrawBrush(tempColor, center, normal, brushSize, brushFalloff);if (showPointIndex 1){ShowPointColorFunc(center, normal);}if (isPaint){PaintPointColor(center, normal);}sceneView.Repaint();HandleUtility.Repaint();}if (showPointIndex 2){ShowPointColorFunc();}}#region 辅助方法private bool IntersectRayMesh(Ray ray,Mesh sharedMesh,Matrix4x4 matrix,out RaycastHit hit){System.Type type typeof(HandleUtility);System.Reflection.MethodInfo method type.GetMethod(IntersectRayMesh, (BindingFlags.Static | BindingFlags.NonPublic));RaycastHit tempHit new RaycastHit();object[] objArr new object[4];objArr[0] ray;objArr[1] sharedMesh;objArr[2] matrix;objArr[3] null;bool isSuccess (bool)method.Invoke(null,objArr);hit (RaycastHit)objArr[3]; return isSuccess;}private void DrawBrush(Color col, Vector3 center, Vector3 normal, float radius,float falloff){if(col.a0.5f){col.a 0.5f;}Handles.color col;Handles.DrawWireDisc(center,HandleUtility.GetHandleSize(center)* normal, radius); Handles.DrawLine(center, center radius * normal );if(falloff0){Handles.color col * 0.7f;Handles.DrawWireDisc(center, HandleUtility.GetHandleSize(center) * normal, (radius radius* falloff));}}private bool CreateCopyMeshAsset(){if(meshObjListnull){return false;}if(HasEditableMesh() false){return false;}string path Application.dataPath /meshes;if(Directory.Exists(path)false){Directory.CreateDirectory(path);AssetDatabase.Refresh();}bool hasError false;DictionaryMesh, Mesh dict new DictionaryMesh, Mesh();for(int i 0;imeshEditList.Count;i){Mesh mesh meshEditList[i].mesh;string meshPath AssetDatabase.GetAssetPath(mesh);if(meshPath.EndsWith(.asset)){continue;}if(dict.ContainsKey(mesh)){meshEditList[i].SetShareMesh(dict[mesh]);}else{Mesh newMesh CopyMesh(mesh);string savePath GetNewSavePath(mesh.name);AssetDatabase.CreateAsset(newMesh, savePath);AssetDatabase.Refresh();Mesh loadMesh (Mesh)AssetDatabase.LoadAssetAtPath(savePath, typeof(Mesh));dict.Add(mesh, loadMesh);meshEditList[i].SetShareMesh(loadMesh); }}if (hasError true){AssetDatabase.SaveAssets();AssetDatabase.Refresh();return false;}AssetDatabase.SaveAssets();AssetDatabase.Refresh();return true;}private string GetNewSavePath(string assetName){string savePath Assets/meshes/ assetName .asset;if(AssetDatabase.LoadAssetAtPath(savePath,typeof(Object))null){return savePath;}int i 1;while(true){i;savePath Assets/meshes/ assetNamei .asset;if (AssetDatabase.LoadAssetAtPath(savePath, typeof(Object)) null){return savePath;}}}private Mesh CopyMesh(Mesh mesh){Mesh newMesh new Mesh();newMesh.vertices mesh.vertices;newMesh.uv mesh.uv;newMesh.triangles mesh.triangles;newMesh.normals mesh.normals;if(mesh.colors.Length0){newMesh.colors new Color[mesh.vertices.Length];Color[] cols new Color[mesh.vertices.Length];for (int i 0;imesh.vertices.Length; i){cols[i] Color.black;}newMesh.SetColors(cols);}else{newMesh.colors mesh.colors;}return newMesh;}#endregion#region Undoprivate ListDrawColorUndoData undoList;private void AddToUndo(){if(meshEditList null||meshEditList.Count 0){return;}Undo.RegisterCompleteObjectUndo(this, paint color);if (undoList null){undoList new ListDrawColorUndoData();}DrawColorUndoData data new DrawColorUndoData(meshEditList);undoList.Add(data);}private void OnUndo(){if(undoList null||undoList.Count0){return;}DrawColorUndoData data undoList[undoList.Count - 1];undoList.RemoveAt(undoList.Count-1);if(meshEditList!nullmeshEditList.Count0){data.Undo(meshEditList);} }#endregion#region 其他选项private void ShowTips(string str){Debug.Log(str);EditorUtility.DisplayDialog(提示, str, 确定);}private void ShowErrorTips(string str){Debug.Log(str);EditorUtility.DisplayDialog(提示, str, 确定);throw new System.Exception(errorTips: str);}private bool ShowSelectTips(string str,string okStr 确定,string cancelStr 取消){return EditorUtility.DisplayDialog(提示, str, okStr,cancelStr);}private void ShowProgress(string title, string content, float rate){EditorUtility.DisplayProgressBar(title, content, rate);}private void HideProgress(){EditorUtility.ClearProgressBar();}private void ShowLine(string str , int w -1, int h 20){if(w0){w Mathf.FloorToInt(this.maxSize.x);}if (string.IsNullOrEmpty(str)){h 5;}GUILayout.Box(str, GUILayout.Width(w), GUILayout.Height(h));}private string SelectFolder(string str){return EditorUtility.OpenFolderPanel(选择文件夹, str, );}private string SelectFile(string str, string ex ){return EditorUtility.OpenFilePanel(选择文件, str, ex);}private void ShowTextArea(string str, int w 500, int h 60){ShowLine();GUILayout.Label(str, GUILayout.Width(w), GUILayout.Height(h));ShowLine();}#endregion}}using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace azhao.tools.VertexColorPainer
{public class MeshEditData{public Transform transform;public GameObject gameObject;private SkinnedMeshRenderer skinnedMeshRenderer;private MeshFilter meshFilter;public Mesh mesh;public Color[] colors;public MeshEditData(GameObject go){transform go.transform;gameObject go;skinnedMeshRenderer go.GetComponentSkinnedMeshRenderer();if (skinnedMeshRenderer ! null){mesh skinnedMeshRenderer.sharedMesh;}else{meshFilter go.GetComponentMeshFilter();if (meshFilter ! null){mesh meshFilter.sharedMesh;}}if (mesh ! null){InitMeshColor();}}public void SetShareMesh(Mesh m){mesh m;if(skinnedMeshRenderer!null){skinnedMeshRenderer.sharedMesh mesh;}if(meshFilter!null){meshFilter.sharedMesh mesh;}}private void InitMeshColor(){if (mesh null){return;}int vertCount mesh.vertexCount;colors new Color[vertCount];for (int i 0; i vertCount; i){if (mesh.colors ! null i mesh.colors.Length){colors[i] mesh.colors[i];}else{colors[i] Color.black;}}}public void DrawVertexColor(int index,Color col,float alpha){if(colors null||colors.Lengthindex){return;}Color newColor colors[index] * (1 - alpha) col * alpha;colors[index] newColor;
; }public void DrawVertexChannelColor(int index,int channel,int mode,int operatorType,float alpha){if (colors null || colors.Length index){return;}float val 0;if(channel (int)BrushChannelType.RED){val colors[index].r;}else if(channel (int)BrushChannelType.GREEN){val colors[index].g;}else if (channel (int)BrushChannelType.BLUE){val colors[index].b;}else if (channel (int)BrushChannelType.ALPHA){val colors[index].a;}if(operatorType (int)OperatorType.ADD){val alpha;if(val1){val 1;}}else{val - alpha;if(val0){val 0;}}if (channel (int)BrushChannelType.RED){if(mode (int)SetColorMode.WEIGHT){float leftVal 1 - val;float totalVal colors[index].g colors[index].b colors[index].a;if(totalVal0){colors[index].g colors[index].b colors[index].a leftVal / 3;}else{colors[index].g leftVal * colors[index].g / totalVal;colors[index].b leftVal * colors[index].b / totalVal;colors[index].a leftVal * colors[index].a / totalVal;}}colors[index].r val;}else if (channel (int)BrushChannelType.GREEN){if (mode (int)SetColorMode.WEIGHT){float leftVal 1 - val;float totalVal colors[index].r colors[index].b colors[index].a;if (totalVal 0){colors[index].r colors[index].b colors[index].a leftVal / 3;}else{colors[index].r leftVal * colors[index].r / totalVal;colors[index].b leftVal * colors[index].b / totalVal;colors[index].a leftVal * colors[index].a / totalVal;}}colors[index].g val;}else if (channel (int)BrushChannelType.BLUE){if (mode (int)SetColorMode.WEIGHT){float leftVal 1 - val;float totalVal colors[index].r colors[index].g colors[index].a;if (totalVal 0){colors[index].r colors[index].g colors[index].a leftVal / 3;}else{colors[index].r leftVal * colors[index].r / totalVal;colors[index].g leftVal * colors[index].g / totalVal;colors[index].a leftVal * colors[index].a / totalVal;}}colors[index].b val;}else if (channel (int)BrushChannelType.ALPHA){if (mode (int)SetColorMode.WEIGHT){float leftVal 1 - val;float totalVal colors[index].r colors[index].g colors[index].b;if (totalVal 0){colors[index].r colors[index].g colors[index].b leftVal / 3;}else{colors[index].r leftVal * colors[index].r / totalVal;colors[index].g leftVal * colors[index].g / totalVal;colors[index].b leftVal * colors[index].b / totalVal;}}colors[index].a val;}}public void SaveMesh(){if(meshnull){return;}mesh.colors colors; }}
}using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace azhao.tools.VertexColorPainer
{public class DrawColorUndoData{private ListColor[] colors;public DrawColorUndoData(ListMeshEditData data){colors new ListColor[]();for(int i 0;idata.Count;i){colors.Add((Color[])data[i].colors.Clone());}}public void Undo(ListMeshEditData data){if(colors null||colors.Count!data.Count){Debug.Log(xxxUndo return);return;}for(int i 0;idata.Count;i){data[i].colors colors[i];}}
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/932157.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!