Path: blob/master/scene/3d/copy_transform_modifier_3d.cpp
20882 views
/**************************************************************************/1/* copy_transform_modifier_3d.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "copy_transform_modifier_3d.h"3132bool CopyTransformModifier3D::_set(const StringName &p_path, const Variant &p_value) {33String path = p_path;3435if (path.begins_with("settings/")) {36int which = path.get_slicec('/', 1).to_int();37String what = path.get_slicec('/', 2);38ERR_FAIL_INDEX_V(which, (int)settings.size(), false);3940if (what == "copy") {41set_copy_flags(which, static_cast<BitField<TransformFlag>>((int)p_value));42} else if (what == "axes") {43set_axis_flags(which, static_cast<BitField<AxisFlag>>((int)p_value));44} else if (what == "invert") {45set_invert_flags(which, static_cast<BitField<AxisFlag>>((int)p_value));46} else if (what == "relative") {47set_relative(which, p_value);48} else if (what == "additive") {49set_additive(which, p_value);50} else {51return false;52}53}54return true;55}5657bool CopyTransformModifier3D::_get(const StringName &p_path, Variant &r_ret) const {58String path = p_path;5960if (path.begins_with("settings/")) {61int which = path.get_slicec('/', 1).to_int();62String what = path.get_slicec('/', 2);63ERR_FAIL_INDEX_V(which, (int)settings.size(), false);6465if (what == "copy") {66r_ret = (int)get_copy_flags(which);67} else if (what == "axes") {68r_ret = (int)get_axis_flags(which);69} else if (what == "invert") {70r_ret = (int)get_invert_flags(which);71} else if (what == "relative") {72r_ret = is_relative(which);73} else if (what == "additive") {74r_ret = is_additive(which);75} else {76return false;77}78}79return true;80}8182void CopyTransformModifier3D::_get_property_list(List<PropertyInfo> *p_list) const {83BoneConstraint3D::get_property_list(p_list);8485LocalVector<PropertyInfo> props;8687for (uint32_t i = 0; i < settings.size(); i++) {88String path = "settings/" + itos(i) + "/";89props.push_back(PropertyInfo(Variant::INT, path + "copy", PROPERTY_HINT_FLAGS, "Position,Rotation,Scale"));90props.push_back(PropertyInfo(Variant::INT, path + "axes", PROPERTY_HINT_FLAGS, "X,Y,Z"));91props.push_back(PropertyInfo(Variant::INT, path + "invert", PROPERTY_HINT_FLAGS, "X,Y,Z"));92props.push_back(PropertyInfo(Variant::BOOL, path + "relative"));93props.push_back(PropertyInfo(Variant::BOOL, path + "additive"));94}9596for (PropertyInfo &p : props) {97_validate_dynamic_prop(p);98p_list->push_back(p);99}100}101102void CopyTransformModifier3D::_validate_dynamic_prop(PropertyInfo &p_property) const {103PackedStringArray split = p_property.name.split("/");104if (split.size() > 2 && split[0] == "settings") {105int which = split[1].to_int();106if (split[2].begins_with("relative") && get_reference_type(which) != REFERENCE_TYPE_BONE) {107p_property.usage = PROPERTY_USAGE_NONE;108}109}110}111112void CopyTransformModifier3D::_validate_setting(int p_index) {113settings[p_index] = memnew(CopyTransform3DSetting);114}115116void CopyTransformModifier3D::set_copy_flags(int p_index, BitField<TransformFlag> p_copy_flags) {117ERR_FAIL_INDEX(p_index, (int)settings.size());118CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);119setting->copy_flags = p_copy_flags;120notify_property_list_changed();121}122123BitField<CopyTransformModifier3D::TransformFlag> CopyTransformModifier3D::get_copy_flags(int p_index) const {124ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0);125CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);126return setting->copy_flags;127}128129void CopyTransformModifier3D::set_axis_flags(int p_index, BitField<AxisFlag> p_axis_flags) {130ERR_FAIL_INDEX(p_index, (int)settings.size());131CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);132setting->axis_flags = p_axis_flags;133notify_property_list_changed();134}135136BitField<CopyTransformModifier3D::AxisFlag> CopyTransformModifier3D::get_axis_flags(int p_index) const {137ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0);138CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);139return setting->axis_flags;140}141142void CopyTransformModifier3D::set_invert_flags(int p_index, BitField<AxisFlag> p_axis_flags) {143ERR_FAIL_INDEX(p_index, (int)settings.size());144CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);145setting->invert_flags = p_axis_flags;146notify_property_list_changed();147}148149BitField<CopyTransformModifier3D::AxisFlag> CopyTransformModifier3D::get_invert_flags(int p_index) const {150ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);151CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);152return setting->invert_flags;153}154155void CopyTransformModifier3D::set_copy_position(int p_index, bool p_enabled) {156ERR_FAIL_INDEX(p_index, (int)settings.size());157CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);158if (p_enabled) {159setting->copy_flags.set_flag(TRANSFORM_FLAG_POSITION);160} else {161setting->copy_flags.clear_flag(TRANSFORM_FLAG_POSITION);162}163}164165bool CopyTransformModifier3D::is_position_copying(int p_index) const {166ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);167CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);168return setting->copy_flags.has_flag(TRANSFORM_FLAG_POSITION);169}170171void CopyTransformModifier3D::set_copy_rotation(int p_index, bool p_enabled) {172ERR_FAIL_INDEX(p_index, (int)settings.size());173CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);174if (p_enabled) {175setting->copy_flags.set_flag(TRANSFORM_FLAG_ROTATION);176} else {177setting->copy_flags.clear_flag(TRANSFORM_FLAG_ROTATION);178}179}180181bool CopyTransformModifier3D::is_rotation_copying(int p_index) const {182ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);183CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);184return setting->copy_flags.has_flag(TRANSFORM_FLAG_ROTATION);185}186187void CopyTransformModifier3D::set_copy_scale(int p_index, bool p_enabled) {188ERR_FAIL_INDEX(p_index, (int)settings.size());189CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);190if (p_enabled) {191setting->copy_flags.set_flag(TRANSFORM_FLAG_SCALE);192} else {193setting->copy_flags.clear_flag(TRANSFORM_FLAG_SCALE);194}195}196197bool CopyTransformModifier3D::is_scale_copying(int p_index) const {198ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);199CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);200return setting->copy_flags.has_flag(TRANSFORM_FLAG_SCALE);201}202203void CopyTransformModifier3D::set_axis_x_enabled(int p_index, bool p_enabled) {204ERR_FAIL_INDEX(p_index, (int)settings.size());205CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);206if (p_enabled) {207setting->axis_flags.set_flag(AXIS_FLAG_X);208} else {209setting->axis_flags.clear_flag(AXIS_FLAG_X);210}211}212213bool CopyTransformModifier3D::is_axis_x_enabled(int p_index) const {214ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);215CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);216return setting->axis_flags.has_flag(AXIS_FLAG_X);217}218219void CopyTransformModifier3D::set_axis_y_enabled(int p_index, bool p_enabled) {220ERR_FAIL_INDEX(p_index, (int)settings.size());221CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);222if (p_enabled) {223setting->axis_flags.set_flag(AXIS_FLAG_Y);224} else {225setting->axis_flags.clear_flag(AXIS_FLAG_Y);226}227}228229bool CopyTransformModifier3D::is_axis_y_enabled(int p_index) const {230ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);231CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);232return setting->axis_flags.has_flag(AXIS_FLAG_Y);233}234235void CopyTransformModifier3D::set_axis_z_enabled(int p_index, bool p_enabled) {236ERR_FAIL_INDEX(p_index, (int)settings.size());237CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);238if (p_enabled) {239setting->axis_flags.set_flag(AXIS_FLAG_Z);240} else {241setting->axis_flags.clear_flag(AXIS_FLAG_Z);242}243}244245bool CopyTransformModifier3D::is_axis_z_enabled(int p_index) const {246ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);247CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);248return setting->axis_flags.has_flag(AXIS_FLAG_Z);249}250251void CopyTransformModifier3D::set_axis_x_inverted(int p_index, bool p_enabled) {252ERR_FAIL_INDEX(p_index, (int)settings.size());253CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);254if (p_enabled) {255setting->invert_flags.set_flag(AXIS_FLAG_X);256} else {257setting->invert_flags.clear_flag(AXIS_FLAG_X);258}259}260261bool CopyTransformModifier3D::is_axis_x_inverted(int p_index) const {262ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);263CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);264return setting->invert_flags.has_flag(AXIS_FLAG_X);265}266267void CopyTransformModifier3D::set_axis_y_inverted(int p_index, bool p_enabled) {268ERR_FAIL_INDEX(p_index, (int)settings.size());269CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);270if (p_enabled) {271setting->invert_flags.set_flag(AXIS_FLAG_Y);272} else {273setting->invert_flags.clear_flag(AXIS_FLAG_Y);274}275}276277bool CopyTransformModifier3D::is_axis_y_inverted(int p_index) const {278ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);279CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);280return setting->invert_flags.has_flag(AXIS_FLAG_Y);281}282283void CopyTransformModifier3D::set_axis_z_inverted(int p_index, bool p_enabled) {284ERR_FAIL_INDEX(p_index, (int)settings.size());285CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);286if (p_enabled) {287setting->invert_flags.set_flag(AXIS_FLAG_Z);288} else {289setting->invert_flags.clear_flag(AXIS_FLAG_Z);290}291}292293bool CopyTransformModifier3D::is_axis_z_inverted(int p_index) const {294ERR_FAIL_INDEX_V(p_index, (int)settings.size(), false);295CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);296return setting->invert_flags.has_flag(AXIS_FLAG_Z);297}298299void CopyTransformModifier3D::set_relative(int p_index, bool p_enabled) {300ERR_FAIL_INDEX(p_index, (int)settings.size());301CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);302setting->relative = p_enabled;303}304305bool CopyTransformModifier3D::is_relative(int p_index) const {306ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0);307CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);308return setting->is_relative();309}310311void CopyTransformModifier3D::set_additive(int p_index, bool p_enabled) {312ERR_FAIL_INDEX(p_index, (int)settings.size());313CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);314setting->additive = p_enabled;315}316317bool CopyTransformModifier3D::is_additive(int p_index) const {318ERR_FAIL_INDEX_V(p_index, (int)settings.size(), 0);319CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);320return setting->additive;321}322323void CopyTransformModifier3D::_bind_methods() {324ClassDB::bind_method(D_METHOD("set_copy_flags", "index", "copy_flags"), &CopyTransformModifier3D::set_copy_flags);325ClassDB::bind_method(D_METHOD("get_copy_flags", "index"), &CopyTransformModifier3D::get_copy_flags);326ClassDB::bind_method(D_METHOD("set_axis_flags", "index", "axis_flags"), &CopyTransformModifier3D::set_axis_flags);327ClassDB::bind_method(D_METHOD("get_axis_flags", "index"), &CopyTransformModifier3D::get_axis_flags);328ClassDB::bind_method(D_METHOD("set_invert_flags", "index", "axis_flags"), &CopyTransformModifier3D::set_invert_flags);329ClassDB::bind_method(D_METHOD("get_invert_flags", "index"), &CopyTransformModifier3D::get_invert_flags);330331ClassDB::bind_method(D_METHOD("set_copy_position", "index", "enabled"), &CopyTransformModifier3D::set_copy_position);332ClassDB::bind_method(D_METHOD("is_position_copying", "index"), &CopyTransformModifier3D::is_position_copying);333ClassDB::bind_method(D_METHOD("set_copy_rotation", "index", "enabled"), &CopyTransformModifier3D::set_copy_rotation);334ClassDB::bind_method(D_METHOD("is_rotation_copying", "index"), &CopyTransformModifier3D::is_rotation_copying);335ClassDB::bind_method(D_METHOD("set_copy_scale", "index", "enabled"), &CopyTransformModifier3D::set_copy_scale);336ClassDB::bind_method(D_METHOD("is_scale_copying", "index"), &CopyTransformModifier3D::is_scale_copying);337338ClassDB::bind_method(D_METHOD("set_axis_x_enabled", "index", "enabled"), &CopyTransformModifier3D::set_axis_x_enabled);339ClassDB::bind_method(D_METHOD("is_axis_x_enabled", "index"), &CopyTransformModifier3D::is_axis_x_enabled);340ClassDB::bind_method(D_METHOD("set_axis_y_enabled", "index", "enabled"), &CopyTransformModifier3D::set_axis_y_enabled);341ClassDB::bind_method(D_METHOD("is_axis_y_enabled", "index"), &CopyTransformModifier3D::is_axis_y_enabled);342ClassDB::bind_method(D_METHOD("set_axis_z_enabled", "index", "enabled"), &CopyTransformModifier3D::set_axis_z_enabled);343ClassDB::bind_method(D_METHOD("is_axis_z_enabled", "index"), &CopyTransformModifier3D::is_axis_z_enabled);344345ClassDB::bind_method(D_METHOD("set_axis_x_inverted", "index", "enabled"), &CopyTransformModifier3D::set_axis_x_inverted);346ClassDB::bind_method(D_METHOD("is_axis_x_inverted", "index"), &CopyTransformModifier3D::is_axis_x_inverted);347ClassDB::bind_method(D_METHOD("set_axis_y_inverted", "index", "enabled"), &CopyTransformModifier3D::set_axis_y_inverted);348ClassDB::bind_method(D_METHOD("is_axis_y_inverted", "index"), &CopyTransformModifier3D::is_axis_y_inverted);349ClassDB::bind_method(D_METHOD("set_axis_z_inverted", "index", "enabled"), &CopyTransformModifier3D::set_axis_z_inverted);350ClassDB::bind_method(D_METHOD("is_axis_z_inverted", "index"), &CopyTransformModifier3D::is_axis_z_inverted);351352ClassDB::bind_method(D_METHOD("set_relative", "index", "enabled"), &CopyTransformModifier3D::set_relative);353ClassDB::bind_method(D_METHOD("is_relative", "index"), &CopyTransformModifier3D::is_relative);354ClassDB::bind_method(D_METHOD("set_additive", "index", "enabled"), &CopyTransformModifier3D::set_additive);355ClassDB::bind_method(D_METHOD("is_additive", "index"), &CopyTransformModifier3D::is_additive);356357ADD_ARRAY_COUNT("Settings", "setting_count", "set_setting_count", "get_setting_count", "settings/");358359BIND_BITFIELD_FLAG(TRANSFORM_FLAG_POSITION);360BIND_BITFIELD_FLAG(TRANSFORM_FLAG_ROTATION);361BIND_BITFIELD_FLAG(TRANSFORM_FLAG_SCALE);362BIND_BITFIELD_FLAG(TRANSFORM_FLAG_ALL);363364BIND_BITFIELD_FLAG(AXIS_FLAG_X);365BIND_BITFIELD_FLAG(AXIS_FLAG_Y);366BIND_BITFIELD_FLAG(AXIS_FLAG_Z);367BIND_BITFIELD_FLAG(AXIS_FLAG_ALL);368}369370void CopyTransformModifier3D::_process_constraint_by_bone(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, int p_reference_bone, float p_amount) {371CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);372Transform3D destination = p_skeleton->get_bone_pose(p_reference_bone);373if (setting->is_relative()) {374Vector3 scl_relative = destination.basis.get_scale() / p_skeleton->get_bone_rest(p_reference_bone).basis.get_scale();375destination.basis = p_skeleton->get_bone_rest(p_reference_bone).basis.get_rotation_quaternion().inverse() * destination.basis.get_rotation_quaternion();376destination.basis.scale_local(scl_relative);377destination.origin = destination.origin - p_skeleton->get_bone_rest(p_reference_bone).origin;378}379_process_copy(p_index, p_skeleton, p_apply_bone, destination, p_amount);380}381382void CopyTransformModifier3D::_process_constraint_by_node(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const NodePath &p_reference_node, float p_amount) {383Node3D *nd = Object::cast_to<Node3D>(get_node_or_null(p_reference_node));384if (!nd) {385return;386}387Transform3D skel_tr = p_skeleton->get_global_transform_interpolated();388int parent = p_skeleton->get_bone_parent(p_apply_bone);389if (parent >= 0) {390skel_tr = skel_tr * p_skeleton->get_bone_global_pose(parent);391}392Transform3D dest_tr = nd->get_global_transform_interpolated();393Transform3D reference_dest = skel_tr.affine_inverse() * dest_tr;394_process_copy(p_index, p_skeleton, p_apply_bone, reference_dest, p_amount);395}396397void CopyTransformModifier3D::_process_copy(int p_index, Skeleton3D *p_skeleton, int p_apply_bone, const Transform3D &p_destination, float p_amount) {398CopyTransform3DSetting *setting = static_cast<CopyTransform3DSetting *>(settings[p_index]);399400Transform3D destination = p_destination;401Vector3 dest_pos = destination.origin;402Quaternion dest_rot = destination.basis.get_rotation_quaternion();403Vector3 dest_scl = destination.basis.get_scale();404405// Mask pos and scale.406for (int i = 0; i < 3; i++) {407if (!setting->axis_flags.has_flag(static_cast<AxisFlag>(1 << i))) {408dest_pos[i] = 0.0;409dest_scl[i] = 1.0;410}411}412413// Mask rot.414switch (static_cast<int>(setting->axis_flags)) {415case 0: {416dest_rot = Quaternion();417} break;418case AXIS_FLAG_X: {419Vector3 axis = get_vector_from_axis(Vector3::AXIS_X);420dest_rot = Quaternion(axis, get_roll_angle(dest_rot, axis));421} break;422case AXIS_FLAG_Y: {423Vector3 axis = get_vector_from_axis(Vector3::AXIS_Y);424dest_rot = Quaternion(axis, get_roll_angle(dest_rot, axis));425} break;426case AXIS_FLAG_Z: {427Vector3 axis = get_vector_from_axis(Vector3::AXIS_Z);428dest_rot = Quaternion(axis, get_roll_angle(dest_rot, axis));429} break;430case AXIS_FLAG_X | AXIS_FLAG_Y: {431Vector3 axis = get_vector_from_axis(Vector3::AXIS_Z);432dest_rot = dest_rot * Quaternion(axis, get_roll_angle(dest_rot, axis)).inverse();433} break;434case AXIS_FLAG_Y | AXIS_FLAG_Z: {435Vector3 axis = get_vector_from_axis(Vector3::AXIS_X);436dest_rot = dest_rot * Quaternion(axis, get_roll_angle(dest_rot, axis)).inverse();437} break;438case AXIS_FLAG_Z | AXIS_FLAG_X: {439Vector3 axis = get_vector_from_axis(Vector3::AXIS_Y);440dest_rot = dest_rot * Quaternion(axis, get_roll_angle(dest_rot, axis)).inverse();441} break;442case AXIS_FLAG_ALL: {443} break;444}445446// Process inversion.447for (int i = 0; i < 3; i++) {448AxisFlag axis = static_cast<AxisFlag>(1 << i);449if (setting->axis_flags.has_flag(axis) && setting->invert_flags.has_flag(axis)) {450dest_pos[i] *= -1;451dest_rot[i] *= -1;452dest_scl[i] = 1.0 / dest_scl[i];453}454}455dest_rot.normalize();456457if (setting->additive) {458destination.origin = p_skeleton->get_bone_pose_position(p_apply_bone) + dest_pos;459destination.basis = p_skeleton->get_bone_pose_rotation(p_apply_bone) * Basis(dest_rot);460destination.basis.scale_local(p_skeleton->get_bone_pose_scale(p_apply_bone) * dest_scl);461} else if (setting->is_relative()) {462Transform3D rest = p_skeleton->get_bone_rest(p_apply_bone);463destination.origin = rest.origin + dest_pos;464destination.basis = rest.basis.get_rotation_quaternion() * Basis(dest_rot);465destination.basis.scale_local(rest.basis.get_scale() * dest_scl);466} else {467destination.origin = dest_pos;468destination.basis = Basis(dest_rot);469destination.basis.scale_local(dest_scl);470}471472// Process interpolation depends on the amount.473destination = p_skeleton->get_bone_pose(p_apply_bone).interpolate_with(destination, p_amount);474475// Apply transform depends on the element mask.476if (setting->copy_flags.has_flag(TRANSFORM_FLAG_POSITION)) {477p_skeleton->set_bone_pose_position(p_apply_bone, destination.origin);478}479if (setting->copy_flags.has_flag(TRANSFORM_FLAG_ROTATION)) {480p_skeleton->set_bone_pose_rotation(p_apply_bone, destination.basis.get_rotation_quaternion());481}482if (setting->copy_flags.has_flag(TRANSFORM_FLAG_SCALE)) {483p_skeleton->set_bone_pose_scale(p_apply_bone, destination.basis.get_scale());484}485}486487CopyTransformModifier3D::~CopyTransformModifier3D() {488clear_settings();489}490491492