Path: blob/master/modules/godot_physics_2d/godot_body_2d.cpp
10277 views
/**************************************************************************/1/* godot_body_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 "godot_body_2d.h"3132#include "godot_area_2d.h"33#include "godot_body_direct_state_2d.h"34#include "godot_constraint_2d.h"35#include "godot_space_2d.h"3637void GodotBody2D::_mass_properties_changed() {38if (get_space() && !mass_properties_update_list.in_list()) {39get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list);40}41}4243void GodotBody2D::update_mass_properties() {44//update shapes and motions4546switch (mode) {47case PhysicsServer2D::BODY_MODE_RIGID: {48real_t total_area = 0;49for (int i = 0; i < get_shape_count(); i++) {50if (is_shape_disabled(i)) {51continue;52}53total_area += get_shape_aabb(i).get_area();54}5556if (calculate_center_of_mass) {57// We have to recompute the center of mass.58center_of_mass_local = Vector2();5960if (total_area != 0.0) {61for (int i = 0; i < get_shape_count(); i++) {62if (is_shape_disabled(i)) {63continue;64}6566real_t area = get_shape_aabb(i).get_area();6768real_t mass_new = area * mass / total_area;6970// NOTE: we assume that the shape origin is also its center of mass.71center_of_mass_local += mass_new * get_shape_transform(i).get_origin();72}7374center_of_mass_local /= mass;75}76}7778if (calculate_inertia) {79inertia = 0;8081for (int i = 0; i < get_shape_count(); i++) {82if (is_shape_disabled(i)) {83continue;84}8586const GodotShape2D *shape = get_shape(i);8788real_t area = get_shape_aabb(i).get_area();89if (area == 0.0) {90continue;91}9293real_t mass_new = area * mass / total_area;9495Transform2D mtx = get_shape_transform(i);96Vector2 scale = mtx.get_scale();97Vector2 shape_origin = mtx.get_origin() - center_of_mass_local;98inertia += shape->get_moment_of_inertia(mass_new, scale) + mass_new * shape_origin.length_squared();99}100}101102_inv_inertia = inertia > 0.0 ? (1.0 / inertia) : 0.0;103104if (mass) {105_inv_mass = 1.0 / mass;106} else {107_inv_mass = 0;108}109110} break;111case PhysicsServer2D::BODY_MODE_KINEMATIC:112case PhysicsServer2D::BODY_MODE_STATIC: {113_inv_inertia = 0;114_inv_mass = 0;115} break;116case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {117_inv_inertia = 0;118_inv_mass = 1.0 / mass;119120} break;121}122123_update_transform_dependent();124}125126void GodotBody2D::reset_mass_properties() {127calculate_inertia = true;128calculate_center_of_mass = true;129_mass_properties_changed();130}131132void GodotBody2D::set_active(bool p_active) {133if (active == p_active) {134return;135}136137active = p_active;138139if (active) {140if (mode == PhysicsServer2D::BODY_MODE_STATIC) {141// Static bodies can't be active.142active = false;143} else if (get_space()) {144get_space()->body_add_to_active_list(&active_list);145}146} else if (get_space()) {147get_space()->body_remove_from_active_list(&active_list);148}149}150151void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) {152switch (p_param) {153case PhysicsServer2D::BODY_PARAM_BOUNCE: {154bounce = p_value;155} break;156case PhysicsServer2D::BODY_PARAM_FRICTION: {157friction = p_value;158} break;159case PhysicsServer2D::BODY_PARAM_MASS: {160real_t mass_value = p_value;161ERR_FAIL_COND(mass_value <= 0);162mass = mass_value;163if (mode >= PhysicsServer2D::BODY_MODE_RIGID) {164_mass_properties_changed();165}166} break;167case PhysicsServer2D::BODY_PARAM_INERTIA: {168real_t inertia_value = p_value;169if (inertia_value <= 0.0) {170calculate_inertia = true;171if (mode == PhysicsServer2D::BODY_MODE_RIGID) {172_mass_properties_changed();173}174} else {175calculate_inertia = false;176inertia = inertia_value;177if (mode == PhysicsServer2D::BODY_MODE_RIGID) {178_inv_inertia = 1.0 / inertia;179}180}181} break;182case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {183calculate_center_of_mass = false;184center_of_mass_local = p_value;185_update_transform_dependent();186} break;187case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {188if (Math::is_zero_approx(gravity_scale)) {189wakeup();190}191gravity_scale = p_value;192} break;193case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE: {194int mode_value = p_value;195linear_damp_mode = (PhysicsServer2D::BodyDampMode)mode_value;196} break;197case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE: {198int mode_value = p_value;199angular_damp_mode = (PhysicsServer2D::BodyDampMode)mode_value;200} break;201case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: {202linear_damp = p_value;203} break;204case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP: {205angular_damp = p_value;206} break;207default: {208}209}210}211212Variant GodotBody2D::get_param(PhysicsServer2D::BodyParameter p_param) const {213switch (p_param) {214case PhysicsServer2D::BODY_PARAM_BOUNCE: {215return bounce;216}217case PhysicsServer2D::BODY_PARAM_FRICTION: {218return friction;219}220case PhysicsServer2D::BODY_PARAM_MASS: {221return mass;222}223case PhysicsServer2D::BODY_PARAM_INERTIA: {224return inertia;225}226case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {227return center_of_mass_local;228}229case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {230return gravity_scale;231}232case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE: {233return linear_damp_mode;234}235case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE: {236return angular_damp_mode;237}238case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: {239return linear_damp;240}241case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP: {242return angular_damp;243}244default: {245}246}247248return 0;249}250251void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {252PhysicsServer2D::BodyMode prev = mode;253mode = p_mode;254255switch (p_mode) {256//CLEAR UP EVERYTHING IN CASE IT NOT WORKS!257case PhysicsServer2D::BODY_MODE_STATIC:258case PhysicsServer2D::BODY_MODE_KINEMATIC: {259_set_inv_transform(get_transform().affine_inverse());260_inv_mass = 0;261_inv_inertia = 0;262_set_static(p_mode == PhysicsServer2D::BODY_MODE_STATIC);263set_active(p_mode == PhysicsServer2D::BODY_MODE_KINEMATIC && contacts.size());264linear_velocity = Vector2();265angular_velocity = 0;266if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC && prev != mode) {267first_time_kinematic = true;268}269} break;270case PhysicsServer2D::BODY_MODE_RIGID: {271_inv_mass = mass > 0 ? (1.0 / mass) : 0;272if (!calculate_inertia) {273_inv_inertia = 1.0 / inertia;274}275_mass_properties_changed();276_set_static(false);277set_active(true);278279} break;280case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {281_inv_mass = mass > 0 ? (1.0 / mass) : 0;282_inv_inertia = 0;283angular_velocity = 0;284_set_static(false);285set_active(true);286}287}288}289290PhysicsServer2D::BodyMode GodotBody2D::get_mode() const {291return mode;292}293294void GodotBody2D::_shapes_changed() {295_mass_properties_changed();296wakeup();297wakeup_neighbours();298}299300void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) {301switch (p_state) {302case PhysicsServer2D::BODY_STATE_TRANSFORM: {303if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {304new_transform = p_variant;305//wakeup_neighbours();306set_active(true);307if (first_time_kinematic) {308_set_transform(p_variant);309_set_inv_transform(get_transform().affine_inverse());310first_time_kinematic = false;311}312} else if (mode == PhysicsServer2D::BODY_MODE_STATIC) {313_set_transform(p_variant);314_set_inv_transform(get_transform().affine_inverse());315wakeup_neighbours();316} else {317Transform2D t = p_variant;318t.orthonormalize();319new_transform = get_transform(); //used as old to compute motion320if (t == new_transform) {321break;322}323_set_transform(t);324_set_inv_transform(get_transform().inverse());325_update_transform_dependent();326}327wakeup();328329} break;330case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: {331linear_velocity = p_variant;332constant_linear_velocity = linear_velocity;333wakeup();334335} break;336case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: {337angular_velocity = p_variant;338constant_angular_velocity = angular_velocity;339wakeup();340341} break;342case PhysicsServer2D::BODY_STATE_SLEEPING: {343if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {344break;345}346bool do_sleep = p_variant;347if (do_sleep) {348linear_velocity = Vector2();349//biased_linear_velocity=Vector3();350angular_velocity = 0;351//biased_angular_velocity=Vector3();352set_active(false);353} else {354if (mode != PhysicsServer2D::BODY_MODE_STATIC) {355set_active(true);356}357}358} break;359case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {360can_sleep = p_variant;361if (mode >= PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) {362set_active(true);363}364365} break;366}367}368369Variant GodotBody2D::get_state(PhysicsServer2D::BodyState p_state) const {370switch (p_state) {371case PhysicsServer2D::BODY_STATE_TRANSFORM: {372return get_transform();373}374case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: {375return linear_velocity;376}377case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: {378return angular_velocity;379}380case PhysicsServer2D::BODY_STATE_SLEEPING: {381return !is_active();382}383case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {384return can_sleep;385}386}387388return Variant();389}390391void GodotBody2D::set_space(GodotSpace2D *p_space) {392if (get_space()) {393wakeup_neighbours();394395if (mass_properties_update_list.in_list()) {396get_space()->body_remove_from_mass_properties_update_list(&mass_properties_update_list);397}398if (active_list.in_list()) {399get_space()->body_remove_from_active_list(&active_list);400}401if (direct_state_query_list.in_list()) {402get_space()->body_remove_from_state_query_list(&direct_state_query_list);403}404}405406_set_space(p_space);407408if (get_space()) {409_mass_properties_changed();410411if (active && !active_list.in_list()) {412get_space()->body_add_to_active_list(&active_list);413}414}415}416417void GodotBody2D::_update_transform_dependent() {418center_of_mass = get_transform().basis_xform(center_of_mass_local);419}420421void GodotBody2D::integrate_forces(real_t p_step) {422if (mode == PhysicsServer2D::BODY_MODE_STATIC) {423return;424}425426ERR_FAIL_NULL(get_space());427428int ac = areas.size();429430bool gravity_done = false;431bool linear_damp_done = false;432bool angular_damp_done = false;433434bool stopped = false;435436gravity = Vector2(0, 0);437438total_linear_damp = 0.0;439total_angular_damp = 0.0;440441// Combine gravity and damping from overlapping areas in priority order.442if (ac) {443areas.sort();444const AreaCMP *aa = &areas[0];445for (int i = ac - 1; i >= 0 && !stopped; i--) {446if (!gravity_done) {447PhysicsServer2D::AreaSpaceOverrideMode area_gravity_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_GRAVITY_OVERRIDE_MODE);448if (area_gravity_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {449Vector2 area_gravity;450aa[i].area->compute_gravity(get_transform().get_origin(), area_gravity);451switch (area_gravity_mode) {452case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:453case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {454gravity += area_gravity;455gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;456} break;457case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:458case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {459gravity = area_gravity;460gravity_done = area_gravity_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;461} break;462default: {463}464}465}466}467if (!linear_damp_done) {468PhysicsServer2D::AreaSpaceOverrideMode area_linear_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);469if (area_linear_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {470real_t area_linear_damp = aa[i].area->get_linear_damp();471switch (area_linear_damp_mode) {472case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:473case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {474total_linear_damp += area_linear_damp;475linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;476} break;477case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:478case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {479total_linear_damp = area_linear_damp;480linear_damp_done = area_linear_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;481} break;482default: {483}484}485}486}487if (!angular_damp_done) {488PhysicsServer2D::AreaSpaceOverrideMode area_angular_damp_mode = (PhysicsServer2D::AreaSpaceOverrideMode)(int)aa[i].area->get_param(PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);489if (area_angular_damp_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {490real_t area_angular_damp = aa[i].area->get_angular_damp();491switch (area_angular_damp_mode) {492case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE:493case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: {494total_angular_damp += area_angular_damp;495angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE;496} break;497case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE:498case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: {499total_angular_damp = area_angular_damp;500angular_damp_done = area_angular_damp_mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE;501} break;502default: {503}504}505}506}507stopped = gravity_done && linear_damp_done && angular_damp_done;508}509}510511// Add default gravity and damping from space area.512if (!stopped) {513GodotArea2D *default_area = get_space()->get_default_area();514ERR_FAIL_NULL(default_area);515516if (!gravity_done) {517Vector2 default_gravity;518default_area->compute_gravity(get_transform().get_origin(), default_gravity);519gravity += default_gravity;520}521522if (!linear_damp_done) {523total_linear_damp += default_area->get_linear_damp();524}525526if (!angular_damp_done) {527total_angular_damp += default_area->get_angular_damp();528}529}530531// Override linear damping with body's value.532switch (linear_damp_mode) {533case PhysicsServer2D::BODY_DAMP_MODE_COMBINE: {534total_linear_damp += linear_damp;535} break;536case PhysicsServer2D::BODY_DAMP_MODE_REPLACE: {537total_linear_damp = linear_damp;538} break;539}540541// Override angular damping with body's value.542switch (angular_damp_mode) {543case PhysicsServer2D::BODY_DAMP_MODE_COMBINE: {544total_angular_damp += angular_damp;545} break;546case PhysicsServer2D::BODY_DAMP_MODE_REPLACE: {547total_angular_damp = angular_damp;548} break;549}550551gravity *= gravity_scale;552553prev_linear_velocity = linear_velocity;554prev_angular_velocity = angular_velocity;555556Vector2 motion;557bool do_motion = false;558559if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {560//compute motion, angular and etc. velocities from prev transform561motion = new_transform.get_origin() - get_transform().get_origin();562linear_velocity = constant_linear_velocity + motion / p_step;563564real_t rot = new_transform.get_rotation() - get_transform().get_rotation();565angular_velocity = constant_angular_velocity + std::remainder(rot, 2.0 * Math::PI) / p_step;566567do_motion = true;568569} else {570if (!omit_force_integration) {571//overridden by direct state query572573Vector2 force = gravity * mass + applied_force + constant_force;574real_t torque = applied_torque + constant_torque;575576real_t damp = 1.0 - p_step * total_linear_damp;577578if (damp < 0) { // reached zero in the given time579damp = 0;580}581582real_t angular_damp_new = 1.0 - p_step * total_angular_damp;583584if (angular_damp_new < 0) { // reached zero in the given time585angular_damp_new = 0;586}587588linear_velocity *= damp;589angular_velocity *= angular_damp_new;590591linear_velocity += _inv_mass * force * p_step;592angular_velocity += _inv_inertia * torque * p_step;593}594595if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) {596motion = linear_velocity * p_step;597do_motion = true;598}599}600601applied_force = Vector2();602applied_torque = 0.0;603604biased_angular_velocity = 0.0;605biased_linear_velocity = Vector2();606607if (do_motion) { //shapes temporarily extend for raycast608_update_shapes_with_motion(motion);609}610611contact_count = 0;612}613614void GodotBody2D::integrate_velocities(real_t p_step) {615if (mode == PhysicsServer2D::BODY_MODE_STATIC) {616return;617}618619ERR_FAIL_NULL(get_space());620621if (fi_callback_data || body_state_callback.is_valid()) {622get_space()->body_add_to_state_query_list(&direct_state_query_list);623}624625if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {626_set_transform(new_transform, false);627_set_inv_transform(new_transform.affine_inverse());628if (contacts.is_empty() && linear_velocity == Vector2() && angular_velocity == 0) {629set_active(false); //stopped moving, deactivate630}631return;632}633634real_t total_angular_velocity = angular_velocity + biased_angular_velocity;635Vector2 total_linear_velocity = linear_velocity + biased_linear_velocity;636637real_t angle_delta = total_angular_velocity * p_step;638real_t angle = get_transform().get_rotation() + angle_delta;639Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;640641if (center_of_mass.length_squared() > CMP_EPSILON2) {642// Calculate displacement due to center of mass offset.643pos += center_of_mass - center_of_mass.rotated(angle_delta);644}645646_set_transform(Transform2D(angle, pos), continuous_cd_mode == PhysicsServer2D::CCD_MODE_DISABLED);647_set_inv_transform(get_transform().inverse());648649if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) {650new_transform = get_transform();651}652653_update_transform_dependent();654}655656void GodotBody2D::wakeup_neighbours() {657for (const Pair<GodotConstraint2D *, int> &E : constraint_list) {658const GodotConstraint2D *c = E.first;659GodotBody2D **n = c->get_body_ptr();660int bc = c->get_body_count();661662for (int i = 0; i < bc; i++) {663if (i == E.second) {664continue;665}666GodotBody2D *b = n[i];667if (b->mode < PhysicsServer2D::BODY_MODE_RIGID) {668continue;669}670671if (!b->is_active()) {672b->set_active(true);673}674}675}676}677678void GodotBody2D::call_queries() {679Variant direct_state_variant = get_direct_state();680681if (fi_callback_data) {682if (!fi_callback_data->callable.is_valid()) {683set_force_integration_callback(Callable());684} else {685const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };686687Callable::CallError ce;688Variant rv;689if (fi_callback_data->udata.get_type() != Variant::NIL) {690fi_callback_data->callable.callp(vp, 2, rv, ce);691692} else {693fi_callback_data->callable.callp(vp, 1, rv, ce);694}695}696}697698if (body_state_callback.is_valid()) {699body_state_callback.call(direct_state_variant);700}701}702703bool GodotBody2D::sleep_test(real_t p_step) {704if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) {705return true;706} else if (!can_sleep) {707return false;708}709710ERR_FAIL_NULL_V(get_space(), true);711712if (Math::abs(angular_velocity) < get_space()->get_body_angular_velocity_sleep_threshold() && Math::abs(linear_velocity.length_squared()) < get_space()->get_body_linear_velocity_sleep_threshold() * get_space()->get_body_linear_velocity_sleep_threshold()) {713still_time += p_step;714715return still_time > get_space()->get_body_time_to_sleep();716} else {717still_time = 0; //maybe this should be set to 0 on set_active?718return false;719}720}721722void GodotBody2D::set_state_sync_callback(const Callable &p_callable) {723body_state_callback = p_callable;724}725726void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {727if (p_callable.is_valid()) {728if (!fi_callback_data) {729fi_callback_data = memnew(ForceIntegrationCallbackData);730}731fi_callback_data->callable = p_callable;732fi_callback_data->udata = p_udata;733} else if (fi_callback_data) {734memdelete(fi_callback_data);735fi_callback_data = nullptr;736}737}738739GodotPhysicsDirectBodyState2D *GodotBody2D::get_direct_state() {740if (!direct_state) {741direct_state = memnew(GodotPhysicsDirectBodyState2D);742direct_state->body = this;743}744return direct_state;745}746747GodotBody2D::GodotBody2D() :748GodotCollisionObject2D(TYPE_BODY),749active_list(this),750mass_properties_update_list(this),751direct_state_query_list(this) {752_set_static(false);753}754755GodotBody2D::~GodotBody2D() {756if (fi_callback_data) {757memdelete(fi_callback_data);758}759if (direct_state) {760memdelete(direct_state);761}762}763764765