Truespace Script Buffer

trueSpace scripts create an undo step for each command in the script that changes the graph. So a single script can have many undo steps generated. The trueSpace script buffer will run a collection of script commands in the form of a string and generate only 1 undo.

Function Set variables can be used to pass complex data structures to the buffer.

If Node.Value() is used inside of a function set then it cannot be called directly from a toolbar button. The Node object seems to be incomplete and will fail with an warning message in the log, but no alert dialog like normal errors. If called using the script buffer command the Node.Value function will work when called from a toolbar button.

var cmd = ''
// note that if System.ThisOwner() is included in the buffer tS will crash
var thisowner = System.ThisOwner()
cmd += var owner = "' + thisowner + '";'
cmd += 'System.Trace(owner)'
RsApp.RunScriptBuffer(cmd);

trueSpace Delete Bug

When selected items are deleted the Node commands still behave as if the selection exists. Code below shows how to check for a valid selection before using it.

// Execute 
// Called to execute the command 
function Execute(params)
{
    if(!IsValidSelection(Node.Selection())) return;
    System.Trace("selection is good");
}
function IsValidSelection(selection)
{
    if(!selection) return false;
    var reWhiteSpace = /^\s/; // whitespace in first character
    var selectionArray = selection.split(";");
    for(var i = 0; i < selectionArray.length; i++) {
        var selClean = selectionArray[i].replace(reWhiteSpace, "");
        if(!Node.Exists(selClean)) {
            return false;
        }
    }
    return true;
}

trueSpace script params

function Execute(params)
{
	var controlIn1 = params.ConValue('controlIn1');
	var controlIn2 = params.ConValue('controlIn2');

	var scriptFrom = params.GetControlIn();

	System.Trace(scriptFrom);

	if(scriptFrom == "controlIn2")
		params.SetControlOut("ControlOut2")
	else
		params.SetControlOut("ControlOut1")

	// params.ConValue("controlOut1") = ...
	// params.ConValue("ControlOut2") = ...
}

params.GetControlIn() gets the name of the control input that runs the script, so can have several input controls and make code decisions based on which input was used
params.SetControlOut(str) does the opposite and lets you choose which output control will fire off

params.SetTerminationFlag() will stop all downstream execution

params.GetControlIn() does not work, so this whole idea is dead

Random trueSpace Notes

The script command Physics.Impulse has max XYZ values of 100. Higher values are ignored. This command only has a small effect on the object motion.

When working with script combined with the axis tool always flatten the axis back into the geometry.

The saturate node for materials does not load into trueSpace. It just gives an error.

RsApp.Help() command needs the xslt file found in the home directory in order to view the resulting xml files properly.

IK locks and IK handles attach to bones, not to joints.

A jscript object cannot properly read changes to a universal array connector if was changed from outside by a command script.

The params object can be used to stop down stream execution of command scripts via params.SetTerminationFlag()

When editing a morph target it seems best to set mesh editor auto triangulation setting to “None” .

Linear interpolation works best for IK skeletons to prevent sliding.

Space.Unselect() command will change 3D selection behavior. Before run 3D view select will select members of a 2D group. After run the 2D group will be selected instead of one of it’s 3D members.

Rough Node Connector Notes

OnLoadDefault – not in script

OnDefaultValue – called when connector is created, maybe can use to save copy of default value of conn to read later

OnSetValue – object node only, called before value is saved on connector. after value is set all connected connectors will be set “invalid”

OnInvalidate – do something if marked as invalid

OnGetValue – object node only, for intensive calculations, is run only when value is requested not when any input changes(OnComputeInputs)

Activity.ToggleAutoRun(source node, enable) – enable false is off, enable true is toggle on/off? for command node only

Space.AutoRunActivities() will run all nodes that are setup with autorun, setup via ToggleAutoRun command or LMB hold icon of the command node and choose “Run automatically”

RtNotifyEvents travel up encapsulation tree to the rootnode, event can be captured by encaps coding

Commands can be run simultaneous shared mode if nothing in the graph changes – no evidence of this since almost everything I write will change the graph. Need test on some pure intensive calculations see if can run parallel (simultaneous shared mode ?== parallel)

Creating Plugins with Unreal4 – 3DBuzz lesson notes

Updated notes for UE4 v4.23.0, Creating Plugins with Unreal4 videos

https://www.3dbuzz.com/forum/threads/204335-Creating-Plugins-with-Unreal-4-some-notes-for-version-4-10-1?p=1616145#post1616145

video 03

don’t create file folder structure, instead
Edit > Plugins > New Plugin
blank template …

edit CoolPlugin.uplugin and change “RunTime” to “Editor”

edit CoolPlugin.Build.cs and add private dependencies
“UnrealEd”,
“InputCore”,
“Core”,
“EditorStyle”,
“CoreUObject”

Use the files created by the New Plugins process, CoolPlugin.h and CoolPlugin.cpp instead of Module.cpp and Module.h
Skip creation of PCH file? – looks like something is built in already?

video 04

Edit > Editor Preferences, General > Miscellaneous, check Display UI Extension Points – shows that “WindowLocalTabSpawners” does not exist, so use “WindowGlobalTabSpawners” instead

replace #include “Slate.h” with

include “SlateBasics.h”

include “SlateExtras.h”

LOCTEXT_NAMESPACE already exists from the New Plugins process

change all references from “Module” to “FCoolPluginModule”

place new code inside the LOCTEXT_NAMESPACE define

video 05

place CoolWindow.h before CoolPlugin.h inside the CoolWindow.cpp file

video 06 – nothing

video 07


first error is for ATriggerBox – search unreal online docs for ATriggerBox – api says #include “Engine/TriggerBox.h”
add #include “Engine/TriggerBox.h” to the CoolPlugin.h file

error – cannot convert from FString to FText
CoolWindow.h change FString GetBoundsActorName() to FText GetBoundsActorName()
CoolWindow.cpp the same change and wrap the return values with FText::FromString(xxx)

error – iterator wont work, undefined class TActorIterator, ATriggerBox already has include so should be ok
search docs for TActorIterator says #include “EngineUtils.h”
add #include “EngineUtils.h” to the CoolPlugin.h file

error – cannot convert TIndirectArray to TArray
hover on GEngine->GetWorldContexts() shows that it returns a TIndirectArray not an TArray – so change TArray to TIndirectArray

video 08


convert FString to FText error for GetAlleySpaceText, wrap return value with FText::FromString(xxx)

video 09


error – UCubeBuilder not defined, search docs shows UBrushBuilder, with a link to UEditorBrushBuilder and now can see a UCubeBuilder link, finally UCubeBuilder says #include “Builders/CubeBuilder.h”
add #include “Builders/CubeBuilder.h” to the CoolPlugin.h file

error – GetBrush is not member of UWorld, so replace GetBrush with GetDefaultBrush

strange FText conversion error const Othertype to FText::EInitToEmptyString, error from file Attribute.h
output console error points to the .Text(FString(TEXT(“Build”)))
replace with .Text(LOCTEXT(“Build”,”Build”))

and now the whole thing works with ue 4.23.0

Question Messagebox

The trueSpace scripting question messagebox can be hidden behind the main display. This is a solution to that problem.

// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
function Question(strText)
{
	var nSecondsToWait = -1;
	var strTitle = "Question";
	// values are hexadecimal
	var MB_YESNO = 4;
	var MB_SYSTEMMODAL = 4096;//1000L force on top
	var MB_ICONQUESTION = 32;//20L question mark symbol

	var nType = MB_YESNO+MB_SYSTEMMODAL+MB_ICONQUESTION;
	var IDYES = 6;
	var IDNO = 7;

	var shell = new ActiveXObject("WScript.shell");
	var button = shell.Popup (strText, nSecondsToWait, strTitle, nType);

	if(button == IDYES) return true;
	return false;
}

if(!Question("Special mesh processing\nDo you wish to continue?")) {
params.ConValue("abort") = 1;
return;
}