载入中...
搜索中...
未找到
AnimationGraphRuntime.cpp
浏览该文件的文档.
2
5
6#include <map>
7#include <memory>
8#include <utility>
9
10namespace eve::animation_editing {
11namespace {
12
13const EditorValue* runtimeField(const EditorValue& value, const char* key) {
14 const auto* object = value.getIf<EditorValue::Object>();
15 if (!object) return nullptr;
16 const auto found = object->find(key);
17 return found == object->end() ? nullptr : &found->second;
18}
19
20} // namespace
21
23 const GraphDocumentData& graph, animation::AnimSkeleton* skeleton, const ClipResolver& clips) const {
24 if (!skeleton || !clips)
25 return eve::editing::failed<animation::AnimStateMachine*>(EditorStatus::Rejected,
26 RuleId("editor.animation.runtime-input"),
27 "Animation skeleton and clip resolver are required");
29 const AnimationGraphCompileResult compiled = domain.compile(graph);
30 if (compiled.status != EditorStatus::Applied)
32 eve::Status(compiled.status, compiled.diagnostics));
33
34 std::map<GraphNodeId, const GraphNodeRecord*> nodes;
35 std::map<GraphPinId, GraphNodeId> pinOwners;
36 for (const GraphNodeRecord& node : graph.nodes) {
37 nodes.emplace(node.id, &node);
38 for (const GraphPinRecord& pin : node.pins) pinOwners.emplace(pin.id, node.id);
39 }
40 std::map<GraphNodeId, GraphNodeId> from;
41 std::map<GraphNodeId, GraphNodeId> to;
42 for (const GraphEdgeRecord& edge : graph.edges) {
43 const GraphNodeId fromNode = pinOwners.at(edge.from);
44 const GraphNodeId toNode = pinOwners.at(edge.to);
45 if (nodes.at(fromNode)->type == "animation.state") from[toNode] = fromNode;
46 else to[fromNode] = toNode;
47 }
48
49 auto machine = std::make_unique<animation::AnimStateMachine>(skeleton);
50 for (const auto& [id, node] : nodes) {
51 if (node->type != "animation.state") continue;
52 const auto* clipAssetValue = runtimeField(node->properties, "clip");
53 const auto* clipAsset = clipAssetValue->getIf<std::string>();
54 animation::AnimClip* clip = clips(*clipAsset);
55 if (!clip)
56 return eve::editing::failed<animation::AnimStateMachine*>(
57 EditorStatus::NotFound, RuleId("editor.animation.clip-not-found"),
58 "Animation clip asset could not be resolved: " + *clipAsset);
59 machine->addState(id.value(), clip);
60 }
61 const auto* entryValue = runtimeField(graph.parameters, "entry");
62 machine->setEntry(*entryValue->getIf<std::string>());
63
64 for (const auto& [id, node] : nodes) {
65 if (node->type != "animation.transition") continue;
66 const double blend = *runtimeField(node->properties, "blendSeconds")->getIf<double>();
67 const bool hasExit = *runtimeField(node->properties, "hasExitTime")->getIf<bool>();
68 const double exitTime = *runtimeField(node->properties, "exitTime")->getIf<double>();
69 const std::string kind = *runtimeField(node->properties, "conditionKind")->getIf<std::string>();
70 const std::string parameter = *runtimeField(node->properties, "parameter")->getIf<std::string>();
71 const std::string op = *runtimeField(node->properties, "operator")->getIf<std::string>();
72 const double threshold = *runtimeField(node->properties, "threshold")->getIf<double>();
73 const bool boolValue = *runtimeField(node->properties, "boolValue")->getIf<bool>();
74 const int transition = machine->addTransition(from.at(id).value(), to.at(id).value(),
75 static_cast<float>(blend));
76 machine->setHasExitTime(transition, hasExit);
77 if (hasExit) machine->setExitTime(transition, static_cast<float>(exitTime));
78 if (kind == "float")
79 machine->addFloatCondition(transition, parameter, op, static_cast<float>(threshold));
80 else if (kind == "bool")
81 machine->addBoolCondition(transition, parameter, boolValue);
82 else if (kind == "trigger")
83 machine->addTriggerCondition(transition, parameter);
84 }
85 return eve::editing::applied<animation::AnimStateMachine*>(machine.release());
86}
87
88} // namespace eve::animation_editing
double value
std::string from
std::uint32_t key
glm::vec4 clip
float blend
HexCoordinates to
Cell the unit walks towards on this segment.
Definition HexUnits.cpp:64
TokenKind kind
std::vector< BvhNode > nodes
std::map< std::string, std::vector< std::string > > graph
Definition Package.cpp:59
const RoadNode * node
const RoadEdge * edge
bool found
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Structured status and zero or more diagnostics for an operation.
Definition Status.h:68
Keyframed skeletal animation clip (local TRS tracks per bone). Script type: AnimClip.
Definition AnimClip.h:145
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
animation.state graph domain matching AnimStateMachine semantics.
AnimationGraphCompileResult compile(const GraphDocumentData &graph) const
Validate and compile a graph into a deterministic runtime-neutral definition.
std::function< animation::AnimClip *(const std::string &asset)> ClipResolver
Result< animation::AnimStateMachine * > build(const GraphDocumentData &graph, animation::AnimSkeleton *skeleton, const ClipResolver &clips) const
Build an AnimStateMachine; caller owns the returned machine.
std::map< std::string, Value > Object
const T * getIf() const
Return an immediately borrowed typed value.
Compilation result for a stable-reference animation state graph asset.
Immutable graph document value sent to a domain compiler.
Directed connection between an output and input pin.
Generic graph node independent of its domain.
Stable typed pin owned by a graph node.