Tycoon C++ Twisting
05 Feb 2019I’ve added twisting! Just rotating each point in a similar way as the bend method does, but in a different axis.
I’ve added twisting! Just rotating each point in a similar way as the bend method does, but in a different axis.
Did some work on the UI today.
The current UI framework from Unreal is called Slate. Slate is a wrapper around the Chromium Embedded Framework (CEF). (The engine of Google Chrome). That means that Slate is using web technology to draw the UI, take a look here: wikipedia
Did you know that Unity, Evernote and many game launchers are using the CEF framework?
You might have used UMG widgets inside Unreal before, UMG is another wrapper above the slate framework. UMG widgets are made with a visual editor and are saved as binary assets in your game project. This might work fine for most simple game menus, but keep in mind that you may need to bind these events using BP to C++. That operation might not scale or perform that well for bigger projects.
Back to slate: slate docs
Work in progress
For my plugin I wanted to populate a new tab in the ‘modes’ window. In unreal this is called an ‘editor mode toolkit’. You can inherent your UI class from: FModeToolkit Take a look at plugin examples for editor modes.
The slate syntax looks like this:
// Create a new widget
SNew(SVerticalBox)
// New 'slot' / row
+ SVerticalBox::Slot()
// Add some properties
.VAlign(VAlign_Top)
.HAlign(HAlign_Left)
[
// Inside this row, make a new widget
SNew(SBox)
.WidthOverride(214.0f)
.HeightOverride(40.0f)
[
// Another one, image this time
SNew(SImage)
.Image(
LoadImage(
"tycoonlabel.tycoonlabel",
FVector2D(214.0f, 40.0f)
))
]
]
You can also make methods to generate new widgets, this is how I created the buttons: Make sure to set the type to be a ‘smart’ shared reference. -> smart pointer lib
TSharedRef<SWidget> FTycoonToolEdModeToolkit::MakeExternalButton(FString label)
{
return SNew(SButton)
.ButtonStyle(FCoreStyle::Get(), "NoBorder")
.ForegroundColor(FSlateColor::UseForeground())
[
SNew(SImage)
.Image(LoadImage(label + "." + label))
]
// Bind method to the click event of this button
.OnClicked(
this,
&FTycoonToolEdModeToolkit::clickHandler,
label
);
}
Sometimes things don’t work properly, or you are just curious about some cool UE4 button. In that case you can use the Widget Reflector Tool, you can pick any widget and inspect it’s properties.
Next steps:
Another tycoon update, this one was quite tricky to figure out for some reason, but I’m finally able to change the bend direction of the tycoon mesh.
Prototyping the concept in Maya
Random tests in Unreal
Rotate each point around the forward axis of the track piece (This is the ‘direction’ input).
Then rotate each point around the Y axis (the actual bend operation).
Apply the inverse rotation at the point again, to align the piece correctly.
Next steps:
Was working in Maya the other day, and I spent some time looking for a simple example that I can use as a starting point for a deformer. I’m currently prototyping my Tycoon bend deformer in Maya as well since prototyping is a bit faster without compiling C++ :)
a MPoint() is a Maya api wrapper around a point. Here we initialize an api mesh object so we can make use of the method .getPoints(). MFnSet docs MPoint docs
DAG path: directed acyclic graph (DAG), path (path to a node): docs
self.mFnSet = om.MFnMesh(dag_path)
# kObject = object / local space
# to get world space use: kWorld
verts = self.mfn_set.getPoints(space=om.MSpace.kObject)
# update all verts
self.mfn_set.setPoints(new_points, space=om.MSpace.kObject)
Full code example:
class YvoDeformer(object):
def __init__(
self
):
self.selection = None
self.mfn_set = None
def deform(self):
self.selection = cmds.ls(sl=True)
if not self.selection:
return
# make duplicate and assign as selection
self.selection = cmds.duplicate(self.selection[0])[0]
cmds.select(self.selection)
selection_list = om.MSelectionList()
selection_list.add(self.selection)
dag_path = selection_list.getDagPath(0)
# assemble an open maya mesh set object using the dag_path
self.mfn_set = om.MFnMesh(dag_path)
verts = self.mfn_set.getPoints(space=om.MSpace.kObject)
new_points = om.MPointArray()
for v in verts:
# move this vertex in the local x axis
v.x += 30.0
# assign the new point to the list
new_points.append(v)
# make sure we don't set an empty array
if not new_points:
return
# update all verts
self.mfn_set.setPoints(new_points, space=om.MSpace.kObject)
Happy new year, random quick thing I felt like doing: was not happy with the autocomplete for Maya python cmds api, so I wrote a little web scraper that scrapes the Autodesk docs page and converts it into a .py file that can be added to your python path. github