Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/2d/physics/static_body_2d.cpp
9906 views
1
/**************************************************************************/
2
/* static_body_2d.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "static_body_2d.h"
32
33
#ifndef NAVIGATION_2D_DISABLED
34
#include "scene/resources/2d/capsule_shape_2d.h"
35
#include "scene/resources/2d/circle_shape_2d.h"
36
#include "scene/resources/2d/concave_polygon_shape_2d.h"
37
#include "scene/resources/2d/convex_polygon_shape_2d.h"
38
#include "scene/resources/2d/navigation_mesh_source_geometry_data_2d.h"
39
#include "scene/resources/2d/navigation_polygon.h"
40
#include "scene/resources/2d/rectangle_shape_2d.h"
41
#include "servers/navigation_server_2d.h"
42
#endif // NAVIGATION_2D_DISABLED
43
44
Callable StaticBody2D::_navmesh_source_geometry_parsing_callback;
45
RID StaticBody2D::_navmesh_source_geometry_parser;
46
47
void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) {
48
constant_linear_velocity = p_vel;
49
50
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity);
51
}
52
53
void StaticBody2D::set_constant_angular_velocity(real_t p_vel) {
54
constant_angular_velocity = p_vel;
55
56
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity);
57
}
58
59
Vector2 StaticBody2D::get_constant_linear_velocity() const {
60
return constant_linear_velocity;
61
}
62
63
real_t StaticBody2D::get_constant_angular_velocity() const {
64
return constant_angular_velocity;
65
}
66
67
void StaticBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
68
if (physics_material_override.is_valid()) {
69
physics_material_override->disconnect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
70
}
71
72
physics_material_override = p_physics_material_override;
73
74
if (physics_material_override.is_valid()) {
75
physics_material_override->connect_changed(callable_mp(this, &StaticBody2D::_reload_physics_characteristics));
76
}
77
_reload_physics_characteristics();
78
}
79
80
Ref<PhysicsMaterial> StaticBody2D::get_physics_material_override() const {
81
return physics_material_override;
82
}
83
84
void StaticBody2D::_reload_physics_characteristics() {
85
if (physics_material_override.is_null()) {
86
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
87
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1);
88
} else {
89
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
90
PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
91
}
92
}
93
94
#ifndef NAVIGATION_2D_DISABLED
95
void StaticBody2D::navmesh_parse_init() {
96
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
97
if (!_navmesh_source_geometry_parser.is_valid()) {
98
_navmesh_source_geometry_parsing_callback = callable_mp_static(&StaticBody2D::navmesh_parse_source_geometry);
99
_navmesh_source_geometry_parser = NavigationServer2D::get_singleton()->source_geometry_parser_create();
100
NavigationServer2D::get_singleton()->source_geometry_parser_set_callback(_navmesh_source_geometry_parser, _navmesh_source_geometry_parsing_callback);
101
}
102
}
103
104
void StaticBody2D::navmesh_parse_source_geometry(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
105
StaticBody2D *static_body = Object::cast_to<StaticBody2D>(p_node);
106
107
if (static_body == nullptr) {
108
return;
109
}
110
111
NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type();
112
if (!(parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH)) {
113
return;
114
}
115
116
uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask();
117
if (!(static_body->get_collision_layer() & parsed_collision_mask)) {
118
return;
119
}
120
121
List<uint32_t> shape_owners;
122
static_body->get_shape_owners(&shape_owners);
123
124
for (uint32_t shape_owner : shape_owners) {
125
if (static_body->is_shape_owner_disabled(shape_owner)) {
126
continue;
127
}
128
129
const int shape_count = static_body->shape_owner_get_shape_count(shape_owner);
130
131
for (int shape_index = 0; shape_index < shape_count; shape_index++) {
132
Ref<Shape2D> s = static_body->shape_owner_get_shape(shape_owner, shape_index);
133
134
if (s.is_null()) {
135
continue;
136
}
137
138
const Transform2D static_body_xform = p_source_geometry_data->root_node_transform * static_body->get_global_transform() * static_body->shape_owner_get_transform(shape_owner);
139
140
RectangleShape2D *rectangle_shape = Object::cast_to<RectangleShape2D>(*s);
141
if (rectangle_shape) {
142
Vector<Vector2> shape_outline;
143
144
const Vector2 &rectangle_size = rectangle_shape->get_size();
145
146
shape_outline.resize(5);
147
shape_outline.write[0] = static_body_xform.xform(-rectangle_size * 0.5);
148
shape_outline.write[1] = static_body_xform.xform(Vector2(rectangle_size.x, -rectangle_size.y) * 0.5);
149
shape_outline.write[2] = static_body_xform.xform(rectangle_size * 0.5);
150
shape_outline.write[3] = static_body_xform.xform(Vector2(-rectangle_size.x, rectangle_size.y) * 0.5);
151
shape_outline.write[4] = static_body_xform.xform(-rectangle_size * 0.5);
152
153
p_source_geometry_data->add_obstruction_outline(shape_outline);
154
}
155
156
CapsuleShape2D *capsule_shape = Object::cast_to<CapsuleShape2D>(*s);
157
if (capsule_shape) {
158
const real_t capsule_height = capsule_shape->get_height();
159
const real_t capsule_radius = capsule_shape->get_radius();
160
161
Vector<Vector2> shape_outline;
162
const real_t turn_step = Math::TAU / 12.0;
163
shape_outline.resize(14);
164
int shape_outline_inx = 0;
165
for (int i = 0; i < 12; i++) {
166
Vector2 ofs = Vector2(0, (i > 3 && i <= 9) ? capsule_height * 0.5 - capsule_radius : -capsule_height * 0.5 + capsule_radius);
167
168
shape_outline.write[shape_outline_inx] = static_body_xform.xform(Vector2(Math::sin(i * turn_step), -Math::cos(i * turn_step)) * capsule_radius + ofs);
169
shape_outline_inx += 1;
170
if (i == 3 || i == 9) {
171
shape_outline.write[shape_outline_inx] = static_body_xform.xform(Vector2(Math::sin(i * turn_step), -Math::cos(i * turn_step)) * capsule_radius - ofs);
172
shape_outline_inx += 1;
173
}
174
}
175
176
p_source_geometry_data->add_obstruction_outline(shape_outline);
177
}
178
179
CircleShape2D *circle_shape = Object::cast_to<CircleShape2D>(*s);
180
if (circle_shape) {
181
const real_t circle_radius = circle_shape->get_radius();
182
183
Vector<Vector2> shape_outline;
184
int circle_edge_count = 12;
185
shape_outline.resize(circle_edge_count);
186
187
const real_t turn_step = Math::TAU / real_t(circle_edge_count);
188
for (int i = 0; i < circle_edge_count; i++) {
189
shape_outline.write[i] = static_body_xform.xform(Vector2(Math::cos(i * turn_step), Math::sin(i * turn_step)) * circle_radius);
190
}
191
192
p_source_geometry_data->add_obstruction_outline(shape_outline);
193
}
194
195
ConcavePolygonShape2D *concave_polygon_shape = Object::cast_to<ConcavePolygonShape2D>(*s);
196
if (concave_polygon_shape) {
197
Vector<Vector2> shape_outline = concave_polygon_shape->get_segments();
198
199
for (int i = 0; i < shape_outline.size(); i++) {
200
shape_outline.write[i] = static_body_xform.xform(shape_outline[i]);
201
}
202
203
p_source_geometry_data->add_obstruction_outline(shape_outline);
204
}
205
206
ConvexPolygonShape2D *convex_polygon_shape = Object::cast_to<ConvexPolygonShape2D>(*s);
207
if (convex_polygon_shape) {
208
Vector<Vector2> shape_outline = convex_polygon_shape->get_points();
209
210
for (int i = 0; i < shape_outline.size(); i++) {
211
shape_outline.write[i] = static_body_xform.xform(shape_outline[i]);
212
}
213
214
p_source_geometry_data->add_obstruction_outline(shape_outline);
215
}
216
}
217
}
218
}
219
#endif // NAVIGATION_2D_DISABLED
220
221
void StaticBody2D::_bind_methods() {
222
ClassDB::bind_method(D_METHOD("set_constant_linear_velocity", "vel"), &StaticBody2D::set_constant_linear_velocity);
223
ClassDB::bind_method(D_METHOD("set_constant_angular_velocity", "vel"), &StaticBody2D::set_constant_angular_velocity);
224
ClassDB::bind_method(D_METHOD("get_constant_linear_velocity"), &StaticBody2D::get_constant_linear_velocity);
225
ClassDB::bind_method(D_METHOD("get_constant_angular_velocity"), &StaticBody2D::get_constant_angular_velocity);
226
227
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
228
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
229
230
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
231
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity", PROPERTY_HINT_NONE, "suffix:px/s"), "set_constant_linear_velocity", "get_constant_linear_velocity");
232
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity", PROPERTY_HINT_NONE, U"radians_as_degrees,suffix:\u00B0/s"), "set_constant_angular_velocity", "get_constant_angular_velocity");
233
}
234
235
StaticBody2D::StaticBody2D(PhysicsServer2D::BodyMode p_mode) :
236
PhysicsBody2D(p_mode) {
237
}
238
239