Made better code formatting

This commit is contained in:
2023-09-15 12:09:17 +03:00
parent 2ac6c4afe1
commit e8a1b7e828
9 changed files with 721 additions and 506 deletions

189
src/modules/.clang-format Normal file
View File

@@ -0,0 +1,189 @@
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 13.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
# AlignArrayOfStructures: None
# AlignConsecutiveMacros: None
# AlignConsecutiveAssignments: None
# AlignConsecutiveBitFields: None
# AlignConsecutiveDeclarations: None
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments: false
# AllowAllArgumentsOnNextLine: true
# AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
# AllowShortFunctionsOnASingleLine: All
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: MultiLine
# AttributeMacros:
# - __capability
# BinPackArguments: true
# BinPackParameters: true
BraceWrapping:
# AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
# BeforeLambdaBody: false
# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakBeforeBinaryOperators: None
# BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Custom
# BreakBeforeInheritanceComma: false
# BreakInheritanceList: BeforeColon
# BreakBeforeTernaryOperators: true
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
# CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
# DeriveLineEnding: true
# DerivePointerAlignment: false
# DisableFormat: false
# EmptyLineAfterAccessModifier: Never
# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
# IfMacros:
# - KJ_IF_MAYBE
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: '".*"'
Priority: 1
- Regex: '^<.*\.h>'
Priority: 2
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
# IncludeIsMainSourceRegex: ''
# IndentAccessModifiers: false
IndentCaseLabels: true
# IndentCaseBlocks: false
# IndentGotoLabels: true
# IndentPPDirectives: None
# IndentExternBlock: AfterExternBlock
# IndentRequires: false
IndentWidth: 8
# IndentWrappedFunctionNames: false
# InsertTrailingCommas: None
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
# LambdaBodyIndentation: Signature
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
# PenaltyBreakAssignment: 2
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
# PenaltyIndentedWhitespace: 0
# PointerAlignment: Right
# PPIndentWidth: -1
# ReferenceAlignment: Pointer
# ReflowComments: true
# ShortNamespaceLines: 1
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: true
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeCaseColon: false
# SpaceBeforeCpp11BracedList: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeParens: ControlStatements
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeRangeBasedForLoopColon: true
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpaceInEmptyBlock: false
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: Never
# SpacesInContainerLiterals: true
# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
## our comment capitalization at the same time.
SpacesInLineCommentPrefix:
Minimum: 0
Maximum: -1
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
# SpaceBeforeSquareBrackets: false
# BitFieldColonSpacing: Both
# StatementAttributeLikeMacros:
# - Q_EMIT
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 8
# UseCRLF: false
UseTab: Always
# WhitespaceSensitiveMacros:
# - STRINGIZE
# - PP_STRINGIZE
# - BOOST_PP_STRINGIZE
# - NS_SWIFT_NAME
# - CF_SWIFT_NAME
---
### C++ specific config ###
Language: Cpp
Standard: c++14
---
### ObjC specific config ###
Language: ObjC
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
---
### Java specific config ###
Language: Java
# BreakAfterJavaFieldAnnotations: false
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
...

View File

@@ -5,28 +5,28 @@
/* private functions */ /* private functions */
namespace ECS { namespace ECS {
static void _animation_process_animation(struct AnimationPlayerData *player, AnimationData *p_anim, static void _animation_process_animation(struct AnimationPlayerData *player, AnimationData *p_anim,
float p_time, float p_delta, float p_interp, float p_time, float p_delta, float p_interp,
bool p_is_current = true, bool p_seeked = false, bool p_is_current = true, bool p_seeked = false,
bool p_started = false); bool p_started = false);
static void _ensure_node_caches(struct AnimationPlayerData *player, static void _ensure_node_caches(struct AnimationPlayerData *player,
AnimationData *p_anim, Node *p_root_override = NULL); AnimationData *p_anim, Node *p_root_override = NULL);
static void _animation_process_data(struct AnimationPlayerData *player, static void _animation_process_data(struct AnimationPlayerData *player,
PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started); PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started);
static void _animation_process2(struct AnimationPlayerData *player, static void _animation_process2(struct AnimationPlayerData *player,
float p_delta, bool p_started); float p_delta, bool p_started);
static void _animation_update_transforms(struct AnimationPlayerData *player); static void _animation_update_transforms(struct AnimationPlayerData *player);
static void _animation_process(struct AnimationPlayerData *player, static void _animation_process(struct AnimationPlayerData *player,
float p_delta); float p_delta);
// static void _node_removed(struct AnimationPlayerData *player, // static void _node_removed(struct AnimationPlayerData *player,
// Node *p_node); // Node *p_node);
static void _stop_playing_caches(struct AnimationPlayerData *player); static void _stop_playing_caches(struct AnimationPlayerData *player);
static void _animation_changed(struct AnimationPlayerData *player); static void _animation_changed(struct AnimationPlayerData *player);
static void _ref_anim(struct AnimationPlayerData *player, static void _ref_anim(struct AnimationPlayerData *player,
const Ref<Animation> &p_anim); const Ref<Animation> &p_anim);
static void _unref_anim(struct AnimationPlayerData *player, static void _unref_anim(struct AnimationPlayerData *player,
const Ref<Animation> &p_anim); const Ref<Animation> &p_anim);
static void _set_process(struct AnimationPlayerData *player, static void _set_process(struct AnimationPlayerData *player,
bool p_process, bool p_force = false); bool p_process, bool p_force = false);
/* protected functions (need redesign) */ /* protected functions (need redesign) */
#if 0 #if 0
bool _set(const StringName &p_name, const Variant &p_value); bool _set(const StringName &p_name, const Variant &p_value);
@@ -36,11 +36,11 @@ void _get_property_list(List<PropertyInfo> *p_list) const;
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
#endif #endif
} } //namespace ECS
void ECS::play(struct ECS::AnimationPlayerData *player, void ECS::play(struct ECS::AnimationPlayerData *player,
const StringName &p_name, const StringName &p_name,
float p_custom_blend, float p_custom_scale, float p_custom_blend, float p_custom_scale,
bool p_from_end) bool p_from_end)
{ {
StringName name = p_name; StringName name = p_name;
@@ -131,7 +131,7 @@ void ECS::play(struct ECS::AnimationPlayerData *player,
} }
} }
static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player, static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
AnimationData *p_anim, Node *p_root_override) AnimationData *p_anim, Node *p_root_override)
{ {
// Already cached? // Already cached?
if (p_anim->node_cache.size() == p_anim->animation->get_track_count()) { if (p_anim->node_cache.size() == p_anim->animation->get_track_count()) {
@@ -256,9 +256,9 @@ static void ECS::_ensure_node_caches(struct ECS::AnimationPlayerData *player,
} }
} }
static void ECS::_animation_process_animation(struct ECS::AnimationPlayerData *player, ECS::AnimationData *p_anim, static void ECS::_animation_process_animation(struct ECS::AnimationPlayerData *player, ECS::AnimationData *p_anim,
float p_time, float p_delta, float p_interp, float p_time, float p_delta, float p_interp,
bool p_is_current, bool p_seeked, bool p_is_current, bool p_seeked,
bool p_started) bool p_started)
{ {
_ensure_node_caches(player, p_anim); _ensure_node_caches(player, p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count()); ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -728,76 +728,92 @@ static void ECS::_animation_process_animation(struct ECS::AnimationPlayerData *p
} }
} }
static void ECS::_animation_process_data(struct ECS::AnimationPlayerData *player, static void ECS::_animation_process_data(struct ECS::AnimationPlayerData *player,
PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started) PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started)
{ {
float delta = p_delta * player->speed_scale * cd.speed_scale; float delta = p_delta * player->speed_scale * cd.speed_scale;
float next_pos = cd.pos + delta; float next_pos = cd.pos + delta;
float len = cd.from->animation->get_length(); if (cd.from->animation.is_null()) {
bool loop = cd.from->animation->has_loop(); ERR_PRINT("bad animation");
if (!loop) { return;
if (next_pos < 0) }
next_pos = 0; float len = cd.from->animation->get_length();
else if (next_pos > len) bool loop = cd.from->animation->has_loop();
next_pos = len; if (!loop) {
} if (next_pos < 0)
bool backwards = signbit(delta); // Negative zero means playing backwards too next_pos = 0;
delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here) else if (next_pos > len)
if (&cd == &player->playback.current) { next_pos = len;
if (!backwards && cd.pos <= len && next_pos == len) { }
//playback finished bool backwards = signbit(delta); // Negative zero means playing backwards too
player->end_reached = true; delta = next_pos - cd.pos; // Fix delta (after determination of backwards because negative zero is lost here)
player->end_notify = cd.pos < len; // Notify only if not already at the end if (&cd == &player->playback.current) {
} if (!backwards && cd.pos <= len && next_pos == len) {
if (backwards && cd.pos >= 0 && next_pos == 0) { //playback finished
//playback finished player->end_reached = true;
player->end_reached = true; player->end_notify = cd.pos < len; // Notify only if not already at the end
player->end_notify = cd.pos > 0; // Notify only if not already at the beginning }
} if (backwards && cd.pos >= 0 && next_pos == 0) {
} else { //playback finished
float looped_next_pos = Math::fposmod(next_pos, len); player->end_reached = true;
if (looped_next_pos == 0 && next_pos != 0) player->end_notify = cd.pos > 0; // Notify only if not already at the beginning
// Loop multiples of the length to it, rather than 0 }
// so state at time=length is previewable in the editor } else {
next_pos = len; float looped_next_pos = Math::fposmod(next_pos, len);
else if (looped_next_pos == 0 && next_pos != 0)
next_pos = looped_next_pos; // Loop multiples of the length to it, rather than 0
} // so state at time=length is previewable in the editor
cd.pos = next_pos; next_pos = len;
_animation_process_animation(player, cd.from, else
cd.pos, delta, p_blend, &cd == &player->playback.current, next_pos = looped_next_pos;
p_seeked, p_started); }
cd.pos = next_pos;
_animation_process_animation(player, cd.from,
cd.pos, delta, p_blend, &cd == &player->playback.current,
p_seeked, p_started);
} }
static void ECS::_animation_process2(struct ECS::AnimationPlayerData *player, static void ECS::_animation_process2(struct ECS::AnimationPlayerData *player,
float p_delta, bool p_started) float p_delta, bool p_started)
{ {
ECS::Playback &c = player->playback; ECS::Playback &c = player->playback;
player->accum_pass++; player->accum_pass++;
_animation_process_data(player, c.current, if (c.current.from->animation.is_null()) {
p_delta, 1.0f, ERR_PRINT("bad animation2");
c.seeked && p_delta != 0, p_started); return;
if (p_delta != 0) }
c.seeked = false; _animation_process_data(player, c.current,
List<Blend>::Element *prev = nullptr; p_delta, 1.0f,
for (List<Blend>::Element *E = c.blend.back(); E; E = prev) { c.seeked && p_delta != 0, p_started);
Blend &b = E->get(); if (p_delta != 0)
float blend = b.blend_left / b.blend_time; c.seeked = false;
_animation_process_data(player, b.data, p_delta, blend, false, false); List<Blend>::Element *prev = nullptr;
b.blend_left -= Math::absf(player->speed_scale * p_delta); for (List<Blend>::Element *E = c.blend.back(); E; E = prev) {
prev = E->prev(); Blend &b = E->get();
if (b.blend_left < 0) float blend = b.blend_left / b.blend_time;
c.blend.erase(E); if (b.data.from->animation.is_null()) {
} ERR_PRINT("bad animation3");
b.blend_left -= Math::absf(player->speed_scale * p_delta);
prev = E->prev();
if (b.blend_left < 0)
c.blend.erase(E);
continue;
}
_animation_process_data(player, b.data, p_delta, blend, false, false);
b.blend_left -= Math::absf(player->speed_scale * p_delta);
prev = E->prev();
if (b.blend_left < 0)
c.blend.erase(E);
}
} }
static void ECS::_animation_update_transforms(struct ECS::AnimationPlayerData *player) static void ECS::_animation_update_transforms(struct ECS::AnimationPlayerData *player)
{ {
int i; int i;
{ {
Transform t; Transform t;
for (i = 0; i < player->cache_update_size; i++) { for (i = 0; i < player->cache_update_size; i++) {
TrackNodeCache *nc = player->cache_update[i]; TrackNodeCache *nc = player->cache_update[i];
t.origin = nc->loc_accum; t.origin = nc->loc_accum;
t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum); t.basis.set_quat_scale(nc->rot_accum, nc->scale_accum);
#if 0 #if 0
/* update transform on skeleton or node */ /* update transform on skeleton or node */
if (nc->skeleton && nc->bone_idx >= 0) if (nc->skeleton && nc->bone_idx >= 0)
@@ -805,74 +821,75 @@ static void ECS::_animation_update_transforms(struct ECS::AnimationPlayerData *p
else if (nc->spatial) else if (nc->spatial)
nc->spatial->set_transform(t); nc->spatial->set_transform(t);
#endif #endif
} }
} }
player->cache_update_size = 0; player->cache_update_size = 0;
for (i = 0; i < player->cache_update_prop_size; i++) { for (i = 0; i < player->cache_update_prop_size; i++) {
TrackNodeCache::PropertyAnim *pa = player->cache_update_prop[i]; TrackNodeCache::PropertyAnim *pa = player->cache_update_prop[i];
switch (pa->special) { switch (pa->special) {
case SP_NONE: { case SP_NONE: {
bool valid; bool valid;
pa->object->set_indexed(pa->subpath, pa->value_accum, &valid); pa->object->set_indexed(pa->subpath, pa->value_accum, &valid);
if (!valid) { if (!valid) {
/* error setting key /* error setting key
ERR_PRINT("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property"); ERR_PRINT("Failed setting key at time " + rtos(playback.current.pos) + " in Animation '" + get_current_animation() + "' at Node '" + get_path() + "', Track '" + String(pa->owner->path) + "'. Check if property exists or the type of key is right for the property");
*/ */
} }
} break; } break;
case SP_NODE2D_POS: case SP_NODE2D_POS:
// static_cast<Node2D *>(pa->object)->set_position(pa->value_accum); // static_cast<Node2D *>(pa->object)->set_position(pa->value_accum);
break; break;
case SP_NODE2D_ROT: case SP_NODE2D_ROT:
// static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum)); // static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum));
break; break;
case SP_NODE2D_SCALE: case SP_NODE2D_SCALE:
// static_cast<Node2D *>(pa->object)->set_scale(pa->value_accum); // static_cast<Node2D *>(pa->object)->set_scale(pa->value_accum);
break; break;
} }
} }
player->cache_update_prop_size = 0; player->cache_update_prop_size = 0;
for (i = 0; i < player->cache_update_bezier_size; i++) { for (i = 0; i < player->cache_update_bezier_size; i++) {
TrackNodeCache::BezierAnim *ba = player->cache_update_bezier[i]; TrackNodeCache::BezierAnim *ba = player->cache_update_bezier[i];
ba->object->set_indexed(ba->bezier_property, ba->bezier_accum); ba->object->set_indexed(ba->bezier_property, ba->bezier_accum);
} }
player->cache_update_bezier_size = 0; player->cache_update_bezier_size = 0;
} }
static void ECS::_set_process(struct ECS::AnimationPlayerData *player, bool p_process, bool p_force) static void ECS::_set_process(struct ECS::AnimationPlayerData *player, bool p_process, bool p_force)
{ {
/* Nothing */ /* Nothing */
} }
static void ECS::_animation_process(struct ECS::AnimationPlayerData *player, float p_time) static void ECS::_animation_process(struct ECS::AnimationPlayerData *player, float p_time)
{ {
if (player->playback.current.from) { if (player->playback.current.from) {
player->end_reached = false; player->end_reached = false;
player->end_notify = false; player->end_notify = false;
_animation_process2(player, p_time, player->playback.started); _animation_process2(player, p_time, player->playback.started);
if (player->playback.started) if (player->playback.started)
player->playback.started = false; player->playback.started = false;
_animation_update_transforms(player); _animation_update_transforms(player);
if (player->end_reached) { if (player->end_reached) {
if (player->queued.size()) { if (player->queued.size()) {
String old = player->playback.assigned; String old = player->playback.assigned;
play(player, player->queued.front()->get()); play(player, player->queued.front()->get());
String new_name = player->playback.assigned; String new_name = player->playback.assigned;
player->queued.pop_front(); player->queued.pop_front();
if (player->end_notify) { if (player->end_notify) {
/* emit animation_changed */ /* emit animation_changed */
} }
} else { } else {
player->playing = false; player->playing = false;
_set_process(player, false); _set_process(player, false);
if (player->end_notify) { if (player->end_notify) {
/* emit animation_finished */ /* emit animation_finished */
} }
} }
player->end_reached = false; player->end_reached = false;
} }
} else } else
_set_process(player, false); _set_process(player, false);
} }
void ECS::_stop_playing_caches(struct ECS::AnimationPlayerData *player) { void ECS::_stop_playing_caches(struct ECS::AnimationPlayerData *player)
{
#if 0 #if 0
for (Set<TrackNodeCache *>::Element *E = player->playing_caches.front(); E; E = E->next()) { for (Set<TrackNodeCache *>::Element *E = player->playing_caches.front(); E; E = E->next()) {
if (E->get()->node && E->get()->audio_playing) { if (E->get()->node && E->get()->audio_playing) {
@@ -891,7 +908,7 @@ void ECS::_stop_playing_caches(struct ECS::AnimationPlayerData *player) {
} }
void ECS::queue(struct ECS::AnimationPlayerData *player, void ECS::queue(struct ECS::AnimationPlayerData *player,
const StringName &p_name) const StringName &p_name)
{ {
if (!player->playing) { if (!player->playing) {
play(player, p_name); play(player, p_name);
@@ -900,7 +917,7 @@ void ECS::queue(struct ECS::AnimationPlayerData *player,
} }
} }
StringName ECS::animation_get_next(struct ECS::AnimationPlayerData *player, StringName ECS::animation_get_next(struct ECS::AnimationPlayerData *player,
const StringName &p_animation) const StringName &p_animation)
{ {
if (!player->animation_set.has(p_animation)) { if (!player->animation_set.has(p_animation)) {
return StringName(); return StringName();
@@ -913,9 +930,11 @@ String ECS::get_current_animation(struct ECS::AnimationPlayerData *player)
return player->playing ? player->playback.assigned : ""; return player->playing ? player->playback.assigned : "";
} }
Error ECS::add_animation(struct ECS::AnimationPlayerData *player, Error ECS::add_animation(struct ECS::AnimationPlayerData *player,
const StringName &p_name, const Ref<Animation> &p_animation) const StringName &p_name, const Ref<Animation> &p_animation)
{ {
ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER);
print_line("animation name: " + p_name);
print_line("animation length: " + itos(p_animation->get_length()));
if (player->animation_set.has(p_name)) { if (player->animation_set.has(p_name)) {
_unref_anim(player, player->animation_set[p_name].animation); _unref_anim(player, player->animation_set[p_name].animation);
@@ -932,7 +951,7 @@ Error ECS::add_animation(struct ECS::AnimationPlayerData *player,
return OK; return OK;
} }
void ECS::remove_animation(struct ECS::AnimationPlayerData *player, void ECS::remove_animation(struct ECS::AnimationPlayerData *player,
const StringName &p_name) const StringName &p_name)
{ {
ERR_FAIL_COND(!player->animation_set.has(p_name)); ERR_FAIL_COND(!player->animation_set.has(p_name));
@@ -945,12 +964,12 @@ void ECS::remove_animation(struct ECS::AnimationPlayerData *player,
clear_caches(player); clear_caches(player);
} }
static void ECS::_ref_anim(struct ECS::AnimationPlayerData *player, static void ECS::_ref_anim(struct ECS::AnimationPlayerData *player,
const Ref<Animation> &p_anim) const Ref<Animation> &p_anim)
{ {
} }
static void ECS::_unref_anim(struct ECS::AnimationPlayerData *player, static void ECS::_unref_anim(struct ECS::AnimationPlayerData *player,
const Ref<Animation> &p_anim) const Ref<Animation> &p_anim)
{ {
} }
@@ -967,5 +986,5 @@ void ECS::clear_caches(struct ECS::AnimationPlayerData *player)
void ECS::advance(struct ECS::AnimationPlayerData *player, float p_time) void ECS::advance(struct ECS::AnimationPlayerData *player, float p_time)
{ {
ECS::_animation_process(player, p_time); ECS::_animation_process(player, p_time);
} }

View File

@@ -4,118 +4,122 @@ namespace ECS {
struct AnimationPlayer; struct AnimationPlayer;
struct AnimationTreee; struct AnimationTreee;
enum AnimationProcessMode { enum AnimationProcessMode {
ANIMATION_PROCESS_PHYSICS, ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE, ANIMATION_PROCESS_IDLE,
ANIMATION_PROCESS_MANUAL, ANIMATION_PROCESS_MANUAL,
}; };
enum AnimationMethodCallMode { enum AnimationMethodCallMode {
ANIMATION_METHOD_CALL_DEFERRED, ANIMATION_METHOD_CALL_DEFERRED,
ANIMATION_METHOD_CALL_IMMEDIATE, ANIMATION_METHOD_CALL_IMMEDIATE,
}; };
enum SpecialProperty { enum SpecialProperty {
SP_NONE, SP_NONE,
SP_NODE2D_POS, SP_NODE2D_POS,
SP_NODE2D_ROT, SP_NODE2D_ROT,
SP_NODE2D_SCALE, SP_NODE2D_SCALE,
}; };
struct TrackNodeCache { struct TrackNodeCache {
NodePath path; NodePath path;
uint32_t id; uint32_t id;
RES resource; RES resource;
#if 0 #if 0
Node *node; Node *node;
Spatial *spatial; Spatial *spatial;
Node2D *node_2d; Node2D *node_2d;
Skeleton *skeleton; Skeleton *skeleton;
#endif #endif
int bone_idx; int bone_idx;
// accumulated transforms // accumulated transforms
Vector3 loc_accum; Vector3 loc_accum;
Quat rot_accum; Quat rot_accum;
Vector3 scale_accum; Vector3 scale_accum;
uint64_t accum_pass; uint64_t accum_pass;
bool audio_playing; bool audio_playing;
float audio_start; float audio_start;
float audio_len; float audio_len;
bool animation_playing; bool animation_playing;
struct PropertyAnim { struct PropertyAnim {
TrackNodeCache *owner; TrackNodeCache *owner;
SpecialProperty special; SpecialProperty special;
Vector<StringName> subpath; Vector<StringName> subpath;
Object *object; Object *object;
Variant value_accum; Variant value_accum;
uint64_t accum_pass; uint64_t accum_pass;
Variant capture; Variant capture;
PropertyAnim() : PropertyAnim() :
owner(nullptr), owner(nullptr),
special(SP_NONE), special(SP_NONE),
object(nullptr), object(nullptr),
accum_pass(0) accum_pass(0)
{ {
} }
}; };
Map<StringName, PropertyAnim> property_anim; Map<StringName, PropertyAnim> property_anim;
struct BezierAnim { struct BezierAnim {
Vector<StringName> bezier_property; Vector<StringName> bezier_property;
TrackNodeCache *owner; TrackNodeCache *owner;
float bezier_accum; float bezier_accum;
Object *object; Object *object;
uint64_t accum_pass; uint64_t accum_pass;
BezierAnim() : BezierAnim() :
owner(nullptr), owner(nullptr),
bezier_accum(0.0), bezier_accum(0.0),
object(nullptr), object(nullptr),
accum_pass(0) {} accum_pass(0) {}
}; };
Map<StringName, BezierAnim> bezier_anim; Map<StringName, BezierAnim> bezier_anim;
TrackNodeCache() : TrackNodeCache() :
id(0), id(0),
#if 0 #if 0
node(nullptr), node(nullptr),
spatial(nullptr), spatial(nullptr),
node_2d(nullptr), node_2d(nullptr),
skeleton(nullptr), skeleton(nullptr),
#endif #endif
bone_idx(-1), bone_idx(-1),
accum_pass(0), accum_pass(0),
audio_playing(false), audio_playing(false),
audio_start(0.0), audio_start(0.0),
audio_len(0.0), audio_len(0.0),
animation_playing(false) {} animation_playing(false)
{
}
}; };
struct AnimationData { struct AnimationData {
String name; String name;
StringName next; StringName next;
Vector<TrackNodeCache *> node_cache; Vector<TrackNodeCache *> node_cache;
Ref<Animation> animation; Ref<Animation> animation;
}; };
struct PlaybackData { struct PlaybackData {
AnimationData *from; AnimationData *from;
float pos; float pos;
float speed_scale; float speed_scale;
PlaybackData() { PlaybackData()
pos = 0; {
speed_scale = 1.0; pos = 0;
from = nullptr; speed_scale = 1.0;
} from = nullptr;
}
}; };
struct Blend { struct Blend {
PlaybackData data; PlaybackData data;
float blend_time; float blend_time;
float blend_left; float blend_left;
Blend() { Blend()
blend_left = 0.0f; {
blend_time = 0.0f; blend_left = 0.0f;
} blend_time = 0.0f;
}
}; };
struct Playback { struct Playback {
List<Blend> blend; List<Blend> blend;
PlaybackData current; PlaybackData current;
StringName assigned; StringName assigned;
bool seeked; bool seeked;
bool started; bool started;
}; };
struct BlendKey { struct BlendKey {
StringName from; StringName from;
@@ -128,117 +132,117 @@ struct TrackNodeCacheKey {
inline bool operator<(const TrackNodeCacheKey &p_right) const inline bool operator<(const TrackNodeCacheKey &p_right) const
{ {
if (id < p_right.id) { if (id < p_right.id) {
return true; return true;
} else if (id > p_right.id) { } else if (id > p_right.id) {
return false; return false;
} else { } else {
return bone_idx < p_right.bone_idx; return bone_idx < p_right.bone_idx;
} }
} }
}; };
enum { enum {
NODE_CACHE_UPDATE_MAX = 1024, NODE_CACHE_UPDATE_MAX = 1024,
BLEND_FROM_MAX = 3 BLEND_FROM_MAX = 3
}; };
struct AnimationPlayerData { struct AnimationPlayerData {
Map<TrackNodeCacheKey, TrackNodeCache> node_cache_map; Map<TrackNodeCacheKey, TrackNodeCache> node_cache_map;
TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX]; TrackNodeCache *cache_update[NODE_CACHE_UPDATE_MAX];
int cache_update_size; int cache_update_size;
TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX]; TrackNodeCache::PropertyAnim *cache_update_prop[NODE_CACHE_UPDATE_MAX];
int cache_update_prop_size; int cache_update_prop_size;
TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX]; TrackNodeCache::BezierAnim *cache_update_bezier[NODE_CACHE_UPDATE_MAX];
int cache_update_bezier_size; int cache_update_bezier_size;
Set<TrackNodeCache *> playing_caches; Set<TrackNodeCache *> playing_caches;
uint64_t accum_pass; uint64_t accum_pass;
float speed_scale; float speed_scale;
float default_blend_time; float default_blend_time;
Map<StringName, AnimationData> animation_set; Map<StringName, AnimationData> animation_set;
Map<BlendKey, float> blend_times; Map<BlendKey, float> blend_times;
Playback playback; Playback playback;
List<StringName> queued; List<StringName> queued;
bool end_reached; bool end_reached;
bool end_notify; bool end_notify;
String autoplay; String autoplay;
bool reset_on_save; bool reset_on_save;
AnimationProcessMode animation_process_mode; AnimationProcessMode animation_process_mode;
AnimationMethodCallMode method_call_mode; AnimationMethodCallMode method_call_mode;
bool processing; bool processing;
bool active; bool active;
NodePath root; NodePath root;
bool playing; bool playing;
}; };
/* public functions */ /* public functions */
StringName find_animation(struct AnimationPlayerData *player, StringName find_animation(struct AnimationPlayerData *player,
const Ref<Animation> &p_animation); const Ref<Animation> &p_animation);
Error add_animation(struct AnimationPlayerData *player, Error add_animation(struct AnimationPlayerData *player,
const StringName &p_name, const Ref<Animation> &p_animation); const StringName &p_name, const Ref<Animation> &p_animation);
void remove_animation(struct AnimationPlayerData *player, void remove_animation(struct AnimationPlayerData *player,
const StringName &p_name); const StringName &p_name);
void rename_animation(struct AnimationPlayerData *player, void rename_animation(struct AnimationPlayerData *player,
const StringName &p_name, const StringName &p_new_name); const StringName &p_name, const StringName &p_new_name);
bool has_animation(struct AnimationPlayerData *player, bool has_animation(struct AnimationPlayerData *player,
const StringName &p_name); const StringName &p_name);
Ref<Animation> get_animation(struct AnimationPlayerData *player, Ref<Animation> get_animation(struct AnimationPlayerData *player,
const StringName &p_name); const StringName &p_name);
void get_animation_list(struct AnimationPlayerData *player, void get_animation_list(struct AnimationPlayerData *player,
List<StringName> *p_animations); List<StringName> *p_animations);
void set_blend_time(struct AnimationPlayerData *player, void set_blend_time(struct AnimationPlayerData *player,
const StringName &p_animation1, const StringName &p_animation2, float p_time); const StringName &p_animation1, const StringName &p_animation2, float p_time);
float get_blend_time(struct AnimationPlayerData *player, float get_blend_time(struct AnimationPlayerData *player,
const StringName &p_animation1, const StringName &p_animation2); const StringName &p_animation1, const StringName &p_animation2);
void animation_set_next(struct AnimationPlayerData *player, void animation_set_next(struct AnimationPlayerData *player,
const StringName &p_animation, const StringName &p_next); const StringName &p_animation, const StringName &p_next);
StringName animation_get_next(struct AnimationPlayerData *player, StringName animation_get_next(struct AnimationPlayerData *player,
const StringName &p_animation); const StringName &p_animation);
void set_default_blend_time(struct AnimationPlayerData *player, void set_default_blend_time(struct AnimationPlayerData *player,
float p_default); float p_default);
float get_default_blend_time(struct AnimationPlayerData *player); float get_default_blend_time(struct AnimationPlayerData *player);
void play(struct AnimationPlayerData *player, void play(struct AnimationPlayerData *player,
const StringName &p_name = StringName(), const StringName &p_name = StringName(),
float p_custom_blend = -1, float p_custom_scale = 1.0, float p_custom_blend = -1, float p_custom_scale = 1.0,
bool p_from_end = false); bool p_from_end = false);
void play_backwards(struct AnimationPlayerData *player, void play_backwards(struct AnimationPlayerData *player,
const StringName &p_name = StringName(), float p_custom_blend = -1); const StringName &p_name = StringName(), float p_custom_blend = -1);
void queue(struct AnimationPlayerData *player, void queue(struct AnimationPlayerData *player,
const StringName &p_name); const StringName &p_name);
PoolVector<String> get_queue(struct AnimationPlayerData *player); PoolVector<String> get_queue(struct AnimationPlayerData *player);
void clear_queue(struct AnimationPlayerData *player); void clear_queue(struct AnimationPlayerData *player);
void stop(struct AnimationPlayerData *player, void stop(struct AnimationPlayerData *player,
bool p_reset = true); bool p_reset = true);
bool is_playing(struct AnimationPlayerData *player); bool is_playing(struct AnimationPlayerData *player);
String get_current_animation(struct AnimationPlayerData *player); String get_current_animation(struct AnimationPlayerData *player);
void set_current_animation(struct AnimationPlayerData *player, void set_current_animation(struct AnimationPlayerData *player,
const String &p_anim); const String &p_anim);
String get_assigned_animation(struct AnimationPlayerData *player); String get_assigned_animation(struct AnimationPlayerData *player);
void set_assigned_animation(struct AnimationPlayerData *player, void set_assigned_animation(struct AnimationPlayerData *player,
const String &p_anim); const String &p_anim);
void set_active(struct AnimationPlayerData *player, void set_active(struct AnimationPlayerData *player,
bool p_active); bool p_active);
bool is_active(struct AnimationPlayerData *player); bool is_active(struct AnimationPlayerData *player);
bool is_valid(struct AnimationPlayerData *player); bool is_valid(struct AnimationPlayerData *player);
void set_speed_scale(struct AnimationPlayerData *player, void set_speed_scale(struct AnimationPlayerData *player,
float p_speed); float p_speed);
float get_speed_scale(struct AnimationPlayerData *player); float get_speed_scale(struct AnimationPlayerData *player);
float get_playing_speed(struct AnimationPlayerData *player); float get_playing_speed(struct AnimationPlayerData *player);
void set_autoplay(struct AnimationPlayerData *player, void set_autoplay(struct AnimationPlayerData *player,
const String &p_name); const String &p_name);
String get_autoplay(struct AnimationPlayerData *player); String get_autoplay(struct AnimationPlayerData *player);
void set_reset_on_save_enabled(struct AnimationPlayerData *player, void set_reset_on_save_enabled(struct AnimationPlayerData *player,
bool p_enabled); bool p_enabled);
bool is_reset_on_save_enabled(struct AnimationPlayerData *player); bool is_reset_on_save_enabled(struct AnimationPlayerData *player);
void set_animation_process_mode(struct AnimationPlayerData *player, void set_animation_process_mode(struct AnimationPlayerData *player,
AnimationProcessMode p_mode); AnimationProcessMode p_mode);
AnimationProcessMode get_animation_process_mode(struct AnimationPlayerData *player); AnimationProcessMode get_animation_process_mode(struct AnimationPlayerData *player);
void set_method_call_mode(struct AnimationPlayerData *player, void set_method_call_mode(struct AnimationPlayerData *player,
AnimationMethodCallMode p_mode); AnimationMethodCallMode p_mode);
AnimationMethodCallMode get_method_call_mode(struct AnimationPlayerData *player); AnimationMethodCallMode get_method_call_mode(struct AnimationPlayerData *player);
void seek(struct AnimationPlayerData *player, void seek(struct AnimationPlayerData *player,
float p_time, bool p_update = false); float p_time, bool p_update = false);
void seek_delta(struct AnimationPlayerData *player, void seek_delta(struct AnimationPlayerData *player,
float p_time, float p_delta); float p_time, float p_delta);
float get_current_animation_position(struct AnimationPlayerData *player); float get_current_animation_position(struct AnimationPlayerData *player);
float get_current_animation_length(struct AnimationPlayerData *player); float get_current_animation_length(struct AnimationPlayerData *player);
void advance(struct AnimationPlayerData *player, float p_time); void advance(struct AnimationPlayerData *player, float p_time);
@@ -246,6 +250,6 @@ void set_root(struct AnimationPlayerData *player, const NodePath &p_root);
NodePath get_root(struct AnimationPlayerData *player); NodePath get_root(struct AnimationPlayerData *player);
void clear_caches(struct AnimationPlayerData *player); void clear_caches(struct AnimationPlayerData *player);
void get_argument_options(struct AnimationPlayerData *player, void get_argument_options(struct AnimationPlayerData *player,
const StringName &p_function, int p_idx, List<String> *r_options); const StringName &p_function, int p_idx, List<String> *r_options);
} } //namespace ECS
#endif #endif

View File

@@ -1,34 +1,34 @@
#include <cassert> #include "character.h"
#include <flecs.h> #include "animation_system.h"
#include <core/rid.h> #include "skeleton-prep.h"
#include <scene/3d/collision_shape.h>
#include <core/engine.h> #include <core/engine.h>
#include <core/rid.h>
#include <core/variant_parser.h> #include <core/variant_parser.h>
#include <flecs.h>
#include <scene/3d/collision_shape.h>
#include <scene/3d/mesh_instance.h> #include <scene/3d/mesh_instance.h>
#include <scene/resources/shape.h>
#include <scene/resources/packed_scene.h>
#include <servers/physics_server.h>
#include <servers/visual_server.h>
#include <scene/resources/animation.h>
#include <scene/resources/skin.h>
#include <scene/animation/animation_player.h> #include <scene/animation/animation_player.h>
#include <scene/main/viewport.h> #include <scene/main/viewport.h>
#include "character.h" #include <scene/resources/animation.h>
#include "skeleton-prep.h" #include <scene/resources/packed_scene.h>
#include "animation_system.h" #include <scene/resources/shape.h>
#include <scene/resources/skin.h>
#include <servers/physics_server.h>
#include <servers/visual_server.h>
#include <cassert>
namespace ECS { namespace ECS {
Skeleton::Skeleton() Skeleton::Skeleton()
{ {
bone_count = 0; bone_count = 0;
skeleton = RID(); skeleton = RID();
dirty = true; dirty = true;
process_order_dirty = true; process_order_dirty = true;
}
Skeleton::~Skeleton()
{
}
} }
Skeleton::~Skeleton()
{
}
} //namespace ECS
ECS::RigidBody::RigidBody(RID rid, enum type type) ECS::RigidBody::RigidBody(RID rid, enum type type)
{ {
@@ -90,12 +90,24 @@ int Character::create_character(int id)
root.emplace<Transform>(); root.emplace<Transform>();
root.emplace<ECS::RigidBody>(body, ECS::RigidBody::TYPE_KINEMATIC); root.emplace<ECS::RigidBody>(body, ECS::RigidBody::TYPE_KINEMATIC);
root.emplace<ECS::Skeleton>(); root.emplace<ECS::Skeleton>();
root.emplace<ECS::AnimationPlayerData>();
List<StringName> anim_list;
scene_data[id].animations.get_key_list(&anim_list);
List<StringName>::Element *e = anim_list.front();
ECS::AnimationPlayerData *player = root.get_mut<ECS::AnimationPlayerData>();
while (e) {
ECS::add_animation(player, e->get(),
scene_data[id].animations[e->get()]);
flecs::log::trace("added animation %s", String(e->get()).ascii().get_data());
e = e->next();
}
root.modified<ECS::AnimationPlayerData>();
root.emplace<ECS::AnimationTree>(); root.emplace<ECS::AnimationTree>();
root.add<ECS::Dirty>(); root.add<ECS::Dirty>();
ECS::MetaData *md = root.get_mut<ECS::MetaData>(); ECS::MetaData *md = root.get_mut<ECS::MetaData>();
md->type_index = id; md->type_index = id;
root.modified<ECS::MetaData>();
root.modified<ECS::MetaData>();
print_line("body created for root"); print_line("body created for root");
for (i = 0; i < scene_data[id].shapes.size(); i++) { for (i = 0; i < scene_data[id].shapes.size(); i++) {
ecs.entity() ecs.entity()
@@ -108,14 +120,14 @@ int Character::create_character(int id)
ecs.entity(scene_data[id].bones[i].name.ascii().get_data()) ecs.entity(scene_data[id].bones[i].name.ascii().get_data())
.child_of(root) .child_of(root)
.emplace<ECS::BoneComponent>(index, parent_index, rest) .emplace<ECS::BoneComponent>(index, parent_index, rest)
.set<ECS::BonePose>({index, Transform()}); .set<ECS::BonePose>({ index, Transform() });
} }
for (i = 0; i < scene_data[id].meshes.size(); i++) { for (i = 0; i < scene_data[id].meshes.size(); i++) {
// flecs::log::trace("creating slot -"); // flecs::log::trace("creating slot -");
flecs::entity entity = ecs.entity(scene_data[id].meshes[i].slot_name.ascii().get_data()) flecs::entity entity = ecs.entity(scene_data[id].meshes[i].slot_name.ascii().get_data())
.child_of(root) .child_of(root)
.emplace<ECS::CharacterSlot>(scene_data[id].meshes[i].mesh, .emplace<ECS::CharacterSlot>(scene_data[id].meshes[i].mesh,
scene_data[id].meshes[i].skin); scene_data[id].meshes[i].skin);
} }
// print_line("character created"); // print_line("character created");
int xid = entities.size(); int xid = entities.size();
@@ -221,7 +233,7 @@ void Character::set_scene(int id, const Ref<PackedScene> &scene)
while (e) { while (e) {
StringName anim_name = e->get(); StringName anim_name = e->get();
Ref<Animation> animation = anim->get_animation(anim_name); Ref<Animation> animation = anim->get_animation(anim_name);
scene_data[id].animations.push_back(animation); scene_data[id].animations[anim_name] = animation;
e = e->next(); e = e->next();
} }
} }
@@ -234,7 +246,7 @@ void Character::set_scene(int id, const Ref<PackedScene> &scene)
scene_data[id].bones.write[i].index = i; scene_data[id].bones.write[i].index = i;
scene_data[id].bones.write[i].parent = skel->get_bone_parent(i); scene_data[id].bones.write[i].parent = skel->get_bone_parent(i);
scene_data[id].bones.write[i].rest = skel->get_bone_rest(i); scene_data[id].bones.write[i].rest = skel->get_bone_rest(i);
// print_line("added bone: " + scene_data[id].bones.write[i].name + " " + itos(i)); // print_line("added bone: " + scene_data[id].bones.write[i].name + " " + itos(i));
} }
} }
for (i = 0; i < tmp->get_child_count(); i++) for (i = 0; i < tmp->get_child_count(); i++)
@@ -267,8 +279,7 @@ void Character::_bind_methods()
void Character::init_bone() void Character::init_bone()
{ {
ecs.component<ECS::BoneComponent>() ecs.component<ECS::BoneComponent>()
.on_add([](flecs::entity e, ECS::BoneComponent &s) .on_add([](flecs::entity e, ECS::BoneComponent &s) {
{
// flecs::log::trace("added bonecomponent %s", e.name().c_str()); // flecs::log::trace("added bonecomponent %s", e.name().c_str());
flecs::entity parent = e.parent(); flecs::entity parent = e.parent();
parent.add<ECS::Dirty>(); parent.add<ECS::Dirty>();
@@ -279,8 +290,7 @@ void Character::init_bone()
parent.remove<ECS::Skinned>(); parent.remove<ECS::Skinned>();
} }
}) })
.on_set([](flecs::entity e, ECS::BoneComponent &s) .on_set([](flecs::entity e, ECS::BoneComponent &s) {
{
flecs::entity parent = e.parent(); flecs::entity parent = e.parent();
ECS::Skeleton *skel = parent.get_mut<ECS::Skeleton>(); ECS::Skeleton *skel = parent.get_mut<ECS::Skeleton>();
if (s.index >= skel->bone_count) { if (s.index >= skel->bone_count) {
@@ -301,12 +311,10 @@ void Character::init_bone()
parent.add<ECS::Dirty>(); parent.add<ECS::Dirty>();
}); });
ecs.component<ECS::BonePose>() ecs.component<ECS::BonePose>()
.on_add([](flecs::entity e, ECS::BonePose &s) .on_add([](flecs::entity e, ECS::BonePose &s) {
{ // flecs::log::trace("added bonepose %s", e.name().c_str());
// flecs::log::trace("added bonepose %s", e.name().c_str());
}) })
.on_set([](flecs::entity e, ECS::BonePose &s) .on_set([](flecs::entity e, ECS::BonePose &s) {
{
#if 0 #if 0
const Transform &xform = s.pose; const Transform &xform = s.pose;
String out; String out;
@@ -317,11 +325,12 @@ void Character::init_bone()
e.add<ECS::Dirty>(); e.add<ECS::Dirty>();
}); });
ecs.system<ECS::BonePose, ECS::Dirty>() ecs.system<ECS::BonePose, ECS::Dirty>()
.with<ECS::Skeleton>().parent() .with<ECS::Skeleton>()
.with<ECS::Bound>().parent() .parent()
.with<ECS::Bound>()
.parent()
.kind(flecs::OnUpdate) .kind(flecs::OnUpdate)
.each([this](flecs::entity e, ECS::BonePose &s, const ECS::Dirty &d) .each([this](flecs::entity e, ECS::BonePose &s, const ECS::Dirty &d) {
{
flecs::entity parent = e.parent(); flecs::entity parent = e.parent();
/* Don't update unbound skeleton */ /* Don't update unbound skeleton */
if (!parent.has<ECS::Bound>()) { if (!parent.has<ECS::Bound>()) {
@@ -342,11 +351,15 @@ void Character::init_bone()
} }
void Character::animation_system_init() void Character::animation_system_init()
{ {
ecs.component<ECS::AnimationPlayerData>(); ecs.component<ECS::AnimationPlayerData>()
.on_set([](flecs::entity e, ECS::AnimationPlayerData &s) {
flecs::log::trace("created animation player");
});
ecs.system<ECS::AnimationPlayerData>("UpdateAnimation") ecs.system<ECS::AnimationPlayerData>("UpdateAnimation")
.kind(flecs::OnUpdate) .kind(flecs::OnUpdate)
.each([](flecs::entity e, ECS::AnimationPlayerData &player) .each([](flecs::entity e, ECS::AnimationPlayerData &player) {
{ if (!player.playing)
ECS::play(&player, "stand1-loop");
ECS::advance(&player, SceneTree::get_singleton()->get_physics_process_time()); ECS::advance(&player, SceneTree::get_singleton()->get_physics_process_time());
}); });
} }
@@ -355,23 +368,20 @@ void Character::initialize()
Error err; Error err;
flecs::log::set_level(0); flecs::log::set_level(0);
SceneTree *st = SceneTree::get_singleton(); SceneTree *st = SceneTree::get_singleton();
ecs.import<skeleton_prep>(); ecs.import <skeleton_prep>();
init_skeleton(); init_skeleton();
ecs.component<ECS::MetaData>() ecs.component<ECS::MetaData>()
.on_add([](flecs::entity e, ECS::MetaData &s) .on_add([](flecs::entity e, ECS::MetaData &s) {
{
flecs::log::trace("added metadata %s", e.name().c_str()); flecs::log::trace("added metadata %s", e.name().c_str());
}); });
init_bone(); init_bone();
init_slot(); init_slot();
ecs.component<ECS::AnimationTree>() ecs.component<ECS::AnimationTree>()
.on_add([](flecs::entity e, ECS::AnimationTree &s) .on_add([](flecs::entity e, ECS::AnimationTree &s) {
{
flecs::log::trace("animationtree slot %s", e.name().c_str()); flecs::log::trace("animationtree slot %s", e.name().c_str());
}); });
ecs.component<ECS::RigidBody>() ecs.component<ECS::RigidBody>()
.on_add([](flecs::entity e, ECS::RigidBody &s) .on_add([](flecs::entity e, ECS::RigidBody &s) {
{
flecs::log::trace("added rigidbody %s", e.name().c_str()); flecs::log::trace("added rigidbody %s", e.name().c_str());
}); });
const String path = "res://characters/"; const String path = "res://characters/";
@@ -385,8 +395,7 @@ void Character::initialize()
ecs.system<ECS::Skeleton>("UpdateBone") ecs.system<ECS::Skeleton>("UpdateBone")
.with<ECS::Bound>() .with<ECS::Bound>()
.kind(flecs::OnUpdate) .kind(flecs::OnUpdate)
.each([](flecs::entity e, ECS::Skeleton &sk) .each([](flecs::entity e, ECS::Skeleton &sk) {
{
flecs::entity root = e.lookup("Root"); flecs::entity root = e.lookup("Root");
if (!root.is_valid() || !root.is_alive()) if (!root.is_valid() || !root.is_alive())
return; return;
@@ -394,7 +403,7 @@ void Character::initialize()
return; return;
float delta = SceneTree::get_singleton()->get_physics_process_time(); float delta = SceneTree::get_singleton()->get_physics_process_time();
struct ECS::BonePose *bp = root.get_mut<ECS::BonePose>(); struct ECS::BonePose *bp = root.get_mut<ECS::BonePose>();
// bp->pose.basis = bp->pose.basis.rotated(Vector3(0, 1, 0), 0.016f); // bp->pose.basis = bp->pose.basis.rotated(Vector3(0, 1, 0), 0.016f);
bp->pose.origin += Vector3(0.2f * delta, 0.0f, 0.0f); bp->pose.origin += Vector3(0.2f * delta, 0.0f, 0.0f);
root.modified<ECS::BonePose>(); root.modified<ECS::BonePose>();
}); });

View File

@@ -10,68 +10,69 @@ class Animation;
class Skin; class Skin;
class SkinReference; class SkinReference;
namespace ECS { namespace ECS {
struct Skeleton { struct Skeleton {
bool dirty; bool dirty;
RID skeleton; RID skeleton;
Ref<Skin> skin; Ref<Skin> skin;
int bone_count; int bone_count;
Vector<int> process_order; Vector<int> process_order;
bool process_order_dirty; bool process_order_dirty;
struct bone_data { struct bone_data {
String name;
bool enabled;
int parent;
bool disable_rest;
bool custom_pose_enable;
Transform
custom_pose,
rest,
pose,
pose_global,
pose_global_no_override;
int sort_index;
};
Vector<uint32_t> skin_bone_indices;
uint32_t *skin_bone_indices_ptrs;
Vector<struct bone_data> bones;
Skeleton();
~Skeleton();
};
struct Bound {};
struct Skinned {};
struct Dirty {};
struct SkeletonOrderPrepared {};
struct SkeletonTransformReady {};
struct MetaData {
int type_index;
};
struct BoneComponent {
flecs::entity_t skeleton;
int index, parent_index;
Transform rest, pose;
BoneComponent(int index, int parent_index, const Transform &rest);
};
struct BonePose {
int index;
Transform pose;
};
struct AnimationTree {
void *root;
AnimationTree(): root(nullptr)
{
}
~AnimationTree()
{
}
};
struct CharacterSlot {
String name; String name;
RID instance; bool enabled;
RID skeleton; int parent;
Ref<ArrayMesh> mesh; bool disable_rest;
Ref<Skin> skin, skin_internal; bool custom_pose_enable;
bool bound; Transform
CharacterSlot(Ref<ArrayMesh> mesh, Ref<Skin> skin); custom_pose,
rest,
pose,
pose_global,
pose_global_no_override;
int sort_index;
};
Vector<uint32_t> skin_bone_indices;
uint32_t *skin_bone_indices_ptrs;
Vector<struct bone_data> bones;
Skeleton();
~Skeleton();
};
struct Bound {};
struct Skinned {};
struct Dirty {};
struct SkeletonOrderPrepared {};
struct SkeletonTransformReady {};
struct MetaData {
int type_index;
};
struct BoneComponent {
flecs::entity_t skeleton;
int index, parent_index;
Transform rest, pose;
BoneComponent(int index, int parent_index, const Transform &rest);
};
struct BonePose {
int index;
Transform pose;
};
struct AnimationTree {
void *root;
AnimationTree() :
root(nullptr)
{
}
~AnimationTree()
{
}
};
struct CharacterSlot {
String name;
RID instance;
RID skeleton;
Ref<ArrayMesh> mesh;
Ref<Skin> skin, skin_internal;
bool bound;
CharacterSlot(Ref<ArrayMesh> mesh, Ref<Skin> skin);
#if 0 #if 0
CharacterSlot(const CharacterSlot &obj); CharacterSlot(const CharacterSlot &obj);
CharacterSlot(CharacterSlot &&obj); CharacterSlot(CharacterSlot &&obj);
@@ -79,32 +80,32 @@ namespace ECS {
CharacterSlot &operator=(CharacterSlot &&obj); CharacterSlot &operator=(CharacterSlot &&obj);
~CharacterSlot(); ~CharacterSlot();
#endif #endif
};
struct RigidBody {
enum type {
TYPE_NONE = 0,
TYPE_STATIC = 1,
TYPE_KINEMATIC,
TYPE_RIGID
}; };
struct RigidBody { bool initialized;
enum type { RID body;
TYPE_NONE = 0, Vector3 velocity;
TYPE_STATIC = 1, enum type type;
TYPE_KINEMATIC, RigidBody(RID rid, enum type type);
TYPE_RIGID ~RigidBody();
}; };
bool initialized; struct CShape {
RID body; Transform offset;
Vector3 velocity; Ref<Shape> shape;
enum type type; CShape(RID body, const Transform &offset, Ref<Shape> shape);
RigidBody(RID rid, enum type type); ~CShape();
~RigidBody(); };
}; } //namespace ECS
struct CShape {
Transform offset;
Ref<Shape> shape;
CShape(RID body, const Transform &offset, Ref<Shape> shape);
~CShape();
};
}
class Character: public Object { class Character : public Object {
GDCLASS(Character, Object) GDCLASS(Character, Object)
public: public:
int create_character(int type_id); int create_character(int type_id);
void destroy_character(int id); void destroy_character(int id);
static Character *singleton; static Character *singleton;
@@ -113,7 +114,8 @@ public:
void set_scene(int id, const Ref<PackedScene> &scene); void set_scene(int id, const Ref<PackedScene> &scene);
Ref<PackedScene> get_scene(int id) const; Ref<PackedScene> get_scene(int id) const;
Character(); Character();
protected:
protected:
flecs::world ecs; flecs::world ecs;
struct shape_data { struct shape_data {
Ref<Shape> shape; Ref<Shape> shape;
@@ -134,7 +136,7 @@ protected:
Ref<PackedScene> scene; Ref<PackedScene> scene;
Vector<struct shape_data> shapes; Vector<struct shape_data> shapes;
Vector<struct mesh_data> meshes; Vector<struct mesh_data> meshes;
Vector<Ref<Animation> > animations; HashMap<StringName, Ref<Animation>> animations;
Vector<struct bone_data> bones; Vector<struct bone_data> bones;
Set<SkinReference *> skin_bindings; Set<SkinReference *> skin_bindings;
} scene_data[2]; } scene_data[2];

View File

@@ -1,35 +1,32 @@
#include <cassert> #include "character.h"
#include <flecs.h>
#include <servers/visual_server.h>
#include <scene/main/scene_tree.h>
#include <core/reference.h> #include <core/reference.h>
#include <core/variant_parser.h>
#include <flecs.h>
#include <scene/main/scene_tree.h>
#include <scene/main/viewport.h> #include <scene/main/viewport.h>
#include <scene/resources/skin.h> #include <scene/resources/skin.h>
#include <core/variant_parser.h> #include <servers/visual_server.h>
#include "character.h" #include <cassert>
void Character::init_skeleton() void Character::init_skeleton()
{ {
VisualServer *vs = VS::get_singleton(); VisualServer *vs = VS::get_singleton();
ecs.component<ECS::Skeleton>() ecs.component<ECS::Skeleton>()
.on_add([](flecs::entity e, ECS::Skeleton &s) .on_add([](flecs::entity e, ECS::Skeleton &s) {
{ // flecs::log::trace("added skeleton %s", e.name().c_str());
// flecs::log::trace("added skeleton %s", e.name().c_str());
if (e.has<ECS::SkeletonOrderPrepared>()) if (e.has<ECS::SkeletonOrderPrepared>())
e.remove<ECS::SkeletonOrderPrepared>(); e.remove<ECS::SkeletonOrderPrepared>();
}) })
.on_set([](flecs::entity e, ECS::Skeleton &s) .on_set([](flecs::entity e, ECS::Skeleton &s) {
{ // flecs::log::trace("on set: set skeleton %s", e.name().c_str());
// flecs::log::trace("on set: set skeleton %s", e.name().c_str());
// s.process_order_dirty = true; // s.process_order_dirty = true;
e.add<ECS::Dirty>(); e.add<ECS::Dirty>();
}); });
ecs.system<ECS::Skeleton>("CreateSkeleton") ecs.system<ECS::Skeleton>("CreateSkeleton")
.without<ECS::Bound>() .without<ECS::Bound>()
.kind(flecs::PreUpdate) .kind(flecs::PreUpdate)
.each([vs](flecs::entity e, ECS::Skeleton &skel) .each([vs](flecs::entity e, ECS::Skeleton &skel) {
{
if (!skel.skeleton.is_valid()) { if (!skel.skeleton.is_valid()) {
skel.skeleton = vs->skeleton_create(); skel.skeleton = vs->skeleton_create();
flecs::log::trace("created skeleton"); flecs::log::trace("created skeleton");
@@ -39,8 +36,7 @@ void Character::init_skeleton()
.with<ECS::Dirty>() .with<ECS::Dirty>()
.without<ECS::SkeletonOrderPrepared>() .without<ECS::SkeletonOrderPrepared>()
.kind(flecs::PreUpdate) .kind(flecs::PreUpdate)
.each([](flecs::entity e, ECS::Skeleton &sk) .each([](flecs::entity e, ECS::Skeleton &sk) {
{
if (sk.process_order_dirty) { if (sk.process_order_dirty) {
flecs::log::trace("skeletons: %d dirty: sorting bones", sk.bone_count); flecs::log::trace("skeletons: %d dirty: sorting bones", sk.bone_count);
int i; int i;
@@ -79,7 +75,7 @@ void Character::init_skeleton()
if (pass_count >= len * len) if (pass_count >= len * len)
flecs::log::err("Skeleton parenthood graph is cyclic"); flecs::log::err("Skeleton parenthood graph is cyclic");
sk.process_order_dirty = false; sk.process_order_dirty = false;
flecs::log::trace("skeletons: %d dirty: sorting bones done", sk.bone_count); flecs::log::trace("skeletons: %d dirty: sorting bones done", sk.bone_count);
} }
e.add<ECS::SkeletonOrderPrepared>(); e.add<ECS::SkeletonOrderPrepared>();
}); });
@@ -88,14 +84,13 @@ void Character::init_skeleton()
.with<ECS::SkeletonOrderPrepared>() .with<ECS::SkeletonOrderPrepared>()
.without<ECS::SkeletonTransformReady>() .without<ECS::SkeletonTransformReady>()
.kind(flecs::OnUpdate) .kind(flecs::OnUpdate)
.each([](flecs::entity e, ECS::Skeleton &sk) .each([](flecs::entity e, ECS::Skeleton &sk) {
{
int i; int i;
VisualServer *vs = VS::get_singleton(); VisualServer *vs = VS::get_singleton();
// flecs::log::trace("skeletons: %d dirty: update try", sk.bone_count); // flecs::log::trace("skeletons: %d dirty: update try", sk.bone_count);
if (sk.process_order_dirty) if (sk.process_order_dirty)
return; return;
// flecs::log::trace("skeletons: %d dirty: update", sk.bone_count); // flecs::log::trace("skeletons: %d dirty: update", sk.bone_count);
struct ECS::Skeleton::bone_data *bonesptr = sk.bones.ptrw(); struct ECS::Skeleton::bone_data *bonesptr = sk.bones.ptrw();
int len = sk.bones.size(); int len = sk.bones.size();
const int *order = sk.process_order.ptr(); const int *order = sk.process_order.ptr();
@@ -146,14 +141,14 @@ void Character::init_skeleton()
} }
} }
} }
// flecs::log::trace("transform should be ready"); // flecs::log::trace("transform should be ready");
e.add<ECS::SkeletonTransformReady>(); e.add<ECS::SkeletonTransformReady>();
assert(sk.skin_bone_indices_ptrs); assert(sk.skin_bone_indices_ptrs);
uint32_t bind_count = sk.skin->get_bind_count(); uint32_t bind_count = sk.skin->get_bind_count();
if (bind_count == 0) if (bind_count == 0)
return; return;
if (!e.has<ECS::Bound>()) if (!e.has<ECS::Bound>())
return; return;
for (i = 0; i < (int)bind_count; i++) { for (i = 0; i < (int)bind_count; i++) {
uint32_t bone_index = sk.skin_bone_indices_ptrs[i]; uint32_t bone_index = sk.skin_bone_indices_ptrs[i];
Transform xform = bonesptr[bone_index].pose_global * sk.skin->get_bind_pose(i); Transform xform = bonesptr[bone_index].pose_global * sk.skin->get_bind_pose(i);

View File

@@ -1,103 +1,100 @@
#include <cassert> #include "character.h"
#include <flecs.h>
#include <servers/visual_server.h>
#include <scene/main/scene_tree.h>
#include <core/reference.h> #include <core/reference.h>
#include <flecs.h>
#include <scene/main/scene_tree.h>
#include <scene/main/viewport.h> #include <scene/main/viewport.h>
#include <scene/resources/skin.h> #include <scene/resources/skin.h>
#include "character.h" #include <servers/visual_server.h>
#include <cassert>
void Character::init_slot() void Character::init_slot()
{ {
SceneTree *st = SceneTree::get_singleton(); SceneTree *st = SceneTree::get_singleton();
VisualServer *vs = VS::get_singleton(); VisualServer *vs = VS::get_singleton();
ecs.component<ECS::CharacterSlot>() ecs.component<ECS::CharacterSlot>()
.on_add([](flecs::entity e, ECS::CharacterSlot &s) .on_add([](flecs::entity e, ECS::CharacterSlot &s) {
{
flecs::log::trace("added slot %s", e.name().c_str()); flecs::log::trace("added slot %s", e.name().c_str());
}) })
.on_remove([vs](flecs::entity e, ECS::CharacterSlot &s) .on_remove([vs](flecs::entity e, ECS::CharacterSlot &s) {
{
if (s.instance.is_valid()) { if (s.instance.is_valid()) {
vs->instance_set_scenario(s.instance, RID()); vs->instance_set_scenario(s.instance, RID());
vs->instance_attach_skeleton(s.instance, RID()); vs->instance_attach_skeleton(s.instance, RID());
vs->instance_set_base(s.instance, RID()); vs->instance_set_base(s.instance, RID());
vs->free(s.instance); vs->free(s.instance);
s.instance = RID(); s.instance = RID();
// print_line("mesh instance slot removed " + s.name); // print_line("mesh instance slot removed " + s.name);
} }
// flecs::log::trace("removed slot %s", e.name().c_str()); // flecs::log::trace("removed slot %s", e.name().c_str());
}) })
.on_set([st](flecs::entity e, ECS::CharacterSlot &s) .on_set([st](flecs::entity e, ECS::CharacterSlot &s) {
{ // flecs::log::trace("set slot %s", e.name().c_str());
// flecs::log::trace("set slot %s", e.name().c_str());
if (s.mesh.is_null() || !s.mesh.is_valid()) if (s.mesh.is_null() || !s.mesh.is_valid())
flecs::log::err("invalid mesh %s", e.name().c_str()); flecs::log::err("invalid mesh %s", e.name().c_str());
}); });
ecs.system<ECS::CharacterSlot>("UpdateSlot") ecs.system<ECS::CharacterSlot>("UpdateSlot")
.without<ECS::Bound>() .without<ECS::Bound>()
.with<ECS::Skeleton>().parent() .with<ECS::Skeleton>()
.parent()
.kind(flecs::PreUpdate) .kind(flecs::PreUpdate)
.each([vs, st](flecs::entity e, ECS::CharacterSlot &slot) .each([vs, st](flecs::entity e, ECS::CharacterSlot &slot) {
{ assert(e.parent().has<ECS::Skeleton>());
assert(e.parent().has<ECS::Skeleton>());
if (!slot.instance.is_valid()) { if (!slot.instance.is_valid()) {
slot.name = e.name().c_str(); slot.name = e.name().c_str();
RID scenario = st->get_root()->get_world()->get_scenario(); RID scenario = st->get_root()->get_world()->get_scenario();
slot.instance = vs->instance_create(); slot.instance = vs->instance_create();
vs->instance_set_scenario(slot.instance, scenario); vs->instance_set_scenario(slot.instance, scenario);
vs->instance_set_base(slot.instance, slot.mesh->get_rid()); vs->instance_set_base(slot.instance, slot.mesh->get_rid());
// flecs::log::trace("created instance for %s", e.name().c_str()); // flecs::log::trace("created instance for %s", e.name().c_str());
} }
}); });
ecs.system<ECS::CharacterSlot>("AttachToSkeleton") ecs.system<ECS::CharacterSlot>("AttachToSkeleton")
.without<ECS::Bound>() .without<ECS::Bound>()
.with<ECS::Skeleton>().parent() .with<ECS::Skeleton>()
.parent()
.with<ECS::Skinned>() .with<ECS::Skinned>()
.kind(flecs::PreUpdate) .kind(flecs::PreUpdate)
.each([vs, st](flecs::entity e, ECS::CharacterSlot &slot) .each([vs, st](flecs::entity e, ECS::CharacterSlot &slot) {
{
flecs::entity parent = e.parent(); flecs::entity parent = e.parent();
assert(parent.has<ECS::Skeleton>()); assert(parent.has<ECS::Skeleton>());
assert(!e.has<ECS::Bound>()); assert(!e.has<ECS::Bound>());
assert(slot.instance.is_valid()); assert(slot.instance.is_valid());
const ECS::Skeleton *skel = parent.get<ECS::Skeleton>(); const ECS::Skeleton *skel = parent.get<ECS::Skeleton>();
assert(skel->skeleton.is_valid()); assert(skel->skeleton.is_valid());
// flecs::log::trace("binding slot for %s", e.name().c_str()); // flecs::log::trace("binding slot for %s", e.name().c_str());
if (skel->skeleton.is_valid()) if (skel->skeleton.is_valid())
slot.skeleton = skel->skeleton; slot.skeleton = skel->skeleton;
if (slot.skin.is_null() && !skel->skin.is_null()) if (slot.skin.is_null() && !skel->skin.is_null())
slot.skin_internal = skel->skin; slot.skin_internal = skel->skin;
if (skel->skeleton.is_valid() && !skel->skin.is_null()) { if (skel->skeleton.is_valid() && !skel->skin.is_null()) {
uint32_t bind_count = skel->skin->get_bind_count(); uint32_t bind_count = skel->skin->get_bind_count();
vs->skeleton_allocate(skel->skeleton, bind_count); vs->skeleton_allocate(skel->skeleton, bind_count);
vs->instance_attach_skeleton(slot.instance, skel->skeleton); vs->instance_attach_skeleton(slot.instance, skel->skeleton);
slot.bound = true; slot.bound = true;
e.add<ECS::Bound>(); e.add<ECS::Bound>();
parent.add<ECS::Bound>(); parent.add<ECS::Bound>();
// flecs::log::trace("bound slot for %s", e.name().c_str()); // flecs::log::trace("bound slot for %s", e.name().c_str());
} }
}); });
ecs.system<ECS::CharacterSlot>("BindSlotsToSkeleton") ecs.system<ECS::CharacterSlot>("BindSlotsToSkeleton")
.with<ECS::Skeleton>().parent() .with<ECS::Skeleton>()
.parent()
.without<ECS::Bound>() .without<ECS::Bound>()
.without<ECS::Skinned>() .without<ECS::Skinned>()
.kind(flecs::PreUpdate) .kind(flecs::PreUpdate)
.each([vs](flecs::entity e, ECS::CharacterSlot &slot) .each([vs](flecs::entity e, ECS::CharacterSlot &slot) {
{
flecs::entity parent = e.parent(); flecs::entity parent = e.parent();
int i; int i;
assert(!e.has<ECS::Bound>()); assert(!e.has<ECS::Bound>());
assert(!e.has<ECS::Skinned>()); assert(!e.has<ECS::Skinned>());
ECS::Skeleton *skel = parent.get_mut<ECS::Skeleton>(); ECS::Skeleton *skel = parent.get_mut<ECS::Skeleton>();
if (skel->skin.is_null() && slot.skin_internal.is_null()) { if (skel->skin.is_null() && slot.skin_internal.is_null()) {
const struct ECS::Skeleton::bone_data *bonesptr = skel->bones.ptr(); const struct ECS::Skeleton::bone_data *bonesptr = skel->bones.ptr();
const int *order = skel->process_order.ptr(); const int *order = skel->process_order.ptr();
// flecs::log::trace("binding slot for %s", e.name().c_str()); // flecs::log::trace("binding slot for %s", e.name().c_str());
slot.skin_internal.instance(); slot.skin_internal.instance();
slot.skin_internal->set_bind_count(skel->bones.size()); slot.skin_internal->set_bind_count(skel->bones.size());
int len = skel->bones.size(); int len = skel->bones.size();
// flecs::log::trace("creating skin for %s", e.name().c_str()); // flecs::log::trace("creating skin for %s", e.name().c_str());
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
const struct ECS::Skeleton::bone_data &b = bonesptr[order[i]]; const struct ECS::Skeleton::bone_data &b = bonesptr[order[i]];
if (b.parent >= 0) if (b.parent >= 0)
@@ -110,7 +107,7 @@ void Character::init_slot()
slot.skin_internal->set_bind_pose(i, slot.skin_internal->get_bind_pose(i).affine_inverse()); slot.skin_internal->set_bind_pose(i, slot.skin_internal->get_bind_pose(i).affine_inverse());
} }
skel->skin = slot.skin_internal; skel->skin = slot.skin_internal;
// flecs::log::trace("created skin for %s: %d", e.name().c_str(), len); // flecs::log::trace("created skin for %s: %d", e.name().c_str(), len);
assert(skel->skeleton.is_valid()); assert(skel->skeleton.is_valid());
skel->skin = slot.skin_internal; skel->skin = slot.skin_internal;
uint32_t bind_count = skel->skin->get_bind_count(); uint32_t bind_count = skel->skin->get_bind_count();
@@ -145,10 +142,10 @@ void Character::init_slot()
skel->skin_bone_indices_ptrs[i] = 0; skel->skin_bone_indices_ptrs[i] = 0;
} }
} }
e.add<ECS::Skinned>(); e.add<ECS::Skinned>();
} else if (!skel->skin.is_null() && slot.skin_internal.is_null()) { } else if (!skel->skin.is_null() && slot.skin_internal.is_null()) {
slot.skin_internal = skel->skin; slot.skin_internal = skel->skin;
e.add<ECS::Skinned>(); e.add<ECS::Skinned>();
} }
}); });
} }

View File

@@ -1,6 +1,6 @@
#include <core/engine.h>
#include "character.h"
#include "register_types.h" #include "register_types.h"
#include "character.h"
#include <core/engine.h>
void register_character_types() void register_character_types()
{ {

View File

@@ -3,9 +3,9 @@
#include <flecs.h> #include <flecs.h>
struct skeleton_prep { struct skeleton_prep {
skeleton_prep(flecs::world &world) skeleton_prep(flecs::world &world)
{ {
world.module<skeleton_prep>(); world.module<skeleton_prep>();
} }
}; };
#endif #endif