载入中...
搜索中...
未找到
Avatar.cpp
浏览该文件的文档.
1#include "avatar/Avatar.h"
3#include "avatar/VrmRuntime.h"
5#include "graphics/Graphics.h"
8
9#include <algorithm>
10#include <simplesquirrel/simplesquirrel.hpp>
11
12namespace eve::avatar {
13namespace {
14
15template <class Map>
16std::vector<std::string> sortedKeys(const Map& values) {
17 std::vector<std::string> names;
18 names.reserve(values.size());
19 for (const auto& [name, value] : values) {
20 (void)value;
21 names.push_back(name);
22 }
23 std::sort(names.begin(), names.end());
24 return names;
25}
26
27} // namespace
28
29void AvatarInstance::ensureParameter(const std::string& name, float value) {
30 if (name.empty()) return;
31 if (parameters_.find(name) == parameters_.end()) {
32 parameterOrder_.push_back(name);
33 parameterMetadata_.emplace(name, ParameterMetadata{value, 0.f, 1.f});
34 }
35 parameters_[name] = value;
36}
37
38bool AvatarInstance::defineParameter(const std::string& name, float defaultValue, float minimum,
39 float maximum) {
40 if (name.empty() || minimum > maximum) return false;
41 ensureParameter(name, defaultValue);
42 parameterMetadata_[name] = {defaultValue, minimum, maximum};
43 return true;
44}
45
46float AvatarInstance::getParameterDefault(const std::string& name) const {
47 const auto found = parameterMetadata_.find(name);
48 return found == parameterMetadata_.end() ? 0.f : found->second.defaultValue;
49}
50
51float AvatarInstance::getParameterMinimum(const std::string& name) const {
52 const auto found = parameterMetadata_.find(name);
53 return found == parameterMetadata_.end() ? 0.f : found->second.minimum;
54}
55
56float AvatarInstance::getParameterMaximum(const std::string& name) const {
57 const auto found = parameterMetadata_.find(name);
58 return found == parameterMetadata_.end() ? 1.f : found->second.maximum;
59}
60
61bool AvatarInstance::removeExpression(const std::string& name) {
62 return expressionDefs_.erase(name) > 0;
63}
64
66 int count = static_cast<int>(expressionDefs_.size());
67 if (vrm_)
68 for (const auto& e : vrm_->document.expressions)
69 if (!expressionDefs_.contains(e.name)) ++count;
70 return count;
71}
72
74 std::vector<std::string> names = sortedKeys(expressionDefs_);
75 if (vrm_)
76 for (const auto& e : vrm_->document.expressions) names.push_back(e.name);
77 std::sort(names.begin(), names.end());
78 names.erase(std::unique(names.begin(), names.end()), names.end());
79 return index < 0 || index >= static_cast<int>(names.size()) ? std::string{}
80 : names[static_cast<size_t>(index)];
81}
82
83bool AvatarInstance::unregisterMotion(const std::string& name) {
84 return motions_.erase(name) > 0;
85}
86
88 return static_cast<int>(motions_.size());
89}
90
91std::string AvatarInstance::getMotionName(int index) const {
92 const std::vector<std::string> names = sortedKeys(motions_);
93 return index < 0 || index >= static_cast<int>(names.size()) ? std::string{}
94 : names[static_cast<size_t>(index)];
95}
96
98 const auto found = motions_.find(name);
99 return found == motions_.end() ? nullptr : found->second;
100}
101
102Live2DBackendFactory Avatar::live2dFactory_ = &createNullLive2DBackend;
103
105
107 // Instances may outlive the module if script GC still holds them; detach.
108 for (AvatarInstance *a : avatars_) {
109 (void)a;
110 }
111 avatars_.clear();
112}
113
114void Avatar::registerInstance(AvatarInstance *a) {
115 if (!a) return;
116 if (std::find(avatars_.begin(), avatars_.end(), a) == avatars_.end())
117 avatars_.push_back(a);
118}
119
120void Avatar::unregisterInstance(AvatarInstance *a) {
121 if (!a) return;
122 auto it = std::find(avatars_.begin(), avatars_.end(), a);
123 if (it != avatars_.end()) avatars_.erase(it);
124}
125
127
129
131
132void Avatar::update(float dt) {
133 std::vector<AvatarInstance *> snapshot = avatars_;
134 for (AvatarInstance *a : snapshot) {
135 if (a) a->update(dt);
136 }
137}
138
140 std::vector<AvatarInstance *> snapshot = avatars_;
141 for (AvatarInstance *a : snapshot) {
142 if (a) a->sync();
143 }
144}
145
147 sync();
148 if (!gfx) return;
149 std::vector<graphics::DrawItem2D> items;
151 for (AvatarInstance* a : avatars_) {
152 if (a) a->collectLive2DDrawItems(items);
153 }
154 graphics::RenderSystem::drawItems(*gfx, items, false);
155}
156
157int Avatar::getAvatarCount() const { return int(avatars_.size()); }
158
160 live2dFactory_ = factory ? factory : &createNullLive2DBackend;
161}
162
164
166 Live2DBackendFactory f = live2dFactory_ ? live2dFactory_ : &createNullLive2DBackend;
167 return f();
168}
169
172 if (!tmp) return "none";
173 std::string n = tmp->getName();
174 delete tmp;
175 return n;
176}
177
180 if (!tmp) return false;
181 const bool available = tmp->isRuntimeAvailable();
182 delete tmp;
183 return available;
184}
185
186void Avatar::expose(ssq::Table &table) {
187 auto cls = table.addClass(name, Avatar::create, false);
188 expose(cls);
189
190 auto av = table.addClass<AvatarInstance>(
191 "AvatarInstance",
192 std::function<AvatarInstance *()>([]() -> AvatarInstance * { return nullptr; }), true);
193
194 av.addFunc("getKind", &AvatarInstance::getKind);
195 av.addFunc("setPosition", &AvatarInstance::setPosition);
196 av.addFunc("getX", &AvatarInstance::getX);
197 av.addFunc("getY", &AvatarInstance::getY);
198 av.addFunc("setScale", &AvatarInstance::setScale);
199 av.addFunc("getScaleX", &AvatarInstance::getScaleX);
200 av.addFunc("getScaleY", &AvatarInstance::getScaleY);
201 av.addFunc("setVisible", &AvatarInstance::setVisible);
202 av.addFunc("isVisible", &AvatarInstance::isVisible);
203 av.addFunc("setLayer", &AvatarInstance::setLayer);
204 av.addFunc("getLayer", &AvatarInstance::getLayer);
205 av.addFunc("setExpression", &AvatarInstance::setExpression);
206 av.addFunc("getExpression", &AvatarInstance::getExpression);
207 av.addFunc("setMotion", &AvatarInstance::setMotion);
208 av.addFunc("getMotion", &AvatarInstance::getMotion);
209 av.addFunc("setParameter", &AvatarInstance::setParameter);
210 av.addFunc("getParameter", &AvatarInstance::getParameter);
211 av.addFunc("hasParameter", &AvatarInstance::hasParameter);
212 av.addFunc("getParameterCount", &AvatarInstance::getParameterCount);
213 av.addFunc("getParameterName", &AvatarInstance::getParameterName);
214 av.addFunc("defineParameter", &AvatarInstance::defineParameter);
215 av.addFunc("getParameterDefault", &AvatarInstance::getParameterDefault);
216 av.addFunc("getParameterMinimum", &AvatarInstance::getParameterMinimum);
217 av.addFunc("getParameterMaximum", &AvatarInstance::getParameterMaximum);
218 av.addFunc("update", &AvatarInstance::update);
219 av.addFunc("sync", &AvatarInstance::sync);
220 av.addFunc("release", &AvatarInstance::release);
221
222 // addLayer / setLayerTexture accept a nullable texture (colored placeholder
223 // layers). ssq's default pointer binding rejects Squirrel `null`, so accept
224 // ssq::Object and translate null -> nullptr.
225 av.addFunc("addLayer", [](AvatarInstance *a, const std::string &name, ssq::Object textureObj,
226 int zIndex) -> bool {
227 graphics::Texture *tex =
228 textureObj.isNull() ? nullptr : textureObj.toPtrUnsafe<graphics::Texture *>();
229 return a->addLayer(name, tex, zIndex);
230 });
231 av.addFunc("setLayerTexture", [](AvatarInstance *a, const std::string &name,
232 ssq::Object textureObj) -> bool {
233 graphics::Texture *tex =
234 textureObj.isNull() ? nullptr : textureObj.toPtrUnsafe<graphics::Texture *>();
235 return a->setLayerTexture(name, tex);
236 });
237 av.addFunc("setLayerVisible", &AvatarInstance::setLayerVisible);
238 av.addFunc("setLayerOffset", &AvatarInstance::setLayerOffset);
239 av.addFunc("setLayerColor", &AvatarInstance::setLayerColor);
240 av.addFunc("setLayerZ", &AvatarInstance::setLayerZ);
241 av.addFunc("setLayerSize", &AvatarInstance::setLayerSize);
242 av.addFunc("getLayerCount", &AvatarInstance::getLayerCount);
243 av.addFunc("getLayerName", &AvatarInstance::getLayerName);
244 av.addFunc("hasLayer", &AvatarInstance::hasLayer);
245 av.addFunc("getLayerRenderable", &AvatarInstance::getLayerRenderable);
246 av.addFunc("defineExpression", &AvatarInstance::defineExpression);
247 av.addFunc("removeExpression", &AvatarInstance::removeExpression);
248 av.addFunc("getExpressionCount", &AvatarInstance::getExpressionCount);
249 av.addFunc("getExpressionName", &AvatarInstance::getExpressionName);
250 av.addFunc("applyExpression", &AvatarInstance::applyExpression);
251 av.addFunc("transitionExpression", &AvatarInstance::transitionExpression);
252
253 av.addFunc("loadLive2DModel", &AvatarInstance::loadLive2DModel);
254 av.addFunc("getLive2DBackendName", &AvatarInstance::getLive2DBackendName);
255 av.addFunc("hasLive2DBackend", &AvatarInstance::hasLive2DBackend);
256
257 av.addFunc("loadVroidModel", [vm = table.getHandle()](AvatarInstance* avatar, const std::string& path) {
258 return eve::script::projectResult(vm, avatar->loadVroidModel(path));
259 });
260 av.addFunc("setHumanoidBoneRotation", [vm = table.getHandle()](AvatarInstance* avatar, const std::string& semantic,
261 float yaw, float pitch, float roll) {
262 return eve::script::projectResult(vm, avatar->setHumanoidBoneRotation(semantic, yaw, pitch, roll));
263 });
264 av.addFunc("getVroidMeshCount", &AvatarInstance::getVroidMeshCount);
265 av.addFunc("getVroidSpringCount", &AvatarInstance::getVroidSpringCount);
266 av.addFunc("getVroidVersion", &AvatarInstance::getVroidVersion);
267 av.addFunc("loadVroidModelPath", &AvatarInstance::loadVroidModelPath);
268 av.addFunc("bindVroidModelData", &AvatarInstance::bindVroidModelData);
269 av.addFunc("loadMorphNamesFromModel", &AvatarInstance::loadMorphNamesFromModel);
270 av.addFunc("setMesh", &AvatarInstance::setMesh);
271 av.addFunc("setTexture", &AvatarInstance::setTexture);
272 av.addFunc("setPosition3D", &AvatarInstance::setPosition3D);
273 av.addFunc("setRotation3D", &AvatarInstance::setRotation3D);
274 av.addFunc("setScale3D", &AvatarInstance::setScale3D);
275 av.addFunc("getRenderable3D", &AvatarInstance::getRenderable3D);
276 av.addFunc("getBoundMesh", &AvatarInstance::getBoundMesh);
277 av.addFunc("getVroidModelPath", &AvatarInstance::getVroidModelPath);
278 av.addFunc("bakeMorphs", &AvatarInstance::bakeMorphs);
279 av.addFunc("bindAnimPlayer", &AvatarInstance::bindAnimPlayer);
280 av.addFunc("bindAnimStateMachine", &AvatarInstance::bindAnimStateMachine);
281 av.addFunc("bindAnimLayerMixer", &AvatarInstance::bindAnimLayerMixer);
282 av.addFunc("setAnimConstraintStack", [](AvatarInstance* a, animation::AnimConstraintStack* stack) -> void {
283 a->setAnimConstraintStack(stack);
284 });
285 av.addFunc("getAnimConstraintStack", &AvatarInstance::getAnimConstraintStack);
286 av.addFunc("setFootIKSolver", [](AvatarInstance* a, animation::FootIKSolver* solver) -> void {
287 a->setFootIKSolver(solver);
288 });
289 av.addFunc("getFootIKSolver", &AvatarInstance::getFootIKSolver);
290 av.addFunc("setDynamicBoneSolver", [](AvatarInstance* a, animation::DynamicBoneSolver* solver) -> void {
291 a->setDynamicBoneSolver(solver);
292 });
293 av.addFunc("getDynamicBoneSolver", &AvatarInstance::getDynamicBoneSolver);
294 av.addFunc("bindAnimSkin", &AvatarInstance::bindAnimSkin);
295 av.addFunc("bindSkinnedPart",
296 [](AvatarInstance* a, int partIndex, const std::string& partName,
297 graphics::Mesh* mesh, graphics::Material* material,
298 animation::AnimSkin* skin) -> int {
299 return static_cast<int>(
300 a->bindSkinnedPart(partIndex, partName, mesh, material, skin));
301 });
302 av.addFunc("unbindSkinnedPart", [](AvatarInstance* a, int partIndex) -> int {
303 return static_cast<int>(a->unbindSkinnedPart(partIndex));
304 });
305 av.addFunc("getSkinnedPartUpdateMode", [](AvatarInstance* a, int partIndex) -> int {
306 return static_cast<int>(a->getSkinnedPartUpdateMode(partIndex));
307 });
308 av.addFunc("registerMotion", &AvatarInstance::registerMotion);
309 av.addFunc("unregisterMotion", &AvatarInstance::unregisterMotion);
310 av.addFunc("getMotionCount", &AvatarInstance::getMotionCount);
311 av.addFunc("getMotionName", &AvatarInstance::getMotionName);
312 av.addFunc("getMotionClip", &AvatarInstance::getMotionClip);
313 av.addFunc("setMotionBlendTime", &AvatarInstance::setMotionBlendTime);
314 av.addFunc("setApplyRootMotion", &AvatarInstance::setApplyRootMotion);
315 av.addFunc("getApplyRootMotion", &AvatarInstance::getApplyRootMotion);
316 av.addFunc("getRootMotionDeltaX", &AvatarInstance::getRootMotionDeltaX);
317 av.addFunc("getRootMotionDeltaZ", &AvatarInstance::getRootMotionDeltaZ);
318 av.addFunc("getAnimationEventCount", &AvatarInstance::getAnimationEventCount);
319 av.addFunc("getAnimationEventLayer", &AvatarInstance::getAnimationEventLayer);
320 av.addFunc("getAnimationEventName", &AvatarInstance::getAnimationEventName);
321 av.addFunc("getAnimationEventPayload", &AvatarInstance::getAnimationEventPayload);
322 av.addFunc("mapHumanoidBone", &AvatarInstance::mapHumanoidBone);
323 av.addFunc("autoMapHumanoidBones", &AvatarInstance::autoMapHumanoidBones);
324 av.addFunc("getHumanoidBoneName", &AvatarInstance::getHumanoidBoneName);
325 av.addFunc("mapViseme", &AvatarInstance::mapViseme);
326 av.addFunc("setViseme", &AvatarInstance::setViseme);
327 av.addFunc("setLookAtTarget", &AvatarInstance::setLookAtTarget);
328 av.addFunc("setLookAtWeight", &AvatarInstance::setLookAtWeight);
329 av.addFunc("clearLookAtTarget", &AvatarInstance::clearLookAtTarget);
330 av.addFunc("attachToBone", &AvatarInstance::attachToBone);
331 av.addFunc("detachAttachment", &AvatarInstance::detachAttachment);
332 av.addFunc("getAttachmentCount", &AvatarInstance::getAttachmentCount);
333 av.addFunc("linkSceneNode", &AvatarInstance::linkSceneNode);
334 av.addFunc("isSceneLinked", &AvatarInstance::isSceneLinked);
335 av.addFunc("bindEquipment", [](AvatarInstance* a, inventory::EquipmentSet* equipment) -> int {
336 return static_cast<int>(a->bindEquipment(equipment));
337 });
338 av.addFunc("unbindEquipment", [](AvatarInstance* a) -> int {
339 return static_cast<int>(a->unbindEquipment());
340 });
341 av.addFunc("syncEquipmentAppearance", [](AvatarInstance* a) -> int {
342 return static_cast<int>(a->syncEquipmentAppearance());
343 });
344 av.addFunc("getEquipmentVisualItem", &AvatarInstance::getEquipmentVisualItem);
345 av.addFunc("defineEquipmentLayer",
346 [](AvatarInstance* a, const std::string& name, int order,
347 const std::string& parent) -> int {
348 return static_cast<int>(a->defineEquipmentLayer(name, order, parent));
349 });
350 av.addFunc("addEquipmentLayerOcclusion",
351 [](AvatarInstance* a, const std::string& outerLayer,
352 const std::string& innerLayer) -> int {
353 return static_cast<int>(
354 a->addEquipmentLayerOcclusion(outerLayer, innerLayer));
355 });
356 av.addFunc("setEquipmentVisualLayer",
357 [](AvatarInstance* a, const std::string& itemId,
358 const std::string& equipmentSlot, const std::string& wearLayer,
359 int withinLayerOrder) -> int {
360 return static_cast<int>(a->setEquipmentVisualLayer(
361 itemId, equipmentSlot, wearLayer, withinLayerOrder));
362 });
363 av.addFunc("getEquipmentRenderStackCount", &AvatarInstance::getEquipmentRenderStackCount);
364 av.addFunc("getEquipmentRenderStackItem", &AvatarInstance::getEquipmentRenderStackItem);
365 av.addFunc("getEquipmentRenderStackLayer", &AvatarInstance::getEquipmentRenderStackLayer);
366 av.addFunc("defineEquipmentVisual2D",
367 [](AvatarInstance* a, const std::string& itemId, const std::string& equipmentSlot,
368 const std::string& layerName, ssq::Object textureObj, int zIndex) -> int {
369 graphics::Texture* texture = textureObj.isNull()
370 ? nullptr
371 : textureObj.toPtrUnsafe<graphics::Texture*>();
372 return static_cast<int>(a->defineEquipmentVisual2D(
373 itemId, equipmentSlot, layerName, texture, zIndex));
374 });
375 av.addFunc("defineEquipmentVisual3D",
376 [](AvatarInstance* a, const std::string& itemId, const std::string& equipmentSlot,
377 graphics::Renderable3D* renderable, const std::string& bone, float ox, float oy,
378 float oz) -> int {
379 return static_cast<int>(a->defineEquipmentVisual3D(
380 itemId, equipmentSlot, renderable, bone, ox, oy, oz));
381 });
382 av.addFunc("defineEquipmentSkinnedVisual3D",
383 [](AvatarInstance* a, const std::string& itemId,
384 const std::string& equipmentSlot, int partIndex,
385 const std::string& partName, graphics::Mesh* mesh,
386 graphics::Material* material, animation::AnimSkin* skin) -> int {
387 return static_cast<int>(a->defineEquipmentSkinnedVisual3D(
388 itemId, equipmentSlot, partIndex, partName, mesh, material, skin));
389 });
390 av.addFunc("bindTween", &AvatarInstance::bindTween);
391 av.addFunc("unbindTween", &AvatarInstance::unbindTween);
392 av.addFunc("getBoundTween", &AvatarInstance::getBoundTween);
393}
394
395void Avatar::expose(ssq::Class &cls) {
396 cls.addFunc("getName", &Avatar::getName);
397 cls.addFunc("newImageAvatar", &Avatar::newImageAvatar);
398 cls.addFunc("newLive2DAvatar", &Avatar::newLive2DAvatar);
399 cls.addFunc("newVroidAvatar", &Avatar::newVroidAvatar);
400 cls.addFunc("update", &Avatar::update);
401 cls.addFunc("sync", &Avatar::sync);
402 cls.addFunc("render", &Avatar::render);
403 cls.addFunc("getAvatarCount", &Avatar::getAvatarCount);
404 // Static method: wrap so SSQ gets an instance-method signature (raw static
405 // function pointers make Class::addFunc recurse until stack overflow).
406 cls.addFunc("getLive2DBackendName",
407 [](Avatar *) -> std::string { return Avatar::getLive2DBackendName(); });
408 cls.addFunc("hasLive2DBackend", [](Avatar*) -> bool { return Avatar::hasLive2DBackend(); });
409}
410
411} // namespace eve::avatar
double value
LogicalId itemId
HSQUIRRELVM vm
Definition ECS.cpp:20
HSQOBJECT cls
Definition ECS.cpp:21
std::map< std::string, Var > values
float maximum[3]
float minimum[3]
glm::vec3 n
Definition Grass.cpp:63
std::uint32_t bone
std::int32_t parent
std::string name
MeleePoint3 a
Definition MeleeHit.cpp:40
std::vector< std::int32_t > order
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:26
float f
std::string path
Definition PlayHost.cpp:110
Mesh * mesh
Material * material
bool found
std::uint32_t count
The single Squirrel projection for common Result, Status and Value.
uint32_t index
double oy
double ox
uint32_t semantic
Definition WfcSimple.cpp:15
virtual std::string getName() const =0
Returns the name.
Keyframed skeletal animation clip (local TRS tracks per bone). Script type: AnimClip.
Definition AnimClip.h:145
Unified avatar instance. Kind is a string: "image" | "live2d" | "vroid". Script-facing API avoids ove...
void setScale(float sx, float sy)
Sets the scale.
void setExpression(const std::string &name)
Sets the expression.
bool bindAnimStateMachine(animation::AnimStateMachine *machine)
Bind an animation state machine that the avatar advances each update.
bool setLayerColor(const std::string &name, float r, float g, float b, float a)
Sets the layer color.
void setApplyRootMotion(bool enabled)
Apply root-bone X/Z deltas to the Avatar transform while animating.
bool setLayerOffset(const std::string &name, float ox, float oy)
Sets the layer offset.
float getParameterDefault(const std::string &name) const
Return a reflected parameter default, or zero for an unknown parameter.
Definition Avatar.cpp:46
float getScaleX() const
Returns the scale x.
std::string getAnimationEventLayer(int index) const
Source layer for an animation event ("base" for the base player).
int getMotionCount() const
Return the number of registered skeletal motions.
Definition Avatar.cpp:87
void setLayer(int layer)
Sets the layer.
std::string getHumanoidBoneName(const std::string &semantic) const
Return the mapped skeleton bone name, or an empty string.
void clearLookAtTarget()
Disable procedural head look-at.
bool isVisible() const
True when visible.
int getVroidSpringCount() const
Number of imported VRM spring chains.
void sync()
Push image / live2d layers into ECS or draw queues.
float getParameter(const std::string &name) const
Returns the parameter.
std::string getMotion() const
Returns the motion.
float getX() const
Returns the x.
bool registerMotion(const std::string &name, animation::AnimClip *clip)
Register a motion name for setMotion(); the clip is not owned.
int autoMapHumanoidBones()
Auto-map common VRM humanoid semantics from the currently bound skeleton.
bool bindAnimPlayer(animation::AnimPlayer *player)
Bind a clip player that the avatar advances and skins each update.
std::string getVroidModelPath() const
Returns the vroid model path.
std::string getExpression() const
Returns the expression.
bool mapViseme(const std::string &viseme, const std::string &morphName)
Map a VRM viseme/expression semantic to an existing mesh morph.
bool detachAttachment(const std::string &name)
Remove an attachment without destroying its Renderable3D.
std::string getAnimationEventPayload(int index) const
Animation event payload, or empty for an invalid index.
void bindTween(animation::Tween *tween)
Drive x/y/sx/sy and matching parameters from a Tween each update().
bool hasLayer(const std::string &name) const
True when layer.
animation::DynamicBoneSolver * getDynamicBoneSolver() const
Return the Avatar-owned solver, or null. @ownership Borrowed from this Avatar. @lifetime Valid until ...
bool attachToBone(const std::string &name, const std::string &boneSemanticOrName, graphics::Renderable3D *renderable, float ox=0.f, float oy=0.f, float oz=0.f)
Attach a non-owned Renderable3D to a mapped humanoid semantic or bone name.
animation::AnimConstraintStack * getAnimConstraintStack() const
Return the Avatar-owned constraint stack, or null. @ownership Borrowed from this Avatar....
bool applyExpression(const std::string &name)
Applies expression.
std::string getParameterName(int index) const
Returns the parameter name.
float getRootMotionDeltaZ() const
Last evaluated root-motion Z delta.
graphics::Renderable2D * getLayerRenderable(const std::string &name)
Return the native Renderable2D owned by a named image layer.
std::string getEquipmentRenderStackItem(int index) const
Active item id at a render-stack index, or empty text.
std::string getKind() const
Returns the kind.
bool bindAnimLayerMixer(animation::AnimLayerMixer *mixer)
Bind an override/additive layer mixer that the avatar advances each update.
graphics::Mesh * getBoundMesh() const
Borrow the first imported mesh, or the manually bound mesh.
bool getApplyRootMotion() const
Return whether root motion is applied to the Avatar transform.
bool linkSceneNode(scene::Scene *scene, const std::string &nodeId)
Link this avatar to a node in Scene's current host.
void setVisible(bool visible)
Sets the visible.
void update(float dt)
Updates .
float getY() const
Returns the y.
int getEquipmentRenderStackCount() const
Number of active visuals in canonical back-to-front render order.
bool loadVroidModelPath(const std::string &path)
Compatibility-only bool projection of loadVroidModel; performs the real import.
int getLayerCount() const
Returns the layer count.
std::string getVroidVersion() const
Imported VRM specification version, or empty before import.
bool bindVroidModelData(model3d::ModelData *data)
Binds vroid model data.
int getExpressionCount() const
Return the number of imported and project-defined expressions.
Definition Avatar.cpp:65
void setMesh(graphics::Mesh *mesh)
Sets the mesh.
bool defineParameter(const std::string &name, float defaultValue, float minimum, float maximum)
Define reflected Avatar parameter metadata for project-built inspectors.
Definition Avatar.cpp:38
bool bindAnimSkin(animation::AnimSkin *skin)
Bind CPU skin data used to deform the avatar mesh from the active pose.
void unbindTween()
Unbinds tween.
std::string getExpressionName(int index) const
Return a stable sorted expression name, or empty text.
Definition Avatar.cpp:73
float getScaleY() const
Returns the scale y.
animation::AnimClip * getMotionClip(const std::string &name) const
Return a registered non-owned motion clip, or nullptr.
Definition Avatar.cpp:97
int loadMorphNamesFromModel(int meshIndex=0)
Register morph target names from ModelData as parameters (weights default 0).
void setParameter(const std::string &name, float value)
Sets the parameter.
float getRootMotionDeltaX() const
Last evaluated root-motion X delta.
bool transitionExpression(const std::string &name, float duration)
Blend numeric/bool expression channels over duration seconds.
std::string getAnimationEventName(int index) const
Animation event name, or empty for an invalid index.
std::string getLayerName(int index) const
Returns the layer name.
bool bakeMorphs()
Push parameter weights onto Mesh morphs and bake GPU verts when possible.
void setTexture(graphics::Texture *texture)
Sets the texture.
bool setLookAtTarget(float x, float y, float z)
Set a world-space target tracked by the mapped humanoid head bone.
bool setViseme(const std::string &viseme, float weight)
Set a mapped viseme weight and clear the previously active viseme.
std::string getEquipmentVisualItem(const std::string &equipmentSlot) const
Return the currently projected item for a slot, or empty text when none is shown.
bool hasLive2DBackend() const
True when live 2 d backend.
std::string getEquipmentRenderStackLayer(int index) const
Wear-layer name at a render-stack index, or empty text.
void setPosition(float x, float y)
Sets the position.
bool mapHumanoidBone(const std::string &semantic, const std::string &boneName)
Map a VRM humanoid semantic (for example "head") to a skeleton bone.
void setMotion(const std::string &name)
Sets the motion.
void setRotation3D(float yaw, float pitch, float roll)
Sets the rotation 3 d.
animation::Tween * getBoundTween() const
Returns the bound tween.
bool loadLive2DModel(const std::string &path)
Loads live 2 d model.
bool setLayerZ(const std::string &name, int zIndex)
Sets the layer z.
int getParameterCount() const
Returns the parameter count.
void setMotionBlendTime(float seconds)
Set the cross-fade duration used when switching registered motions.
bool isSceneLinked() const
Return whether this avatar is currently scene-driven.
bool removeExpression(const std::string &name)
Remove a project-defined expression.
Definition Avatar.cpp:61
bool unregisterMotion(const std::string &name)
Remove a registered motion without destroying its clip.
Definition Avatar.cpp:83
animation::FootIKSolver * getFootIKSolver() const
Return the Avatar-owned paired-foot IK solver, or null. @ownership Borrowed from this Avatar....
std::string getMotionName(int index) const
Return a stable sorted motion name, or empty text.
Definition Avatar.cpp:91
std::string getLive2DBackendName() const
Returns the live 2 d backend name.
bool setLayerSize(const std::string &name, float w, float h)
Sets the layer size.
int getAttachmentCount() const
Return the number of active bone attachments.
void setScale3D(float sx, float sy, float sz)
Sets the scale 3 d.
int getVroidMeshCount() const
Number of imported mesh primitives; zero before successful import.
float getParameterMinimum(const std::string &name) const
Return a reflected parameter minimum, or zero for an unknown parameter.
Definition Avatar.cpp:51
bool setLayerVisible(const std::string &name, bool visible)
Sets the layer visible.
void setLookAtWeight(float weight)
Set VRM-style head look-at influence in the range 0..1.
float getParameterMaximum(const std::string &name) const
Return a reflected parameter maximum, or one for an unknown parameter.
Definition Avatar.cpp:56
bool hasParameter(const std::string &name) const
True when parameter.
int getLayer() const
Returns the layer.
bool defineExpression(const std::string &name, const std::string &spec)
Spec: "eyes=1;mouth=smile;blush=0" (semicolon-separated name=value).
graphics::Renderable3D * getRenderable3D() const
Borrow the first imported render projection, or the manual projection.
void setPosition3D(float x, float y, float z)
Sets the position 3 d.
int getAnimationEventCount() const
Number of animation events emitted by the latest update.
Avatar module — layered character rendering for VN / portrait use. Script: avatar <- eve....
Definition Avatar.h:25
static void registerLive2DBackend(Live2DBackendFactory factory)
C++ / plugin: replace Live2D backend factory. Pass nullptr to restore the built-in NullLive2DBackend ...
Definition Avatar.cpp:159
static Live2DBackendFactory live2DBackendFactory()
Live 2 d backend factory.
Definition Avatar.cpp:163
Avatar()=default
Avatar.
void render(graphics::Graphics *gfx)
Sync then draw Image/Live2D avatars via the shared 2D sprite queue (does not present)....
Definition Avatar.cpp:146
void update(float dt)
Updates .
Definition Avatar.cpp:132
AvatarInstance * newLive2DAvatar()
Creates a live 2 d avatar. @ownership Caller deletes unless documented otherwise.
Definition Avatar.cpp:128
~Avatar() override
Avatar.
Definition Avatar.cpp:106
static bool hasLive2DBackend()
True when the active backend is a real rendering runtime, not the null stub.
Definition Avatar.cpp:178
AvatarInstance * newImageAvatar()
Creates a image avatar. @ownership Caller deletes unless documented otherwise.
Definition Avatar.cpp:126
int getAvatarCount() const
Returns the avatar count.
Definition Avatar.cpp:157
static std::string getLive2DBackendName()
Backend name currently in effect ("null" when using the built-in stub).
Definition Avatar.cpp:170
friend class AvatarInstance
Definition Avatar.h:67
AvatarInstance * newVroidAvatar()
Creates a vroid avatar. @ownership Caller deletes unless documented otherwise.
Definition Avatar.cpp:130
static ILive2DBackend * createLive2DBackend()
Always returns a backend: custom factory, else NullLive2DBackend.
Definition Avatar.cpp:165
void sync()
Sync all live avatars into renderables.
Definition Avatar.cpp:139
Optional Live2D runtime backend (Cubism etc.). Registered from C++ / plugins.
virtual std::string getName() const =0
Returns the name.
virtual bool isRuntimeAvailable() const
True only for a backend that can render a real Live2D model.
static void collectSprites(std::vector< DrawItem2D > &out)
Append visible Renderable2D sprites into a shared queue.
static void drawItems(Graphics &gfx, std::vector< DrawItem2D > &items, bool present)
Sort and draw items. If present=true, calls gfx.present() at the end. Map::render uses present=false ...
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
const char * defaultValue
ILive2DBackend *(*)() Live2DBackendFactory
ILive2DBackend * createNullLive2DBackend()
Creates null live 2 d backend.
std::unordered_map< std::string, SkillDefinition > & table()
Definition Skill.cpp:65
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.