Skip to content

Commit

Permalink
[animgraph] Refactored AnimGraphInstance to be independant of the Ani…
Browse files Browse the repository at this point in the history
…mGraph prefab
  • Loading branch information
EspeuteClement committed Dec 19, 2024
1 parent 2b29a2f commit c54e153
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 48 deletions.
14 changes: 3 additions & 11 deletions hide/view/animgraph/AnimGraphEditor.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package hide.view.animgraph;

using Lambda;
import hide.view.GraphInterface;
import hrt.animgraph.*;

Expand Down Expand Up @@ -72,23 +72,15 @@ class AnimGraphEditor extends GenericGraphEditor {
{
if (previewModel == null)
return;
var anim = animGraph.getAnimation();
var anim = animGraph.getAnimation(previewNode);
previewModel.playAnimation(anim);
previewAnimation = cast previewModel.currentAnimation;
refreshPamamList();
}

if (previewNode != null) {
var index = animGraph.nodes.indexOf(newOutput);
if (index == -1)
throw "Invalid node";
previewAnimation.outputNode = cast previewAnimation.animGraph.nodes[index];
@:privateAccess previewAnimation.bind(previewAnimation.target);
}

// copy runtime parameters
for (index => param in animGraph.parameters) {
previewAnimation.animGraph.parameters[index].runtimeValue = param.runtimeValue;
animGraph.parameters[index].runtimeValue = param.runtimeValue;
}
graphEditor.refreshPreviewButtons();
}
Expand Down
5 changes: 2 additions & 3 deletions hrt/animgraph/AnimGraph.hx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ typedef SerializedEdge = {

@:access(hrt.animgraph.AnimGraphInstance)
class AnimGraph extends hrt.prefab.Prefab {
public var instance(default, null) : AnimGraphInstance;

var nodes: Array<Node> = [];
var parameters : Array<Parameter> = [];
Expand All @@ -35,8 +34,8 @@ class AnimGraph extends hrt.prefab.Prefab {
Get the animation "template" for this AnimGraph.
This anim should be instanciated using getInstance() after that (or use the h3d.scene.Object.playAnimation() function that does this for you)
**/
public function getAnimation(previewNode: Node = null) : AnimGraphInstance {
return instance ??= new AnimGraphInstance(this);
public function getAnimation(previewNode: hrt.animgraph.nodes.AnimNode = null) : AnimGraphInstance {
return AnimGraphInstance.fromAnimGraph(this, previewNode);
}

override function save() {
Expand Down
89 changes: 58 additions & 31 deletions hrt/animgraph/AnimGraphInstance.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package hrt.animgraph;

using Lambda;
using hrt.tools.MapUtils;
class AnimGraphAnimatedObject extends h3d.anim.Animation.AnimatedObject {
public var id : Int;

Expand All @@ -12,8 +13,7 @@ class AnimGraphAnimatedObject extends h3d.anim.Animation.AnimatedObject {
@:access(hrt.animgraph.AnimGraph)
@:access(hrt.animgraph.Node)
class AnimGraphInstance extends h3d.anim.Animation {
var animGraph : AnimGraph;
var outputNode : hrt.animgraph.nodes.AnimNode;
var rootNode : hrt.animgraph.nodes.AnimNode;
var workMatrix = new h3d.Matrix();

var boneMap: Map<String, Int> = [];
Expand All @@ -24,38 +24,70 @@ class AnimGraphInstance extends h3d.anim.Animation {
var syncCtx = new hrt.animgraph.nodes.AnimNode.GetBoneTransformContext();
var defaultPoseNode = new hrt.animgraph.nodes.DefaultPose();

function new(animGraph:AnimGraph) {
// Todo : Define a true length for the animation OR make so animations can have an undefined length
super(animGraph.name, 1000, 1/60.0);
this.animGraph = animGraph;
static function fromAnimGraph(animGraph:AnimGraph, outputNode: hrt.animgraph.nodes.AnimNode = null) : AnimGraphInstance {
outputNode ??= cast animGraph.nodes.find((node) -> Std.downcast(node, hrt.animgraph.nodes.Output) != null);
if (outputNode == null)
throw "Animgraph has no output node";

defaultPoseNode = new hrt.animgraph.nodes.DefaultPose();
var output : hrt.animgraph.nodes.Output = cast Lambda.find(animGraph.nodes, (node) -> Std.downcast(node, hrt.animgraph.nodes.Output) != null);
if (output != null) {
map(output, updateNodeInputs);
outputNode = output.a;
}
var inst = new AnimGraphInstance(outputNode, animGraph.name, 1000, 1/60.0);

for (param in animGraph.parameters) {
parameterMap.set(param.name, param);
inst.parameterMap.set(param.name, param);
param.runtimeValue = param.defaultValue;
}

return inst;
}

function new(rootNode: hrt.animgraph.nodes.AnimNode, name: String, framesCount: Int, sampling: Float) {
// Todo : Define a true length for the animation OR make so animations can have an undefined length
super(name, framesCount, sampling);
this.rootNode = rootNode;

defaultPoseNode = new hrt.animgraph.nodes.DefaultPose();
}

override function clone(?target: h3d.anim.Animation) : h3d.anim.Animation {
if (target != null) throw "Unexpected";
var newAnimGraph : AnimGraph = cast animGraph.clone();
var inst = super.clone(new AnimGraphInstance(newAnimGraph));

var inst = new AnimGraphInstance(null, name, frameCount, sampling);
inst.rootNode = cast cloneRec(rootNode, inst);
super.clone(inst);
return inst;
}

static function cloneRec(node: hrt.animgraph.Node, inst: AnimGraphInstance) : hrt.animgraph.Node {
var cloned = hrt.animgraph.Node.createFromDynamic(node.serializeToDynamic());

var clonedParam = Std.downcast(cloned, hrt.animgraph.nodes.FloatParameter);
if (clonedParam != null) {
var nodeParam : hrt.animgraph.nodes.FloatParameter = cast node;
clonedParam.parameter = inst.parameterMap.getOrPut(nodeParam.parameter.name, {
var newParam = new hrt.animgraph.AnimGraph.Parameter();
@:privateAccess newParam.copyFromOther(nodeParam.parameter);
nodeParam.parameter.runtimeValue = nodeParam.parameter.defaultValue;
newParam;
});
}

for (id => edge in node.inputEdges) {
if (edge?.target != null) {
var targetClone = cloneRec(edge.target, inst);
cloned.inputEdges[id] = {target: targetClone, outputIndex: edge.outputIndex};
} else {
cloned.inputEdges[id] = null;
}
}
return cloned;
}

public function getBones(ctx : hrt.animgraph.nodes.AnimNode.GetBoneContext) : Map<String, Int> {
if (outputNode == null)
if (rootNode == null)
return null;

map(outputNode, updateNodeInputs);
map(rootNode, updateNodeInputs);

boneMap = outputNode.getBones(ctx);
boneMap = rootNode.getBones(ctx);
return boneMap;
}

Expand All @@ -76,14 +108,14 @@ class AnimGraphInstance extends h3d.anim.Animation {
}

override function sync(decompose : Bool = false ) {
if (outputNode == null)
if (rootNode == null)
return;
for (obj in objects) {
var obj : AnimGraphAnimatedObject = cast obj;
workMatrix.identity();
syncCtx.reset(obj);

outputNode.getBoneTransform(obj.id, workMatrix, syncCtx);
rootNode.getBoneTransform(obj.id, workMatrix, syncCtx);

@:privateAccess
var targetMatrix = if (obj.targetSkin != null) {
Expand Down Expand Up @@ -137,7 +169,7 @@ class AnimGraphInstance extends h3d.anim.Animation {
function map(root: Node, cb: (node:Node) -> Void) {
function rec (node: Node) {
cb(node);
for (inputId => edge in node.inputEdges) {
for (edge in node.inputEdges) {
if (edge == null) continue;
rec(edge.target);
}
Expand All @@ -147,22 +179,17 @@ class AnimGraphInstance extends h3d.anim.Animation {

override function update(dt:Float):Float {
var dt2 = super.update(dt);
if (outputNode == null)
if (rootNode == null)
return dt2;

for (node in animGraph.nodes) {
node.tickedThisFrame = false;
}

tickRec(outputNode, dt);
map(rootNode, (node) -> node.tickedThisFrame = false);
tickRec(rootNode, dt);

return dt2;
}

function tickRec(node: hrt.animgraph.Node, dt: Float) {
var inputs = node.getInputs();

for (inputId => edge in node.inputEdges) {
for (edge in node.inputEdges) {
if (edge == null) continue;
var outputNode = edge.target;
if (!outputNode.tickedThisFrame) {
Expand Down
2 changes: 1 addition & 1 deletion hrt/animgraph/Macros.hx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Macros {
cl = cl.superClass?.t.get();
}

if (inheritAnimNode) {
if (inheritAnimNode && cl.name != "Output" /* Output don't have an anim output ironically */) {
outputs.push(macro {
name: "",
type: Node.OutputType.TAnimation,
Expand Down
2 changes: 1 addition & 1 deletion hrt/animgraph/nodes/FloatParameter.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class FloatParameter extends Node {
}

override function tick(dt: Float) : Void {
value = parameter.runtimeValue;
value = parameter?.runtimeValue ?? 0;
}

override function getOutputNameOverride(name: String) : String {
Expand Down
10 changes: 9 additions & 1 deletion hrt/animgraph/nodes/Output.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package hrt.animgraph.nodes;
/**
The result of this node can be used as an animation by other systems
**/
class Output extends Node {
class Output extends AnimNode {

@:input var a: AnimNode;

Expand All @@ -29,4 +29,12 @@ class Output extends Node {
};
return info;
}

override function getBones(ctx:hrt.animgraph.nodes.AnimNode.GetBoneContext):Map<String, Int> {
return a.getBones(ctx);
}

override function getBoneTransform(boneId:Int, outMatrix:h3d.Matrix, ctx:hrt.animgraph.nodes.AnimNode.GetBoneTransformContext) {
return a.getBoneTransform(boneId, outMatrix, ctx);
}
}

0 comments on commit c54e153

Please sign in to comment.