Created
February 6, 2018 04:13
-
-
Save levilansing/9bbbc7985c7c4896426f125526af7fe4 to your computer and use it in GitHub Desktop.
Unity3d Editor script to put pivot point in ProBuilder objects back on the mesh after manipulating the faces/edges/verts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Fix ProBuilder Pivot | |
* An action to move the pivot back to the mesh in cases where you've | |
* manipulated the edges/faces of a mesh and left the pivot far behind | |
* Author: Levi Lansing (https://github.com/levilansing) | |
* Feb 2018 | |
*/ | |
using UnityEngine; | |
using UnityEditor; | |
using ProBuilder2.Common; | |
using ProBuilder2.EditorCommon; | |
namespace Zephlabs.Actions | |
{ | |
/** | |
* This class is responsible for loading the pb_MenuAction into the toolbar and menu. | |
*/ | |
[InitializeOnLoad] | |
static class RegisterCustomAction { | |
/** | |
* Static initializer is called when Unity loads the assembly. | |
*/ | |
static RegisterCustomAction() | |
{ | |
// This registers a new MakeFacesDoubleSided menu action with the toolbar. | |
pb_EditorToolbarLoader.RegisterMenuItem(InitCustomAction); | |
} | |
/** | |
* Helper function to load a new menu action object. | |
*/ | |
static pb_MenuAction InitCustomAction() | |
{ | |
return new FixProBuilderPivot(); | |
} | |
/** | |
* Usually you'll want to add a menu item entry for your action. | |
* https://docs.unity3d.com/ScriptReference/MenuItem.html | |
*/ | |
[MenuItem("Tools/ProBuilder/Fix Pivot %#&F", true)] | |
static bool MenuVerifyDoSomethingWithPbObject() | |
{ | |
// Using pb_EditorToolbarLoader.GetInstance keeps MakeFacesDoubleSided as a singleton. | |
FixProBuilderPivot instance = pb_EditorToolbarLoader.GetInstance<FixProBuilderPivot>(); | |
return instance != null && instance.IsEnabled(); | |
} | |
[MenuItem("Tools/ProBuilder/Fix Pivot %#&F", false, pb_Constant.MENU_GEOMETRY + 3)] | |
static void MenuDoDoSomethingWithPbObject() | |
{ | |
FixProBuilderPivot instance = pb_EditorToolbarLoader.GetInstance<FixProBuilderPivot>(); | |
if(instance != null) | |
pb_EditorUtility.ShowNotification(instance.DoAction().notification); | |
} | |
} | |
/** | |
* This is the actual action that will be executed. | |
*/ | |
public class FixProBuilderPivot : pb_MenuAction | |
{ | |
public override pb_ToolbarGroup group { get { return pb_ToolbarGroup.Geometry; } } | |
public override Texture2D icon { get { return null; } } | |
public override pb_TooltipContent tooltip { get { return _tooltip; } } | |
/** | |
* What to show in the hover tooltip window. pb_TooltipContent is similar to GUIContent, with the exception that it also | |
* includes an optional params[] char list in the constructor to define shortcut keys (ex, CMD_CONTROL, K). | |
*/ | |
static readonly pb_TooltipContent _tooltip = new pb_TooltipContent | |
( | |
"Fix Pivot", | |
"Moves the pivot to a vertex on the edge of the mesh." | |
); | |
/** | |
* Determines if the action should be enabled or grayed out. | |
*/ | |
public override bool IsEnabled() | |
{ | |
// `selection` is a helper property on pb_MenuAction that returns a pb_Object[] array from the current selection. | |
return pb_Editor.instance != null && selection != null && selection.Length > 0; | |
} | |
/** | |
* Determines if the action should be loaded in the menu (ex, face actions shouldn't be shown when in vertex editing mode). | |
*/ | |
public override bool IsHidden() | |
{ | |
return pb_Editor.instance == null || pb_Editor.instance.editLevel != EditLevel.Geometry; | |
} | |
/** | |
* Do the thing. Return a pb_ActionResult indicating the success/failure of action. | |
*/ | |
public override pb_ActionResult DoAction() | |
{ | |
pbUndo.RecordObjects(selection, "Fix Pivot"); | |
foreach(pb_Object pb in selection) | |
{ | |
// find bottom-most, left-most, nearest vertex | |
var index = 0; | |
var mf = pb.GetComponent<MeshFilter>(); | |
if (mf != null) { | |
var mesh = mf.sharedMesh; | |
if (mesh) { | |
var minY = mesh.vertices[0].y; | |
for (int i = 0; i < mesh.vertices.Length; i++) { | |
var vert = mesh.vertices[i]; | |
if (minY > vert.y) { | |
minY= vert.y; | |
index = i; | |
} | |
} | |
var minX = mesh.vertices[index].x; | |
for (int i = 0; i < mesh.vertices.Length; i++) { | |
var vert = mesh.vertices[i]; | |
if (Mathf.Approximately(vert.y, minY) && minX > vert.x) { | |
minX = vert.x; | |
index = i; | |
} | |
} | |
var minZ = mesh.vertices[index].z; | |
for (int i = 0; i < mesh.vertices.Length; i++) { | |
var vert = mesh.vertices[i]; | |
if (Mathf.Approximately(vert.y, minY) && Mathf.Approximately(vert.x, minX) && minZ > vert.z) { | |
minZ = vert.z; | |
index = i; | |
} | |
} | |
} | |
} | |
pb_EditorUtility.SetPivotAndSnapWithPref(pb, new int[] { index }); | |
pb.ToMesh(); | |
pb.Refresh(); | |
pb.Optimize(); | |
} | |
// This is necessary! Otherwise the pb_Editor will be working with caches from | |
// outdated meshes and throw errors. | |
pb_Editor.Refresh(); | |
return new pb_ActionResult(Status.Success, "Fix Pivot"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment