top of page

Over the course of my last 10 weeks at SCAD, I created a plugin for Unreal Engine that allows a user to manipulate the Pivot Point of their static mesh from within the editor. The plugin uses both Blueprints and C++ to function. I noticed how much of a hassle it was to have control over a mesh's pivot point once it was already imported into the engine, so I got the idea to create this plugin as a way to relieve that stress. 

CODE BREAKDOWN

EASY-PIVOT USER INTERFACE

Before I started with the code, I defaulted to creating a UI for the plugin first. From my research, I came to understand that there was a widget type specifically made to assist with visualizing plugins. I created an Editor Utility Widget and worked out a basic design that included the buttons I would want to prioritize for the plugin.

DESIGN_Easy_Pivot_Design_Old.png

At the time, the plugin only included five buttons to manipulate the pivot point. Three of the buttons manipulated the pivot point of a mesh in preset ways while the remaining two were based off of the mesh’s original pivot point locations. The final version of the UI included eight buttons and three inputs for a custom pivot point location. There is an extra ‘Testing’ button that I used for debugging purposes when running the plugin.

EASY-PIVOT CODE & BLUEPRINTS

When starting the coding process, I first looked at how regular Blueprint nodes were scripted in Unreal. After doing slight research on how this was done, I made two very basic nodes as a test. The first node simply returns the squared value of an input float. The other was a look into how to construct nodes with multiple returns/outputs.

The node being used in the UI Blueprint

The node initialized in plugin's header file

The node being defined in the .cpp file

The node being used in the UI Blueprint and defined in the .cpp file

The node initialized in plugin's header file

Once I began to get comfortable with creating custom nodes in C++, I started to go deeper and figure out what I could construct from the nodes already in the editor. The first thing I wanted to figure out was a way to get the selected actor(s) and cast them as static meshes. I was able to achieve this using built-in nodes:

After figuring out how to do this in the editor, my focus changed to recreating this function as a custom node in C++. I used the existing GetSelectedActors() function in the UVRScoutingInteractor class and made it so that my version of the node will only return one selection from the array. I also created another node that will take the output, cast the selection into an AstaticMeshActor object, and return the selection as that casted object.

The next part to tackle was getting & setting the pivot offset of the Static Mesh from the script. I created a simple node called that runs the GetPivotOffset() method found within the AActor class. The node then returns the vector that is procured from that action.

I then created another node to set the new pivot offset of a Static Mesh using a Vector that gets passed as an argument. The node calls my selection function to receive the mesh it needs to manipulate and then calls the SetPivotOffset() method to change its pivot offset to the passed vector.

The nodes I needed to figure out next were the ones dedicated to setting the pivot offset at specific locations of a selected mesh. The first one I attempted was to place the pivot point at the absolute center of the mesh’s body. This was achieved simply by zero-ing out the pivot offset. I make the node return this information so that it may be passed to update the visual information on the UI.

Branching from this, my next intention was to create a node that would set the pivot point at the center-bottom of the mesh’s body. Before this however, I had to figure out how to get the data of the mesh’s physical bounds. For this purpose, I created a function to receive the mesh’s bounding box information. I figured this out by reading the Unreal documentation.

​

By means of various print nodes in the Blueprint editor, I realized how the GetComponentsBoundingBox() method breaks down information. I created two outputs for the node: OriginBox and BoxExtent as either could prove useful for anything I may decide to implement later. By using the Min and Max attributes of the Bounding Box, I was able to fill the vector spaces of the OriginBox and BoxExtent vectors. I used for loops to do this more efficiently. I noticed that the OriginBox is calculated by taking the Max Bound and adding it to the Min, then dividing the sum by 2; the same was true for the Box Extent except that I divided the difference between the Max and Min by 2. I then ended the function by returning the entire Bounding Box.

Using the bounding box function I created, I was then able to return to creating the center-bottom function/node. For the center-bottom coordinates, I kept X and Y at 0 and used the inversed Z-value from the BoxExtent vector. The function then returns this information to be used for the UI.

Following the original pivot point locations, the last of the main three were to set the pivot point at the world’s origin. To calculate this, I took the world location of the actor as a vector and inversed the values. By setting the pivot point at the inversed values, it zeroes out to the position of where the actor originally moved from.

Now that the main pivot buttons were created and functional, I wanted to increase the options available. I decided to create “Quick-Pivot” locations and custom locations based off of coordinates given to the UI. For the “Quick-Toggle-Pivot” locations, my first idea was to create an enumerator that would store the different options for the user to choose.

​Using this Enum, I made a new function that manipulated the pivot point using a switch/case statement. Each of the options used the BoxExtent vector in separate ways to achieve multiple pivot positions on the mesh.

Within the UI, I created two buttons that served the function of quickly changing the pivot to these options. When clicked, the pivot is automatically changed, and this information is also recorded onto the UI. I made sure that the list starts again at its beginning or end if the user decides to click through the buttons rapidly; this ensures that the list does not go out of bounds and causes an error for the user.

The last type of pivot location I wanted to create for the user was an option for custom placement. By using spin boxes in the UI, the user is able to enter any number and set the pivot to that location in the world space once a confirmation button is clicked.

During the process of creating the other functions, I added two buttons: one that stores a custom pivot location and one that resets it to that specified location. This served as a temporary save for the user if they liked a location and wanted to return to it while testing other options out.

As mentioned before, the Pivot location is always updated for display on the UI. This keeps the user aware of where their pivot point is currently located on their mesh.

Shown here are all of the header declarations for each of the plugin’s functions:

TIMELINE

My general timeline for the Easy Pivot tool took place over the course of 10 weeks with about 3 – 4 weeks being used exclusively for research and rehashing my understanding of C++, Unreal Plugin development, and Unreal C++ jargon. During this process, I created an spreadsheet to keep track of progress.

bottom of page