summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/physics_body_2d.cpp9
-rw-r--r--scene/2d/physics_body_2d.h1
-rw-r--r--scene/3d/physics_body_3d.cpp9
-rw-r--r--scene/3d/physics_body_3d.h1
-rw-r--r--scene/gui/control.cpp21
-rw-r--r--scene/gui/control.h1
-rw-r--r--scene/gui/graph_node.cpp4
-rw-r--r--scene/gui/graph_node.h2
-rw-r--r--scene/main/multiplayer_api.cpp22
-rw-r--r--scene/resources/particles_material.cpp52
-rw-r--r--scene/resources/particles_material.h19
11 files changed, 107 insertions, 34 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index c7ef3a47ad..163340e306 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -787,6 +787,12 @@ int RigidDynamicBody2D::get_max_contacts_reported() const {
return max_contacts_reported;
}
+int RigidDynamicBody2D::get_contact_count() const {
+ PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid());
+ ERR_FAIL_NULL_V(bs, 0);
+ return bs->get_contact_count();
+}
+
void RigidDynamicBody2D::apply_central_impulse(const Vector2 &p_impulse) {
PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
}
@@ -966,6 +972,7 @@ void RigidDynamicBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody2D::set_max_contacts_reported);
ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody2D::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidDynamicBody2D::get_contact_count);
ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody2D::set_use_custom_integrator);
ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody2D::is_using_custom_integrator);
@@ -1023,7 +1030,7 @@ void RigidDynamicBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
ADD_PROPERTY(PropertyInfo(Variant::INT, "continuous_cd", PROPERTY_HINT_ENUM, "Disabled,Cast Ray,Cast Shape"), "set_continuous_collision_detection_mode", "get_continuous_collision_detection_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 75ea535424..2f9a27b41e 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -284,6 +284,7 @@ public:
void set_max_contacts_reported(int p_amount);
int get_max_contacts_reported() const;
+ int get_contact_count() const;
void set_continuous_collision_detection_mode(CCDMode p_mode);
CCDMode get_continuous_collision_detection_mode() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index d8c0516a94..6b4ec7121f 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -865,6 +865,12 @@ int RigidDynamicBody3D::get_max_contacts_reported() const {
return max_contacts_reported;
}
+int RigidDynamicBody3D::get_contact_count() const {
+ PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(get_rid());
+ ERR_FAIL_NULL_V(bs, 0);
+ return bs->get_contact_count();
+}
+
void RigidDynamicBody3D::apply_central_impulse(const Vector3 &p_impulse) {
PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse);
}
@@ -1031,6 +1037,7 @@ void RigidDynamicBody3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody3D::set_max_contacts_reported);
ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody3D::get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidDynamicBody3D::get_contact_count);
ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody3D::set_use_custom_integrator);
ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody3D::is_using_custom_integrator);
@@ -1089,7 +1096,7 @@ void RigidDynamicBody3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "continuous_cd"), "set_use_continuous_collision_detection", "is_using_continuous_collision_detection");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_contacts_reported", PROPERTY_HINT_RANGE, "0,64,1,or_greater"), "set_max_contacts_reported", "get_max_contacts_reported");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "contact_monitor"), "set_contact_monitor", "is_contact_monitor_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep");
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 96e1688c23..200eee0b98 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -300,6 +300,7 @@ public:
void set_max_contacts_reported(int p_amount);
int get_max_contacts_reported() const;
+ int get_contact_count() const;
void set_use_continuous_collision_detection(bool p_enable);
bool is_using_continuous_collision_detection() const;
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 66cb41ee65..03fcef17f5 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -3622,3 +3622,24 @@ void Control::_bind_methods() {
GDVIRTUAL_BIND(_gui_input, "event");
}
+
+Control::~Control() {
+ // Resources need to be disconnected.
+ for (KeyValue<StringName, Ref<Texture2D>> &E : data.icon_override) {
+ E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+ for (KeyValue<StringName, Ref<StyleBox>> &E : data.style_override) {
+ E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+ for (KeyValue<StringName, Ref<Font>> &E : data.font_override) {
+ E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed));
+ }
+
+ // Then override maps can be simply cleared.
+ data.icon_override.clear();
+ data.style_override.clear();
+ data.font_override.clear();
+ data.font_size_override.clear();
+ data.color_override.clear();
+ data.constant_override.clear();
+}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index d7e120260c..c69067f82f 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -610,6 +610,7 @@ public:
virtual Control *make_custom_tooltip(const String &p_text) const;
Control() {}
+ ~Control();
};
VARIANT_ENUM_CAST(Control::FocusMode);
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 1a478a5fe1..7d31e929dc 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -32,9 +32,7 @@
#include "core/string/translation.h"
-#ifdef TOOLS_ENABLED
#include "graph_edit.h"
-#endif
struct _MinSizeCache {
int min_size;
@@ -445,6 +443,7 @@ void GraphNode::_edit_set_position(const Point2 &p_position) {
}
set_position(p_position);
}
+#endif
void GraphNode::_validate_property(PropertyInfo &p_property) const {
GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent());
@@ -454,7 +453,6 @@ void GraphNode::_validate_property(PropertyInfo &p_property) const {
}
}
}
-#endif
void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right, bool p_draw_stylebox) {
ERR_FAIL_COND_MSG(p_idx < 0, vformat("Cannot set slot with p_idx (%d) lesser than zero.", p_idx));
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index 6d5bb4361e..d575b6ceed 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -101,7 +101,6 @@ private:
#ifdef TOOLS_ENABLED
void _edit_set_position(const Point2 &p_position) override;
- void _validate_property(PropertyInfo &p_property) const;
#endif
protected:
@@ -112,6 +111,7 @@ protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _validate_property(PropertyInfo &p_property) const;
public:
bool has_point(const Point2 &p_point) const override;
diff --git a/scene/main/multiplayer_api.cpp b/scene/main/multiplayer_api.cpp
index 95574042a8..2d2103f031 100644
--- a/scene/main/multiplayer_api.cpp
+++ b/scene/main/multiplayer_api.cpp
@@ -59,18 +59,18 @@ Ref<MultiplayerAPI> MultiplayerAPI::create_default_interface() {
// The variant is compressed and encoded; The first byte contains all the meta
// information and the format is:
-// - The first LSB 5 bits are used for the variant type.
+// - The first LSB 6 bits are used for the variant type.
// - The next two bits are used to store the encoding mode.
-// - The most significant is used to store the boolean value.
-#define VARIANT_META_TYPE_MASK 0x1F
-#define VARIANT_META_EMODE_MASK 0x60
+// - Boolean values uses the encoding mode to store the value.
+#define VARIANT_META_TYPE_MASK 0x3F
+#define VARIANT_META_EMODE_MASK 0xC0
#define VARIANT_META_BOOL_MASK 0x80
-#define ENCODE_8 0 << 5
-#define ENCODE_16 1 << 5
-#define ENCODE_32 2 << 5
-#define ENCODE_64 3 << 5
+#define ENCODE_8 0 << 6
+#define ENCODE_16 1 << 6
+#define ENCODE_32 2 << 6
+#define ENCODE_64 3 << 6
Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_allow_object_decoding) {
- // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31
+ // Unreachable because `VARIANT_MAX` == 38 and `ENCODE_VARIANT_MASK` == 77
CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK);
uint8_t *buf = r_buffer;
@@ -80,9 +80,9 @@ Error MultiplayerAPI::encode_and_compress_variant(const Variant &p_variant, uint
switch (p_variant.get_type()) {
case Variant::BOOL: {
if (buf) {
- // We still have 1 free bit in the meta, so let's use it.
+ // We don't use encode_mode for booleans, so we can use it to store the value.
buf[0] = (p_variant.operator bool()) ? (1 << 7) : 0;
- buf[0] |= encode_mode | p_variant.get_type();
+ buf[0] |= p_variant.get_type();
}
r_len += 1;
} break;
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 0fe5c8f2db..29a06622a3 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -287,7 +287,7 @@ void ParticlesMaterial::_update_shader() {
code += "uniform sampler2D anim_offset_texture : repeat_disable;\n";
}
- if (collision_enabled) {
+ if (collision_mode == COLLISION_RIGID) {
code += "uniform float collision_friction;\n";
code += "uniform float collision_bounce;\n";
}
@@ -695,8 +695,10 @@ void ParticlesMaterial::_update_shader() {
}
code += " vec3 noise_direction = get_noise_direction(TRANSFORM[3].xyz, EMISSION_TRANSFORM[3].xyz, time_noise);\n";
// If collision happened, turbulence is no longer applied.
+ // We don't need this check when the collision mode is "hide on contact",
+ // as the particle will be hidden anyway.
String extra_tab = "";
- if (collision_enabled) {
+ if (collision_mode != COLLISION_RIGID) {
code += " if (!COLLIDED) {\n";
extra_tab = " ";
}
@@ -704,7 +706,7 @@ void ParticlesMaterial::_update_shader() {
code += extra_tab + " float vel_mag = length(VELOCITY);\n";
code += extra_tab + " float vel_infl = clamp(mix(turbulence_influence_min, turbulence_influence_max, rand_from_seed(alt_seed)) * turbulence_influence, 0.0, 1.0);\n";
code += extra_tab + " VELOCITY = mix(VELOCITY, normalize(noise_direction) * vel_mag * (1.0 + (1.0 - vel_infl) * 0.2), vel_infl);\n";
- if (collision_enabled) {
+ if (collision_mode != COLLISION_RIGID) {
code += " }";
}
}
@@ -828,7 +830,7 @@ void ParticlesMaterial::_update_shader() {
code += " TRANSFORM[3].z = 0.0;\n";
}
- if (collision_enabled) {
+ if (collision_mode == COLLISION_RIGID) {
code += " if (COLLIDED) {\n";
code += " if (length(VELOCITY) > 3.0) {\n";
code += " TRANSFORM[3].xyz += COLLISION_NORMAL * COLLISION_DEPTH;\n";
@@ -851,6 +853,18 @@ void ParticlesMaterial::_update_shader() {
code += " TRANSFORM[1].xyz *= base_scale * sign(tex_scale.g) * max(abs(tex_scale.g), 0.001);\n";
code += " TRANSFORM[2].xyz *= base_scale * sign(tex_scale.b) * max(abs(tex_scale.b), 0.001);\n";
+ if (collision_mode == COLLISION_RIGID) {
+ code += " if (COLLIDED) {\n";
+ code += " TRANSFORM[3].xyz+=COLLISION_NORMAL * COLLISION_DEPTH;\n";
+ code += " VELOCITY -= COLLISION_NORMAL * dot(COLLISION_NORMAL, VELOCITY) * (1.0 + collision_bounce);\n";
+ code += " VELOCITY = mix(VELOCITY,vec3(0.0),collision_friction * DELTA * 100.0);\n";
+ code += " }\n";
+ } else if (collision_mode == COLLISION_HIDE_ON_CONTACT) {
+ code += " if (COLLIDED) {\n";
+ code += " ACTIVE = false;\n";
+ code += " }\n";
+ }
+
if (sub_emitter_mode != SUB_EMITTER_DISABLED) {
code += " int emit_count = 0;\n";
switch (sub_emitter_mode) {
@@ -1436,6 +1450,14 @@ void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
}
+
+ if (p_property.name == "collision_friction" && collision_mode != COLLISION_RIGID) {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
+
+ if (p_property.name == "collision_bounce" && collision_mode != COLLISION_RIGID) {
+ p_property.usage = PROPERTY_USAGE_NONE;
+ }
}
void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) {
@@ -1483,13 +1505,14 @@ bool ParticlesMaterial::is_attractor_interaction_enabled() const {
return attractor_interaction_enabled;
}
-void ParticlesMaterial::set_collision_enabled(bool p_enabled) {
- collision_enabled = p_enabled;
+void ParticlesMaterial::set_collision_mode(CollisionMode p_collision_mode) {
+ collision_mode = p_collision_mode;
_queue_shader_change();
+ notify_property_list_changed();
}
-bool ParticlesMaterial::is_collision_enabled() const {
- return collision_enabled;
+ParticlesMaterial::CollisionMode ParticlesMaterial::get_collision_mode() const {
+ return collision_mode;
}
void ParticlesMaterial::set_collision_use_scale(bool p_scale) {
@@ -1623,8 +1646,8 @@ void ParticlesMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticlesMaterial::set_attractor_interaction_enabled);
ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticlesMaterial::is_attractor_interaction_enabled);
- ClassDB::bind_method(D_METHOD("set_collision_enabled", "enabled"), &ParticlesMaterial::set_collision_enabled);
- ClassDB::bind_method(D_METHOD("is_collision_enabled"), &ParticlesMaterial::is_collision_enabled);
+ ClassDB::bind_method(D_METHOD("set_collision_mode", "mode"), &ParticlesMaterial::set_collision_mode);
+ ClassDB::bind_method(D_METHOD("get_collision_mode"), &ParticlesMaterial::get_collision_mode);
ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticlesMaterial::set_collision_use_scale);
ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticlesMaterial::is_collision_using_scale);
@@ -1734,7 +1757,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_GROUP("Attractor Interaction", "attractor_interaction_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "attractor_interaction_enabled"), "set_attractor_interaction_enabled", "is_attractor_interaction_enabled");
ADD_GROUP("Collision", "collision_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_enabled"), "set_collision_enabled", "is_collision_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mode", PROPERTY_HINT_ENUM, "Disabled,Rigid,Hide On Contact"), "set_collision_mode", "get_collision_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_friction", "get_collision_friction");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_collision_bounce", "get_collision_bounce");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_use_scale"), "set_collision_use_scale", "is_collision_using_scale");
@@ -1776,6 +1799,11 @@ void ParticlesMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END);
BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION);
BIND_ENUM_CONSTANT(SUB_EMITTER_MAX);
+
+ BIND_ENUM_CONSTANT(COLLISION_DISABLED);
+ BIND_ENUM_CONSTANT(COLLISION_RIGID);
+ BIND_ENUM_CONSTANT(COLLISION_HIDE_ON_CONTACT);
+ BIND_ENUM_CONSTANT(COLLISION_MAX);
}
ParticlesMaterial::ParticlesMaterial() :
@@ -1834,7 +1862,7 @@ ParticlesMaterial::ParticlesMaterial() :
set_sub_emitter_keep_velocity(false);
set_attractor_interaction_enabled(true);
- set_collision_enabled(false);
+ set_collision_mode(COLLISION_DISABLED);
set_collision_bounce(0.0);
set_collision_friction(0.0);
set_collision_use_scale(false);
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index 116d8b7d06..2e94e7e01a 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -93,6 +93,14 @@ public:
SUB_EMITTER_MAX
};
+ // When extending, make sure not to overflow the size of the MaterialKey below.
+ enum CollisionMode {
+ COLLISION_DISABLED,
+ COLLISION_RIGID,
+ COLLISION_HIDE_ON_CONTACT,
+ COLLISION_MAX
+ };
+
private:
union MaterialKey {
// The bit size of the struct must be kept below or equal to 32 bits.
@@ -106,7 +114,7 @@ private:
uint32_t has_emission_color : 1;
uint32_t sub_emitter : 2;
uint32_t attractor_enabled : 1;
- uint32_t collision_enabled : 1;
+ uint32_t collision_mode : 2;
uint32_t collision_scale : 1;
uint32_t turbulence_enabled : 1;
};
@@ -153,7 +161,7 @@ private:
mk.emission_shape = emission_shape;
mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid();
mk.sub_emitter = sub_emitter_mode;
- mk.collision_enabled = collision_enabled;
+ mk.collision_mode = collision_mode;
mk.attractor_enabled = attractor_interaction_enabled;
mk.collision_scale = collision_scale;
mk.turbulence_enabled = turbulence_enabled;
@@ -300,7 +308,7 @@ private:
//do not save emission points here
bool attractor_interaction_enabled = false;
- bool collision_enabled = false;
+ CollisionMode collision_mode;
bool collision_scale = false;
float collision_friction = 0.0f;
float collision_bounce = 0.0f;
@@ -385,8 +393,8 @@ public:
void set_attractor_interaction_enabled(bool p_enable);
bool is_attractor_interaction_enabled() const;
- void set_collision_enabled(bool p_enabled);
- bool is_collision_enabled() const;
+ void set_collision_mode(CollisionMode p_collision_mode);
+ CollisionMode get_collision_mode() const;
void set_collision_use_scale(bool p_scale);
bool is_collision_using_scale() const;
@@ -425,5 +433,6 @@ VARIANT_ENUM_CAST(ParticlesMaterial::Parameter)
VARIANT_ENUM_CAST(ParticlesMaterial::ParticleFlags)
VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape)
VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode)
+VARIANT_ENUM_CAST(ParticlesMaterial::CollisionMode)
#endif // PARTICLES_MATERIAL_H