Skip to content

Commit

Permalink
Merge branch 'master' into dynamic-bones
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoVgr committed Feb 5, 2025
2 parents 6c997bb + a50b3c0 commit e6f998b
Show file tree
Hide file tree
Showing 18 changed files with 239 additions and 25 deletions.
5 changes: 5 additions & 0 deletions bin/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -4518,6 +4518,11 @@ blend-space-2d-root main-panel graph-container svg .preview-axis {
stroke: #008a00;
stroke-width: 2;
}
blend-space-2d-root main-panel graph-container svg .preview-axis-real {
fill: none;
stroke: #008a00;
stroke-width: 1;
}
blend-space-2d-root main-panel graph-container drag-handler {
z-index: 1;
position: absolute;
Expand Down
6 changes: 6 additions & 0 deletions bin/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -5361,6 +5361,12 @@ blend-space-2d-root {
stroke: #008a00;
stroke-width: 2;
}

.preview-axis-real {
fill: none;
stroke: #008a00;
stroke-width: 1;
}
}

drag-handler {
Expand Down
12 changes: 6 additions & 6 deletions hide/view/GraphEditor.hx
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,12 @@ class GraphEditor extends hide.comp.Component {
fn(false);
}

public function commitUndo() {
public function commitUndo(noDataChange: Bool = false) {
if (currentUndoBuffer.length <= 0) {
return;
}
var buffer = currentUndoBuffer;
editor.getUndo().change(Custom(execUndo.bind(buffer)));
editor.getUndo().change(Custom(execUndo.bind(buffer)), null, noDataChange);
currentUndoBuffer = [];
}

Expand Down Expand Up @@ -257,7 +257,7 @@ class GraphEditor extends hide.comp.Component {
opSelect(id, true, save.buffer);
}
currentUndoBuffer = save.buffer;
commitUndo();
commitUndo(true);
undoSave = null;
return;
}
Expand Down Expand Up @@ -1041,7 +1041,7 @@ class GraphEditor extends hide.comp.Component {
for (id => _ in boxes) {
opSelect(id, true, currentUndoBuffer);
}
commitUndo();
commitUndo(true);
}

public function setSelection(nodes: Array<IGraphNode>) {
Expand All @@ -1051,7 +1051,7 @@ class GraphEditor extends hide.comp.Component {
opSelect(node.id, true, currentUndoBuffer);
}

commitUndo();
commitUndo(true);
}

public function centerSelection() {
Expand Down Expand Up @@ -1281,7 +1281,7 @@ class GraphEditor extends hide.comp.Component {
clearSelectionBoxesUndo(currentUndoBuffer);
}
opSelect(box.node.id, true, currentUndoBuffer);
commitUndo();
commitUndo(true);
}
elt.get(0).setPointerCapture(e.pointerId);
beginMove(e);
Expand Down
8 changes: 4 additions & 4 deletions hide/view/animgraph/AnimGraphEditor.hx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class AnimGraphEditor extends GenericGraphEditor {
refreshPamamList();

var dl = new Element("<dl></dl>").appendTo(propertiesContainer);
addAnimSetSelector(dl, undo, () -> previewState.providerIndex, (i: Int) -> {
addAnimSetSelector(dl, {animDirectory: animGraph.animFolder, assetPath: state.path}, undo, () -> previewState.providerIndex, (i: Int) -> {
previewState.providerIndex = i;
savePreviewState();
refreshPreview();
Expand Down Expand Up @@ -238,13 +238,13 @@ class AnimGraphEditor extends GenericGraphEditor {
return options;
}

static public function addAnimSetSelector(target: Element, undo: hide.ui.UndoHistory, getIndex: () -> Int, setIndex:(Int) -> Void) {
static public function addAnimSetSelector(target: Element, context:hrt.animgraph.AnimGraph.EditorProviderContext, undo: hide.ui.UndoHistory, getIndex: () -> Int, setIndex:(Int) -> Void) {
if (hrt.animgraph.AnimGraph.customEditorResolverProvider != null)
{
var div = new Element("<div></div>").appendTo(target);
div.append(new Element("<dt>Anim Set</dt>"));

var providers = hrt.animgraph.AnimGraph.customEditorResolverProvider(_);
var providers = hrt.animgraph.AnimGraph.customEditorResolverProvider(context);

var button = new hide.comp.Button(div, null, null, {hasDropdown: true});
button.label = providers[getIndex()].name;
Expand Down Expand Up @@ -297,7 +297,7 @@ class AnimGraphEditor extends GenericGraphEditor {

var resolver = null;
if (AnimGraph.customEditorResolverProvider != null) {
var providers = AnimGraph.customEditorResolverProvider(_);
var providers = AnimGraph.customEditorResolverProvider({animDirectory: animGraph.animFolder, assetPath: state.path});
if (providers != null && previewState.providerIndex > providers.length) {
previewState.providerIndex = 0;
savePreviewState();
Expand Down
44 changes: 41 additions & 3 deletions hide/view/animgraph/BlendSpace2DEditor.hx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class BlendSpace2DEditor extends hide.view.FileView {

var animPreview : hrt.animgraph.AnimGraphInstance;

var previewBlendPos : hide.Element;

inline function getPointPos(clientX : Float, clientY : Float, snap: Bool) : h2d.col.Point {
var x = hxd.Math.clamp(graphXToLocal(clientX), blendSpace2D.minX, blendSpace2D.maxX);
var y = hxd.Math.clamp(graphYToLocal(clientY), blendSpace2D.minY, blendSpace2D.maxY);
Expand Down Expand Up @@ -361,7 +363,7 @@ class BlendSpace2DEditor extends hide.view.FileView {
@:privateAccess blendSpaceNode.blendSpace = blendSpace2D;
var resolver = null;
if (hrt.animgraph.AnimGraph.customEditorResolverProvider != null) {
var resolvers = hrt.animgraph.AnimGraph.customEditorResolverProvider(_);
var resolvers = hrt.animgraph.AnimGraph.customEditorResolverProvider({animDirectory: blendSpace2D.animFolder, assetPath: state.path});
if (resolvers != null) {
if (previewState.providerIndex > resolvers.length) {
previewState.providerIndex = 0;
Expand All @@ -380,7 +382,7 @@ class BlendSpace2DEditor extends hide.view.FileView {

var resolver = null;
if (hrt.animgraph.AnimGraph.customEditorResolverProvider != null) {
var resolvers = hrt.animgraph.AnimGraph.customEditorResolverProvider(_);
var resolvers = hrt.animgraph.AnimGraph.customEditorResolverProvider({animDirectory: blendSpace2D.animFolder, assetPath: state.path});
if (resolvers != null) {
resolver = resolvers[previewState.providerIndex]?.resolver;
}
Expand All @@ -401,6 +403,9 @@ class BlendSpace2DEditor extends hide.view.FileView {
}
}
}

updatePreviewAxis();
animPreview.resetSmoothedValues();
}
}

Expand All @@ -418,7 +423,9 @@ class BlendSpace2DEditor extends hide.view.FileView {
<div class="group" name="BlendSpace">
<dl>
<dt>Min/MaxX</dt><dd><input type="number" field="minX"/><input type="number" field="maxX"/></dd>
<dt>Smooth X</dt><dd><input type="range" min="0.0" max="1.0" field="smoothX"/></dd>
<dt>Min/MaxY</dt><dd><input type="number" field="minY"/><input type="number" field="maxY"/></dd>
<dt>Smooth Y</dt><dd><input type="range" min="0.0" max="1.0" field="smoothY"/></dd>
</dl>
</div>
'), blendSpace2D, (_) -> {
Expand Down Expand Up @@ -467,7 +474,7 @@ class BlendSpace2DEditor extends hide.view.FileView {
updatePreviewAxis();
});

AnimGraphEditor.addAnimSetSelector(preview.find("dl"), undo, () -> previewState.providerIndex, (i: Int) -> {
AnimGraphEditor.addAnimSetSelector(preview.find("dl"), {animDirectory: blendSpace2D.animFolder, assetPath: state.path}, undo, () -> previewState.providerIndex, (i: Int) -> {
previewState.providerIndex = i;
savePreviewState();
refreshPreviewAnimation();
Expand Down Expand Up @@ -552,6 +559,20 @@ class BlendSpace2DEditor extends hide.view.FileView {

}

var queuedRequest : Int = -1;
function onRequestAnimationFrame(dt: Float) {
if (previewBlendPos != null && animPreview != null) {
var root : hrt.animgraph.nodes.BlendSpace2D.BlendSpace2D = cast @:privateAccess animPreview.rootNode;
var rx = @:privateAccess root.realX;
var ry = @:privateAccess root.realY;
previewBlendPos.attr("transform", 'translate(${localXToGraph(rx)}, ${localYToGraph(ry)})');

queuedRequest = js.Browser.window.requestAnimationFrame(onRequestAnimationFrame);
return;
}
queuedRequest = -1;
}

function createPoint() {

}
Expand Down Expand Up @@ -669,6 +690,23 @@ class BlendSpace2DEditor extends hide.view.FileView {
final size = 10;
graph.line(g, -size, -size, size, size).addClass("preview-axis");
graph.line(g, -size, size, size, -size).addClass("preview-axis");

if (animPreview != null) {
var root : hrt.animgraph.nodes.BlendSpace2D.BlendSpace2D = cast @:privateAccess animPreview.rootNode;
var rx = @:privateAccess root.realX;
var ry = @:privateAccess root.realY;

previewBlendPos = graph.group(graph.element);
previewBlendPos.attr("transform", 'translate(${localXToGraph(rx)}, ${localYToGraph(ry)})');
final size = 10;
graph.line(previewBlendPos, -size, -size, size, size).addClass("preview-axis-real");
graph.line(previewBlendPos, -size, size, size, -size).addClass("preview-axis-real");

if (queuedRequest < 0) {
queuedRequest = js.Browser.window.requestAnimationFrame(onRequestAnimationFrame);
}
}

}
}

Expand Down
4 changes: 2 additions & 2 deletions hrt/animgraph/AnimGraph.hx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ 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: hrt.animgraph.nodes.AnimNode = null, resolver: hrt.animgraph.AnimGraphInstance.AnimResolver = null) : AnimGraphInstance {
public function getAnimation(previewNode: hrt.animgraph.nodes.AnimNode = null, modelCache: h3d.prim.ModelCache = null, resolver: hrt.animgraph.AnimGraphInstance.AnimResolver = null) : AnimGraphInstance {
if (resolver == null && customResolverProvider != null) {
resolver = customResolverProvider(this);
}
return AnimGraphInstance.fromAnimGraph(this, previewNode, resolver);
return AnimGraphInstance.fromAnimGraph(this, previewNode, modelCache, resolver);
}

override function save() {
Expand Down
37 changes: 34 additions & 3 deletions hrt/animgraph/AnimGraphInstance.hx
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,31 @@ class AnimGraphInstance extends h3d.anim.Animation {
var defaultPoseNode = new hrt.animgraph.nodes.DefaultPose();

var resolver : AnimResolver = null;
var modelCache: h3d.prim.ModelCache;

var tmpMatrix : h3d.Matrix = new h3d.Matrix();

var tmpMatrix : h3d.Matrix = new h3d.Matrix();

#if editor
var editorSkipClone : Bool = false;
#end

static function fromAnimGraph(animGraph:AnimGraph, outputNode: hrt.animgraph.nodes.AnimNode = null, resolver: AnimResolver) : AnimGraphInstance {
static function fromAnimGraph(animGraph:AnimGraph, outputNode: hrt.animgraph.nodes.AnimNode = null, modelCache: h3d.prim.ModelCache = null, resolver: AnimResolver) : AnimGraphInstance {
outputNode ??= cast animGraph.nodes.find((node) -> Std.downcast(node, hrt.animgraph.nodes.Output) != null);
if (outputNode == null)
throw "Animgraph has no output node";

var inst = new AnimGraphInstance(outputNode, resolver, animGraph.name, 1000, 1/60.0);
var inst = new AnimGraphInstance(outputNode, modelCache, resolver, animGraph.name, 1000, 1/60.0);
return inst;
}

public function new(rootNode: hrt.animgraph.nodes.AnimNode, resolver: AnimResolver = null, name: String, framesCount: Int, sampling: Float) {
public function new(rootNode: hrt.animgraph.nodes.AnimNode, modelCache: h3d.prim.ModelCache = null, resolver: AnimResolver = null, 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;
this.resolver = resolver ?? defaultResolver;
this.modelCache = modelCache ?? new h3d.prim.ModelCache();
defaultPoseNode = new hrt.animgraph.nodes.DefaultPose();
}

Expand Down Expand Up @@ -80,6 +84,17 @@ class AnimGraphInstance extends h3d.anim.Animation {
}
}

/**
Force nodes in the graph that smooth their input over time to match the
current value of their parameters
**/
public function resetSmoothedValues() {
tickRec(rootNode, 0.0);
map(rootNode, (node) -> {
node.resetSmoothedValues();
});
}

override function clone(?target: h3d.anim.Animation) : h3d.anim.Animation {
#if editor
if (editorSkipClone) {
Expand Down Expand Up @@ -128,16 +143,32 @@ class AnimGraphInstance extends h3d.anim.Animation {
map(rootNode, updateNodeInputs);

boneMap = rootNode.getBones(ctx);
rootNode.onEvent = onEventHandler;

map(rootNode, (node) -> {
var animNode = Std.downcast(node, hrt.animgraph.nodes.AnimNode);
if (animNode != null) {
animNode.setupAnimEvents();
}
});

return boneMap;
}

function onEventHandler(name: String) {
if (onEvent != null) {
onEvent(name);
}
}

override function bind(base:h3d.scene.Object) {
objects = [];
target = base;

var ctx = new hrt.animgraph.nodes.AnimNode.GetBoneContext();
ctx.targetObject = base;
ctx.resolver = resolver.bind(this, base);
ctx.modelCache = this.modelCache;

var bones = getBones(ctx);
if (bones != null) {
Expand Down
4 changes: 4 additions & 0 deletions hrt/animgraph/BlendSpace2D.hx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ class BlendSpace2D extends hrt.prefab.Prefab {

@:s var minX = 0.0;
@:s var maxX = 1.0;
@:s var smoothX = 0.0;

@:s var minY = 0.0;
@:s var maxY = 1.0;
@:s var smoothY = 0.0;


var instance : BlendSpace2DInstance;

Expand Down
8 changes: 8 additions & 0 deletions hrt/animgraph/Node.hx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ implements hide.view.GraphInterface.IGraphNode

}

/**
Called on the node when AnimGraphInstance.resetSmoothedValues is called
Should reset all the smoothed parameters to their input value OR default values
**/
public function resetSmoothedValues() : Void {

}


// Serialization api

Expand Down
4 changes: 2 additions & 2 deletions hrt/animgraph/Resource.hx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class Resource extends hxd.res.Resource {
return animGraph;
}

public function loadAnim(resolver: hrt.animgraph.AnimGraphInstance.AnimResolver = null) : AnimGraphInstance {
return load().getAnimation(resolver);
public function loadAnim(modelCache: h3d.prim.ModelCache = null, resolver: hrt.animgraph.AnimGraphInstance.AnimResolver = null) : AnimGraphInstance {
return load().getAnimation(modelCache, resolver);
}

public static var CACHE_VERSION = 0;
Expand Down
8 changes: 7 additions & 1 deletion hrt/animgraph/nodes/AnimNode.hx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class GetBoneContext {

public var targetObject:h3d.scene.Object;
public var resolver : (path: String) -> Null<String>;
public var modelCache : h3d.prim.ModelCache;
}

class GetBoneTransformContext {
Expand Down Expand Up @@ -48,10 +49,12 @@ class GetBoneTransformContext {
/**
An anim node outpus a animation that can be consumed as input parameter by other nodes
**/
class AnimNode extends Node {
abstract class AnimNode extends Node {
var numAnimInput : Int;
var boneIdToAnimInputBone : Array<Int>;

var onEvent : (String) -> Void;

inline function getInputBoneId(boneId: Int, inputId: Int) {
return boneId * numAnimInput + inputId;
}
Expand Down Expand Up @@ -102,6 +105,9 @@ class AnimNode extends Node {
function getBoneTransform(boneId: Int, outMatrix: h3d.Matrix, ctx: GetBoneTransformContext) : Void {
}

abstract function setupAnimEvents() : Void;


#if editor

override function getInfo():hide.view.GraphInterface.GraphNodeInfo {
Expand Down
9 changes: 9 additions & 0 deletions hrt/animgraph/nodes/Blend.hx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ class Blend extends AnimNode {
outMatrix._33 = m1._33 * a + m2._33 * b;
}

function setupAnimEvents() {
a.onEvent = (name:String) -> {
if (alpha < 0.5) onEvent(name);
}
b.onEvent = (name:String) -> {
if (alpha > 0.5) onEvent(name);
}
}

#if editor
override function getSize():Int {
return Node.SIZE_SMALL;
Expand Down
Loading

0 comments on commit e6f998b

Please sign in to comment.