World Editor API allows for plugin/tool world operations like obtaining terrain resolution, but mostly for Prefab operations such as editing and saving a Prefab (called Entity Template in the API for historical reason – hence the .et extension) using BaseContainer references.
Game classes such as WorldEditorAPI, ScriptEditor etc must not be a strong ref script-side; on scripts reload, these references are not nulled and could point to anything.
classTAG_MyClass{WorldEditorAPIm_WorldEditorAPI;// wrongprotectedvoidMethod(){// m_WorldEditorAPI.DoSomething();WorldEditorAPI worldEditorAPI =GetWorldEditorAPI();
worldEditorAPI.DoSomething();// correct}// many ways to get WorldEditorAPIprotectedWorldEditorAPIGetWorldEditorAPI(){int method =Math.RandomInt(0, 4);if(method == 0){WorldEditor worldEditor =Workbench.GetModule(WorldEditor);if(!worldEditor)// safetyreturn;return worldEditor.GetApi();}elseif(method == 1){return((WorldEditor)Workbench.GetModule(WorldEditor)).GetApi();// one-lined method}elseif(method == 2){returnSCR_WorldEditorToolHelper.GetWorldEditorAPI();// this helper does it for you}elseif(method == 3)// if the current class is a WorldEditorTool child, m_API is available{returnm_API;// this reference is managed by Workbench itself}returnnull;}}
//! Load ResourceName into a Resource//! \param[in] resourceName the resourceName to load//! \param[out] resource it is important to keep a strong reference to the loaded resource,//! otherwise its BaseContainer/IEntitySource will be dropped by memory management//! \return the provided resourceName's IEntitySourceprotectedIEntitySourceGetPrefabFromResourceName(ResourceName resourceName,outResource resource){
resource =Resource.Load(resourceName);if(!resource.IsValid()){
resource =null;returnnull;}return resource.GetResource().ToEntitySource();}
values are set as string through WorldEditorAPI in .et files.
For example, a true bool value will be represented as 1 in a .et file, therefore "1" must be provided (see bool.ToString(true) for more information).
⚠
Prefab actions must be wrapped between EntityAction begin/end methods below – the Workbench will remind you of that anyway with a VME.
worldEditorAPI.BeginEntityAction();// actions here
worldEditorAPI.EndEntityAction();
Direct Value
The SetVariableValue method is used:
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_bVariable", bValue.ToString(true));// .ToString(true) to write it as "1"
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_fVariable", fValue.ToString());
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_iVariable", iValue.ToString());
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_sVariable", sValue);// no .ToString() for string
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_vVariable", vValue.ToString(false));// .ToString(false) to write it as "0 1 2" and not "<0, 1, 2>"
Native Type Array
The SetVariableValue method is used, setting values with separating commas:
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_aBoolArray","0,1,0,0,1,1,0,0,0,1,1,0,1,1,1,1,0,1,1,1,0,1,0,1");
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_aFloatArray","1.1,2,3.14159");
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_aIntArray","1,2,3,4,5,6,-10");
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_aStringArray","value1,value2,value3");// note: commas cannot be escaped, making string with commas NOT supported
worldEditorAPI.SetVariableValue(myEntitySource,null,"m_aVectorArray","0 1 0,0 0 1,1 0 0");
Object Creation
Two cases are identified: the object can either be a direct object property or an array item.
In the first case (direct object property), the CreateObjectVariableMember method must be used:
// assuming an object is myEntitySource.m_SubObject// public, protected or private, WorldEditorAPI can write any Attribute
worldEditorAPI.CreateObjectVariableMember(myEntitySource,null,"m_SubObject","SubObjectClassName");// returns true if type is valid and the object was created
In the second case (array element), the CreateObjectArrayVariableMember method is used:
// assuming an object is an item of the myEntitySource.m_aSubObjects array
worldEditorAPI.CreateObjectArrayVariableMember(myEntitySource,null,"m_aSubObjects","SubObjectClassName", 0);// returns true if type and index are valid and the object was created// but... how to get the existing index?// we can use the BaseContainer.Get method on the entitySource// using BaseContainer methods is fine as long as it is for reading information, not set themBaseContainerList subObjectsArray = myEntitySource.GetObjectArray("m_aSubObjects");int nextIndex = subObjectsArray.Count();
Object Value
To set an object's value, the path parameter, an array of ContainerIdPathEntry must be used:
// let's reuse the myEntitySource.m_SubObject situation// m_SubObject has a "m_sMessage" property we want to set// m_SubObject cannot be set as SetVariableValue's first argument, as it is not the root container (myEntitySource being its parent)
worldEditorAPI.SetVariableValue(myEntitySource,{newContainerIdPathEntry("m_SubObject")},"m_sMessage","Hello there");
ⓘ
For performance reason, the path can be cached in order to create array and objects for each property.
Here for the sake of examples and teaching, arrays are created on the fly.
An array item is accessed using the ContainerIdPathEntry's index parameter, to determine which item is targeted
// let's reuse the myEntitySource.m_aSubObjects array situation
worldEditorAPI.SetVariableValue(myEntitySource,{newContainerIdPathEntry("m_aSubObjects", 3)},"m_sMessage","Hello there");// changes the fourth array item
A component is accessed the same way - using the "components" path:
worldEditorAPI.SetVariableValue(myEntitySource,{newContainerIdPathEntry("components", 0)},"m_sMessage","Hello there");// if the first component must be edited
Delete Value
worldEditorAPI.ClearVariableValue(myEntitySource,null,"m_sName");// erases "m_sName" from this Prefab's definition (not from parents or children)
An array cannot be deleted this way. All its items should be removed through RemoveObjectArrayVariableMember usage instead:
BaseContainerList subObjectsArray = myEntitySource.GetObjectArray("m_aSubObjects");for(int i = subObjectsArray.Count()- 1; i >= 0;--i){
worldEditorAPI.RemoveObjectArrayVariableMember(myEntitySource,null,"m_aSubObjects", i);}