Path: blob/master/scene/2d/physics/physical_bone_2d.cpp
9906 views
/**************************************************************************/1/* physical_bone_2d.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 "physical_bone_2d.h"3132#include "scene/2d/physics/joints/joint_2d.h"3334void PhysicalBone2D::_notification(int p_what) {35switch (p_what) {36case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {37// Position the RigidBody in the correct position.38if (follow_bone_when_simulating) {39_position_at_bone2d();40}4142// Keep the child joint in the correct position.43if (child_joint && auto_configure_joint) {44child_joint->set_global_position(get_global_position());45}46} break;4748case NOTIFICATION_READY: {49_find_skeleton_parent();50_find_joint_child();5152// Configure joint.53if (child_joint && auto_configure_joint) {54_auto_configure_joint();55}5657// Simulate physics if set.58if (simulate_physics) {59_start_physics_simulation();60} else {61_stop_physics_simulation();62}6364set_physics_process_internal(true);65} break;66}67}6869void PhysicalBone2D::_position_at_bone2d() {70// Reset to Bone2D position71if (parent_skeleton) {72Bone2D *bone_to_use = parent_skeleton->get_bone(bone2d_index);73ERR_FAIL_NULL_MSG(bone_to_use, "It's not possible to position the bone with ID: " + itos(bone2d_index) + ".");74set_global_transform(bone_to_use->get_global_transform());75}76}7778void PhysicalBone2D::_find_skeleton_parent() {79Node *current_parent = get_parent();8081while (current_parent != nullptr) {82Skeleton2D *potential_skeleton = Object::cast_to<Skeleton2D>(current_parent);83if (potential_skeleton) {84parent_skeleton = potential_skeleton;85break;86} else {87PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(current_parent);88if (potential_parent_bone) {89current_parent = potential_parent_bone->get_parent();90} else {91current_parent = nullptr;92}93}94}95}9697void PhysicalBone2D::_find_joint_child() {98for (int i = 0; i < get_child_count(); i++) {99Node *child_node = get_child(i);100Joint2D *potential_joint = Object::cast_to<Joint2D>(child_node);101if (potential_joint) {102child_joint = potential_joint;103break;104}105}106}107108PackedStringArray PhysicalBone2D::get_configuration_warnings() const {109PackedStringArray warnings = RigidBody2D::get_configuration_warnings();110111if (!parent_skeleton) {112warnings.push_back(RTR("A PhysicalBone2D only works with a Skeleton2D or another PhysicalBone2D as a parent node!"));113}114if (parent_skeleton && bone2d_index <= -1) {115warnings.push_back(RTR("A PhysicalBone2D needs to be assigned to a Bone2D node in order to function! Please set a Bone2D node in the inspector."));116}117if (!child_joint) {118PhysicalBone2D *parent_bone = Object::cast_to<PhysicalBone2D>(get_parent());119if (parent_bone) {120warnings.push_back(RTR("A PhysicalBone2D node should have a Joint2D-based child node to keep bones connected! Please add a Joint2D-based node as a child to this node!"));121}122}123124return warnings;125}126127void PhysicalBone2D::_auto_configure_joint() {128if (!auto_configure_joint) {129return;130}131132if (child_joint) {133// Node A = parent | Node B = this node134Node *parent_node = get_parent();135PhysicalBone2D *potential_parent_bone = Object::cast_to<PhysicalBone2D>(parent_node);136137if (potential_parent_bone) {138child_joint->set_node_a(child_joint->get_path_to(potential_parent_bone));139child_joint->set_node_b(child_joint->get_path_to(this));140} else {141WARN_PRINT("Cannot setup joint without a parent PhysicalBone2D node.");142}143144// Place the child joint at this node's position.145child_joint->set_global_position(get_global_position());146}147}148149void PhysicalBone2D::_start_physics_simulation() {150if (_internal_simulate_physics) {151return;152}153154// Reset to Bone2D position.155_position_at_bone2d();156157// Apply the layers and masks.158PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());159PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());160PhysicsServer2D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority());161162// Apply the correct mode.163_apply_body_mode();164165_internal_simulate_physics = true;166set_physics_process_internal(true);167}168169void PhysicalBone2D::_stop_physics_simulation() {170if (_internal_simulate_physics) {171_internal_simulate_physics = false;172173// Reset to Bone2D position174_position_at_bone2d();175176set_physics_process_internal(false);177PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);178PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);179PhysicsServer2D::get_singleton()->body_set_collision_priority(get_rid(), 1.0);180PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);181}182}183184Joint2D *PhysicalBone2D::get_joint() const {185return child_joint;186}187188bool PhysicalBone2D::get_auto_configure_joint() const {189return auto_configure_joint;190}191192void PhysicalBone2D::set_auto_configure_joint(bool p_auto_configure) {193auto_configure_joint = p_auto_configure;194_auto_configure_joint();195}196197void PhysicalBone2D::set_simulate_physics(bool p_simulate) {198if (p_simulate == simulate_physics) {199return;200}201simulate_physics = p_simulate;202203if (simulate_physics) {204_start_physics_simulation();205} else {206_stop_physics_simulation();207}208}209210bool PhysicalBone2D::get_simulate_physics() const {211return simulate_physics;212}213214bool PhysicalBone2D::is_simulating_physics() const {215return _internal_simulate_physics;216}217218void PhysicalBone2D::set_bone2d_nodepath(const NodePath &p_nodepath) {219bone2d_nodepath = p_nodepath;220notify_property_list_changed();221}222223NodePath PhysicalBone2D::get_bone2d_nodepath() const {224return bone2d_nodepath;225}226227void PhysicalBone2D::set_bone2d_index(int p_bone_idx) {228ERR_FAIL_COND_MSG(p_bone_idx < 0, "Bone index is out of range: The index is too low!");229230if (!is_inside_tree()) {231bone2d_index = p_bone_idx;232return;233}234235if (parent_skeleton) {236ERR_FAIL_INDEX_MSG(p_bone_idx, parent_skeleton->get_bone_count(), "Passed-in Bone index is out of range!");237bone2d_index = p_bone_idx;238239bone2d_nodepath = get_path_to(parent_skeleton->get_bone(bone2d_index));240} else {241WARN_PRINT("Cannot verify bone index...");242bone2d_index = p_bone_idx;243}244245notify_property_list_changed();246}247248int PhysicalBone2D::get_bone2d_index() const {249return bone2d_index;250}251252void PhysicalBone2D::set_follow_bone_when_simulating(bool p_follow_bone) {253follow_bone_when_simulating = p_follow_bone;254255if (_internal_simulate_physics) {256_stop_physics_simulation();257_start_physics_simulation();258}259}260261bool PhysicalBone2D::get_follow_bone_when_simulating() const {262return follow_bone_when_simulating;263}264265void PhysicalBone2D::_bind_methods() {266ClassDB::bind_method(D_METHOD("get_joint"), &PhysicalBone2D::get_joint);267ClassDB::bind_method(D_METHOD("get_auto_configure_joint"), &PhysicalBone2D::get_auto_configure_joint);268ClassDB::bind_method(D_METHOD("set_auto_configure_joint", "auto_configure_joint"), &PhysicalBone2D::set_auto_configure_joint);269270ClassDB::bind_method(D_METHOD("set_simulate_physics", "simulate_physics"), &PhysicalBone2D::set_simulate_physics);271ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone2D::get_simulate_physics);272ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone2D::is_simulating_physics);273274ClassDB::bind_method(D_METHOD("set_bone2d_nodepath", "nodepath"), &PhysicalBone2D::set_bone2d_nodepath);275ClassDB::bind_method(D_METHOD("get_bone2d_nodepath"), &PhysicalBone2D::get_bone2d_nodepath);276ClassDB::bind_method(D_METHOD("set_bone2d_index", "bone_index"), &PhysicalBone2D::set_bone2d_index);277ClassDB::bind_method(D_METHOD("get_bone2d_index"), &PhysicalBone2D::get_bone2d_index);278ClassDB::bind_method(D_METHOD("set_follow_bone_when_simulating", "follow_bone"), &PhysicalBone2D::set_follow_bone_when_simulating);279ClassDB::bind_method(D_METHOD("get_follow_bone_when_simulating"), &PhysicalBone2D::get_follow_bone_when_simulating);280281ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "bone2d_nodepath", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Bone2D"), "set_bone2d_nodepath", "get_bone2d_nodepath");282ADD_PROPERTY(PropertyInfo(Variant::INT, "bone2d_index", PROPERTY_HINT_RANGE, "-1, 1000, 1"), "set_bone2d_index", "get_bone2d_index");283ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_configure_joint"), "set_auto_configure_joint", "get_auto_configure_joint");284ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simulate_physics"), "set_simulate_physics", "get_simulate_physics");285ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_bone_when_simulating"), "set_follow_bone_when_simulating", "get_follow_bone_when_simulating");286}287288PhysicalBone2D::PhysicalBone2D() {289// Stop the RigidBody from executing its force integration.290PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0);291PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0);292PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);293294child_joint = nullptr;295}296297PhysicalBone2D::~PhysicalBone2D() {298}299300301