public override void OnInspectorGUI() { if (Selection.activeGameObject) { MC = (QT_ModifyColor)target; QT_ModifyColorSample.GMC = MC; //do a bunch of checks to make sure it's a mesh/skinned mesh, prefab,and has a collider. if (RunInitialSetup(MC)) { if (isSetup == false) { //prep the data, put the working temp mesh in the mesh slots so people can see it in the sceneview. if (MC.isMesh) { MC.mesh = MC.sourceMF.sharedMesh; MC.tempMesh = DuplicateMesh(MC.mesh); MC.tempMesh.name = "TEMP ModifyColor Mesh!"; SetupInitialColors(MC); MC.sourceMF.sharedMesh = MC.tempMesh; EditorUtility.SetDirty(MC.sourceMF); } else if (MC.isSM) { MC.mesh = MC.sourceSMR.sharedMesh; MC.tempMesh = DuplicateMesh(MC.mesh); MC.tempMesh.name = "TEMP ModifyColor Mesh!"; SetupInitialColors(MC); MC.sourceSMR.sharedMesh = MC.tempMesh; EditorUtility.SetDirty(MC.sourceSMR); } isSetup = true; } // if (MC.isPWMesh) // MC.pwMeshOverride = EditorGUILayout.Toggle("New Channel Mapping", MC.pwMeshOverride); hideWireframe = EditorGUILayout.Toggle("Hide Wireframe", hideWireframe); EditorUtility.SetSelectedWireframeHidden(MC.gameObject.GetComponent <Renderer>(), hideWireframe); EditorGUILayout.Space(); //found a PW mesh if (MC.isPWMesh && MC.pwMeshOverride == false) { EditorGUILayout.HelpBox("PolyWorld Mesh Detected. Using preexisting channel mapping.", MessageType.Info); } MC.globalAlpha = EditorGUILayout.Slider("Global Alpha: ", MC.globalAlpha, 0f, 1f); //setup the UI for each color channel. for (int x = 0; x < MC.AllChannels.Length; x++) { if (QT_ModifyColorSample.isSampling && QT_ModifyColorSample.channelIndex == x) { GUI.color += new Color(0f, -1f, -1f); status = "Click on a Triangle in Scene View"; } else if (MC.AllChannels[x].targetVertices.Count == 0 || MC.AllChannels[x].targetVertices == null)// && MC.isPWMesh == false || MC.AllChannels[x].targetVertices.Count == 0 && MC.pwMeshOverride == true) { GUI.color += new Color(-.5f, 0.5f, -.5f); status = "Channel Clear"; } else { GUI.color += new Color(+.5f, 1f, -.5f); status = "Channel in Use"; } EditorGUILayout.BeginHorizontal(); GUILayout.Label("Channel " + (x + 1) + ": " + status); GUI.color = new Color(1f, 1f, 1f); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); MC.tempColors[x] = EditorGUILayout.ColorField("Assign Color: ", MC.tempColors[x]); //if it's not a polyworld mesh, or the override is enabled, let the user sample a color right on the mesh to override. if (!MC.isPWMesh || MC.pwMeshOverride) { if (GUILayout.Button("Sample Color on Mesh")) { if (MC.GetComponent <Collider>().enabled) { //ghetto, I know. Love to know how else to do this. QT_ModifyColorSample.isSampling = !QT_ModifyColorSample.isSampling; QT_ModifyColorSample.channelIndex = x; } else { EditorUtility.DisplayDialog("Enable Collider", "Please enable the collider to sample color data from the mesh.", "OK"); } } } EditorGUILayout.EndHorizontal(); MC.tempSmoothness[x] = EditorGUILayout.Slider("Smoothness", MC.tempSmoothness[x], 0, 1); MC.tempMetallic[x] = EditorGUILayout.Slider("Metallic", MC.tempMetallic[x], 0, 1); MC.AllChannels[x].Color = new float[4] { MC.tempColors[x].r, MC.tempColors[x].g, MC.tempColors[x].b, MC.tempColors[x].a }; MC.AllChannels[x].Smoothness = MC.tempSmoothness[x]; MC.AllChannels[x].Metallic = MC.tempMetallic[x]; //Non Polyworld meshes, or PW meshes with the override, get to sample then tweak the hue/brightness range of the overridden color. if (!MC.isPWMesh || MC.pwMeshOverride) { MC.AllChannels[x].hueRange = EditorGUILayout.Slider("Hue Range", MC.AllChannels[x].hueRange, 0, 1); MC.AllChannels[x].satRange = EditorGUILayout.Slider("Saturation Range", MC.AllChannels[x].satRange, 0, 1); MC.AllChannels[x].valRange = EditorGUILayout.Slider("Brightness Range", MC.AllChannels[x].valRange, 0, 1); UpdateTargetVertices(MC, MC.AllChannels[x].sampledColor, x); EditorGUILayout.Space(); } EditorGUILayout.Space(); } //keep the previous value range. Good for surface variety. MC.preserveShading = EditorGUILayout.Toggle("Preserve Shading", MC.preserveShading); if (MC.preserveShading) { MC.Contrast = EditorGUILayout.Slider("Fade:", MC.Contrast, 0f, 1f); MC.ContrastClamp1 = EditorGUILayout.Slider("Shadows:", MC.ContrastClamp1, 0f, 1f); MC.ContrastClamp2 = EditorGUILayout.Slider("Highlights:", MC.ContrastClamp2, 0f, 1f); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Load Palette")) { LoadPalette(MC); } if (GUILayout.Button("Save Palette")) { SavePalette(MC); } //apply debug colors to easily see how they are applied. if (GUILayout.Button("Use Debug Colors")) { MC.tempColors[0] = Color.red; MC.tempColors[1] = Color.green; MC.tempColors[2] = Color.blue; MC.tempColors[3] = Color.yellow; MC.tempColors[4] = Color.magenta; MC.tempColors[5] = Color.white; } EditorGUILayout.EndHorizontal(); //clear all data. if (GUILayout.Button("Reset Mesh")) { QT_ModifyColorSample.isSampling = false; for (int p = 0; p < MC.AllChannels.Length; p++) { //if (!MC.isPWMesh || MC.pwMeshOverride) MC.AllChannels[p].targetVertices.Clear(); MC.AllChannels[p].sampledColor = new Color(1, 0, 1, 0.123f); MC.AllChannels[p].hueRange = .5f; MC.AllChannels[p].valRange = .25f; MC.isPWMesh = false; } isSetup = false; } EditorGUILayout.Space(); //update the mesh collider on the new game object. MC.updateMeshCollider = EditorGUILayout.Toggle("Update Mesh Collider", MC.updateMeshCollider); //replace the current prefab with the new gameobject with the new colored mesh. MC.Replace = EditorGUILayout.Toggle("Overwrite Prefab", MC.Replace); //if we don't replace the prefab, create a new one. if (!MC.Replace) { MC.newPrefabName = EditorGUILayout.TextField("New Prefab Name:", MC.newPrefabName); if (MC.newPrefabName.Equals(MC.gameObject.transform.root.gameObject.name)) { EditorGUILayout.HelpBox("New Prefab Name is the same as the current root prefab name. Please providea unique name for the new gameobject.", MessageType.Warning); } } //else MC.meshFileName = EditorGUILayout.TextField("Mesh Filename:", MC.meshFileName); //if the original value range is empty, setup them up and normalize. if (MC.originalValues != null) { MC.newValues = new float[MC.tempMesh.colors32.Length]; MC.newShading = new float[MC.tempMesh.colors32.Length]; for (int x = 0; x < MC.newValues.Length; x++) { MC.newValues[x] = MC.originalValues[x]; MC.newShading[x] = MC.originalValues[x]; } MC.newValues = MC.RemapFloats(MC.originalValues, MC.Highlights, MC.Shadows); MC.newShading = MC.RemapFloats(MC.originalValues, 0f, 1f); for (int p = 0; p < MC.newShading.Length; p++) { MC.newShading[p] = Mathf.Clamp(MC.newShading[p], MC.ContrastClamp1, MC.ContrastClamp2); MC.newShading[p] += MC.Contrast; MC.newShading[p] = Mathf.Clamp01(MC.newShading[p]); } //copy the originalvcs into the newcolors array to get overwritten by even newer colors. Color[] newColors = new Color[MC.originalVCs.Length]; Vector2[] newUV4s = new Vector2[MC.originalVCs.Length]; for (int b = 0; b < newColors.Length; b++) { newColors[b] = MC.originalVCs[b]; } //in every channel, go through every target vertex and apply the color //we go in reverse order so the colors are layered accordingly. for (int c = MC.AllChannels.Length - 1; c >= 0; c--) { for (int z = 0; z < MC.AllChannels[c].targetVertices.Count; z++) { int vertIndex = MC.AllChannels[c].targetVertices[z]; //lerp between the allchannel color and newcolors via alpha of the allchannels //allchannels corresponds to the channels in the inspector and its data float newR = Mathf.Lerp(newColors[vertIndex].r, MC.AllChannels[c].Color[0], MC.AllChannels[c].Color[3] * MC.globalAlpha); float newG = Mathf.Lerp(newColors[vertIndex].g, MC.AllChannels[c].Color[1], MC.AllChannels[c].Color[3] * MC.globalAlpha); float newB = Mathf.Lerp(newColors[vertIndex].b, MC.AllChannels[c].Color[2], MC.AllChannels[c].Color[3] * MC.globalAlpha); float channelAlpha = SetChannelVertexAlpha(c); //add the correct alpha color value per channel so it becomes a PW mesh newColors[vertIndex] = new Color(newR, newG, newB); //now to a global fade if (MC.preserveShading) { newColors[vertIndex] *= MC.newShading[vertIndex]; } newColors[vertIndex].a = channelAlpha; newUV4s[vertIndex].x = MC.AllChannels[c].Smoothness; newUV4s[vertIndex].y = MC.AllChannels[c].Metallic; } } //assign the new color choices. MC.AssignVCs(newColors); MC.AssignUV4s(newUV4s); } if (GUILayout.Button("Save Changes to Disk")) { //if we input bad stuff if (MC.Replace == false && MC.newPrefabName.Equals(MC.gameObject.transform.root.gameObject.name)) { EditorUtility.DisplayDialog("Bad Prefab Name", "You have chosen a new prefab name that is the same as the old one. Please give a unique name to the new prefab.", "OK"); } else { //begin to write all the new data. WriteData(); //delete the modifycolor component on the active game object since we don't need it anymore. DestroyImmediate(activeGO.GetComponent <QT_ModifyColor>()); } } } if (GUILayout.Button("Help")) { Application.OpenURL("http://qt-ent.com/PolyWorld/scripts/"); } } }
//checks to see if it's a mesh and prefab and has a collider. private bool RunInitialSetup(QT_ModifyColor MC) { bool pass=true; activeGO = Selection.activeGameObject; activeRootGO = Selection.activeGameObject.transform.root.gameObject; if (PrefabUtility.GetPrefabType(activeRootGO) != PrefabType.PrefabInstance) { EditorGUILayout.HelpBox(MC.gameObject.name + " is not a Prefab. Please convert this gameobject hierarchy to a prefab before using the Modify Color script.", MessageType.Warning); pass = false; return pass; } else pass = true; MC.sourceMF = activeGO.GetComponent<MeshFilter>(); if (MC.sourceMF) MC.isMesh = true; MC.sourceSMR = activeGO.GetComponent<SkinnedMeshRenderer>(); if (MC.sourceSMR) MC.isSM = true; if (!MC.isMesh && !MC.isSM) { EditorGUILayout.HelpBox(MC.gameObject.name + " does not contain a mesh. Modify Color requires a gameobject with a Meshfilter or SkinnedMeshRenderer component and a mesh.", MessageType.Warning); pass = false; return pass; } else pass = true; if (!MC.GetComponent<MeshCollider>()) { EditorGUILayout.HelpBox("This GameObject temporarily requires a mesh collider to accurately specify color changes.", MessageType.Warning); pass = false; return pass; } else { MC.hasCollider = true; pass = true; } if (MC.GetComponent<MeshCollider>().sharedMesh == null) { EditorGUILayout.HelpBox("The MeshCollider contains no reference to a mesh. Provide one to continue.", MessageType.Warning); pass = false; return pass; } else pass = true; /* if (pass) { GOHierarchy = new List<Transform>(); //disable the other children because it messes with the modifycolor script. CollectGOs(activeRootGO); foreach (Transform child in GOHierarchy) { if (!child.gameObject.name.Equals(activeGO.name) || child.gameObject.activeInHierarchy == true) { if (!child.GetComponent<MeshFilter>() || !child.GetComponent<SkinnedMeshRenderer>()) GOHierarchy.Remove(child); else child.gameObject.SetActive(false); } } }*/ return pass; }
//checks to see if it's a mesh and prefab and has a collider. private bool RunInitialSetup(QT_ModifyColor MC) { bool pass = true; activeGO = Selection.activeGameObject; activeRootGO = Selection.activeGameObject.transform.root.gameObject; if (PrefabUtility.GetPrefabType(activeRootGO) != PrefabType.PrefabInstance) { EditorGUILayout.HelpBox(MC.gameObject.name + " is not a Prefab. Please convert this gameobject hierarchy to a prefab before using the Modify Color script.", MessageType.Warning); pass = false; return(pass); } else { pass = true; } MC.sourceMF = activeGO.GetComponent <MeshFilter>(); if (MC.sourceMF) { MC.isMesh = true; } MC.sourceSMR = activeGO.GetComponent <SkinnedMeshRenderer>(); if (MC.sourceSMR) { MC.isSM = true; } if (!MC.isMesh && !MC.isSM) { EditorGUILayout.HelpBox(MC.gameObject.name + " does not contain a mesh. Modify Color requires a gameobject with a Meshfilter or SkinnedMeshRenderer component and a mesh.", MessageType.Warning); pass = false; return(pass); } else { pass = true; } if (!MC.GetComponent <MeshCollider>()) { EditorGUILayout.HelpBox("This GameObject temporarily requires a mesh collider to accurately specify color changes.", MessageType.Warning); pass = false; return(pass); } else { MC.hasCollider = true; pass = true; } if (MC.GetComponent <MeshCollider>().sharedMesh == null) { EditorGUILayout.HelpBox("The MeshCollider contains no reference to a mesh. Provide one to continue.", MessageType.Warning); pass = false; return(pass); } else { pass = true; } /* * if (pass) * { * GOHierarchy = new List<Transform>(); * //disable the other children because it messes with the modifycolor script. * CollectGOs(activeRootGO); * foreach (Transform child in GOHierarchy) * { * if (!child.gameObject.name.Equals(activeGO.name) || child.gameObject.activeInHierarchy == true) * { * * if (!child.GetComponent<MeshFilter>() || !child.GetComponent<SkinnedMeshRenderer>()) * GOHierarchy.Remove(child); * else * child.gameObject.SetActive(false); * } * * } * * * * }*/ return(pass); }
public override void OnInspectorGUI() { if (Selection.activeGameObject) { MC = (QT_ModifyColor)target; QT_ModifyColorSample.GMC = MC; //do a bunch of checks to make sure it's a mesh/skinned mesh, prefab,and has a collider. if (RunInitialSetup(MC)) { if (isSetup == false) { //prep the data, put the working temp mesh in the mesh slots so people can see it in the sceneview. if (MC.isMesh) { MC.mesh = MC.sourceMF.sharedMesh; MC.tempMesh = DuplicateMesh(MC.mesh); MC.tempMesh.name = "TEMP ModifyColor Mesh!"; SetupInitialColors(MC); MC.sourceMF.sharedMesh = MC.tempMesh; EditorUtility.SetDirty(MC.sourceMF); } else if (MC.isSM) { MC.mesh = MC.sourceSMR.sharedMesh; MC.tempMesh = DuplicateMesh(MC.mesh); MC.tempMesh.name = "TEMP ModifyColor Mesh!"; SetupInitialColors(MC); MC.sourceSMR.sharedMesh = MC.tempMesh; EditorUtility.SetDirty(MC.sourceSMR); } isSetup = true; } // if (MC.isPWMesh) // MC.pwMeshOverride = EditorGUILayout.Toggle("New Channel Mapping", MC.pwMeshOverride); hideWireframe = EditorGUILayout.Toggle("Hide Wireframe", hideWireframe); EditorUtility.SetSelectedWireframeHidden(MC.gameObject.GetComponent<Renderer>(), hideWireframe); EditorGUILayout.Space(); //found a PW mesh if (MC.isPWMesh && MC.pwMeshOverride == false) EditorGUILayout.HelpBox("PolyWorld Mesh Detected. Using preexisting channel mapping.", MessageType.Info); MC.globalAlpha = EditorGUILayout.Slider("Global Alpha: ", MC.globalAlpha, 0f, 1f); //setup the UI for each color channel. for (int x = 0; x < MC.AllChannels.Length; x++) { if (QT_ModifyColorSample.isSampling && QT_ModifyColorSample.channelIndex == x) { GUI.color += new Color(0f, -1f, -1f); status = "Click on a Triangle in Scene View"; } else if (MC.AllChannels[x].targetVertices.Count == 0 || MC.AllChannels[x].targetVertices == null)// && MC.isPWMesh == false || MC.AllChannels[x].targetVertices.Count == 0 && MC.pwMeshOverride == true) { GUI.color += new Color(-.5f, 0.5f, -.5f); status = "Channel Clear"; } else { GUI.color += new Color(+.5f, 1f, -.5f); status = "Channel in Use"; } EditorGUILayout.BeginHorizontal(); GUILayout.Label("Channel " + (x + 1) + ": " + status); GUI.color = new Color(1f, 1f, 1f); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); MC.tempColors[x] = EditorGUILayout.ColorField("Assign Color: ", MC.tempColors[x]); //if it's not a polyworld mesh, or the override is enabled, let the user sample a color right on the mesh to override. if (!MC.isPWMesh || MC.pwMeshOverride) { if (GUILayout.Button("Sample Color on Mesh")) { if (MC.GetComponent<Collider>().enabled) { //ghetto, I know. Love to know how else to do this. QT_ModifyColorSample.isSampling = !QT_ModifyColorSample.isSampling; QT_ModifyColorSample.channelIndex = x; } else EditorUtility.DisplayDialog("Enable Collider", "Please enable the collider to sample color data from the mesh.", "OK"); } } EditorGUILayout.EndHorizontal(); MC.AllChannels[x].Color = new float[4] { MC.tempColors[x].r, MC.tempColors[x].g, MC.tempColors[x].b, MC.tempColors[x].a }; //Non Polyworld meshes, or PW meshes with the override, get to sample then tweak the hue/brightness range of the overridden color. if (!MC.isPWMesh || MC.pwMeshOverride) { MC.AllChannels[x].hueRange = EditorGUILayout.Slider("Hue Range", MC.AllChannels[x].hueRange, 0, 1); MC.AllChannels[x].satRange = EditorGUILayout.Slider("Saturation Range", MC.AllChannels[x].satRange, 0, 1); MC.AllChannels[x].valRange = EditorGUILayout.Slider("Brightness Range", MC.AllChannels[x].valRange, 0, 1); UpdateTargetVertices(MC, MC.AllChannels[x].sampledColor, x); EditorGUILayout.Space(); } EditorGUILayout.Space(); } //keep the previous value range. Good for surface variety. MC.preserveShading = EditorGUILayout.Toggle("Preserve Shading", MC.preserveShading); if (MC.preserveShading) { MC.Contrast = EditorGUILayout.Slider("Fade:", MC.Contrast, 0f, 1f); MC.ContrastClamp1 = EditorGUILayout.Slider("Shadows:", MC.ContrastClamp1, 0f, 1f); MC.ContrastClamp2 = EditorGUILayout.Slider("Highlights:", MC.ContrastClamp2, 0f, 1f); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Load Palette")) LoadPalette(MC); if (GUILayout.Button("Save Palette")) SavePalette(MC); //apply debug colors to easily see how they are applied. if (GUILayout.Button("Use Debug Colors")) { MC.tempColors[0] = Color.red; MC.tempColors[1] = Color.green; MC.tempColors[2] = Color.blue; MC.tempColors[3] = Color.yellow; MC.tempColors[4] = Color.magenta; MC.tempColors[5] = Color.white; } EditorGUILayout.EndHorizontal(); //clear all data. if (GUILayout.Button("Reset Mesh")) { QT_ModifyColorSample.isSampling = false; for (int p = 0; p < MC.AllChannels.Length; p++) { //if (!MC.isPWMesh || MC.pwMeshOverride) MC.AllChannels[p].targetVertices.Clear(); MC.AllChannels[p].sampledColor = new Color(1, 0, 1, 0.123f); MC.AllChannels[p].hueRange = .5f; MC.AllChannels[p].valRange = .25f; MC.isPWMesh = false; } isSetup = false; } EditorGUILayout.Space(); //update the mesh collider on the new game object. MC.updateMeshCollider = EditorGUILayout.Toggle("Update Mesh Collider", MC.updateMeshCollider); //replace the current prefab with the new gameobject with the new colored mesh. MC.Replace = EditorGUILayout.Toggle("Overwrite Prefab", MC.Replace); //if we don't replace the prefab, create a new one. if (!MC.Replace) { MC.newPrefabName = EditorGUILayout.TextField("New Prefab Name:", MC.newPrefabName); if (MC.newPrefabName.Equals(MC.gameObject.transform.root.gameObject.name)) EditorGUILayout.HelpBox("New Prefab Name is the same as the current root prefab name. Please providea unique name for the new gameobject.", MessageType.Warning); } //else MC.meshFileName = EditorGUILayout.TextField("Mesh Filename:", MC.meshFileName); //if the original value range is empty, setup them up and normalize. if (MC.originalValues != null) { MC.newValues = new float[MC.tempMesh.colors32.Length]; MC.newShading = new float[MC.tempMesh.colors32.Length]; for (int x = 0; x < MC.newValues.Length; x++) { MC.newValues[x] = MC.originalValues[x]; MC.newShading[x] = MC.originalValues[x]; } MC.newValues = MC.RemapFloats(MC.originalValues, MC.Highlights, MC.Shadows); MC.newShading = MC.RemapFloats(MC.originalValues, 0f, 1f); for (int p = 0; p < MC.newShading.Length; p++) { MC.newShading[p] = Mathf.Clamp(MC.newShading[p], MC.ContrastClamp1, MC.ContrastClamp2); MC.newShading[p] += MC.Contrast; MC.newShading[p] = Mathf.Clamp01(MC.newShading[p]); } //copy the originalvcs into the newcolors array to get overwritten by even newer colors. Color[] newColors = new Color[MC.originalVCs.Length]; for (int b = 0; b < newColors.Length; b++) newColors[b] = MC.originalVCs[b]; //in every channel, go through every target vertex and apply the color //we go in reverse order so the colors are layered accordingly. for (int c=MC.AllChannels.Length-1;c>=0;c--)//int c = 0; c < MC.AllChannels.Length; c++) { for (int z = 0; z < MC.AllChannels[c].targetVertices.Count; z++) { int vertIndex = MC.AllChannels[c].targetVertices[z]; //lerp between the allchannel color and newcolors via alpha of the allchannels float newR = Mathf.Lerp(newColors[vertIndex].r, MC.AllChannels[c].Color[0], MC.AllChannels[c].Color[3] * MC.globalAlpha); float newG = Mathf.Lerp(newColors[vertIndex].g, MC.AllChannels[c].Color[1], MC.AllChannels[c].Color[3] * MC.globalAlpha); float newB = Mathf.Lerp(newColors[vertIndex].b, MC.AllChannels[c].Color[2], MC.AllChannels[c].Color[3] * MC.globalAlpha); newColors[vertIndex] = new Color(newR, newG, newB); //now to a global fade if (MC.preserveShading) newColors[vertIndex] *= MC.newShading[vertIndex]; } } //assign the new color choices. MC.AssignVCs(newColors); } if (GUILayout.Button("Save Changes to Disk")) { //if we input bad stuff if (MC.Replace == false && MC.newPrefabName.Equals(MC.gameObject.transform.root.gameObject.name)) EditorUtility.DisplayDialog("Bad Prefab Name", "You have chosen a new prefab name that is the same as the old one. Please give a unique name to the new prefab.", "OK"); else { //begin to write all the new data. WriteData(); //delete the modifycolor component on the active game object since we don't need it anymore. DestroyImmediate(activeGO.GetComponent<QT_ModifyColor>()); } } } if (GUILayout.Button("Help")) { Application.OpenURL("http://qt-ent.com/PolyWorld/scripts/"); } } }