Extending the Fx System
This page contains advanced-level tutorials on how to extend the Fx System for game-specific needs, by adding your own FxTasks.
Creating a new FxTask
An FxTask is simply a task that you want to occur at a particular time. A task might be adding a node to the world, triggering a game system, or manipulating other nodes. There are 3 supported task types from which you can create a new task.
|_FxTask||This is the most basic task class. It can be set to start and stop. The _FxAnimationCmd, _FxModelFader, _FxTransformer classes all use _FxTask.|
|_FxResource||All the functionality of _FxTask with the added ability to load a resource from the Repository and insure the resource is loaded before runtime.|
|_Fx3dController||Combines _FxTask and _FxResource and adds the ability to position the instantiated resource in the world.|
Desire: My game needs the ability to draw lines across the screen.
Implement: Create class MyFxLinePainter adding parent class _FxTask.
Desire: We've added PlasmaCloud instances to the Heroblade renderer. We want to combine them with other Fxs.
Implement: Create class MyFxPlasmaCloud adding parent classes _Fx3dController.
The _FxTaskExtender class must be added to your new task as a parent class in order for the new task to be saved properly.
Implementing required methods
There are a few methods you must implement in your new task's class methods script in order for your task to work.
In this method, you implement all the mechanics necessary to occur when your task is told to start.
In this method, you implement any mechanics necessary to stop your task. Some tasks, such as _FxAnimationCmd or _FxAttacher occur instantly (having no significant duration) and thus need not implement this method.
method SetupNewInstance(newInstance as NodeRef of Class HBNode)
This method is called after your new task's instance is created, but before it is activated. This allows you to set instance properties from those specified in your new task.
Creating new Events
The Fx System is an event-based sequencer. Each type of task has events that it can generate. Most have common events such as start and stop events. Some have special events which are unique to themselves, such the_FxEmitter "ONTARGETACHIEVED" event.
To generate a custom event, this method must be called from the FxGroup node.
method _ProcessFxEvent(event as String, taskname as String, eventData as LookupList indexed by String of String)
eventData as LookupList indexed by String of String // for passing in extra data var fxg = me.GetMyFxGroup() fxg._ProcessFxEvent("MYWAYCOOLEVENT", me._fxName, eventData)
Extending FxGUI Editor
- See also: FxGUI
There are several classes and controls to be created to support a game-specific FxTask.
Creating an FxGUI Extension class
- Create a game-specific extension client-side class. Example: HJ_FxGUIExtension
- Glom this class onto client-side prototype FXEDIT using console command |MPAC. Example: |MPAC FXEDIT HJ_FxGUIExtension
- Create class methods script for the new class which will implement methods called by the FxGUI Editor. (documented below under FxGUI Extension Methods)
Creating FxGUI controls
You will need to create 3 GUI Controls for each custom FxTask you create. An icon representing the task, a property panel for filling out new properties, and a property window which holds the new property panel as well as other common panels.
Each custom FxTask will need an icon representing it in the toolbar. Steps to create:
- Create new GUI control inheriting from FxIconPanel_v2.
- Change the GlomClass to _FxToolbarIcon.
- Change control named 'iconImage' to use the texture that will have your new icon. Icons in the toolbar are displayed at size 36 x 36 (Though the size on the texture can be larger.)
- Save the new control.
A property panel is the part of the fx gui editor that allows you to set the properties of your custom FxTask to meaningful values. Steps to create:
- Create a client-side class which will support the panel. Set Parent class to _PropertyPanel. Example: HJFXBabblerPropertyPanel
- Create a new gui control inheriting from _panel.
- Set the width to be 250. The height needed will depend on the number of properties, but 200 is a good start.
- For the panel's defaultStatePresentation, set the color's alpha to 0.
- Set GlomClass to the support class created in step 1.
- Add control FxPropertySectionHeader_v2. Change the label text in it to name of your new task. Example text: HJFXBabbler
- Add controls to set your properties. Many of the basic types already exist for your use. They reside in folder CleanEngine/Systems/FX/properties. Each control added should be named to match the name of the field it will be setting. Example: For field HJfxText which is a string, add gui control FxPropertyString_v2 and name the control HJfxText. You may also wish to set a tooltip and change the included label to a denote your field.
- Save the new control.
A property window houses all the property panels needed to set properties on your class. You will need to create one property window for each custom FxTask and add the property panels needed to it. Although the order that property panels are added is not important, you will want to add them in this suggested order to maintain consistency.
- Create client-side class to support your new property window. Add parent class PropertyWindow to this class. Example: HJFXBabblerPropertyWindow
- Create new gui control inheriting from FxBasePropertyWindow.
- Set GlomClass on your control to the class created in Step 1.
- Add property panels (setting dockMode to TOP) to scrollable.clientarea:
- FxResourcePropertyPanel_v2 (if your class has parent _FxResource or _Fx3DController)
- Fx3dControllerPropertyPanel_v2 (if your class has parent _Fx3DController)
- Adjust the size of your property window
- Save the control.
Property Panel Support Methods
Implement the following methods in your property panel class methods script.
method InitFields(subj as NodeRef of Class _FxEmitter)
Some controls needs to be initialized once created. The opportunity to do this occurs here in the InitFields methods. For example, if you have used FxPropertyDownDown_v2 to set an enum or string field, you may need to drop down menu with appropriate options.
Example:stopList as List of String add back "NORMAL" to stopList add back "HIDE" to stopList var p = FindGUIControlByName(me, "_fxHowToStop") p.InitFxProperty_DropDown(stopList)
method PopulateFields(subj as NodeRef of Class _FxEmitter)
Here we set the property controls in the gui to display the values from your custom FxTask. This should be fairly straight forward.
Example:var p = FindGUIControlByName(me, "_fxTargetBoneName") p.SetFxProperty_String(subj._fxTargetBoneName) p = FindGUIControlByName(c, "_fxSpeed") p.SetFxProperty_ComplexValue(subj._fxSpeed)
Some properties in your FxTask may only be significant if other properties are set to certain values. This method allows you the opportunity to show or hide properties in your property panel based on this context.
Example:if FindGUIControlByName(me, "_fxTargetName").GetFxProperty_DropDown() <> "NOTARGET" ShowFxProperty(FindGUIControlByName(me, "_fxTargetBoneName")) ShowFxProperty(FindGUIControlByName(me, "_fxSpeed")) ShowFxProperty(FindGUIControlByName(me, "_fxTolerance")) ShowFxProperty(FindGUIControlByName(me, "_fxOffset")) else HideFxProperty(FindGUIControlByName(me, "_fxTargetBoneName")) HideFxProperty(FindGUIControlByName(me, "_fxSpeed")) HideFxProperty(FindGUIControlByName(me, "_fxTolerance")) HideFxProperty(FindGUIControlByName(me, "_fxOffset")) .
FxGUI Extension Methods
Now that the necessary gui controls are created, several methods must be implemented to bring them into use.
Add these methods to your game-specific FxGUIExtension class methods script.
method HE_GetFxExtensionToolbarIcons() as List of NodeRef of Class GUIControl
Called by the FxGUI Editor to get a list of custom icons to add to the toolbar.
Example:method HE_GetFxExtensionToolbarIcons() as List of NodeRef of Class GUIControl //---------------------------------------------------------------------------- // Used by $FXEDIT to add game specific FxTask icons to the fx editor toolbar //---------------------------------------------------------------------------- theIcons as List of NodeRef of Class GUIControl icon as NodeRef of Class GUIControl icon = CreateNodeFromPrototype("HJFX_BabbleIcon") icon.build = true add back icon to theIcons return theIcons .
method HE_CreateFxNodeFromFxIconName(theName as String) as NodeRef
Called when you drop a custom icon from the toolbar onto the task browser, invoking the need to create a new FxTask node and add it to the FxGroup node tree (represented in the task browser). The name passed in is the name of the toolbar icon. From this name, you must create your custom FxTask node and return it.
Example:method HE_CreateFxNodeFromFxIconName(theName as String) as NodeRef // Used by Fx Editor to create FxTask nodes when icon is dragged onto // the task browser theNode as NodeRef when theName is "hjfx_babbleicon" theNode = CreateNodeFromClass("HJFXBabbler") . . return theNode .
GUI Related Methods
Several methods need to be implemented in your custom FxTask class methods script to support editing in the FxGUI.
method _CreateFxIconForFxTask() as NodeRef of Class GUIControl
In this method, you must create the gui control that is the toolbar icon for your custom FxTask.
Example:method _CreateFxIconForFxTask() as NodeRef of Class GUIControl icon as NodeRef of Class GUIControl icon = CreateNodeFromPrototype("HJFX_BabbleIcon") icon.build = true return icon .
method _GetFxIconForFxTaskPrefix() as String
This must return a string that will be a prefix denoting your class
Example:method _GetFxIconForFxTaskPrefix() as String //----------------------- // Prefix for HJFXBabbler //----------------------- return "fxbabble_" .
method _GetNewFxNameForFxNode() as String
This must return a string that is the default name of your custom task as shown in the task browser.
Example:method _GetNewFxNameForFxNode() as String //----------------------------- // Default name for HJFXBabbler //----------------------------- return "Babbler" .
method _AlterFxTaskIconImage(image as NodeRef of Class GUIControl)
This sets the image of the icon in the task browser to match your icon's image.
Example:method _AlterFxTaskIconImage(image as NodeRef of Class GUIControl) image.texture = "\GUI\faces.dds" image.defaultStatePresentation.position.x = 100 image.defaultStatePresentation.position.y = 0 image.defaultStatePresentation.size.x = 50 image.defaultStatePresentation.size.y = 50 .
method _CreatePropertyWindowForFxTask() as NodeRef of Class GUIControl
Must create a return a property window for your custom FxTask.
Example:method _CreatePropertyWindowForFxTask() as NodeRef of Class GUIControl pw as NodeRef of Class GUIControl pw = CreateNodeFromPrototype("HJFxBabblerPropertyWindow") pw.build = true return pw .
method _GetValidListOfFxEvents() as List of String
Must return a list of valid events that your custom FxTask can generate.
Example:method _GetValidListOfFxEvents() as List of String events as List of String add back "ONFXSTART" to events add back "ONANIMATIONNOTE" to events return events .
method SetFxEnumValue(fieldName as String, newValue as String)
This method is necessary if your new task has any enum fields.
Example:method SetFxEnumValue(fieldName as String, newValue as String) when fieldName is "_fxHowToStop" me._fxHowToStop = newValue . default parentClass::SetFxEnumValue(fieldName, newValue) . . .
Additional Extension Methods
These methods can also be added to your game-specific FxGUIExtention class methods script. They are intended to give you the option to open and close additional controls of your own design.
Called when the FxGUI Editor is opened after selecting an Fx to edit.
Called when the FxGUI Editor is closed (via the close button on the toolbar)