Skip to content

Commit

Permalink
experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
TokageItLab committed Oct 19, 2024
1 parent 80f0b33 commit e85c4af
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 0 deletions.
59 changes: 59 additions & 0 deletions doc/classes/BoneExpander3D.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="BoneExpander3D" inherits="SkeletonModifier3D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="add_setting">
<return type="int" />
<param index="0" name="bone" type="int" />
<param index="1" name="scale" type="Vector3" default="Vector3(1, 1, 1)" />
<description>
</description>
</method>
<method name="clear_setting">
<return type="void" />
<description>
</description>
</method>
<method name="get_bone" qualifiers="const">
<return type="int" />
<param index="0" name="_unnamed_arg0" type="int" />
<description>
</description>
</method>
<method name="get_bone_scale" qualifiers="const">
<return type="Vector3" />
<param index="0" name="_unnamed_arg0" type="int" />
<description>
</description>
</method>
<method name="remove_setting">
<return type="void" />
<param index="0" name="index" type="int" />
<description>
</description>
</method>
<method name="set_bone">
<return type="void" />
<param index="0" name="bone" type="int" />
<param index="1" name="_unnamed_arg1" type="int" />
<description>
</description>
</method>
<method name="set_bone_scale">
<return type="void" />
<param index="0" name="scale" type="int" />
<param index="1" name="_unnamed_arg1" type="Vector3" />
<description>
</description>
</method>
</methods>
<members>
<member name="setting_size" type="int" setter="set_setting_size" getter="get_setting_size" default="0">
</member>
</members>
</class>
186 changes: 186 additions & 0 deletions scene/3d/bone_expander_3d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/**************************************************************************/
/* bone_expander_3d.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "bone_expander_3d.h"

bool BoneExpander3D::_set(const StringName &p_path, const Variant &p_value) {
String path = p_path;

if (path.begins_with("settings/")) {
int which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
ERR_FAIL_INDEX_V(which, settings.size(), false);

if (what == "bone") {
set_bone(which, p_value);
} else if (what == "bone_scale") {
set_bone_scale(which, p_value);
} else {
return false;
}
}
return true;
}

bool BoneExpander3D::_get(const StringName &p_path, Variant &r_ret) const {
String path = p_path;

if (path.begins_with("settings/")) {
int which = path.get_slicec('/', 1).to_int();
String what = path.get_slicec('/', 2);
ERR_FAIL_INDEX_V(which, settings.size(), false);

if (what == "bone") {
r_ret = get_bone(which);
} else if (what == "bone_scale") {
r_ret = get_bone_scale(which);
} else {
return false;
}
}
return true;
}

void BoneExpander3D::_get_property_list(List<PropertyInfo> *p_list) const {
String enum_hint;
Skeleton3D *skeleton = get_skeleton();
if (skeleton) {
enum_hint = skeleton->get_concatenated_bone_names();
}

for (int i = 0; i < settings.size(); i++) {
String path = "settings/" + itos(i) + "/";
p_list->push_back(PropertyInfo(Variant::INT, path + "bone", PROPERTY_HINT_ENUM, enum_hint));
p_list->push_back(PropertyInfo(Variant::VECTOR3, path + "bone_scale"));
}
}

int BoneExpander3D::get_setting_size() {
return settings.size();
}

void BoneExpander3D::set_setting_size(int p_size) {
ERR_FAIL_COND(p_size < 0);

int delta = p_size - settings.size() + 1;
settings.resize(p_size);

if (delta > 1) {
for (int i = 1; i < delta; i++) {
validate_scale(p_size - i);
}
}

notify_property_list_changed();
}

void BoneExpander3D::validate_scale(int p_index) {
Vector3 scl = settings[p_index].second;
if (Math::is_zero_approx(scl.x * scl.y * scl.z)) {
settings.write[p_index].second = DEFAULT_SCALE;
}
}

int BoneExpander3D::add_setting(int p_bone, Vector3 p_scale) {
int pos = settings.size();
settings.push_back(BoneExpander3DSetting(p_bone, p_scale));
return pos;
}

void BoneExpander3D::remove_setting(int p_index) {
settings.remove_at(p_index);
}

void BoneExpander3D::clear_settings() {
settings.clear();
}

void BoneExpander3D::set_bone(int p_index, int p_bone) {
ERR_FAIL_INDEX(p_index, settings.size());
settings.write[p_index].first = p_bone;
}

int BoneExpander3D::get_bone(int p_index) const {
ERR_FAIL_INDEX_V(p_index, settings.size(), -1);
return settings[p_index].first;
}

void BoneExpander3D::set_bone_scale(int p_index, Vector3 p_scale) {
ERR_FAIL_INDEX(p_index, settings.size());
ERR_FAIL_COND_MSG(Math::is_zero_approx(p_scale.x * p_scale.y * p_scale.z), "Scale must not be zero.");
settings.write[p_index].second = p_scale;
}

Vector3 BoneExpander3D::get_bone_scale(int p_index) const {
ERR_FAIL_INDEX_V(p_index, settings.size(), Vector3(1, 1, 1));
return settings[p_index].second;
}

void BoneExpander3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_setting_size", "size"), &BoneExpander3D::set_setting_size);
ClassDB::bind_method(D_METHOD("get_setting_size"), &BoneExpander3D::get_setting_size);
ClassDB::bind_method(D_METHOD("add_setting", "bone", "scale"), &BoneExpander3D::add_setting, DEFVAL(Vector3(1, 1, 1)));
ClassDB::bind_method(D_METHOD("remove_setting", "index"), &BoneExpander3D::remove_setting);
ClassDB::bind_method(D_METHOD("clear_setting"), &BoneExpander3D::clear_settings);

ClassDB::bind_method(D_METHOD("set_bone", "bone"), &BoneExpander3D::set_bone);
ClassDB::bind_method(D_METHOD("get_bone"), &BoneExpander3D::get_bone);

ClassDB::bind_method(D_METHOD("set_bone_scale", "scale"), &BoneExpander3D::set_bone_scale);
ClassDB::bind_method(D_METHOD("get_bone_scale"), &BoneExpander3D::get_bone_scale);

ADD_PROPERTY(PropertyInfo(Variant::INT, "setting_size", PROPERTY_HINT_RANGE, "0,1000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, "Settings,settings/"), "set_setting_size", "get_setting_size");
}

void BoneExpander3D::_process_modification() {
Skeleton3D *skeleton = get_skeleton();
if (!skeleton) {
return;
}

for (const BoneExpander3DSetting &setting : settings) {
int bone = setting.first;
if (bone < 0) {
continue;
}

Vector3 src = skeleton->get_bone_pose_scale(bone);
Vector3 dst = setting.second;
skeleton->set_bone_pose_scale(bone, src * dst);
dst = DEFAULT_SCALE / dst;

Vector<int> children = skeleton->get_bone_children(bone);
for (const int &child : children) {
Transform3D pose = skeleton->get_bone_pose(child);
pose.scale(dst);
skeleton->set_bone_pose_unsafe(child, pose);
}
}
}
68 changes: 68 additions & 0 deletions scene/3d/bone_expander_3d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**************************************************************************/
/* bone_expander_3d.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef BONE_EXPANDER_3D_H
#define BONE_EXPANDER_3D_H

#include "scene/3d/skeleton_modifier_3d.h"

class BoneExpander3D : public SkeletonModifier3D {
GDCLASS(BoneExpander3D, SkeletonModifier3D);

const Vector3 DEFAULT_SCALE = Vector3(1, 1, 1);

typedef Pair<int, Vector3> BoneExpander3DSetting;
Vector<BoneExpander3DSetting> settings;

void validate_scale(int p_index);

protected:
bool _get(const StringName &p_path, Variant &r_ret) const;
bool _set(const StringName &p_path, const Variant &p_value);
void _get_property_list(List<PropertyInfo> *p_list) const;

static void _bind_methods();

virtual void _process_modification() override;

public:
int get_setting_size();
void set_setting_size(int p_size);
int add_setting(int p_bone, Vector3 p_scale = Vector3(1, 1, 1));
void remove_setting(int p_index);
void clear_settings();

void set_bone(int p_index, int p_bone);
int get_bone(int p_index) const;
void set_bone_scale(int p_index, Vector3 p_scale);
Vector3 get_bone_scale(int p_index) const;
};

#endif // BONE_EXPANDER_3D_H
3 changes: 3 additions & 0 deletions scene/3d/skeleton_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,9 @@ Transform3D Skeleton3D::get_bone_pose(int p_bone) const {
return bones[p_bone].pose_cache;
}

void Skeleton3D::set_bone_pose_unsafe(int p_bone, const Transform3D &p_pose) {
bones[p_bone].pose_cache = p_pose;
}
void Skeleton3D::_make_dirty() {
if (dirty) {
return;
Expand Down
2 changes: 2 additions & 0 deletions scene/3d/skeleton_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ class Skeleton3D : public Node3D {
void reset_bone_pose(int p_bone);
void reset_bone_poses();

void set_bone_pose_unsafe(int p_bone, const Transform3D &p_pose);

void localize_rests(); // Used for loaders and tools.

Ref<Skin> create_skin_from_rest_transforms();
Expand Down
2 changes: 2 additions & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
#include "scene/3d/audio_listener_3d.h"
#include "scene/3d/audio_stream_player_3d.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/bone_expander_3d.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/cpu_particles_3d.h"
#include "scene/3d/decal.h"
Expand Down Expand Up @@ -606,6 +607,7 @@ void register_scene_types() {
GDREGISTER_CLASS(PhysicalBone3D);
GDREGISTER_CLASS(SoftBody3D);

GDREGISTER_CLASS(BoneExpander3D);
GDREGISTER_CLASS(SkeletonIK3D);
GDREGISTER_CLASS(BoneAttachment3D);

Expand Down

0 comments on commit e85c4af

Please sign in to comment.