diff options
Diffstat (limited to 'scene')
41 files changed, 2855 insertions, 974 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index b52dd8d660..9ac12de45e 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -37,124 +37,6 @@ #include "scene/scene_string_names.h" #include "servers/visual_server.h" -bool CanvasItemMaterial::_set(const StringName &p_name, const Variant &p_value) { - - if (p_name == SceneStringNames::get_singleton()->shader_shader) { - set_shader(p_value); - return true; - } else { - - if (shader.is_valid()) { - - StringName pr = shader->remap_param(p_name); - if (!pr) { - String n = p_name; - if (n.find("param/") == 0) { //backwards compatibility - pr = n.substr(6, n.length()); - } - } - if (pr) { - VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); - return true; - } - } - } - - return false; -} - -bool CanvasItemMaterial::_get(const StringName &p_name, Variant &r_ret) const { - - if (p_name == SceneStringNames::get_singleton()->shader_shader) { - - r_ret = get_shader(); - return true; - - } else { - - if (shader.is_valid()) { - - StringName pr = shader->remap_param(p_name); - if (pr) { - r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); - return true; - } - } - } - - return false; -} - -void CanvasItemMaterial::_get_property_list(List<PropertyInfo> *p_list) const { - - p_list->push_back(PropertyInfo(Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph")); - - if (!shader.is_null()) { - - shader->get_param_list(p_list); - } -} - -void CanvasItemMaterial::set_shader(const Ref<Shader> &p_shader) { - - ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode() != Shader::MODE_CANVAS_ITEM); - - shader = p_shader; - - RID rid; - if (shader.is_valid()) - rid = shader->get_rid(); - - VS::get_singleton()->material_set_shader(_get_material(), rid); - _change_notify(); //properties for shader exposed - emit_changed(); -} - -Ref<Shader> CanvasItemMaterial::get_shader() const { - - return shader; -} - -void CanvasItemMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { - - VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); -} - -Variant CanvasItemMaterial::get_shader_param(const StringName &p_param) const { - - return VS::get_singleton()->material_get_param(_get_material(), p_param); -} - -void CanvasItemMaterial::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shader", "shader:Shader"), &CanvasItemMaterial::set_shader); - ClassDB::bind_method(D_METHOD("get_shader:Shader"), &CanvasItemMaterial::get_shader); - ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &CanvasItemMaterial::set_shader_param); - ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &CanvasItemMaterial::get_shader_param); -} - -void CanvasItemMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { - - String f = p_function.operator String(); - if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { - - if (shader.is_valid()) { - List<PropertyInfo> pl; - shader->get_param_list(&pl); - for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { - r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\""); - } - } - } - Resource::get_argument_options(p_function, p_idx, r_options); -} - -CanvasItemMaterial::CanvasItemMaterial() { -} - -CanvasItemMaterial::~CanvasItemMaterial() { -} - /////////////////////////////////////////////////////////////////// bool CanvasItem::is_visible_in_tree() const { @@ -206,7 +88,7 @@ void CanvasItem::show() { return; _propagate_visibility_changed(true); - _change_notify("visibility/visible"); + _change_notify("visible"); } void CanvasItem::hide() { @@ -221,7 +103,7 @@ void CanvasItem::hide() { return; _propagate_visibility_changed(false); - _change_notify("visibility/visible"); + _change_notify("visible"); } Variant CanvasItem::edit_get_state() const { @@ -770,7 +652,7 @@ bool CanvasItem::is_draw_behind_parent_enabled() const { return behind; } -void CanvasItem::set_material(const Ref<CanvasItemMaterial> &p_material) { +void CanvasItem::set_material(const Ref<ShaderMaterial> &p_material) { material = p_material; RID rid; @@ -791,7 +673,7 @@ bool CanvasItem::get_use_parent_material() const { return use_parent_material; } -Ref<CanvasItemMaterial> CanvasItem::get_material() const { +Ref<ShaderMaterial> CanvasItem::get_material() const { return material; } @@ -801,7 +683,7 @@ Vector2 CanvasItem::make_canvas_pos_local(const Vector2 &screen_point) const { ERR_FAIL_COND_V(!is_inside_tree(), screen_point); Transform2D local_matrix = (get_canvas_transform() * - get_global_transform()) + get_global_transform()) .affine_inverse(); return local_matrix.xform(screen_point); @@ -895,8 +777,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d); //ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport); - ClassDB::bind_method(D_METHOD("set_material", "material:CanvasItemMaterial"), &CanvasItem::set_material); - ClassDB::bind_method(D_METHOD("get_material:CanvasItemMaterial"), &CanvasItem::get_material); + ClassDB::bind_method(D_METHOD("set_material", "material:ShaderMaterial"), &CanvasItem::set_material); + ClassDB::bind_method(D_METHOD("get_material:ShaderMaterial"), &CanvasItem::get_material); ClassDB::bind_method(D_METHOD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material); ClassDB::bind_method(D_METHOD("get_use_parent_material"), &CanvasItem::get_use_parent_material); @@ -922,7 +804,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); ADD_GROUP("Material", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), "set_material", "get_material"); + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"), "set_material", "get_material"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material"); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), "set_as_toplevel","is_set_as_toplevel") ; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index a188ce495a..a5074991da 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -41,38 +41,6 @@ class Font; class StyleBox; -class CanvasItemMaterial : public Material { - - GDCLASS(CanvasItemMaterial, Material); - Ref<Shader> shader; - -public: - /*enum ShadingMode { - SHADING_NORMAL, - SHADING_UNSHADED, - SHADING_ONLY_LIGHT, - };*/ - -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; - - static void _bind_methods(); - - void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; - -public: - void set_shader(const Ref<Shader> &p_shader); - Ref<Shader> get_shader() const; - - void set_shader_param(const StringName &p_param, const Variant &p_value); - Variant get_shader_param(const StringName &p_param) const; - - CanvasItemMaterial(); - ~CanvasItemMaterial(); -}; - class CanvasItem : public Node { GDCLASS(CanvasItem, Node); @@ -114,7 +82,7 @@ private: bool notify_local_transform; bool notify_transform; - Ref<CanvasItemMaterial> material; + Ref<ShaderMaterial> material; mutable Transform2D global_transform; mutable bool global_invalid; @@ -234,8 +202,8 @@ public: RID get_canvas() const; Ref<World2D> get_world_2d() const; - void set_material(const Ref<CanvasItemMaterial> &p_material); - Ref<CanvasItemMaterial> get_material() const; + void set_material(const Ref<ShaderMaterial> &p_material); + Ref<ShaderMaterial> get_material() const; void set_use_parent_material(bool p_use_parent_material); bool get_use_parent_material() const; diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 1ba6ec46cf..16b6342299 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -63,9 +63,10 @@ void Node2D::edit_set_state(const Variant &p_state) { angle = state[1]; _scale = state[2]; _update_transform(); - _change_notify("transform/rot"); - _change_notify("transform/scale"); - _change_notify("transform/pos"); + _change_notify("rotation"); + _change_notify("rotation_deg"); + _change_notify("scale"); + _change_notify("position"); } void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { @@ -95,15 +96,16 @@ void Node2D::edit_set_rect(const Rect2 &p_edit_rect) { _scale *= new_scale; _update_transform(); - _change_notify("transform/scale"); - _change_notify("transform/pos"); + _change_notify("scale"); + _change_notify("position"); } void Node2D::edit_rotate(float p_rot) { angle += p_rot; _update_transform(); - _change_notify("transform/rot"); + _change_notify("rotation"); + _change_notify("rotation_deg"); } void Node2D::_update_xform_values() { @@ -134,7 +136,7 @@ void Node2D::set_position(const Point2 &p_pos) { ((Node2D *)this)->_update_xform_values(); pos = p_pos; _update_transform(); - _change_notify("transform/pos"); + _change_notify("position"); } void Node2D::set_rotation(float p_radians) { @@ -143,7 +145,8 @@ void Node2D::set_rotation(float p_radians) { ((Node2D *)this)->_update_xform_values(); angle = p_radians; _update_transform(); - _change_notify("transform/rot"); + _change_notify("rotation"); + _change_notify("rotation_deg"); } void Node2D::set_rotation_in_degrees(float p_degrees) { @@ -169,7 +172,7 @@ void Node2D::set_scale(const Size2 &p_scale) { if (_scale.y == 0) _scale.y = CMP_EPSILON; _update_transform(); - _change_notify("transform/scale"); + _change_notify("scale"); } Point2 Node2D::get_position() const { @@ -349,6 +352,7 @@ void Node2D::set_z(int p_z) { ERR_FAIL_COND(p_z > VS::CANVAS_ITEM_Z_MAX); z = p_z; VS::get_singleton()->canvas_item_set_z(get_canvas_item(), z); + _change_notify("z"); } void Node2D::set_z_as_relative(bool p_enabled) { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 88845a7290..00187f28bc 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1168,7 +1168,7 @@ Vector2 KinematicBody2D::move(const Vector2 &p_motion) { #endif } -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_bounces, float p_floor_max_angle) { Vector2 motion = (move_and_slide_floor_velocity + p_linear_velocity) * get_fixed_process_delta_time(); Vector2 lv = p_linear_velocity; @@ -1189,7 +1189,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const //all is a wall move_and_slide_on_wall = true; } else { - if (get_collision_normal().dot(p_floor_direction) > Math::cos(Math::deg2rad((float)45))) { //floor + if (get_collision_normal().dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor move_and_slide_on_floor = true; move_and_slide_floor_velocity = get_collider_velocity(); @@ -1198,15 +1198,16 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const revert_motion(); return Vector2(); } - } else if (get_collision_normal().dot(p_floor_direction) < Math::cos(Math::deg2rad((float)45))) { //ceiling + } else if (get_collision_normal().dot(-p_floor_direction) <= Math::cos(p_floor_max_angle)) { //ceiling move_and_slide_on_ceiling = true; } else { move_and_slide_on_wall = true; } } - motion = get_collision_normal().slide(motion); - lv = get_collision_normal().slide(lv); + Vector2 n = get_collision_normal(); + motion = motion.slide(n); + lv = lv.slide(n); Variant collider = _get_collider(); if (collider.get_type() != Variant::NIL) { move_and_slide_colliders.push_back(collider); @@ -1307,7 +1308,7 @@ void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move", "rel_vec"), &KinematicBody2D::move); ClassDB::bind_method(D_METHOD("move_to", "position"), &KinematicBody2D::move_to); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4)); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec"), &KinematicBody2D::test_move); ClassDB::bind_method(D_METHOD("get_travel"), &KinematicBody2D::get_travel); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index e51b512302..6ce6f14d36 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -314,7 +314,7 @@ public: void set_collision_margin(float p_margin); float get_collision_margin() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4); + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), float p_slope_stop_min_velocity = 5, int p_max_bounces = 4, float p_floor_max_angle = Math::deg2rad((float)45)); bool is_move_and_slide_on_floor() const; bool is_move_and_slide_on_wall() const; bool is_move_and_slide_on_ceiling() const; diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index db822ed306..804af7d9c6 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -65,12 +65,14 @@ Ref<BitMap> TouchScreenButton::get_bitmask() const { void TouchScreenButton::set_shape(const Ref<Shape2D> &p_shape) { + if (shape.is_valid()) + shape->disconnect("changed", this, "update"); + shape = p_shape; - if (!is_inside_tree()) - return; - if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) - return; + if (shape.is_valid()) + shape->connect("changed", this, "update"); + update(); } @@ -82,11 +84,17 @@ Ref<Shape2D> TouchScreenButton::get_shape() const { void TouchScreenButton::set_shape_centered(bool p_shape_centered) { shape_centered = p_shape_centered; + update(); +} - if (!is_inside_tree()) - return; - if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) - return; +bool TouchScreenButton::is_shape_visible() const { + + return shape_visible; +} + +void TouchScreenButton::set_shape_visible(bool p_shape_visible) { + + shape_visible = p_shape_visible; update(); } @@ -118,6 +126,8 @@ void TouchScreenButton::_notification(int p_what) { draw_texture(texture, Point2()); } + if (!shape_visible) + return; if (!get_tree()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) return; if (shape.is_valid()) { @@ -375,6 +385,9 @@ void TouchScreenButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape_centered", "bool"), &TouchScreenButton::set_shape_centered); ClassDB::bind_method(D_METHOD("is_shape_centered"), &TouchScreenButton::is_shape_centered); + ClassDB::bind_method(D_METHOD("set_shape_visible", "bool"), &TouchScreenButton::set_shape_visible); + ClassDB::bind_method(D_METHOD("is_shape_visible"), &TouchScreenButton::is_shape_visible); + ClassDB::bind_method(D_METHOD("set_action", "action"), &TouchScreenButton::set_action); ClassDB::bind_method(D_METHOD("get_action"), &TouchScreenButton::get_action); @@ -393,6 +406,7 @@ void TouchScreenButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "bitmask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_bitmask", "get_bitmask"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_centered"), "set_shape_centered", "is_shape_centered"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shape_visible"), "set_shape_visible", "is_shape_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "passby_press"), "set_passby_press", "is_passby_press_enabled"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action", "get_action"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_mode", PROPERTY_HINT_ENUM, "Always,TouchScreen Only"), "set_visibility_mode", "get_visibility_mode"); @@ -408,6 +422,7 @@ TouchScreenButton::TouchScreenButton() { passby_press = false; visibility = VISIBILITY_ALWAYS; shape_centered = true; + shape_visible = true; unit_rect = Ref<RectangleShape2D>(memnew(RectangleShape2D)); unit_rect->set_extents(Vector2(0.5, 0.5)); } diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h index 201d908bf6..2262723ed3 100644 --- a/scene/2d/screen_button.h +++ b/scene/2d/screen_button.h @@ -50,6 +50,7 @@ private: Ref<BitMap> bitmask; Ref<Shape2D> shape; bool shape_centered; + bool shape_visible; Ref<RectangleShape2D> unit_rect; @@ -85,6 +86,9 @@ public: void set_shape_centered(bool p_shape_centered); bool is_shape_centered() const; + void set_shape_visible(bool p_shape_visible); + bool is_shape_visible() const; + void set_action(const String &p_action); String get_action() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 02b41fbd0c..8e57517175 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -304,7 +304,7 @@ void TileMap::_update_dirty_quadrants() { VS::get_singleton()->free(E->get().id); } q.occluder_instances.clear(); - Ref<CanvasItemMaterial> prev_material; + Ref<ShaderMaterial> prev_material; RID prev_canvas_item; RID prev_debug_canvas_item; @@ -324,7 +324,7 @@ void TileMap::_update_dirty_quadrants() { if (!tex.is_valid()) continue; - Ref<CanvasItemMaterial> mat = tile_set->tile_get_material(c.id); + Ref<ShaderMaterial> mat = tile_set->tile_get_material(c.id); RID canvas_item; RID debug_canvas_item; diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp index ac424475ea..e887aac439 100644 --- a/scene/3d/baked_light_instance.cpp +++ b/scene/3d/baked_light_instance.cpp @@ -250,7 +250,7 @@ Vector<Color> BakedLight::_get_bake_texture(Image &p_image, const Color &p_color BakedLight::MaterialCache BakedLight::_get_material_cache(Ref<Material> p_material) { //this way of obtaining materials is inaccurate and also does not support some compressed formats very well - Ref<FixedSpatialMaterial> mat = p_material; + Ref<SpatialMaterial> mat = p_material; Ref<Material> material = mat; //hack for now @@ -262,7 +262,7 @@ BakedLight::MaterialCache BakedLight::_get_material_cache(Ref<Material> p_materi if (mat.is_valid()) { - Ref<ImageTexture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO); + Ref<ImageTexture> albedo_tex = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO); Image img_albedo; if (albedo_tex.is_valid()) { @@ -272,7 +272,7 @@ BakedLight::MaterialCache BakedLight::_get_material_cache(Ref<Material> p_materi mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo()); - Ref<ImageTexture> emission_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_EMISSION); + Ref<ImageTexture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); Color emission_col = mat->get_emission(); emission_col.r *= mat->get_emission_energy(); @@ -1591,11 +1591,11 @@ void BakedLight::create_debug_mesh(DebugMode p_mode) { } { - Ref<FixedSpatialMaterial> fsm; + Ref<SpatialMaterial> fsm; fsm.instance(); - fsm->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + fsm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); fsm->set_albedo(Color(1, 1, 1, 1)); mesh->surface_set_material(0, fsm); diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index cb1292a9d1..6cdd42ed65 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -919,7 +919,7 @@ Vector<Color> GIProbe::_get_bake_texture(Image &p_image, const Color &p_color) { GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_material, Baker *p_baker) { //this way of obtaining materials is inaccurate and also does not support some compressed formats very well - Ref<FixedSpatialMaterial> mat = p_material; + Ref<SpatialMaterial> mat = p_material; Ref<Material> material = mat; //hack for now @@ -931,7 +931,7 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater if (mat.is_valid()) { - Ref<Texture> albedo_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_ALBEDO); + Ref<Texture> albedo_tex = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO); Image img_albedo; if (albedo_tex.is_valid()) { @@ -942,7 +942,7 @@ GIProbe::Baker::MaterialCache GIProbe::_get_material_cache(Ref<Material> p_mater mc.albedo = _get_bake_texture(img_albedo, mat->get_albedo()); - Ref<ImageTexture> emission_tex = mat->get_texture(FixedSpatialMaterial::TEXTURE_EMISSION); + Ref<ImageTexture> emission_tex = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION); Color emission_col = mat->get_emission(); emission_col.r *= mat->get_emission_energy(); @@ -1365,11 +1365,11 @@ void GIProbe::_create_debug_mesh(Baker *p_baker) { } { - Ref<FixedSpatialMaterial> fsm; + Ref<SpatialMaterial> fsm; fsm.instance(); - fsm->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - fsm->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + fsm->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + fsm->set_flag(SpatialMaterial::FLAG_UNSHADED, true); fsm->set_albedo(Color(1, 1, 1, 1)); mesh->surface_set_material(0, fsm); diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index ea61253ac7..2a92d6652c 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -30,532 +30,1353 @@ #include "scene/resources/surface_tool.h" #include "servers/visual_server.h" -#if 0 -/* -static const char* _var_names[Particles::VAR_MAX]={ - "vars/lifetime", - "vars/spread", - "vars/gravity", - "vars/linear_vel", - "vars/angular_vel", - "vars/linear_accel", - "vars/radial_accel", - "vars/tan_accel", - "vars/initial_size", - "vars/final_size", - "vars/initial_angle", - "vars/height", - "vars/height_speed_scale", -}; -*/ -static const char* _rand_names[Particles::VAR_MAX]={ - "rand/lifetime", - "rand/spread", - "rand/gravity", - "rand/linear_vel", - "rand/angular_vel", - "rand/linear_accel", - "rand/radial_accel", - "rand/tan_accel", - "rand/damping", - "rand/initial_size", - "rand/final_size", - "rand/initial_angle", - "rand/height", - "rand/height_speed_scale", -}; - -static const Particles::Variable _var_indices[Particles::VAR_MAX]={ - Particles::VAR_LIFETIME, - Particles::VAR_SPREAD, - Particles::VAR_GRAVITY, - Particles::VAR_LINEAR_VELOCITY, - Particles::VAR_ANGULAR_VELOCITY, - Particles::VAR_LINEAR_ACCELERATION, - Particles::VAR_DRAG, - Particles::VAR_TANGENTIAL_ACCELERATION, - Particles::VAR_DAMPING, - Particles::VAR_INITIAL_SIZE, - Particles::VAR_FINAL_SIZE, - Particles::VAR_INITIAL_ANGLE, - Particles::VAR_HEIGHT, - Particles::VAR_HEIGHT_SPEED_SCALE, -}; - - - -AABB Particles::get_aabb() const { - - return AABB( Vector3(-1,-1,-1), Vector3(2, 2, 2 ) ); +Rect3 Particles::get_aabb() const { + + return Rect3(); } PoolVector<Face3> Particles::get_faces(uint32_t p_usage_flags) const { return PoolVector<Face3>(); } +void Particles::set_emitting(bool p_emitting) { + + emitting = p_emitting; + VS::get_singleton()->particles_set_emitting(particles, emitting); +} void Particles::set_amount(int p_amount) { - ERR_FAIL_INDEX(p_amount,1024); - amount=p_amount; - VisualServer::get_singleton()->particles_set_amount(particles,p_amount); + amount = p_amount; + VS::get_singleton()->particles_set_amount(particles, amount); } -int Particles::get_amount() const { +void Particles::set_lifetime(float p_lifetime) { - return amount; + lifetime = p_lifetime; + VS::get_singleton()->particles_set_lifetime(particles, lifetime); } +void Particles::set_pre_process_time(float p_time) { -void Particles::set_emitting(bool p_emitting) { + pre_process_time = p_time; + VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); +} +void Particles::set_explosiveness_ratio(float p_ratio) { + + explosiveness_ratio = p_ratio; + VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); +} +void Particles::set_randomness_ratio(float p_ratio) { - emitting=p_emitting; - VisualServer::get_singleton()->particles_set_emitting(particles,p_emitting); + randomness_ratio = p_ratio; + VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); +} +void Particles::set_custom_aabb(const Rect3 &p_aabb) { + + custom_aabb = p_aabb; + VS::get_singleton()->particles_set_custom_aabb(particles, custom_aabb); +} +void Particles::set_gravity(const Vector3 &p_gravity) { + + gravity = p_gravity; + VS::get_singleton()->particles_set_gravity(particles, gravity); +} +void Particles::set_use_local_coordinates(bool p_enable) { - setup_timer(); + local_coords = p_enable; + VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); } +void Particles::set_process_material(const Ref<Material> &p_material) { + + process_material = p_material; + RID material_rid; + if (process_material.is_valid()) + material_rid = process_material->get_rid(); + VS::get_singleton()->particles_set_process_material(particles, material_rid); +} + bool Particles::is_emitting() const { return emitting; } +int Particles::get_amount() const { -void Particles::set_visibility_aabb(const AABB& p_aabb) { + return amount; +} +float Particles::get_lifetime() const { + + return lifetime; +} +float Particles::get_pre_process_time() const { + + return pre_process_time; +} +float Particles::get_explosiveness_ratio() const { - visibility_aabb=p_aabb; - VisualServer::get_singleton()->particles_set_visibility_aabb(particles,p_aabb); - update_gizmo(); + return explosiveness_ratio; +} +float Particles::get_randomness_ratio() const { + return randomness_ratio; } -AABB Particles::get_visibility_aabb() const { +Rect3 Particles::get_custom_aabb() const { - return visibility_aabb; + return custom_aabb; } +Vector3 Particles::get_gravity() const { + return gravity; +} +bool Particles::get_use_local_coordinates() const { -void Particles::set_emission_points(const PoolVector<Vector3>& p_points) { + return local_coords; +} +Ref<Material> Particles::get_process_material() const { - using_points = p_points.size(); - VisualServer::get_singleton()->particles_set_emission_points(particles,p_points); + return process_material; } -PoolVector<Vector3> Particles::get_emission_points() const { +void Particles::set_draw_order(DrawOrder p_order) { - if (!using_points) - return PoolVector<Vector3>(); + draw_order = p_order; + VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); +} - return VisualServer::get_singleton()->particles_get_emission_points(particles); +Particles::DrawOrder Particles::get_draw_order() const { + return draw_order; } -void Particles::set_emission_half_extents(const Vector3& p_half_extents) { +void Particles::set_draw_passes(int p_count) { - emission_half_extents=p_half_extents; - VisualServer::get_singleton()->particles_set_emission_half_extents(particles,p_half_extents); + ERR_FAIL_COND(p_count < 1); + draw_passes.resize(p_count); + VS::get_singleton()->particles_set_draw_passes(particles, p_count); + _change_notify(); +} +int Particles::get_draw_passes() const { + return draw_passes.size(); } -Vector3 Particles::get_emission_half_extents() const { +void Particles::set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh) { - return emission_half_extents; + ERR_FAIL_INDEX(p_pass, draw_passes.size()); + + draw_passes[p_pass] = p_mesh; + + RID mesh_rid; + if (p_mesh.is_valid()) + mesh_rid = p_mesh->get_rid(); + + VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); } -void Particles::set_emission_base_velocity(const Vector3& p_base_velocity) { +Ref<Mesh> Particles::get_draw_pass_mesh(int p_pass) const { - emission_base_velocity=p_base_velocity; - VisualServer::get_singleton()->particles_set_emission_base_velocity(particles,p_base_velocity); + ERR_FAIL_INDEX_V(p_pass, draw_passes.size(), Ref<Mesh>()); + return draw_passes[p_pass]; } -Vector3 Particles::get_emission_base_velocity() const { +void Particles::set_fixed_fps(int p_count) { + fixed_fps = p_count; + VS::get_singleton()->particles_set_fixed_fps(particles, p_count); +} - return emission_base_velocity; +int Particles::get_fixed_fps() const { + return fixed_fps; } -void Particles::set_gravity_normal(const Vector3& p_normal) { +void Particles::set_fractional_delta(bool p_enable) { + fractional_delta = p_enable; + VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); +} - gravity_normal=p_normal; - VisualServer::get_singleton()->particles_set_gravity_normal(particles,p_normal); +bool Particles::get_fractional_delta() const { + return fractional_delta; +} + +void Particles::_validate_property(PropertyInfo &property) const { + + if (property.name.begins_with("draw_pass_")) { + int index = property.name.get_slicec('_', 2).to_int() - 1; + if (index >= draw_passes.size()) { + property.usage = 0; + return; + } + } } -Vector3 Particles::get_gravity_normal() const { +void Particles::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_emitting", "emitting"), &Particles::set_emitting); + ClassDB::bind_method(D_METHOD("set_amount", "amount"), &Particles::set_amount); + ClassDB::bind_method(D_METHOD("set_lifetime", "secs"), &Particles::set_lifetime); + ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &Particles::set_pre_process_time); + ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &Particles::set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &Particles::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_custom_aabb", "aabb"), &Particles::set_custom_aabb); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &Particles::set_gravity); + ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &Particles::set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &Particles::set_fixed_fps); + ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &Particles::set_fractional_delta); + ClassDB::bind_method(D_METHOD("set_process_material", "material:Material"), &Particles::set_process_material); + + ClassDB::bind_method(D_METHOD("is_emitting"), &Particles::is_emitting); + ClassDB::bind_method(D_METHOD("get_amount"), &Particles::get_amount); + ClassDB::bind_method(D_METHOD("get_lifetime"), &Particles::get_lifetime); + ClassDB::bind_method(D_METHOD("get_pre_process_time"), &Particles::get_pre_process_time); + ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &Particles::get_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &Particles::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_custom_aabb"), &Particles::get_custom_aabb); + ClassDB::bind_method(D_METHOD("get_gravity"), &Particles::get_gravity); + ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &Particles::get_use_local_coordinates); + ClassDB::bind_method(D_METHOD("get_fixed_fps"), &Particles::get_fixed_fps); + ClassDB::bind_method(D_METHOD("get_fractional_delta"), &Particles::get_fractional_delta); + ClassDB::bind_method(D_METHOD("get_process_material:Material"), &Particles::get_process_material); + + ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &Particles::set_draw_order); + + ClassDB::bind_method(D_METHOD("get_draw_order"), &Particles::get_draw_order); + + ClassDB::bind_method(D_METHOD("set_draw_passes", "passes"), &Particles::set_draw_passes); + ClassDB::bind_method(D_METHOD("set_draw_pass_mesh", "pass", "mesh:Mesh"), &Particles::set_draw_pass_mesh); + + ClassDB::bind_method(D_METHOD("get_draw_passes"), &Particles::get_draw_passes); + ClassDB::bind_method(D_METHOD("get_draw_pass_mesh:Mesh", "pass"), &Particles::get_draw_pass_mesh); + + ADD_GROUP("Parameters", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,100000,1"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01"), "set_lifetime", "get_lifetime"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "preprocess", PROPERTY_HINT_RANGE, "0.00,600.0,0.01"), "set_pre_process_time", "get_pre_process_time"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::RECT3, "custom_aabb"), "set_custom_aabb", "get_custom_aabb"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity"), "set_gravity", "get_gravity"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ParticlesMaterial,ShaderMaterial"), "set_process_material", "get_process_material"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_order", PROPERTY_HINT_ENUM, "Index,Lifetime,View Depth"), "set_draw_order", "get_draw_order"); + ADD_GROUP("Draw Passes", "draw_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); + for (int i = 0; i < MAX_DRAW_PASSES; i++) { + + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "draw_pass_" + itos(i + 1), PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_draw_pass_mesh", "get_draw_pass_mesh", i); + } + + BIND_CONSTANT(DRAW_ORDER_INDEX); + BIND_CONSTANT(DRAW_ORDER_LIFETIME); + BIND_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + BIND_CONSTANT(MAX_DRAW_PASSES); +} - return gravity_normal; +Particles::Particles() { + particles = VS::get_singleton()->particles_create(); + set_base(particles); + set_emitting(true); + set_amount(100); + set_lifetime(1); + set_fixed_fps(0); + set_fractional_delta(true); + set_pre_process_time(0); + set_explosiveness_ratio(0); + set_randomness_ratio(0); + set_gravity(Vector3(0, -9.8, 0)); + set_use_local_coordinates(true); + set_draw_passes(1); } -void Particles::set_variable(Variable p_variable,float p_value) { +Particles::~Particles() { - ERR_FAIL_INDEX(p_variable,VAR_MAX); - var[p_variable]=p_value; - VisualServer::get_singleton()->particles_set_variable(particles,(VS::ParticleVariable)p_variable,p_value); - if (p_variable==VAR_SPREAD) - update_gizmo(); + VS::get_singleton()->free(particles); } -float Particles::get_variable(Variable p_variable) const { +////////////////////////////////////// - ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1); - return var[p_variable]; +Mutex *ParticlesMaterial::material_mutex = NULL; +SelfList<ParticlesMaterial>::List ParticlesMaterial::dirty_materials; +Map<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData> ParticlesMaterial::shader_map; +ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = NULL; +void ParticlesMaterial::init_shaders() { + +#ifndef NO_THREADS + material_mutex = Mutex::create(); +#endif + + shader_names = memnew(ShaderNames); + + shader_names->spread = "spread"; + shader_names->flatness = "flatness"; + shader_names->initial_linear_velocity = "initial_linear_velocity"; + shader_names->initial_angle = "initial_angle"; + shader_names->angular_velocity = "angular_velocity"; + shader_names->orbit_velocity = "orbit_velocity"; + shader_names->linear_accel = "linear_accel"; + shader_names->radial_accel = "radial_accel"; + shader_names->tangent_accel = "tangent_accel"; + shader_names->damping = "damping"; + shader_names->scale = "scale"; + shader_names->hue_variation = "hue_variation"; + shader_names->anim_speed = "anim_speed"; + shader_names->anim_offset = "anim_offset"; + + shader_names->initial_linear_velocity = "initial_linear_velocity_random"; + shader_names->initial_angle_random = "initial_angle_random"; + shader_names->angular_velocity_random = "angular_velocity_random"; + shader_names->orbit_velocity_random = "orbit_velocity_random"; + shader_names->linear_accel_random = "linear_accel_random"; + shader_names->radial_accel_random = "radial_accel_random"; + shader_names->tangent_accel_random = "tangent_accel_random"; + shader_names->damping_random = "damping_random"; + shader_names->scale_random = "scale_random"; + shader_names->hue_variation_random = "hue_variation_random"; + shader_names->anim_speed_random = "anim_speed_random"; + shader_names->anim_offset_random = "anim_offset_random"; + + shader_names->angle_texture = "angle_texture"; + shader_names->angular_velocity_texture = "angular_velocity_texture"; + shader_names->orbit_velocity_texture = "orbit_velocity_texture"; + shader_names->linear_accel_texture = "linear_accel_texture"; + shader_names->radial_accel_texture = "radial_accel_texture"; + shader_names->tangent_accel_texture = "tangent_accel_texture"; + shader_names->damping_texture = "damping_texture"; + shader_names->scale_texture = "scale_texture"; + shader_names->hue_variation_texture = "hue_variation_texture"; + shader_names->anim_speed_texture = "anim_speed_texture"; + shader_names->anim_offset_texture = "anim_offset_texture"; + + shader_names->color = "color_value"; + shader_names->color_ramp = "color_ramp"; + + shader_names->emission_sphere_radius = "emission_sphere_radius"; + shader_names->emission_box_extents = "emission_box_extents"; + shader_names->emission_texture_point_count = "emission_texture_point_count"; + shader_names->emission_texture_points = "emission_texture_points"; + shader_names->emission_texture_normal = "emission_texture_normal"; + + shader_names->trail_divisor = "trail_divisor"; + shader_names->trail_size_modifier = "trail_size_modifier"; + shader_names->trail_color_modifier = "trail_color_modifier"; } -void Particles::set_randomness(Variable p_variable,float p_randomness) { +void ParticlesMaterial::finish_shaders() { - ERR_FAIL_INDEX(p_variable,VAR_MAX); - var_random[p_variable]=p_randomness; - VisualServer::get_singleton()->particles_set_randomness(particles,(VS::ParticleVariable)p_variable,p_randomness); +#ifndef NO_THREADS + memdelete(material_mutex); +#endif + memdelete(shader_names); } -float Particles::get_randomness(Variable p_variable) const { - ERR_FAIL_INDEX_V(p_variable,VAR_MAX,-1); - return var_random[p_variable]; +void ParticlesMaterial::_update_shader() { + + print_line("updating shader"); + + dirty_materials.remove(&element); + + MaterialKey mk = _compute_key(); + if (mk.key == current_key.key) + return; //no update required in the end + + if (shader_map.has(current_key)) { + shader_map[current_key].users--; + if (shader_map[current_key].users == 0) { + //deallocate shader, as it's no longer in use + VS::get_singleton()->free(shader_map[current_key].shader); + shader_map.erase(current_key); + } + } + current_key = mk; + + if (shader_map.has(mk)) { + + VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + shader_map[mk].users++; + return; + } + + //must create a shader! + + String code = "shader_type particles;\n"; + + code += "uniform float spread;\n"; + code += "uniform float flatness;\n"; + code += "uniform float initial_linear_velocity;\n"; + code += "uniform float initial_angle;\n"; + code += "uniform float angular_velocity;\n"; + code += "uniform float orbit_velocity;\n"; + code += "uniform float linear_accel;\n"; + code += "uniform float radial_accel;\n"; + code += "uniform float tangent_accel;\n"; + code += "uniform float damping;\n"; + code += "uniform float scale;\n"; + code += "uniform float hue_variation;\n"; + code += "uniform float anim_speed;\n"; + code += "uniform float anim_offset;\n"; + + code += "uniform float initial_linear_velocity_random;\n"; + code += "uniform float initial_angle_random;\n"; + code += "uniform float angular_velocity_random;\n"; + code += "uniform float orbit_velocity_random;\n"; + code += "uniform float linear_accel_random;\n"; + code += "uniform float radial_accel_random;\n"; + code += "uniform float tangent_accel_random;\n"; + code += "uniform float damping_random;\n"; + code += "uniform float scale_random;\n"; + code += "uniform float hue_variation_random;\n"; + code += "uniform float anim_speed_random;\n"; + code += "uniform float anim_offset_random;\n"; + + code += "uniform vec4 color_value : hint_color;\n"; + + code += "uniform int trail_divisor;\n"; + + if (color_ramp.is_valid()) + code += "uniform sampler2D color_ramp;\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += "uniform sampler2D linear_velocity_texture;\n"; + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += "uniform sampler2D orbit_velocity_texture;\n"; + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += "uniform sampler2D angular_velocity_texture;\n"; + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += "uniform sampler2D linear_accel_texture;\n"; + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += "uniform sampler2D radial_accel_texture;\n"; + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += "uniform sampler2D tangent_accel_texture;\n"; + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += "uniform sampler2D damping_texture;\n"; + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += "uniform sampler2D angle_texture;\n"; + if (tex_parameters[PARAM_SCALE].is_valid()) + code += "uniform sampler2D scale_texture;\n"; + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += "uniform sampler2D hue_variation_texture;\n"; + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += "uniform sampler2D anim_speed_texture;\n"; + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += "uniform sampler2D anim_offset_texture;\n"; + + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += "uniform float emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += "uniform vec3 emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += "uniform sampler2D emission_texture_normal : hint_black;\n"; + } //fallthrough + case EMISSION_SHAPE_POINTS: { + code += "uniform sampler2D emission_texture_points : hint_black;\n"; + code += "uniform int emission_texture_point_count;\n"; + } break; + } + + if (trail_size_modifier.is_valid()) { + code += "uniform sampler2D trail_size_modifier;\n"; + } + + if (trail_color_modifier.is_valid()) { + code += "uniform sampler2D trail_color_modifier;\n"; + } + + //need a random function + code += "\n\n"; + code += "float rand_from_seed(inout uint seed) {\n"; + code += " int k;\n"; + code += " int s = int(seed);\n"; + code += " if (s == 0)\n"; + code += " s = 305420679;\n"; + code += " k = s / 127773;\n"; + code += " s = 16807 * (s - k * 127773) - 2836 * k;\n"; + code += " if (s < 0)\n"; + code += " s += 2147483647;\n"; + code += " seed = uint(s);\n"; + code += " return float(seed % uint(65536))/65535.0;\n"; + code += "}\n"; + //improve seed quality + code += "uint hash(uint x) {\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n"; + code += " x = (x >> uint(16)) ^ x;\n"; + code += " return x;\n"; + code += "}\n"; + code += "void vertex() {\n\n"; + code += "\n"; + + code += " uint base_number=NUMBER/uint(trail_divisor);\n"; + code += " uint alt_seed=hash(base_number+uint(1));\n"; + code += " float angle_rand=rand_from_seed(alt_seed);\n"; + code += " float scale_rand=rand_from_seed(alt_seed);\n"; + code += " float hue_rot_rand=rand_from_seed(alt_seed);\n"; + code += " float anim_offset_rand=rand_from_seed(alt_seed);\n"; + code += "\n"; + code += "\n"; + code += "\n"; + code += "\n"; + code += " if (RESTART) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(0.0,0.0),0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + code += " float angle1 = rand_from_seed(alt_seed)*spread*3.1416;\n"; + code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n"; + code += " vec3 rot_xz=vec3( sin(angle1), 0.0, cos(angle1) );\n"; + code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n"; + code += " VELOCITY=(rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; + code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; + code += " CUSTOM.x=base_angle*3.1416/180.0;\n"; //angle + code += " CUSTOM.y=0.0;\n"; //phase + code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random);\n"; //animation offset (0-1) + switch (emission_shape) { + case EMISSION_SHAPE_POINT: { + //do none + } break; + case EMISSION_SHAPE_SPHERE: { + code += " TRANSFORM[3].xyz = normalize(vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0 ))*emission_sphere_radius;\n"; + } break; + case EMISSION_SHAPE_BOX: { + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0-1.0, rand_from_seed(alt_seed) * 2.0-1.0)*emission_box_extents;\n"; + } break; + case EMISSION_SHAPE_POINTS: + case EMISSION_SHAPE_DIRECTED_POINTS: { + code += " int point = min(emission_texture_point_count-1,int(rand_from_seed(alt_seed) * float(emission_texture_point_count)));\n"; + code += " ivec2 tex_size = textureSize( emission_texture_points, 0 );\n"; + code += " ivec2 tex_ofs = ivec2( point % tex_size.x, point / tex_size.x );\n"; + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, tex_ofs,0).xyz;\n"; + if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { + code += " vec3 normal = texelFetch(emission_texture_normal, tex_ofs,0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " VELOCITY = mat3(tangent,bitangent,normal) * VELOCITY;\n"; + } + } break; + } + code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY,0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + + code += " } else {\n"; + + code += " CUSTOM.y+=DELTA/LIFETIME;\n"; + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " float tex_linear_velocity = textureLod(linear_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_linear_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) + code += " float tex_orbit_velocity = textureLod(orbit_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_orbit_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) + code += " float tex_angular_velocity = textureLod(angular_velocity_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_angular_velocity = 0.0;\n"; + + if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) + code += " float tex_linear_accel = textureLod(linear_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_linear_accel = 0.0;\n"; + + if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) + code += " float tex_radial_accel = textureLod(radial_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_radial_accel = 0.0;\n"; + + if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) + code += " float tex_tangent_accel = textureLod(tangent_accel_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_tangent_accel = 0.0;\n"; + + if (tex_parameters[PARAM_DAMPING].is_valid()) + code += " float tex_damping = textureLod(damping_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_damping = 0.0;\n"; + + if (tex_parameters[PARAM_ANGLE].is_valid()) + code += " float tex_angle = textureLod(angle_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_angle = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) + code += " float tex_anim_speed = textureLod(anim_speed_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_anim_speed = 0.0;\n"; + + if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) + code += " float tex_anim_offset = textureLod(anim_offset_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_anim_offset = 0.0;\n"; + + code += " vec3 force = vec3(0.0); \n"; + code += " vec3 pos = TRANSFORM[3].xyz; \n"; + code += " //apply linear acceleration\n"; + code += " force+=normalize(VELOCITY) * (linear_accel+tex_linear_accel)*mix(1.0,rand_from_seed(alt_seed),linear_accel_random);\n"; + code += " //apply radial acceleration\n"; + code += " vec3 org = vec3(0.0);\n"; + code += " // if (!p_system->local_coordinates)\n"; + code += " //org=p_transform.origin;\n"; + code += " force+=normalize(pos-org) * (radial_accel+tex_radial_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random);\n"; + code += " //apply tangential acceleration;\n"; + code += " force+=normalize(cross(normalize(pos-org),normalize(GRAVITY))) * ((tangent_accel+tex_tangent_accel)*mix(1.0,rand_from_seed(alt_seed),radial_accel_random));\n"; + code += " //apply attractor forces\n"; + code += " VELOCITY+=force * DELTA;\n"; + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) + code += " VELOCITY=normalize(VELOCITY)*tex_linear_velocity;\n"; + code += " if (damping+tex_damping>0.0) {\n"; + code += " \n"; + code += " float v = length(VELOCITY);\n"; + code += " float damp = (damping+tex_damping)*mix(1.0,rand_from_seed(alt_seed),damping_random);\n"; + code += " v -= damp * DELTA;\n"; + code += " if (v<0.0) {\n"; + code += " VELOCITY=vec3(0.0);\n"; + code += " } else {\n"; + code += " VELOCITY=normalize(VELOCITY) * v;\n"; + code += " }\n"; + code += " }\n"; + code += " float base_angle=(initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random)*3.1416/180.0;\n"; + code += " CUSTOM.x=((base_angle+tex_angle)+CUSTOM.y*LIFETIME*(angular_velocity+tex_angular_velocity)*mix(1.0,rand_from_seed(alt_seed)*2.0-1.0,angular_velocity_random))*3.1416/180.0;\n"; //angle + code += " CUSTOM.z=(anim_offset+tex_anim_offset)*mix(1.0,anim_offset_rand,anim_offset_random)+CUSTOM.y*LIFETIME*(anim_speed+tex_anim_speed)*mix(1.0,rand_from_seed(alt_seed),anim_speed_random);\n"; //angle + code += " }\n"; + //apply color + //apply hue rotation + if (tex_parameters[PARAM_SCALE].is_valid()) + code += " float tex_scale = textureLod(scale_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_scale = 1.0;\n"; + + if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) + code += " float tex_hue_variation = textureLod(hue_variation_texture,vec2(CUSTOM.y,0.0),0.0).r;\n"; + else + code += " float tex_hue_variation = 0.0;\n"; + + code += " float hue_rot_angle = (hue_variation+tex_hue_variation)*3.1416*2.0*mix(1.0,hue_rot_rand*2.0-1.0,hue_variation_random);\n"; + code += " float hue_rot_c = cos(hue_rot_angle);\n"; + code += " float hue_rot_s = sin(hue_rot_angle);\n"; + code += " mat4 hue_rot_mat = mat4( vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.299, 0.587, 0.114, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 1.0)) +\n"; + code += " \n"; + code += " mat4( vec4(0.701, -0.587, -0.114, 0.0),\n"; + code += " vec4(-0.299, 0.413, -0.114, 0.0),\n"; + code += " vec4(-0.300, -0.588, 0.886, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_c +\n"; + code += "\n"; + code += " mat4( vec4(0.168, 0.330, -0.497, 0.0),\n"; + code += " vec4(-0.328, 0.035, 0.292, 0.0),\n"; + code += " vec4(1.250, -1.050, -0.203, 0.0),\n"; + code += " vec4(0.000, 0.000, 0.000, 0.0)) * hue_rot_s;\n"; + if (color_ramp.is_valid()) { + code += " COLOR = textureLod(color_ramp,vec2(CUSTOM.y,0.0),0.0) * hue_rot_mat;\n"; + } else { + code += " COLOR = color_value * hue_rot_mat;\n"; + } + if (trail_color_modifier.is_valid()) { + code += "if (trail_divisor>1) { COLOR*=textureLod(trail_color_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0); }\n"; + } + code += "\n"; + //orient particle Y towards velocity + if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + code += " if (length(VELOCITY)>0.0) {TRANSFORM[1].xyz=normalize(VELOCITY);} else {TRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);}\n"; + code += " if (TRANSFORM[1].xyz==normalize(TRANSFORM[0].xyz)) {\n"; + code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; + code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; + code += " } else {\n"; + code += "\tTRANSFORM[2].xyz=normalize(cross(normalize(TRANSFORM[0].xyz),normalize(TRANSFORM[1].xyz)));\n"; + code += "\tTRANSFORM[0].xyz=normalize(cross(normalize(TRANSFORM[1].xyz),normalize(TRANSFORM[2].xyz)));\n"; + code += " }\n"; + } else { + code += "\tTRANSFORM[0].xyz=normalize(TRANSFORM[0].xyz);\n"; + code += "\tTRANSFORM[1].xyz=normalize(TRANSFORM[1].xyz);\n"; + code += "\tTRANSFORM[2].xyz=normalize(TRANSFORM[2].xyz);\n"; + } + //turn particle by rotation in Y + if (flags[FLAG_ROTATE_Y]) { + code += "\tTRANSFORM = TRANSFORM * mat4( vec4(cos(CUSTOM.x),0.0,-sin(CUSTOM.x),0.0), vec4(0.0,1.0,0.0,0.0),vec4(sin(CUSTOM.x),0.0,cos(CUSTOM.x),0.0),vec4(0.0,0.0,0.0,1.0));\n"; + } + //scale by scale + code += " float base_scale=mix(scale*tex_scale,1.0,scale_random*scale_rand);\n"; + if (trail_size_modifier.is_valid()) { + code += "if (trail_divisor>1) { base_scale*=textureLod(trail_size_modifier,vec2(float(int(NUMBER)%trail_divisor)/float(trail_divisor-1),0.0),0.0).r; } \n"; + } + + code += " TRANSFORM[0].xyz*=base_scale;\n"; + code += " TRANSFORM[1].xyz*=base_scale;\n"; + code += " TRANSFORM[2].xyz*=base_scale;\n"; + code += "}\n"; + code += "\n"; + + ShaderData shader_data; + shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.users = 1; + + VS::get_singleton()->shader_set_code(shader_data.shader, code); + + shader_map[mk] = shader_data; + + VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void Particles::set_color_phase_pos(int p_phase, float p_pos) { +void ParticlesMaterial::flush_changes() { - ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES); - color_phase[p_phase].pos=p_pos; - VisualServer::get_singleton()->particles_set_color_phase_pos(particles,p_phase,p_pos); + if (material_mutex) + material_mutex->lock(); + while (dirty_materials.first()) { + + dirty_materials.first()->self()->_update_shader(); + } + + if (material_mutex) + material_mutex->unlock(); } -float Particles::get_color_phase_pos(int p_phase) const { - ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,-1); - return color_phase[p_phase].pos; +void ParticlesMaterial::_queue_shader_change() { + + if (material_mutex) + material_mutex->lock(); + + print_line("queuing change"); + if (!element.in_list()) { + print_line("not in list, adding"); + dirty_materials.add(&element); + } + + if (material_mutex) + material_mutex->unlock(); } -void Particles::set_color_phase_color(int p_phase, const Color& p_color) { +bool ParticlesMaterial::_is_shader_dirty() const { + + bool dirty = false; + + if (material_mutex) + material_mutex->lock(); + + dirty = element.in_list(); - ERR_FAIL_INDEX(p_phase,VS::MAX_PARTICLE_COLOR_PHASES); - color_phase[p_phase].color=p_color; - VisualServer::get_singleton()->particles_set_color_phase_color(particles,p_phase,p_color); + if (material_mutex) + material_mutex->unlock(); + return dirty; } -Color Particles::get_color_phase_color(int p_phase) const { - ERR_FAIL_INDEX_V(p_phase,VS::MAX_PARTICLE_COLOR_PHASES,Color()); - return color_phase[p_phase].color; +void ParticlesMaterial::set_spread(float p_spread) { + spread = p_spread; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } -void Particles::set_material(const Ref<Material>& p_material) { +float ParticlesMaterial::get_spread() const { - material=p_material; - if(material.is_null()) { - VisualServer::get_singleton()->particles_set_material(particles,RID()); - } else { - VisualServer::get_singleton()->particles_set_material(particles,material->get_rid()); + return spread; +} + +void ParticlesMaterial::set_flatness(float p_flatness) { + + flatness = p_flatness; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); +} +float ParticlesMaterial::get_flatness() const { + + return flatness; +} + +void ParticlesMaterial::set_param(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + parameters[p_param] = p_value; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); + } break; + case PARAM_MAX: { + }; } +} +float ParticlesMaterial::get_param(Parameter p_param) const { + + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); + return parameters[p_param]; } -void Particles::setup_timer() { +void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + randomness[p_param] = p_value; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); + } break; + case PARAM_MAX: { + }; + } +} +float ParticlesMaterial::get_param_randomness(Parameter p_param) const { - if (emitting && emit_timeout > 0) { + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); - timer->set_wait_time(emit_timeout); - timer->start(); - timer->set_one_shot(true); - }; -}; + return randomness[p_param]; +} -void Particles::set_emit_timeout(float p_timeout) { +static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { - emit_timeout = p_timeout; - setup_timer(); -}; + Ref<CurveTexture> curve = p_texture; + if (!curve.is_valid()) + return; -float Particles::get_emit_timeout() const { + if (curve->get_max() == 1.0) { + curve->set_max(p_max); + } + if (curve->get_min() == 0.0) { + curve->set_min(p_min); + } +} - return emit_timeout; -}; +void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { + + ERR_FAIL_INDEX(p_param, PARAM_MAX); + + tex_parameters[p_param] = p_texture; + + switch (p_param) { + case PARAM_INITIAL_LINEAR_VELOCITY: { + //do none for this one + } break; + case PARAM_ANGULAR_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_ORBIT_VELOCITY: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); + _adjust_curve_range(p_texture, -500, 500); + } break; + case PARAM_LINEAR_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_RADIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_TANGENTIAL_ACCEL: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); + _adjust_curve_range(p_texture, -200, 200); + } break; + case PARAM_DAMPING: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); + _adjust_curve_range(p_texture, 0, 100); + } break; + case PARAM_ANGLE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); + _adjust_curve_range(p_texture, -360, 360); + } break; + case PARAM_SCALE: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); + + Ref<CurveTexture> curve = p_texture; + if (curve.is_valid()) { + if (curve->get_min() == 0 && curve->get_max() == 1) { + + curve->set_max(32); + PoolVector<Vector2> points; + points.push_back(Vector2(0, 1)); + points.push_back(Vector2(1, 1)); + curve->set_points(points); + } + } + } break; + case PARAM_HUE_VARIATION: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); + _adjust_curve_range(p_texture, -1, 1); + } break; + case PARAM_ANIM_SPEED: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); + _adjust_curve_range(p_texture, 0, 200); + } break; + case PARAM_ANIM_OFFSET: { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); + } break; + case PARAM_MAX: { + }; + } + + _queue_shader_change(); +} +Ref<Texture> ParticlesMaterial::get_param_texture(Parameter p_param) const { -Ref<Material> Particles::get_material() const { + ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture>()); - return material; + return tex_parameters[p_param]; } -void Particles::set_height_from_velocity(bool p_enable) { +void ParticlesMaterial::set_color(const Color &p_color) { - height_from_velocity=p_enable; - VisualServer::get_singleton()->particles_set_height_from_velocity(particles,height_from_velocity); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); + color = p_color; } -bool Particles::has_height_from_velocity() const { +Color ParticlesMaterial::get_color() const { - return height_from_velocity; + return color; } -void Particles::set_color_phases(int p_phases) { +void ParticlesMaterial::set_color_ramp(const Ref<Texture> &p_texture) { - color_phase_count=p_phases; - VisualServer::get_singleton()->particles_set_color_phases(particles,p_phases); + color_ramp = p_texture; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); + _queue_shader_change(); + _change_notify(); } -int Particles::get_color_phases() const{ +Ref<Texture> ParticlesMaterial::get_color_ramp() const { - return color_phase_count; + return color_ramp; } -bool Particles::_can_gizmo_scale() const { +void ParticlesMaterial::set_flag(Flags p_flag, bool p_enable) { + ERR_FAIL_INDEX(p_flag, FLAG_MAX); + flags[p_flag] = p_enable; + _queue_shader_change(); +} - return false; +bool ParticlesMaterial::get_flag(Flags p_flag) const { + ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); + return flags[p_flag]; } -void Particles::set_use_local_coordinates(bool p_use) { +void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { - local_coordinates=p_use; - VisualServer::get_singleton()->particles_set_use_local_coordinates(particles,local_coordinates); + emission_shape = p_shape; + _change_notify(); + _queue_shader_change(); } -bool Particles::is_using_local_coordinates() const{ +void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { - return local_coordinates; + emission_sphere_radius = p_radius; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); } +void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { -RES Particles::_get_gizmo_geometry() const { + emission_box_extents = p_extents; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); +} - Ref<SurfaceTool> surface_tool( memnew( SurfaceTool )); +void ParticlesMaterial::set_emission_point_texture(const Ref<Texture> &p_points) { - Ref<FixedSpatialMaterial> mat( memnew( FixedSpatialMaterial )); + emission_point_texture = p_points; + RID texture; + if (p_points.is_valid()) + texture = p_points->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, texture); +} - mat->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.0,0.6,0.7,0.2) ); - mat->set_parameter( FixedSpatialMaterial::PARAM_EMISSION,Color(0.5,0.7,0.8) ); - mat->set_blend_mode( Material::BLEND_MODE_ADD ); - mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - //mat->set_hint(Material::HINT_NO_DEPTH_DRAW,true); +void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture> &p_normals) { + emission_normal_texture = p_normals; + RID texture; + if (p_normals.is_valid()) + texture = p_normals->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, texture); +} - surface_tool->begin(Mesh::PRIMITIVE_TRIANGLES); - surface_tool->set_material(mat); +void ParticlesMaterial::set_emission_point_count(int p_count) { - int sides=16; - int sections=24; + emission_point_count = p_count; + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); +} - //float len=1; - float deg=Math::deg2rad(var[VAR_SPREAD]*180); - if (deg==180) - deg=179.5; +ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { - Vector3 to=Vector3(0,0,-1); + return emission_shape; +} - for(int j=0;j<sections;j++) { +float ParticlesMaterial::get_emission_sphere_radius() const { - Vector3 p1=Matrix3(Vector3(1,0,0),deg*j/sections).xform(to); - Vector3 p2=Matrix3(Vector3(1,0,0),deg*(j+1)/sections).xform(to); + return emission_sphere_radius; +} +Vector3 ParticlesMaterial::get_emission_box_extents() const { - for(int i=0;i<sides;i++) { + return emission_box_extents; +} +Ref<Texture> ParticlesMaterial::get_emission_point_texture() const { - Vector3 p1r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p1); - Vector3 p1s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p1); - Vector3 p2s = Matrix3(Vector3(0,0,1),Math_PI*2*float(i+1)/sides).xform(p2); - Vector3 p2r = Matrix3(Vector3(0,0,1),Math_PI*2*float(i)/sides).xform(p2); + return emission_point_texture; +} +Ref<Texture> ParticlesMaterial::get_emission_normal_texture() const { - surface_tool->add_normal(p1r.normalized()); - surface_tool->add_vertex(p1r); - surface_tool->add_normal(p1s.normalized()); - surface_tool->add_vertex(p1s); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); + return emission_normal_texture; +} - surface_tool->add_normal(p1r.normalized()); - surface_tool->add_vertex(p1r); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); - surface_tool->add_normal(p2r.normalized()); - surface_tool->add_vertex(p2r); +int ParticlesMaterial::get_emission_point_count() const { - if (j==sections-1) { + return emission_point_count; +} - surface_tool->add_normal(p2r.normalized()); - surface_tool->add_vertex(p2r); - surface_tool->add_normal(p2s.normalized()); - surface_tool->add_vertex(p2s); - surface_tool->add_normal(Vector3(0,0,1)); - surface_tool->add_vertex(Vector3()); - } - } - } +void ParticlesMaterial::set_trail_divisor(int p_divisor) { + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); + trail_divisor = p_divisor; + _change_notify(); +} - Ref<Mesh> mesh = surface_tool->commit(); +int ParticlesMaterial::get_trail_divisor() const { - Ref<FixedSpatialMaterial> mat_aabb( memnew( FixedSpatialMaterial )); + return trail_divisor; +} - mat_aabb->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.8,0.8,0.9,0.7) ); - mat_aabb->set_line_width(3); - mat_aabb->set_flag( Material::FLAG_UNSHADED, true ); +void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - surface_tool->begin(Mesh::PRIMITIVE_LINES); - surface_tool->set_material(mat_aabb); + trail_size_modifier = p_trail_size_modifier; - for(int i=0;i<12;i++) { + Ref<CurveTexture> curve = trail_size_modifier; + if (curve.is_valid()) { + if (curve->get_min() == 0 && curve->get_max() == 1) { - Vector3 f,t; - visibility_aabb.get_edge(i,f,t); - surface_tool->add_vertex(f); - surface_tool->add_vertex(t); + curve->set_max(32); + PoolVector<Vector2> points; + points.push_back(Vector2(0, 1)); + points.push_back(Vector2(1, 1)); + curve->set_points(points); + } } - return surface_tool->commit(mesh); - + RID texture; + if (p_trail_size_modifier.is_valid()) + texture = p_trail_size_modifier->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, texture); + _queue_shader_change(); } +Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { -void Particles::_bind_methods() { + return trail_size_modifier; +} - ClassDB::bind_method(D_METHOD("set_amount","amount"),&Particles::set_amount); - ClassDB::bind_method(D_METHOD("get_amount"),&Particles::get_amount); - ClassDB::bind_method(D_METHOD("set_emitting","enabled"),&Particles::set_emitting); - ClassDB::bind_method(D_METHOD("is_emitting"),&Particles::is_emitting); - ClassDB::bind_method(D_METHOD("set_visibility_aabb","aabb"),&Particles::set_visibility_aabb); - ClassDB::bind_method(D_METHOD("get_visibility_aabb"),&Particles::get_visibility_aabb); - ClassDB::bind_method(D_METHOD("set_emission_half_extents","half_extents"),&Particles::set_emission_half_extents); - ClassDB::bind_method(D_METHOD("get_emission_half_extents"),&Particles::get_emission_half_extents); - ClassDB::bind_method(D_METHOD("set_emission_base_velocity","base_velocity"),&Particles::set_emission_base_velocity); - ClassDB::bind_method(D_METHOD("get_emission_base_velocity"),&Particles::get_emission_base_velocity); - ClassDB::bind_method(D_METHOD("set_emission_points","points"),&Particles::set_emission_points); - ClassDB::bind_method(D_METHOD("get_emission_points"),&Particles::get_emission_points); - ClassDB::bind_method(D_METHOD("set_gravity_normal","normal"),&Particles::set_gravity_normal); - ClassDB::bind_method(D_METHOD("get_gravity_normal"),&Particles::get_gravity_normal); - ClassDB::bind_method(D_METHOD("set_variable","variable","value"),&Particles::set_variable); - ClassDB::bind_method(D_METHOD("get_variable","variable"),&Particles::get_variable); - ClassDB::bind_method(D_METHOD("set_randomness","variable","randomness"),&Particles::set_randomness); - ClassDB::bind_method(D_METHOD("get_randomness","variable"),&Particles::get_randomness); - ClassDB::bind_method(D_METHOD("set_color_phase_pos","phase","pos"),&Particles::set_color_phase_pos); - ClassDB::bind_method(D_METHOD("get_color_phase_pos","phase"),&Particles::get_color_phase_pos); - ClassDB::bind_method(D_METHOD("set_color_phase_color","phase","color"),&Particles::set_color_phase_color); - ClassDB::bind_method(D_METHOD("get_color_phase_color","phase"),&Particles::get_color_phase_color); - ClassDB::bind_method(D_METHOD("set_material","material:Material"),&Particles::set_material); - ClassDB::bind_method(D_METHOD("get_material:Material"),&Particles::get_material); - ClassDB::bind_method(D_METHOD("set_emit_timeout","timeout"),&Particles::set_emit_timeout); - ClassDB::bind_method(D_METHOD("get_emit_timeout"),&Particles::get_emit_timeout); - ClassDB::bind_method(D_METHOD("set_height_from_velocity","enable"),&Particles::set_height_from_velocity); - ClassDB::bind_method(D_METHOD("has_height_from_velocity"),&Particles::has_height_from_velocity); - ClassDB::bind_method(D_METHOD("set_use_local_coordinates","enable"),&Particles::set_use_local_coordinates); - ClassDB::bind_method(D_METHOD("is_using_local_coordinates"),&Particles::is_using_local_coordinates); - - ClassDB::bind_method(D_METHOD("set_color_phases","count"),&Particles::set_color_phases); - ClassDB::bind_method(D_METHOD("get_color_phases"),&Particles::get_color_phases); - - ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material" ), "set_material", "get_material") ; - - ADD_PROPERTY( PropertyInfo( Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1024,1" ), "set_amount", "get_amount") ; - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "emitting" ), "set_emitting", "is_emitting") ; - ADD_PROPERTY( PropertyInfo( Variant::_AABB, "visibility" ), "set_visibility_aabb", "get_visibility_aabb") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_extents" ), "set_emission_half_extents", "get_emission_half_extents") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "emission_base_velocity" ), "set_emission_base_velocity", "get_emission_base_velocity") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3_ARRAY, "emission_points" ), "set_emission_points", "get_emission_points") ; - ADD_PROPERTY( PropertyInfo( Variant::VECTOR3, "gravity_normal" ), "set_gravity_normal", "get_gravity_normal") ; - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "local_coords" ), "set_use_local_coordinates", "is_using_local_coordinates") ; - ADD_PROPERTY( PropertyInfo( Variant::REAL, "emit_timeout",PROPERTY_HINT_RANGE,"0,256,0.01"), "set_emit_timeout", "get_emit_timeout") ; - - - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/lifetime", PROPERTY_HINT_RANGE,"0.1,60,0.01"), "set_variable", "get_variable", VAR_LIFETIME ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/spread", PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_SPREAD ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/gravity", PROPERTY_HINT_RANGE,"-48,48,0.01"), "set_variable", "get_variable", VAR_GRAVITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_VELOCITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/angular_vel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_ANGULAR_VELOCITY ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/linear_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_LINEAR_ACCELERATION ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/radial_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_DRAG ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/tan_accel", PROPERTY_HINT_RANGE,"-100,100,0.01"), "set_variable", "get_variable", VAR_TANGENTIAL_ACCELERATION ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/damping", PROPERTY_HINT_RANGE,"0,128,0.01"), "set_variable", "get_variable", VAR_DAMPING ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_INITIAL_SIZE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/final_size", PROPERTY_HINT_RANGE,"0,100,0.01"), "set_variable", "get_variable", VAR_FINAL_SIZE ); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/initial_angle",PROPERTY_HINT_RANGE,"0,1,0.01"), "set_variable", "get_variable", VAR_INITIAL_ANGLE ); - ADD_PROPERTY( PropertyInfo( Variant::BOOL, "vars/height_from_velocity"), "set_height_from_velocity", "has_height_from_velocity") ; - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT); - ADD_PROPERTYI( PropertyInfo( Variant::REAL, "vars/height_speed_scale",PROPERTY_HINT_RANGE,"0,4096,0.01"), "set_variable", "get_variable", VAR_HEIGHT_SPEED_SCALE ); - - for(int i=0;i<VAR_MAX;i++) - ADD_PROPERTYI( PropertyInfo( Variant::REAL, _rand_names[i], PROPERTY_HINT_RANGE,"-16.0,16.0,0.01"),"set_randomness", "get_randomness",_var_indices[i] ); - - - ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1"), "set_color_phases", "get_color_phases"); - - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - String phase="phase_"+itos(i)+"/"; - ADD_PROPERTYI( PropertyInfo( Variant::REAL, phase+"pos", PROPERTY_HINT_RANGE,"0,1,0.01"),"set_color_phase_pos","get_color_phase_pos",i ); - ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color"),"set_color_phase_color","get_color_phase_color",i ); - } +void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { + + trail_color_modifier = p_trail_color_modifier; + RID texture; + if (p_trail_color_modifier.is_valid()) + texture = p_trail_color_modifier->get_rid(); + VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, texture); + _queue_shader_change(); +} - BIND_CONSTANT( VAR_LIFETIME ); - BIND_CONSTANT( VAR_SPREAD ); - BIND_CONSTANT( VAR_GRAVITY ); - BIND_CONSTANT( VAR_LINEAR_VELOCITY ); - BIND_CONSTANT( VAR_ANGULAR_VELOCITY ); - BIND_CONSTANT( VAR_LINEAR_ACCELERATION ); - BIND_CONSTANT( VAR_DRAG ); - BIND_CONSTANT( VAR_TANGENTIAL_ACCELERATION ); - BIND_CONSTANT( VAR_INITIAL_SIZE ); - BIND_CONSTANT( VAR_FINAL_SIZE ); - BIND_CONSTANT( VAR_INITIAL_ANGLE ); - BIND_CONSTANT( VAR_HEIGHT ); - BIND_CONSTANT( VAR_HEIGHT_SPEED_SCALE ); - BIND_CONSTANT( VAR_MAX ); +Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { + return trail_color_modifier; } -Particles::Particles() { +void ParticlesMaterial::_validate_property(PropertyInfo &property) const { - particles = VisualServer::get_singleton()->particles_create(); - timer = memnew(Timer); - add_child(timer); - emit_timeout = 0; + if (property.name == "color" && color_ramp.is_valid()) { + property.usage = 0; + } - set_amount(64); - set_emitting(true); - set_visibility_aabb(AABB( Vector3(-4,-4,-4), Vector3(8,8,8) ) ); + if (property.name == "emission_sphere_radius" && emission_shape != EMISSION_SHAPE_SPHERE) { + property.usage = 0; + } - for (int i=0;i<VAR_MAX;i++) { - set_randomness((Variable)i,0.0); + if (property.name == "emission_box_extents" && emission_shape != EMISSION_SHAPE_BOX) { + property.usage = 0; } - set_variable( VAR_LIFETIME, 5.0); - set_variable( VAR_SPREAD, 0.2); - set_variable( VAR_GRAVITY, 9.8); - set_variable( VAR_LINEAR_VELOCITY, 0.2); - set_variable( VAR_ANGULAR_VELOCITY, 0.0); - set_variable( VAR_LINEAR_ACCELERATION, 0.0); - set_variable( VAR_DRAG, 0.0); - set_variable( VAR_TANGENTIAL_ACCELERATION, 0.0); - set_variable( VAR_DAMPING, 0.0); - set_variable( VAR_INITIAL_SIZE, 1.0); - set_variable( VAR_FINAL_SIZE, 1.0); - set_variable( VAR_INITIAL_ANGLE, 0.0); - set_variable( VAR_HEIGHT, 1.0); - set_variable( VAR_HEIGHT_SPEED_SCALE, 0.0); - - color_phase_count=0; - - set_color_phase_pos(0,0.0); - set_color_phase_pos(1,1.0); - set_color_phase_pos(2,1.0); - set_color_phase_pos(3,1.0); - - set_color_phase_color(0,Color(1,1,1)); - set_color_phase_color(1,Color(0,0,0)); - set_color_phase_color(2,Color(0,0,0)); - set_color_phase_color(3,Color(0,0,0)); - - set_gravity_normal(Vector3(0,-1.0,0)); - set_emission_half_extents(Vector3(0.1,0.1,0.1)); - - height_from_velocity=false; - - Vector<Variant> pars; - pars.push_back(false); - timer->connect("timeout", this, "set_emitting", pars); - set_base(particles); - local_coordinates=false; + if (property.name == "emission_point_texture" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + property.usage = 0; + } + + if (property.name == "emission_normal_texture" && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS) { + property.usage = 0; + } + + if (property.name == "emission_point_count" && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) { + property.usage = 0; + } } +void ParticlesMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); + + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); + + ClassDB::bind_method(D_METHOD("set_param", "param", "value"), &ParticlesMaterial::set_param); + ClassDB::bind_method(D_METHOD("get_param", "param"), &ParticlesMaterial::get_param); + + ClassDB::bind_method(D_METHOD("set_param_randomness", "param", "randomness"), &ParticlesMaterial::set_param_randomness); + ClassDB::bind_method(D_METHOD("get_param_randomness", "param"), &ParticlesMaterial::get_param_randomness); + + ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); + ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); + + ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); + + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp:Texture"), &ParticlesMaterial::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp:Texture"), &ParticlesMaterial::get_color_ramp); + + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &ParticlesMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag", "flag"), &ParticlesMaterial::get_flag); + + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); + + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); + + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); + + ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture:Texture"), &ParticlesMaterial::set_emission_point_texture); + ClassDB::bind_method(D_METHOD("get_emission_point_texture:Texture"), &ParticlesMaterial::get_emission_point_texture); + + ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture:Texture"), &ParticlesMaterial::set_emission_normal_texture); + ClassDB::bind_method(D_METHOD("get_emission_normal_texture:Texture"), &ParticlesMaterial::get_emission_normal_texture); + + ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); + ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + + ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); + ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); + + ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture:CurveTexture"), &ParticlesMaterial::set_trail_size_modifier); + ClassDB::bind_method(D_METHOD("get_trail_size_modifier:CurveTexture"), &ParticlesMaterial::get_trail_size_modifier); + + ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture:GradientTexture"), &ParticlesMaterial::set_trail_color_modifier); + ClassDB::bind_method(D_METHOD("get_trail_color_modifier:GradientTexture"), &ParticlesMaterial::get_trail_color_modifier); + + ADD_GROUP("Trail", "trail_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_GROUP("Emission Shape", "emission_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_point_texture", "get_emission_point_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_emission_normal_texture", "get_emission_normal_texture"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count"); + ADD_GROUP("Flags", "flag_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_flag", "get_flag", FLAG_ALIGN_Y_TO_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_flag", "get_flag", FLAG_ROTATE_Y); + ADD_GROUP("Spread", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "flatness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_flatness", "get_flatness"); + ADD_GROUP("Initial Velocity", "initial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_param", "get_param", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "initial_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_INITIAL_LINEAR_VELOCITY); + ADD_GROUP("Angular Velocity", "angular_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity", PROPERTY_HINT_RANGE, "-360,360,0.01"), "set_param", "get_param", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGULAR_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angular_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGULAR_VELOCITY); + ADD_GROUP("Orbit Velocity", "orbit_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity", PROPERTY_HINT_RANGE, "-1000,1000,0.01"), "set_param", "get_param", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "orbit_velocity_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ORBIT_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orbit_velocity_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ORBIT_VELOCITY); + ADD_GROUP("Linear Accel", "linear_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_LINEAR_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "linear_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_LINEAR_ACCEL); + ADD_GROUP("Radial Accel", "radial_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "radial_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_RADIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "radial_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_RADIAL_ACCEL); + ADD_GROUP("Tangential Accel", "tangential_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel", PROPERTY_HINT_RANGE, "-100,100,0.01"), "set_param", "get_param", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "tangential_accel_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_TANGENTIAL_ACCEL); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_TANGENTIAL_ACCEL); + ADD_GROUP("Damping", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param", "get_param", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "damping_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_DAMPING); + ADD_GROUP("Angle", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle", PROPERTY_HINT_RANGE, "-720,720,0.1"), "set_param", "get_param", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angle_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANGLE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "angle_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANGLE); + ADD_GROUP("Scale", ""); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale", PROPERTY_HINT_RANGE, "0,1000,0.01"), "set_param", "get_param", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "scale_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_SCALE); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "scale_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_SCALE); + ADD_GROUP("Color", ""); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); + + ADD_GROUP("Hue Variation", "hue_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); + ADD_GROUP("Animation", "anim_"); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_speed_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_speed_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_SPEED); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); + ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + + BIND_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); + BIND_CONSTANT(PARAM_ANGULAR_VELOCITY); + BIND_CONSTANT(PARAM_ORBIT_VELOCITY); + BIND_CONSTANT(PARAM_LINEAR_ACCEL); + BIND_CONSTANT(PARAM_RADIAL_ACCEL); + BIND_CONSTANT(PARAM_TANGENTIAL_ACCEL); + BIND_CONSTANT(PARAM_DAMPING); + BIND_CONSTANT(PARAM_ANGLE); + BIND_CONSTANT(PARAM_SCALE); + BIND_CONSTANT(PARAM_HUE_VARIATION); + BIND_CONSTANT(PARAM_ANIM_SPEED); + BIND_CONSTANT(PARAM_ANIM_OFFSET); + BIND_CONSTANT(PARAM_MAX); + + BIND_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); + BIND_CONSTANT(FLAG_ROTATE_Y); + BIND_CONSTANT(FLAG_MAX); + + BIND_CONSTANT(EMISSION_SHAPE_POINT); + BIND_CONSTANT(EMISSION_SHAPE_SPHERE); + BIND_CONSTANT(EMISSION_SHAPE_BOX); + BIND_CONSTANT(EMISSION_SHAPE_POINTS); + BIND_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); +} -Particles::~Particles() { +ParticlesMaterial::ParticlesMaterial() + : element(this) { + + set_spread(45); + set_flatness(0); + set_param(PARAM_INITIAL_LINEAR_VELOCITY, 1); + set_param(PARAM_ORBIT_VELOCITY, 0); + set_param(PARAM_LINEAR_ACCEL, 0); + set_param(PARAM_RADIAL_ACCEL, 0); + set_param(PARAM_TANGENTIAL_ACCEL, 0); + set_param(PARAM_DAMPING, 0); + set_param(PARAM_ANGLE, 0); + set_param(PARAM_SCALE, 1); + set_param(PARAM_HUE_VARIATION, 0); + set_param(PARAM_ANIM_SPEED, 0); + set_param(PARAM_ANIM_OFFSET, 0); + set_emission_shape(EMISSION_SHAPE_POINT); + set_emission_sphere_radius(1); + set_emission_box_extents(Vector3(1, 1, 1)); + set_trail_divisor(1); + emission_point_count = 1; + + for (int i = 0; i < PARAM_MAX; i++) { + set_param_randomness(Parameter(i), 0); + } + + for (int i = 0; i < FLAG_MAX; i++) { + flags[i] = false; + } - VisualServer::get_singleton()->free(particles); + set_color(Color(1, 1, 1, 1)); + + current_key.key = 0; + current_key.invalid_key = 1; + + _queue_shader_change(); } -#endif +ParticlesMaterial::~ParticlesMaterial() { +} diff --git a/scene/3d/particles.h b/scene/3d/particles.h index 6cb1caad3a..7ca3bab4db 100644 --- a/scene/3d/particles.h +++ b/scene/3d/particles.h @@ -37,130 +37,336 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -#if 0 + class Particles : public GeometryInstance { +private: + GDCLASS(Particles, GeometryInstance); + public: + enum DrawOrder { + DRAW_ORDER_INDEX, + DRAW_ORDER_LIFETIME, + DRAW_ORDER_VIEW_DEPTH, + }; - enum Variable { - VAR_LIFETIME=VS::PARTICLE_LIFETIME, - VAR_SPREAD=VS::PARTICLE_SPREAD, - VAR_GRAVITY=VS::PARTICLE_GRAVITY, - VAR_LINEAR_VELOCITY=VS::PARTICLE_LINEAR_VELOCITY, - VAR_ANGULAR_VELOCITY=VS::PARTICLE_ANGULAR_VELOCITY, - VAR_LINEAR_ACCELERATION=VS::PARTICLE_LINEAR_ACCELERATION, - VAR_DRAG=VS::PARTICLE_RADIAL_ACCELERATION, - VAR_TANGENTIAL_ACCELERATION=VS::PARTICLE_TANGENTIAL_ACCELERATION, - VAR_DAMPING=VS::PARTICLE_DAMPING, - VAR_INITIAL_SIZE=VS::PARTICLE_INITIAL_SIZE, - VAR_FINAL_SIZE=VS::PARTICLE_FINAL_SIZE, - VAR_INITIAL_ANGLE=VS::PARTICLE_INITIAL_ANGLE, - VAR_HEIGHT=VS::PARTICLE_HEIGHT, - VAR_HEIGHT_SPEED_SCALE=VS::PARTICLE_HEIGHT_SPEED_SCALE, - VAR_MAX=VS::PARTICLE_VAR_MAX + enum { + MAX_DRAW_PASSES = 4 }; private: - GDCLASS( Particles, GeometryInstance ); - RID particles; - int amount; bool emitting; - float emit_timeout; - AABB visibility_aabb; - Vector3 gravity_normal; - Vector3 emission_half_extents; - bool using_points; - float var[VAR_MAX]; - float var_random[VAR_MAX]; - bool height_from_velocity; - Vector3 emission_base_velocity; - bool local_coordinates; - - struct ColorPhase { - - Color color; - float pos; - }; - - virtual bool _can_gizmo_scale() const; - virtual RES _get_gizmo_geometry() const; - - int color_phase_count; + int amount; + float lifetime; + float pre_process_time; + float explosiveness_ratio; + float randomness_ratio; + Rect3 custom_aabb; + Vector3 gravity; + bool local_coords; + int fixed_fps; + bool fractional_delta; - ColorPhase color_phase[4]; + Ref<Material> process_material; - Ref<Material> material; + DrawOrder draw_order; - Timer* timer; - void setup_timer(); + Vector<Ref<Mesh> > draw_passes; protected: - static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; public: - - - AABB get_aabb() const; + Rect3 get_aabb() const; PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; + void set_emitting(bool p_emitting); void set_amount(int p_amount); - int get_amount() const; + void set_lifetime(float p_lifetime); + void set_pre_process_time(float p_time); + void set_explosiveness_ratio(float p_ratio); + void set_randomness_ratio(float p_ratio); + void set_custom_aabb(const Rect3 &p_aabb); + void set_gravity(const Vector3 &p_gravity); + void set_use_local_coordinates(bool p_enable); + void set_process_material(const Ref<Material> &p_material); - void set_emitting(bool p_emitting); bool is_emitting() const; + int get_amount() const; + float get_lifetime() const; + float get_pre_process_time() const; + float get_explosiveness_ratio() const; + float get_randomness_ratio() const; + Rect3 get_custom_aabb() const; + Vector3 get_gravity() const; + bool get_use_local_coordinates() const; + Ref<Material> get_process_material() const; - void set_visibility_aabb(const AABB& p_aabb); - AABB get_visibility_aabb() const; + void set_fixed_fps(int p_count); + int get_fixed_fps() const; - void set_emission_half_extents(const Vector3& p_half_extents); - Vector3 get_emission_half_extents() const; + void set_fractional_delta(bool p_enable); + bool get_fractional_delta() const; - void set_emission_base_velocity(const Vector3& p_base_velocity); - Vector3 get_emission_base_velocity() const; + void set_draw_order(DrawOrder p_order); + DrawOrder get_draw_order() const; - void set_emission_points(const PoolVector<Vector3>& p_points); - PoolVector<Vector3> get_emission_points() const; + void set_draw_passes(int p_count); + int get_draw_passes() const; - void set_gravity_normal(const Vector3& p_normal); - Vector3 get_gravity_normal() const; + void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh); + Ref<Mesh> get_draw_pass_mesh(int p_pass) const; - void set_variable(Variable p_variable,float p_value); - float get_variable(Variable p_variable) const; + Particles(); + ~Particles(); +}; - void set_randomness(Variable p_variable,float p_randomness); - float get_randomness(Variable p_variable) const; +VARIANT_ENUM_CAST(Particles::DrawOrder) - void set_color_phases(int p_phases); - int get_color_phases() const; +class ParticlesMaterial : public Material { - void set_color_phase_pos(int p_phase, float p_pos); - float get_color_phase_pos(int p_phase) const; + GDCLASS(ParticlesMaterial, Material) - void set_color_phase_color(int p_phase, const Color& p_color); - Color get_color_phase_color(int p_phase) const; +public: + enum Parameter { + + PARAM_INITIAL_LINEAR_VELOCITY, + PARAM_ANGULAR_VELOCITY, + PARAM_ORBIT_VELOCITY, + PARAM_LINEAR_ACCEL, + PARAM_RADIAL_ACCEL, + PARAM_TANGENTIAL_ACCEL, + PARAM_DAMPING, + PARAM_ANGLE, + PARAM_SCALE, + PARAM_HUE_VARIATION, + PARAM_ANIM_SPEED, + PARAM_ANIM_OFFSET, + PARAM_MAX + }; - void set_height_from_velocity(bool p_enable); - bool has_height_from_velocity() const; + enum Flags { + FLAG_ALIGN_Y_TO_VELOCITY, + FLAG_ROTATE_Y, + FLAG_MAX + }; - void set_material(const Ref<Material>& p_material); - Ref<Material> get_material() const; + enum EmissionShape { + EMISSION_SHAPE_POINT, + EMISSION_SHAPE_SPHERE, + EMISSION_SHAPE_BOX, + EMISSION_SHAPE_POINTS, + EMISSION_SHAPE_DIRECTED_POINTS, + }; - void set_emit_timeout(float p_timeout); - float get_emit_timeout() const; +private: + union MaterialKey { + + struct { + uint32_t texture_mask : 16; + uint32_t texture_color : 1; + uint32_t flags : 2; + uint32_t emission_shape : 2; + uint32_t trail_size_texture : 1; + uint32_t trail_color_texture : 1; + uint32_t invalid_key : 1; + }; + + uint32_t key; + + bool operator<(const MaterialKey &p_key) const { + return key < p_key.key; + } + }; - void set_use_local_coordinates(bool p_use); - bool is_using_local_coordinates() const; + struct ShaderData { + RID shader; + int users; + }; - void start_emitting(float p_time); + static Map<MaterialKey, ShaderData> shader_map; + + MaterialKey current_key; + + _FORCE_INLINE_ MaterialKey _compute_key() const { + + MaterialKey mk; + mk.key = 0; + for (int i = 0; i < PARAM_MAX; i++) { + if (tex_parameters[i].is_valid()) { + mk.texture_mask |= (1 << i); + } + } + for (int i = 0; i < FLAG_MAX; i++) { + if (flags[i]) { + mk.flags |= (1 << i); + } + } + + mk.texture_color = color_ramp.is_valid() ? 1 : 0; + mk.emission_shape = emission_shape; + mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; + mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; + + return mk; + } + + static Mutex *material_mutex; + static SelfList<ParticlesMaterial>::List dirty_materials; + + struct ShaderNames { + StringName spread; + StringName flatness; + StringName initial_linear_velocity; + StringName initial_angle; + StringName angular_velocity; + StringName orbit_velocity; + StringName linear_accel; + StringName radial_accel; + StringName tangent_accel; + StringName damping; + StringName scale; + StringName hue_variation; + StringName anim_speed; + StringName anim_offset; + + StringName initial_linear_velocity_random; + StringName initial_angle_random; + StringName angular_velocity_random; + StringName orbit_velocity_random; + StringName linear_accel_random; + StringName radial_accel_random; + StringName tangent_accel_random; + StringName damping_random; + StringName scale_random; + StringName hue_variation_random; + StringName anim_speed_random; + StringName anim_offset_random; + + StringName angle_texture; + StringName angular_velocity_texture; + StringName orbit_velocity_texture; + StringName linear_accel_texture; + StringName radial_accel_texture; + StringName tangent_accel_texture; + StringName damping_texture; + StringName scale_texture; + StringName hue_variation_texture; + StringName anim_speed_texture; + StringName anim_offset_texture; + + StringName color; + StringName color_ramp; + + StringName emission_sphere_radius; + StringName emission_box_extents; + StringName emission_texture_point_count; + StringName emission_texture_points; + StringName emission_texture_normal; + + StringName trail_divisor; + StringName trail_size_modifier; + StringName trail_color_modifier; + }; + static ShaderNames *shader_names; - Particles(); - ~Particles(); + SelfList<ParticlesMaterial> element; + void _update_shader(); + _FORCE_INLINE_ void _queue_shader_change(); + _FORCE_INLINE_ bool _is_shader_dirty() const; + + float spread; + float flatness; + + float parameters[PARAM_MAX]; + float randomness[PARAM_MAX]; + + Ref<Texture> tex_parameters[PARAM_MAX]; + Color color; + Ref<Texture> color_ramp; + + bool flags[FLAG_MAX]; + + EmissionShape emission_shape; + float emission_sphere_radius; + Vector3 emission_box_extents; + Ref<Texture> emission_point_texture; + Ref<Texture> emission_normal_texture; + int emission_point_count; + + int trail_divisor; + + Ref<CurveTexture> trail_size_modifier; + Ref<GradientTexture> trail_color_modifier; + + //do not save emission points here + +protected: + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const; + +public: + void set_spread(float p_spread); + float get_spread() const; + + void set_flatness(float p_flatness); + float get_flatness() const; + + void set_param(Parameter p_param, float p_value); + float get_param(Parameter p_param) const; + + void set_param_randomness(Parameter p_param, float p_value); + float get_param_randomness(Parameter p_param) const; + + void set_param_texture(Parameter p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_param_texture(Parameter p_param) const; + + void set_color(const Color &p_color); + Color get_color() const; + + void set_color_ramp(const Ref<Texture> &p_texture); + Ref<Texture> get_color_ramp() const; + + void set_flag(Flags p_flag, bool p_enable); + bool get_flag(Flags p_flag) const; + + void set_emission_shape(EmissionShape p_shape); + void set_emission_sphere_radius(float p_radius); + void set_emission_box_extents(Vector3 p_extents); + void set_emission_point_texture(const Ref<Texture> &p_points); + void set_emission_normal_texture(const Ref<Texture> &p_normals); + void set_emission_point_count(int p_count); + + EmissionShape get_emission_shape() const; + float get_emission_sphere_radius() const; + Vector3 get_emission_box_extents() const; + Ref<Texture> get_emission_point_texture() const; + Ref<Texture> get_emission_normal_texture() const; + int get_emission_point_count() const; + + void set_trail_divisor(int p_divisor); + int get_trail_divisor() const; + + void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); + Ref<CurveTexture> get_trail_size_modifier() const; + + void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); + Ref<GradientTexture> get_trail_color_modifier() const; + + static void init_shaders(); + static void finish_shaders(); + static void flush_changes(); + + ParticlesMaterial(); + ~ParticlesMaterial(); }; -VARIANT_ENUM_CAST( Particles::Variable ); -#endif +VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) +VARIANT_ENUM_CAST(ParticlesMaterial::Flags) +VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) + #endif diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 1125a7a4d2..1d399a426f 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -220,9 +220,10 @@ void Spatial::set_transform(const Transform &p_transform) { data.local_transform = p_transform; data.dirty |= DIRTY_VECTORS; - _change_notify("transform/translation"); - _change_notify("transform/rotation"); - _change_notify("transform/scale"); + _change_notify("translation"); + _change_notify("rotation"); + _change_notify("rotation_deg"); + _change_notify("scale"); _propagate_transform_changed(this); if (data.notify_local_transform) { notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); @@ -510,22 +511,11 @@ Ref<World> Spatial::get_world() const { return data.viewport->find_world(); } -#ifdef TOOLS_ENABLED -void Spatial::set_import_transform(const Transform &p_transform) { - data.import_transform = p_transform; -} - -Transform Spatial::get_import_transform() const { - - return data.import_transform; -} -#endif - void Spatial::_propagate_visibility_changed() { notification(NOTIFICATION_VISIBILITY_CHANGED); emit_signal(SceneStringNames::get_singleton()->visibility_changed); - _change_notify("visibility/visible"); + _change_notify("visible"); #ifdef TOOLS_ENABLED if (data.gizmo.is_valid()) _update_gizmo(); @@ -728,9 +718,6 @@ void Spatial::_bind_methods() { #ifdef TOOLS_ENABLED ClassDB::bind_method(D_METHOD("_update_gizmo"), &Spatial::_update_gizmo); - ClassDB::bind_method(D_METHOD("_set_import_transform"), &Spatial::set_import_transform); - ClassDB::bind_method(D_METHOD("_get_import_transform"), &Spatial::get_import_transform); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "_import_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_import_transform", "_get_import_transform"); #endif ClassDB::bind_method(D_METHOD("update_gizmo"), &Spatial::update_gizmo); diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index e5817883dd..a322060216 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -94,7 +94,6 @@ class Spatial : public Node { Ref<SpatialGizmo> gizmo; bool gizmo_disabled; bool gizmo_dirty; - Transform import_transform; #endif } data; @@ -188,11 +187,6 @@ public: void hide(); bool is_visible_in_tree() const; -#ifdef TOOLS_ENABLED - void set_import_transform(const Transform &p_transform); - Transform get_import_transform() const; -#endif - Spatial(); ~Spatial(); }; diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 852881abd4..0207868f66 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -318,9 +318,6 @@ void GeometryInstance::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material_override", "get_material_override"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0"), "set_extra_cull_margin", "get_extra_cull_margin"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_as_billboard"), "set_flag", "get_flag", FLAG_BILLBOARD); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_as_y_billboard"), "set_flag", "get_flag", FLAG_BILLBOARD_FIX_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_depth_scale"), "set_flag", "get_flag", FLAG_DEPH_SCALE); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "visible_in_all_rooms"), "set_flag", "get_flag", FLAG_VISIBLE_IN_ALL_ROOMS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "use_in_baked_light"), "set_flag", "get_flag", FLAG_USE_BAKED_LIGHT); @@ -333,9 +330,6 @@ void GeometryInstance::_bind_methods() { //ADD_SIGNAL( MethodInfo("visibility_changed")); BIND_CONSTANT(FLAG_CAST_SHADOW); - BIND_CONSTANT(FLAG_BILLBOARD); - BIND_CONSTANT(FLAG_BILLBOARD_FIX_Y); - BIND_CONSTANT(FLAG_DEPH_SCALE); BIND_CONSTANT(FLAG_VISIBLE_IN_ALL_ROOMS); BIND_CONSTANT(FLAG_MAX); diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index 9f1cba923f..0c7ff10052 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -84,9 +84,6 @@ class GeometryInstance : public VisualInstance { public: enum Flags { FLAG_CAST_SHADOW = VS::INSTANCE_FLAG_CAST_SHADOW, - FLAG_BILLBOARD = VS::INSTANCE_FLAG_BILLBOARD, - FLAG_BILLBOARD_FIX_Y = VS::INSTANCE_FLAG_BILLBOARD_FIX_Y, - FLAG_DEPH_SCALE = VS::INSTANCE_FLAG_DEPH_SCALE, FLAG_VISIBLE_IN_ALL_ROOMS = VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT, FLAG_MAX = VS::INSTANCE_FLAG_MAX, diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d2f3eea721..c249d3dd64 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1347,12 +1347,12 @@ Control::AnchorType Control::get_anchor(Margin p_margin) const { void Control::_change_notify_margins() { // this avoids sending the whole object data again on a change - _change_notify("margin/left"); - _change_notify("margin/top"); - _change_notify("margin/right"); - _change_notify("margin/bottom"); - _change_notify("rect/pos"); - _change_notify("rect/size"); + _change_notify("margin_left"); + _change_notify("margin_top"); + _change_notify("margin_right"); + _change_notify("margin_bottom"); + _change_notify("rect_pos"); + _change_notify("rect_size"); } void Control::set_margin(Margin p_margin, float p_value) { @@ -2158,7 +2158,7 @@ void Control::set_rotation(float p_radians) { data.rotation = p_radians; update(); _notify_transform(); - _change_notify("rect/rotation"); + _change_notify("rect_rotation"); } float Control::get_rotation() const { diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 35d54d9843..df8bfcf691 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -177,7 +177,18 @@ void WindowDialog::_notification(int p_what) { Size2 size = get_size(); Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog"); - panel->draw(canvas, Rect2(Point2(), size)); + int margin_left = static_cast<int>(panel->get_margin(MARGIN_LEFT)); + int margin_top = static_cast<int>(panel->get_margin(MARGIN_TOP)); + int margin_right = static_cast<int>(panel->get_margin(MARGIN_RIGHT)); + int margin_bottom = static_cast<int>(panel->get_margin(MARGIN_BOTTOM)); + + Rect2 rect; + rect.pos.x = -margin_left; + rect.pos.y = -margin_top; + rect.size.width = size.width + margin_left + margin_right; + rect.size.height = size.height + margin_top + margin_bottom; + + panel->draw(canvas, rect); int title_height = get_constant("title_height", "WindowDialog"); Color title_color = get_color("title_color", "WindowDialog"); diff --git a/scene/gui/patch_9_rect.cpp b/scene/gui/patch_9_rect.cpp index d0bd45e435..e1ac2be7e6 100644 --- a/scene/gui/patch_9_rect.cpp +++ b/scene/gui/patch_9_rect.cpp @@ -37,27 +37,13 @@ void NinePatchRect::_notification(int p_what) { if (texture.is_null()) return; - Size2 s = get_size(); + Rect2 rect = Rect2(Point2(), get_size()); + Rect2 src_rect = region_rect; + + texture->get_rect_region(rect, src_rect, rect, src_rect); + RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_nine_patch(ci, Rect2(Point2(), s), region_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center); - //draw_texture_rect(texture,Rect2(Point2(),s),false,modulate); - - /* - Vector<Point2> points; - points.resize(4); - points[0]=Point2(0,0); - points[1]=Point2(s.x,0); - points[2]=Point2(s.x,s.y); - points[3]=Point2(0,s.y); - Vector<Point2> uvs; - uvs.resize(4); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid()); -*/ + VS::get_singleton()->canvas_item_add_nine_patch(ci, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center); } } @@ -116,16 +102,16 @@ void NinePatchRect::set_patch_margin(Margin p_margin, int p_size) { minimum_size_changed(); switch (p_margin) { case MARGIN_LEFT: - _change_notify("patch_margin/left"); + _change_notify("patch_margin_left"); break; case MARGIN_TOP: - _change_notify("patch_margin/top"); + _change_notify("patch_margin_top"); break; case MARGIN_RIGHT: - _change_notify("patch_margin/right"); + _change_notify("patch_margin_right"); break; case MARGIN_BOTTOM: - _change_notify("patch_margin/bottom"); + _change_notify("patch_margin_bottom"); break; } } diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index f15f3a6078..626d1d9663 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -33,7 +33,7 @@ void Range::_value_changed_notify() { _value_changed(shared->val); emit_signal("value_changed", shared->val); update(); - _change_notify("range/value"); + _change_notify("value"); } void Range::Shared::emit_value_changed() { @@ -87,26 +87,26 @@ void Range::set_min(double p_min) { shared->min = p_min; set_value(shared->val); - shared->emit_changed("range/min"); + shared->emit_changed("min"); } void Range::set_max(double p_max) { shared->max = p_max; set_value(shared->val); - shared->emit_changed("range/max"); + shared->emit_changed("max"); } void Range::set_step(double p_step) { shared->step = p_step; - shared->emit_changed("range/step"); + shared->emit_changed("step"); } void Range::set_page(double p_page) { shared->page = p_page; set_value(shared->val); - shared->emit_changed("range/page"); + shared->emit_changed("page"); } double Range::get_value() const { diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index 5b6f17e0f7..11d068b048 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -185,7 +185,7 @@ void SplitContainer::_resort() { } update(); - _change_notify("split/offset"); + _change_notify("split_offset"); } Size2 SplitContainer::get_minimum_size() const { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3b7ad910d6..7a7ce57ef7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -812,8 +812,8 @@ void TextEdit::_notification(int p_what) { keyword_color = *col; } - if (select_identifiers_enabled && hilighted_word != String()) { - if (hilighted_word == range) { + if (select_identifiers_enabled && highlighted_word != String()) { + if (highlighted_word == range) { underlined = true; } } @@ -1463,9 +1463,9 @@ void TextEdit::_gui_input(const InputEvent &p_gui_input) { int row, col; _get_mouse_pos(Point2i(mb.x, mb.y), row, col); - if (mb.mod.command && hilighted_word != String()) { + if (mb.mod.command && highlighted_word != String()) { - emit_signal("symbol_lookup", hilighted_word, row, col); + emit_signal("symbol_lookup", highlighted_word, row, col); return; } @@ -1608,13 +1608,13 @@ void TextEdit::_gui_input(const InputEvent &p_gui_input) { if (mm.mod.command && mm.button_mask == 0) { String new_word = get_word_at_pos(Vector2(mm.x, mm.y)); - if (new_word != hilighted_word) { - hilighted_word = new_word; + if (new_word != highlighted_word) { + highlighted_word = new_word; update(); } } else { - if (hilighted_word != String()) { - hilighted_word = String(); + if (highlighted_word != String()) { + highlighted_word = String(); update(); } } @@ -1655,11 +1655,11 @@ void TextEdit::_gui_input(const InputEvent &p_gui_input) { if (k.pressed) { - hilighted_word = get_word_at_pos(get_local_mouse_pos()); + highlighted_word = get_word_at_pos(get_local_mouse_pos()); update(); } else { - hilighted_word = String(); + highlighted_word = String(); update(); } } @@ -3174,7 +3174,7 @@ void TextEdit::insert_text_at_cursor(const String &p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { - if (hilighted_word != String()) + if (highlighted_word != String()) return CURSOR_POINTING_HAND; int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index e38d484b0d..4032cf2533 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -252,7 +252,7 @@ class TextEdit : public Control { bool raised_from_completion; - String hilighted_word; + String highlighted_word; uint64_t last_dblclk; diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_main_loop.cpp index 79ee4a6f75..fb40eec463 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_main_loop.cpp @@ -374,6 +374,10 @@ void SceneTree::input_text(const String &p_text) { root_lock--; } +bool SceneTree::is_input_handled() { + return input_handled; +} + void SceneTree::input_event(const InputEvent &p_event) { if (is_editor_hint() && (p_event.type == InputEvent::JOYPAD_MOTION || p_event.type == InputEvent::JOYPAD_BUTTON)) @@ -761,12 +765,12 @@ Ref<Material> SceneTree::get_debug_navigation_material() { if (navigation_material.is_valid()) return navigation_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); /* line_material->set_flag(Material::FLAG_UNSHADED, true); line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_color());*/ + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_color());*/ navigation_material = line_material; @@ -778,12 +782,12 @@ Ref<Material> SceneTree::get_debug_navigation_disabled_material() { if (navigation_disabled_material.is_valid()) return navigation_disabled_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); /* line_material->set_flag(Material::FLAG_UNSHADED, true); line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_disabled_color());*/ + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,get_debug_navigation_disabled_color());*/ navigation_disabled_material = line_material; @@ -794,12 +798,12 @@ Ref<Material> SceneTree::get_debug_collision_material() { if (collision_material.is_valid()) return collision_material; - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); /*line_material->set_flag(Material::FLAG_UNSHADED, true); line_material->set_line_width(3.0); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - line_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, true); - line_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_collisions_color());*/ + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); + line_material->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY, true); + line_material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,get_debug_collisions_color());*/ collision_material = line_material; @@ -813,11 +817,11 @@ Ref<Mesh> SceneTree::get_debug_contact_mesh() { debug_contact_mesh = Ref<Mesh>(memnew(Mesh)); - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); /*mat->set_flag(Material::FLAG_UNSHADED,true); mat->set_flag(Material::FLAG_DOUBLE_SIDED,true); - mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); - mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,get_debug_collision_contact_color());*/ + mat->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); + mat->set_parameter(SpatialMaterial::PARAM_DIFFUSE,get_debug_collision_contact_color());*/ Vector3 diamond[6] = { Vector3(-1, 0, 0), @@ -2153,6 +2157,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause); ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled); + ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled); ClassDB::bind_method(D_METHOD("create_timer:SceneTreeTimer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true)); diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_main_loop.h index fadf77e30f..47220b9b63 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_main_loop.h @@ -350,6 +350,7 @@ public: void quit(); void set_input_as_handled(); + bool is_input_handled(); _FORCE_INLINE_ float get_fixed_process_time() const { return fixed_process_time; } _FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; } diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 2263e82312..aeb72a6d1e 100755 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -50,8 +50,7 @@ void Timer::_notification(int p_what) { if (time_left < 0) { if (!one_shot) - //time_left=wait_time+time_left; - time_left = wait_time; + time_left += wait_time; else stop(); @@ -66,8 +65,7 @@ void Timer::_notification(int p_what) { if (time_left < 0) { if (!one_shot) - //time_left = wait_time + time_left; - time_left = wait_time; + time_left += wait_time; else stop(); emit_signal("timeout"); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 06dae328f4..de00033a3b 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -423,7 +423,7 @@ void register_scene_types() { ClassDB::register_class<GIProbeData>(); ClassDB::register_class<AnimationTreePlayer>(); ClassDB::register_class<Portal>(); - //ClassDB::register_type<Particles>(); + ClassDB::register_class<Particles>(); ClassDB::register_class<Position3D>(); ClassDB::register_class<Quad>(); ClassDB::register_class<NavigationMeshInstance>(); @@ -471,7 +471,8 @@ void register_scene_types() { ClassDB::register_class<MeshLibrary>(); AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel()))); - ClassDB::register_class<CanvasItemMaterial>(); + ClassDB::register_class<Shader>(); + ClassDB::register_class<ShaderMaterial>(); ClassDB::register_virtual_class<CanvasItem>(); ClassDB::register_class<Node2D>(); ClassDB::register_class<Particles2D>(); @@ -519,21 +520,22 @@ void register_scene_types() { /* REGISTER RESOURCES */ ClassDB::register_virtual_class<Shader>(); - //ClassDB::register_virtual_type<ShaderGraph>(); - ClassDB::register_class<CanvasItemShader>(); -//ClassDB::register_type<CanvasItemShaderGraph>(); #ifndef _3D_DISABLED ClassDB::register_class<Mesh>(); + ClassDB::register_class<QuadMesh>(); ClassDB::register_virtual_class<Material>(); - ClassDB::register_class<FixedSpatialMaterial>(); - SceneTree::add_idle_callback(FixedSpatialMaterial::flush_changes); - FixedSpatialMaterial::init_shaders(); + ClassDB::register_class<SpatialMaterial>(); + ClassDB::add_compatibility_class("FixedSpatialMaterial", "SpatialMaterial"); + SceneTree::add_idle_callback(SpatialMaterial::flush_changes); + SpatialMaterial::init_shaders(); + + ClassDB::register_class<ParticlesMaterial>(); + SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); + ParticlesMaterial::init_shaders(); + //ClassDB::register_type<ShaderMaterial>(); ClassDB::register_class<RoomBounds>(); - //ClassDB::register_type<MaterialShaderGraph>(); - ClassDB::register_class<SpatialShader>(); - ClassDB::register_class<ParticlesShader>(); ClassDB::register_class<MultiMesh>(); ClassDB::register_class<MeshLibrary>(); @@ -564,6 +566,8 @@ void register_scene_types() { ClassDB::register_class<ImageTexture>(); ClassDB::register_class<AtlasTexture>(); ClassDB::register_class<LargeTexture>(); + ClassDB::register_class<CurveTexture>(); + ClassDB::register_class<GradientTexture>(); ClassDB::register_class<CubeMap>(); ClassDB::register_class<Animation>(); ClassDB::register_virtual_class<Font>(); @@ -651,6 +655,7 @@ void unregister_scene_types() { memdelete(resource_loader_text); } - FixedSpatialMaterial::finish_shaders(); + SpatialMaterial::finish_shaders(); + ParticlesMaterial::finish_shaders(); SceneStringNames::free(); } diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 60490d70ca..50f535fde9 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -120,7 +120,7 @@ static Ref<Texture> make_icon(T p_src) { } static Ref<Shader> make_shader(const char *vertex_code, const char *fragment_code, const char *lighting_code) { - Ref<Shader> shader = (memnew(Shader(Shader::MODE_CANVAS_ITEM))); + Ref<Shader> shader = (memnew(Shader())); //shader->set_code(vertex_code, fragment_code, lighting_code); return shader; @@ -544,7 +544,7 @@ void fill_default_theme(Ref<Theme> &t, const Ref<Font> &default_font, const Ref< t->set_font("title_font", "WindowDialog", large_font); t->set_color("title_color", "WindowDialog", Color(0, 0, 0)); - t->set_constant("title_height", "WindowDialog", 18 * scale); + t->set_constant("title_height", "WindowDialog", 20 * scale); t->set_icon("close", "WindowDialog", make_icon(close_png)); t->set_icon("close_hilite", "WindowDialog", make_icon(close_hl_png)); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 410f4962fa..407357ea67 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -44,14 +44,132 @@ Material::~Material() { VisualServer::get_singleton()->free(material); } +/////////////////////////////////// + +bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { + + if (p_name == SceneStringNames::get_singleton()->shader_shader) { + set_shader(p_value); + return true; + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/") == 0) { //backwards compatibility + pr = n.substr(6, n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + return true; + } + } + } + + return false; +} + +bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { + + if (p_name == SceneStringNames::get_singleton()->shader_shader) { + + r_ret = get_shader(); + return true; + + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); + return true; + } + } + } + + return false; +} + +void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { + + p_list->push_back(PropertyInfo(Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader,ShaderGraph")); + + if (!shader.is_null()) { + + shader->get_param_list(p_list); + } +} + +void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { + + shader = p_shader; + + RID rid; + if (shader.is_valid()) + rid = shader->get_rid(); + + VS::get_singleton()->material_set_shader(_get_material(), rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref<Shader> ShaderMaterial::get_shader() const { + + return shader; +} + +void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { + + VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); +} + +Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { + + return VS::get_singleton()->material_get_param(_get_material(), p_param); +} + +void ShaderMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shader", "shader:Shader"), &ShaderMaterial::set_shader); + ClassDB::bind_method(D_METHOD("get_shader:Shader"), &ShaderMaterial::get_shader); + ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); + ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); +} + +void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + + String f = p_function.operator String(); + if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { + r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\""); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} + +ShaderMaterial::ShaderMaterial() { +} + +ShaderMaterial::~ShaderMaterial() { +} + ///////////////////////////////// -Mutex *FixedSpatialMaterial::material_mutex = NULL; -SelfList<FixedSpatialMaterial>::List FixedSpatialMaterial::dirty_materials; -Map<FixedSpatialMaterial::MaterialKey, FixedSpatialMaterial::ShaderData> FixedSpatialMaterial::shader_map; -FixedSpatialMaterial::ShaderNames *FixedSpatialMaterial::shader_names = NULL; +Mutex *SpatialMaterial::material_mutex = NULL; +SelfList<SpatialMaterial>::List SpatialMaterial::dirty_materials; +Map<SpatialMaterial::MaterialKey, SpatialMaterial::ShaderData> SpatialMaterial::shader_map; +SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = NULL; -void FixedSpatialMaterial::init_shaders() { +void SpatialMaterial::init_shaders() { #ifndef NO_THREADS material_mutex = Mutex::create(); @@ -81,6 +199,10 @@ void FixedSpatialMaterial::init_shaders() { shader_names->uv2_scale = "uv2_scale"; shader_names->uv2_offset = "uv2_offset"; + shader_names->particle_h_frames = "particle_h_frames"; + shader_names->particle_v_frames = "particle_v_frames"; + shader_names->particles_anim_loop = "particles_anim_loop"; + shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; shader_names->texture_names[TEXTURE_SPECULAR] = "texture_specular"; shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission"; @@ -98,7 +220,7 @@ void FixedSpatialMaterial::init_shaders() { shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; } -void FixedSpatialMaterial::finish_shaders() { +void SpatialMaterial::finish_shaders() { #ifndef NO_THREADS memdelete(material_mutex); @@ -107,7 +229,7 @@ void FixedSpatialMaterial::finish_shaders() { memdelete(shader_names); } -void FixedSpatialMaterial::_update_shader() { +void SpatialMaterial::_update_shader() { dirty_materials.remove(&element); @@ -135,7 +257,7 @@ void FixedSpatialMaterial::_update_shader() { //must create a shader! - String code = "render_mode "; + String code = "shader_type spatial;\nrender_mode "; switch (blend_mode) { case BLEND_MODE_MIX: code += "blend_mix"; break; case BLEND_MODE_ADD: code += "blend_add"; break; @@ -180,6 +302,11 @@ void FixedSpatialMaterial::_update_shader() { code += "uniform vec2 uv1_offset;\n"; code += "uniform vec2 uv2_scale;\n"; code += "uniform vec2 uv2_offset;\n"; + if (billboard_mode == BILLBOARD_PARTICLES) { + code += "uniform int particles_anim_h_frames;\n"; + code += "uniform int particles_anim_v_frames;\n"; + code += "uniform bool particles_anim_loop;\n"; + } if (features[FEATURE_EMISSION]) { @@ -235,6 +362,58 @@ void FixedSpatialMaterial::_update_shader() { code += "\tPOINT_SIZE=point_size;\n"; } code += "\tUV=UV*uv1_scale+uv1_offset;\n"; + + switch (billboard_mode) { + case BILLBOARD_DISABLED: { + + } break; + case BILLBOARD_ENABLED: { + + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)),0.0),WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_PARTICLES: { + + //make billboard + code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; + //rotate by rotation + code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x),0.0,0.0), vec4(sin(INSTANCE_CUSTOM.x),cos(INSTANCE_CUSTOM.x),0.0,0.0),vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));\n"; + //set modelview + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; + + //handle animation + code += "\tint particle_total_frames = particles_anim_h_frames * particles_anim_v_frames;\n"; + code += "\tint particle_frame = int(INSTANCE_CUSTOM.y * float(particle_total_frames));\n"; + code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0,particle_total_frames-1); else particle_frame=abs(particle_frame)%particle_total_frames;\n"; + //code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; + //code += "\tUV+= UV * vec2(float(particle_frame % particles_anim_h_frames),float(particle_frame / particles_anim_v_frames));\n"; + //handle rotation + // code += "\tmat4 rotation = mat4(" + + } break; + } + + if (flags[FLAG_FIXED_SIZE]) { + + code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; + //orthogonal matrix, try to do about the same + //with viewport size + code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n"; + code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t} else {\n"; + //just scale by depth + code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t}\n"; + } + if (detail_uv == DETAIL_UV_2) { code += "\tUV2=UV2*uv2_scale+uv2_offset;\n"; } @@ -336,7 +515,7 @@ void FixedSpatialMaterial::_update_shader() { code += "}\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(VS::SHADER_SPATIAL); + shader_data.shader = VS::get_singleton()->shader_create(); shader_data.users = 1; VS::get_singleton()->shader_set_code(shader_data.shader, code); @@ -346,7 +525,7 @@ void FixedSpatialMaterial::_update_shader() { VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void FixedSpatialMaterial::flush_changes() { +void SpatialMaterial::flush_changes() { if (material_mutex) material_mutex->lock(); @@ -360,7 +539,7 @@ void FixedSpatialMaterial::flush_changes() { material_mutex->unlock(); } -void FixedSpatialMaterial::_queue_shader_change() { +void SpatialMaterial::_queue_shader_change() { if (material_mutex) material_mutex->lock(); @@ -373,7 +552,7 @@ void FixedSpatialMaterial::_queue_shader_change() { material_mutex->unlock(); } -bool FixedSpatialMaterial::_is_shader_dirty() const { +bool SpatialMaterial::_is_shader_dirty() const { bool dirty = false; @@ -387,187 +566,187 @@ bool FixedSpatialMaterial::_is_shader_dirty() const { return dirty; } -void FixedSpatialMaterial::set_albedo(const Color &p_albedo) { +void SpatialMaterial::set_albedo(const Color &p_albedo) { albedo = p_albedo; VS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); } -Color FixedSpatialMaterial::get_albedo() const { +Color SpatialMaterial::get_albedo() const { return albedo; } -void FixedSpatialMaterial::set_specular_mode(SpecularMode p_mode) { +void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { specular_mode = p_mode; _change_notify(); _queue_shader_change(); } -FixedSpatialMaterial::SpecularMode FixedSpatialMaterial::get_specular_mode() const { +SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { return specular_mode; } -void FixedSpatialMaterial::set_specular(const Color &p_specular) { +void SpatialMaterial::set_specular(const Color &p_specular) { specular = p_specular; VS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); } -Color FixedSpatialMaterial::get_specular() const { +Color SpatialMaterial::get_specular() const { return specular; } -void FixedSpatialMaterial::set_roughness(float p_roughness) { +void SpatialMaterial::set_roughness(float p_roughness) { roughness = p_roughness; VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); } -float FixedSpatialMaterial::get_roughness() const { +float SpatialMaterial::get_roughness() const { return roughness; } -void FixedSpatialMaterial::set_metalness(float p_metalness) { +void SpatialMaterial::set_metalness(float p_metalness) { metalness = p_metalness; VS::get_singleton()->material_set_param(_get_material(), shader_names->metalness, p_metalness); } -float FixedSpatialMaterial::get_metalness() const { +float SpatialMaterial::get_metalness() const { return metalness; } -void FixedSpatialMaterial::set_emission(const Color &p_emission) { +void SpatialMaterial::set_emission(const Color &p_emission) { emission = p_emission; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); } -Color FixedSpatialMaterial::get_emission() const { +Color SpatialMaterial::get_emission() const { return emission; } -void FixedSpatialMaterial::set_emission_energy(float p_emission_energy) { +void SpatialMaterial::set_emission_energy(float p_emission_energy) { emission_energy = p_emission_energy; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); } -float FixedSpatialMaterial::get_emission_energy() const { +float SpatialMaterial::get_emission_energy() const { return emission_energy; } -void FixedSpatialMaterial::set_normal_scale(float p_normal_scale) { +void SpatialMaterial::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); } -float FixedSpatialMaterial::get_normal_scale() const { +float SpatialMaterial::get_normal_scale() const { return normal_scale; } -void FixedSpatialMaterial::set_rim(float p_rim) { +void SpatialMaterial::set_rim(float p_rim) { rim = p_rim; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); } -float FixedSpatialMaterial::get_rim() const { +float SpatialMaterial::get_rim() const { return rim; } -void FixedSpatialMaterial::set_rim_tint(float p_rim_tint) { +void SpatialMaterial::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); } -float FixedSpatialMaterial::get_rim_tint() const { +float SpatialMaterial::get_rim_tint() const { return rim_tint; } -void FixedSpatialMaterial::set_clearcoat(float p_clearcoat) { +void SpatialMaterial::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); } -float FixedSpatialMaterial::get_clearcoat() const { +float SpatialMaterial::get_clearcoat() const { return clearcoat; } -void FixedSpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { +void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { clearcoat_gloss = p_clearcoat_gloss; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); } -float FixedSpatialMaterial::get_clearcoat_gloss() const { +float SpatialMaterial::get_clearcoat_gloss() const { return clearcoat_gloss; } -void FixedSpatialMaterial::set_anisotropy(float p_anisotropy) { +void SpatialMaterial::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; VS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); } -float FixedSpatialMaterial::get_anisotropy() const { +float SpatialMaterial::get_anisotropy() const { return anisotropy; } -void FixedSpatialMaterial::set_height_scale(float p_height_scale) { +void SpatialMaterial::set_height_scale(float p_height_scale) { height_scale = p_height_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->height_scale, p_height_scale); } -float FixedSpatialMaterial::get_height_scale() const { +float SpatialMaterial::get_height_scale() const { return height_scale; } -void FixedSpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { +void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { subsurface_scattering_strength = p_subsurface_scattering_strength; VS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } -float FixedSpatialMaterial::get_subsurface_scattering_strength() const { +float SpatialMaterial::get_subsurface_scattering_strength() const { return subsurface_scattering_strength; } -void FixedSpatialMaterial::set_refraction(float p_refraction) { +void SpatialMaterial::set_refraction(float p_refraction) { refraction = p_refraction; VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); } -float FixedSpatialMaterial::get_refraction() const { +float SpatialMaterial::get_refraction() const { return refraction; } -void FixedSpatialMaterial::set_refraction_roughness(float p_refraction_roughness) { +void SpatialMaterial::set_refraction_roughness(float p_refraction_roughness) { refraction_roughness = p_refraction_roughness; VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_roughness, refraction_roughness); } -float FixedSpatialMaterial::get_refraction_roughness() const { +float SpatialMaterial::get_refraction_roughness() const { return refraction_roughness; } -void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { +void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { if (detail_uv == p_detail_uv) return; @@ -575,12 +754,12 @@ void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { detail_uv = p_detail_uv; _queue_shader_change(); } -FixedSpatialMaterial::DetailUV FixedSpatialMaterial::get_detail_uv() const { +SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { return detail_uv; } -void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_blend_mode(BlendMode p_mode) { if (blend_mode == p_mode) return; @@ -588,22 +767,22 @@ void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { return blend_mode; } -void FixedSpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_detail_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { return detail_blend_mode; } -void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { +void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { if (depth_draw_mode == p_mode) return; @@ -611,12 +790,12 @@ void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { depth_draw_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DepthDrawMode FixedSpatialMaterial::get_depth_draw_mode() const { +SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { return depth_draw_mode; } -void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { +void SpatialMaterial::set_cull_mode(CullMode p_mode) { if (cull_mode == p_mode) return; @@ -624,12 +803,12 @@ void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { cull_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::CullMode FixedSpatialMaterial::get_cull_mode() const { +SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { return cull_mode; } -void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { +void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { if (diffuse_mode == p_mode) return; @@ -637,12 +816,12 @@ void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { diffuse_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DiffuseMode FixedSpatialMaterial::get_diffuse_mode() const { +SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { return diffuse_mode; } -void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { +void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); @@ -653,13 +832,13 @@ void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { _queue_shader_change(); } -bool FixedSpatialMaterial::get_flag(Flags p_flag) const { +bool SpatialMaterial::get_flag(Flags p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); return flags[p_flag]; } -void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { +void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { ERR_FAIL_INDEX(p_feature, FEATURE_MAX); if (features[p_feature] == p_enabled) @@ -670,13 +849,13 @@ void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { _queue_shader_change(); } -bool FixedSpatialMaterial::get_feature(Feature p_feature) const { +bool SpatialMaterial::get_feature(Feature p_feature) const { ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); return features[p_feature]; } -void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { +void SpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { ERR_FAIL_INDEX(p_param, TEXTURE_MAX); textures[p_param] = p_texture; @@ -684,19 +863,19 @@ void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> VS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); } -Ref<Texture> FixedSpatialMaterial::get_texture(TextureParam p_param) const { +Ref<Texture> SpatialMaterial::get_texture(TextureParam p_param) const { ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref<Texture>()); return textures[p_param]; } -void FixedSpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { +void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { property.usage = 0; } } -void FixedSpatialMaterial::_validate_property(PropertyInfo &property) const { +void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); _validate_feature("emission", FEATURE_EMISSION, property); _validate_feature("rim", FEATURE_RIM, property); @@ -714,187 +893,253 @@ void FixedSpatialMaterial::_validate_property(PropertyInfo &property) const { if (property.name == "specular/metalness" && specular_mode == SPECULAR_MODE_SPECULAR) { property.usage = 0; } + + if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { + property.usage = 0; + } } -void FixedSpatialMaterial::set_line_width(float p_line_width) { +void SpatialMaterial::set_line_width(float p_line_width) { line_width = p_line_width; VS::get_singleton()->material_set_line_width(_get_material(), line_width); } -float FixedSpatialMaterial::get_line_width() const { +float SpatialMaterial::get_line_width() const { return line_width; } -void FixedSpatialMaterial::set_point_size(float p_point_size) { +void SpatialMaterial::set_point_size(float p_point_size) { point_size = p_point_size; VS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); } -float FixedSpatialMaterial::get_point_size() const { +float SpatialMaterial::get_point_size() const { return point_size; } -void FixedSpatialMaterial::set_uv1_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv1_scale(const Vector2 &p_scale) { uv1_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv1_scale() const { +Vector2 SpatialMaterial::get_uv1_scale() const { return uv1_scale; } -void FixedSpatialMaterial::set_uv1_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv1_offset(const Vector2 &p_offset) { uv1_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv1_offset() const { +Vector2 SpatialMaterial::get_uv1_offset() const { return uv1_offset; } -void FixedSpatialMaterial::set_uv2_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv2_scale(const Vector2 &p_scale) { uv2_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv2_scale() const { +Vector2 SpatialMaterial::get_uv2_scale() const { return uv2_scale; } -void FixedSpatialMaterial::set_uv2_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv2_offset(const Vector2 &p_offset) { uv2_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv2_offset() const { +Vector2 SpatialMaterial::get_uv2_offset() const { return uv2_offset; } -void FixedSpatialMaterial::_bind_methods() { +void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { + + billboard_mode = p_mode; + _queue_shader_change(); + _change_notify(); +} + +SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { + + return billboard_mode; +} + +void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { + + particles_anim_h_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_h_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_h_frames() const { + + return particles_anim_h_frames; +} +void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { + + particles_anim_v_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_v_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_v_frames() const { - ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &FixedSpatialMaterial::set_albedo); - ClassDB::bind_method(D_METHOD("get_albedo"), &FixedSpatialMaterial::get_albedo); + return particles_anim_v_frames; +} - ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &FixedSpatialMaterial::set_specular_mode); - ClassDB::bind_method(D_METHOD("get_specular_mode"), &FixedSpatialMaterial::get_specular_mode); +void SpatialMaterial::set_particles_anim_loop(int p_frames) { - ClassDB::bind_method(D_METHOD("set_specular", "specular"), &FixedSpatialMaterial::set_specular); - ClassDB::bind_method(D_METHOD("get_specular"), &FixedSpatialMaterial::get_specular); + particles_anim_loop = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, p_frames); +} - ClassDB::bind_method(D_METHOD("set_metalness", "metalness"), &FixedSpatialMaterial::set_metalness); - ClassDB::bind_method(D_METHOD("get_metalness"), &FixedSpatialMaterial::get_metalness); +int SpatialMaterial::get_particles_anim_loop() const { - ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &FixedSpatialMaterial::set_roughness); - ClassDB::bind_method(D_METHOD("get_roughness"), &FixedSpatialMaterial::get_roughness); + return particles_anim_loop; +} - ClassDB::bind_method(D_METHOD("set_emission", "emission"), &FixedSpatialMaterial::set_emission); - ClassDB::bind_method(D_METHOD("get_emission"), &FixedSpatialMaterial::get_emission); +void SpatialMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &FixedSpatialMaterial::set_emission_energy); - ClassDB::bind_method(D_METHOD("get_emission_energy"), &FixedSpatialMaterial::get_emission_energy); + ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); + ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); - ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &FixedSpatialMaterial::set_normal_scale); - ClassDB::bind_method(D_METHOD("get_normal_scale"), &FixedSpatialMaterial::get_normal_scale); + ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); + ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); - ClassDB::bind_method(D_METHOD("set_rim", "rim"), &FixedSpatialMaterial::set_rim); - ClassDB::bind_method(D_METHOD("get_rim"), &FixedSpatialMaterial::get_rim); + ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); + ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); - ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &FixedSpatialMaterial::set_rim_tint); - ClassDB::bind_method(D_METHOD("get_rim_tint"), &FixedSpatialMaterial::get_rim_tint); + ClassDB::bind_method(D_METHOD("set_metalness", "metalness"), &SpatialMaterial::set_metalness); + ClassDB::bind_method(D_METHOD("get_metalness"), &SpatialMaterial::get_metalness); - ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &FixedSpatialMaterial::set_clearcoat); - ClassDB::bind_method(D_METHOD("get_clearcoat"), &FixedSpatialMaterial::get_clearcoat); + ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); + ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); - ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &FixedSpatialMaterial::set_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &FixedSpatialMaterial::get_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); + ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); - ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &FixedSpatialMaterial::set_anisotropy); - ClassDB::bind_method(D_METHOD("get_anisotropy"), &FixedSpatialMaterial::get_anisotropy); + ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); - ClassDB::bind_method(D_METHOD("set_height_scale", "height_scale"), &FixedSpatialMaterial::set_height_scale); - ClassDB::bind_method(D_METHOD("get_height_scale"), &FixedSpatialMaterial::get_height_scale); + ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); + ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); - ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &FixedSpatialMaterial::set_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &FixedSpatialMaterial::get_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); + ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); - ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &FixedSpatialMaterial::set_refraction); - ClassDB::bind_method(D_METHOD("get_refraction"), &FixedSpatialMaterial::get_refraction); + ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); + ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); - ClassDB::bind_method(D_METHOD("set_refraction_roughness", "refraction_roughness"), &FixedSpatialMaterial::set_refraction_roughness); - ClassDB::bind_method(D_METHOD("get_refraction_roughness"), &FixedSpatialMaterial::get_refraction_roughness); + ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); + ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); - ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &FixedSpatialMaterial::set_line_width); - ClassDB::bind_method(D_METHOD("get_line_width"), &FixedSpatialMaterial::get_line_width); + ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &FixedSpatialMaterial::set_point_size); - ClassDB::bind_method(D_METHOD("get_point_size"), &FixedSpatialMaterial::get_point_size); + ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); + ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); - ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &FixedSpatialMaterial::set_detail_uv); - ClassDB::bind_method(D_METHOD("get_detail_uv"), &FixedSpatialMaterial::get_detail_uv); + ClassDB::bind_method(D_METHOD("set_height_scale", "height_scale"), &SpatialMaterial::set_height_scale); + ClassDB::bind_method(D_METHOD("get_height_scale"), &SpatialMaterial::get_height_scale); - ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &FixedSpatialMaterial::set_blend_mode); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &FixedSpatialMaterial::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &FixedSpatialMaterial::set_depth_draw_mode); - ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &FixedSpatialMaterial::get_depth_draw_mode); + ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); + ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); - ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &FixedSpatialMaterial::set_cull_mode); - ClassDB::bind_method(D_METHOD("get_cull_mode"), &FixedSpatialMaterial::get_cull_mode); + ClassDB::bind_method(D_METHOD("set_refraction_roughness", "refraction_roughness"), &SpatialMaterial::set_refraction_roughness); + ClassDB::bind_method(D_METHOD("get_refraction_roughness"), &SpatialMaterial::get_refraction_roughness); - ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &FixedSpatialMaterial::set_diffuse_mode); - ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &FixedSpatialMaterial::get_diffuse_mode); + ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); + ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &FixedSpatialMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag"), &FixedSpatialMaterial::get_flag); + ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); + ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); - ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &FixedSpatialMaterial::set_feature); - ClassDB::bind_method(D_METHOD("get_feature", "feature"), &FixedSpatialMaterial::get_feature); + ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); + ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); - ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &FixedSpatialMaterial::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &FixedSpatialMaterial::get_texture); + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); - ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &FixedSpatialMaterial::set_detail_blend_mode); - ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &FixedSpatialMaterial::get_detail_blend_mode); + ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); + ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); - ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &FixedSpatialMaterial::set_uv1_scale); - ClassDB::bind_method(D_METHOD("get_uv1_scale"), &FixedSpatialMaterial::get_uv1_scale); + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); + ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); - ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &FixedSpatialMaterial::set_uv1_offset); - ClassDB::bind_method(D_METHOD("get_uv1_offset"), &FixedSpatialMaterial::get_uv1_offset); + ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); + ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); - ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &FixedSpatialMaterial::set_uv2_scale); - ClassDB::bind_method(D_METHOD("get_uv2_scale"), &FixedSpatialMaterial::get_uv2_scale); + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag"), &SpatialMaterial::get_flag); - ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &FixedSpatialMaterial::set_uv2_offset); - ClassDB::bind_method(D_METHOD("get_uv2_offset"), &FixedSpatialMaterial::get_uv2_offset); + ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); + ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); + + ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &SpatialMaterial::set_texture); + ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &SpatialMaterial::get_texture); + + ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); + ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); + + ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); + ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); + + ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); + ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); + + ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); + ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); + + ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); + ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); + + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); + + ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "frames"), &SpatialMaterial::set_particles_anim_loop); + ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); ADD_GROUP("Flags", "flags_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_on_top"), "set_flag", "get_flag", FLAG_ONTOP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); ADD_GROUP("Parameters", "params_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Labert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Lambert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_GROUP("Particles Anim", "particles_anim_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); ADD_GROUP("Albedo", "albedo_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); @@ -913,7 +1158,7 @@ void FixedSpatialMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_emission_energy", "get_emission_energy"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "emission_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_EMISSION); - ADD_GROUP("NormapMap", "normal_"); + ADD_GROUP("NormalMap", "normal_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "normal_enabled"), "set_feature", "get_feature", FEATURE_NORMAL_MAPPING); ADD_PROPERTY(PropertyInfo(Variant::REAL, "normal_scale", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_normal_scale", "get_normal_scale"); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_NORMAL); @@ -1023,6 +1268,7 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); BIND_CONSTANT(FLAG_SRGB_VERTEX_COLOR) BIND_CONSTANT(FLAG_USE_POINT_SIZE) + BIND_CONSTANT(FLAG_FIXED_SIZE) BIND_CONSTANT(FLAG_MAX); BIND_CONSTANT(DIFFUSE_LAMBERT); @@ -1032,9 +1278,14 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(SPECULAR_MODE_METALLIC); BIND_CONSTANT(SPECULAR_MODE_SPECULAR); + + BIND_CONSTANT(BILLBOARD_DISABLED); + BIND_CONSTANT(BILLBOARD_ENABLED); + BIND_CONSTANT(BILLBOARD_FIXED_Y); + BIND_CONSTANT(BILLBOARD_PARTICLES); } -FixedSpatialMaterial::FixedSpatialMaterial() +SpatialMaterial::SpatialMaterial() : element(this) { //initialize to right values @@ -1061,6 +1312,10 @@ FixedSpatialMaterial::FixedSpatialMaterial() set_uv1_scale(Vector2(1, 1)); set_uv2_offset(Vector2(0, 0)); set_uv2_scale(Vector2(1, 1)); + set_billboard_mode(BILLBOARD_DISABLED); + set_particles_anim_h_frames(1); + set_particles_anim_v_frames(1); + set_particles_anim_loop(false); detail_uv = DETAIL_UV_1; blend_mode = BLEND_MODE_MIX; @@ -1081,7 +1336,7 @@ FixedSpatialMaterial::FixedSpatialMaterial() _queue_shader_change(); } -FixedSpatialMaterial::~FixedSpatialMaterial() { +SpatialMaterial::~SpatialMaterial() { if (material_mutex) material_mutex->lock(); diff --git a/scene/resources/material.h b/scene/resources/material.h index a8288153c3..147e7a46ba 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -56,9 +56,34 @@ public: virtual ~Material(); }; -class FixedSpatialMaterial : public Material { +class ShaderMaterial : public Material { - GDCLASS(FixedSpatialMaterial, Material) + GDCLASS(ShaderMaterial, Material); + Ref<Shader> shader; + +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; + + static void _bind_methods(); + + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + +public: + void set_shader(const Ref<Shader> &p_shader); + Ref<Shader> get_shader() const; + + void set_shader_param(const StringName &p_param, const Variant &p_value); + Variant get_shader_param(const StringName &p_param) const; + + ShaderMaterial(); + ~ShaderMaterial(); +}; + +class SpatialMaterial : public Material { + + GDCLASS(SpatialMaterial, Material) public: enum TextureParam { @@ -128,6 +153,7 @@ public: FLAG_ALBEDO_FROM_VERTEX_COLOR, FLAG_SRGB_VERTEX_COLOR, FLAG_USE_POINT_SIZE, + FLAG_FIXED_SIZE, FLAG_MAX }; @@ -143,20 +169,28 @@ public: SPECULAR_MODE_SPECULAR, }; + enum BillboardMode { + BILLBOARD_DISABLED, + BILLBOARD_ENABLED, + BILLBOARD_FIXED_Y, + BILLBOARD_PARTICLES, + }; + private: union MaterialKey { struct { - uint32_t feature_mask : 14; + uint32_t feature_mask : 11; uint32_t detail_uv : 1; uint32_t blend_mode : 2; uint32_t depth_draw_mode : 2; uint32_t cull_mode : 2; - uint32_t flags : 5; + uint32_t flags : 6; uint32_t detail_blend_mode : 2; uint32_t diffuse_mode : 2; uint32_t invalid_key : 1; uint32_t specular_mode : 1; + uint32_t billboard_mode : 2; }; uint32_t key; @@ -196,6 +230,7 @@ private: mk.detail_blend_mode = detail_blend_mode; mk.diffuse_mode = diffuse_mode; mk.specular_mode = specular_mode; + mk.billboard_mode = billboard_mode; return mk; } @@ -222,14 +257,17 @@ private: StringName uv1_offset; StringName uv2_scale; StringName uv2_offset; + StringName particle_h_frames; + StringName particle_v_frames; + StringName particles_anim_loop; StringName texture_names[TEXTURE_MAX]; }; static Mutex *material_mutex; - static SelfList<FixedSpatialMaterial>::List dirty_materials; + static SelfList<SpatialMaterial>::List dirty_materials; static ShaderNames *shader_names; - SelfList<FixedSpatialMaterial> element; + SelfList<SpatialMaterial> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); @@ -253,6 +291,9 @@ private: float refraction_roughness; float line_width; float point_size; + int particles_anim_h_frames; + int particles_anim_v_frames; + bool particles_anim_loop; Vector2 uv1_scale; Vector2 uv1_offset; @@ -269,6 +310,7 @@ private: bool flags[FLAG_MAX]; DiffuseMode diffuse_mode; SpecularMode specular_mode; + BillboardMode billboard_mode; bool features[FEATURE_MAX]; @@ -377,23 +419,35 @@ public: void set_uv2_offset(const Vector2 &p_offset); Vector2 get_uv2_offset() const; + void set_billboard_mode(BillboardMode p_mode); + BillboardMode get_billboard_mode() const; + + void set_particles_anim_h_frames(int p_frames); + int get_particles_anim_h_frames() const; + void set_particles_anim_v_frames(int p_frames); + int get_particles_anim_v_frames() const; + + void set_particles_anim_loop(int p_frames); + int get_particles_anim_loop() const; + static void init_shaders(); static void finish_shaders(); static void flush_changes(); - FixedSpatialMaterial(); - virtual ~FixedSpatialMaterial(); + SpatialMaterial(); + virtual ~SpatialMaterial(); }; -VARIANT_ENUM_CAST(FixedSpatialMaterial::TextureParam) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DetailUV) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Feature) -VARIANT_ENUM_CAST(FixedSpatialMaterial::BlendMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DepthDrawMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::CullMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Flags) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DiffuseMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) +VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) +VARIANT_ENUM_CAST(SpatialMaterial::Feature) +VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) +VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) +VARIANT_ENUM_CAST(SpatialMaterial::CullMode) +VARIANT_ENUM_CAST(SpatialMaterial::Flags) +VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) +VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) ////////////////////// diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index f951cf1620..8da8f09007 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -192,6 +192,9 @@ bool Mesh::_set(const StringName &p_name, const Variant &p_value) { bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { + if (_is_generated()) + return false; + String sname = p_name; if (p_name == "blend_shape/names") { @@ -268,6 +271,9 @@ bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { void Mesh::_get_property_list(List<PropertyInfo> *p_list) const { + if (_is_generated()) + return; + if (blend_shapes.size()) { p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::INT, "blend_shape/mode", PROPERTY_HINT_ENUM, "Normalized,Relative")); @@ -1025,3 +1031,71 @@ Mesh::~Mesh() { VisualServer::get_singleton()->free(mesh); } + +//////////////////////// + +void QuadMesh::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &QuadMesh::set_material); + ClassDB::bind_method(D_METHOD("get_material:Material"), &QuadMesh::get_material); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material", "get_material"); +} + +void QuadMesh::set_material(const Ref<Material> &p_material) { + + surface_set_material(0, p_material); +} + +Ref<Material> QuadMesh::get_material() const { + + return surface_get_material(0); +} + +QuadMesh::QuadMesh() { + + PoolVector<Vector3> faces; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + + faces.resize(4); + normals.resize(4); + tangents.resize(4 * 4); + uvs.resize(4); + + for (int i = 0; i < 4; i++) { + + static const Vector3 quad_faces[4] = { + Vector3(-1, -1, 0), + Vector3(-1, 1, 0), + Vector3(1, 1, 0), + Vector3(1, -1, 0), + }; + + faces.set(i, quad_faces[i]); + normals.set(i, Vector3(0, 0, 1)); + tangents.set(i * 4 + 0, 1.0); + tangents.set(i * 4 + 1, 0.0); + tangents.set(i * 4 + 2, 0.0); + tangents.set(i * 4 + 3, 1.0); + + static const Vector2 quad_uv[4] = { + Vector2(0, 1), + Vector2(0, 0), + Vector2(1, 0), + Vector2(1, 1), + }; + + uvs.set(i, quad_uv[i]); + } + + Array arr; + arr.resize(ARRAY_MAX); + arr[ARRAY_VERTEX] = faces; + arr[ARRAY_NORMAL] = normals; + arr[ARRAY_TANGENT] = tangents; + arr[ARRAY_TEX_UV] = uvs; + + add_surface_from_arrays(PRIMITIVE_TRIANGLE_FAN, arr); +} diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 8b1936ed06..77907ddbcd 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -128,6 +128,8 @@ private: void _recompute_aabb(); protected: + virtual bool _is_generated() const { return false; } + 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; @@ -189,6 +191,20 @@ public: ~Mesh(); }; +class QuadMesh : public Mesh { + + GDCLASS(QuadMesh, Mesh) + +protected: + virtual bool _is_generated() const { return true; } + static void _bind_methods(); + +public: + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; + QuadMesh(); +}; + VARIANT_ENUM_CAST(Mesh::ArrayType); VARIANT_ENUM_CAST(Mesh::PrimitiveType); VARIANT_ENUM_CAST(Mesh::BlendShapeMode); diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index fd058a4a6f..a0a8a9eca2 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -29,6 +29,7 @@ #include "shader.h" #include "os/file_access.h" #include "scene/scene_string_names.h" +#include "servers/visual/shader_language.h" #include "servers/visual_server.h" #include "texture.h" @@ -39,6 +40,18 @@ Shader::Mode Shader::get_mode() const { void Shader::set_code(const String &p_code) { + String type = ShaderLanguage::get_shader_type(p_code); + + print_line("mode: " + type); + + if (type == "canvas_item") { + mode = MODE_CANVAS_ITEM; + } else if (type == "particles") { + mode = MODE_PARTICLES; + } else { + mode = MODE_SPATIAL; + } + VisualServer::get_singleton()->shader_set_code(shader, p_code); params_cache_dirty = true; emit_signal(SceneStringNames::get_singleton()->changed); @@ -128,10 +141,10 @@ void Shader::_bind_methods() { BIND_CONSTANT(MODE_PARTICLES); } -Shader::Shader(Mode p_mode) { +Shader::Shader() { - mode = p_mode; - shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); + mode = MODE_SPATIAL; + shader = VisualServer::get_singleton()->shader_create(); params_cache_dirty = true; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index bc98fbf737..984ea84fb4 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -88,37 +88,10 @@ public: virtual RID get_rid() const; - Shader(Mode p_mode); + Shader(); ~Shader(); }; VARIANT_ENUM_CAST(Shader::Mode); -class SpatialShader : public Shader { - - GDCLASS(SpatialShader, Shader); - -public: - SpatialShader() - : Shader(MODE_SPATIAL){}; -}; - -class CanvasItemShader : public Shader { - - GDCLASS(CanvasItemShader, Shader); - -public: - CanvasItemShader() - : Shader(MODE_CANVAS_ITEM){}; -}; - -class ParticlesShader : public Shader { - - GDCLASS(ParticlesShader, Shader); - -public: - ParticlesShader() - : Shader(MODE_PARTICLES){}; -}; - #endif // SHADER_H diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 7a503207bc..a3bb52d0f1 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -103,9 +103,11 @@ void StyleBoxTexture::set_texture(RES p_texture) { if (texture == p_texture) return; texture = p_texture; + region_rect = Rect2(Point2(), texture->get_size()); emit_signal("texture_changed"); emit_changed(); } + RES StyleBoxTexture::get_texture() const { return texture; @@ -130,12 +132,12 @@ void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { if (texture.is_null()) return; - Rect2 r = p_rect; - r.pos.x -= expand_margin[MARGIN_LEFT]; - r.pos.y -= expand_margin[MARGIN_TOP]; - r.size.x += expand_margin[MARGIN_LEFT] + expand_margin[MARGIN_RIGHT]; - r.size.y += expand_margin[MARGIN_TOP] + expand_margin[MARGIN_BOTTOM]; - VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, r, region_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center, modulate); + Rect2 rect = p_rect; + Rect2 src_rect = region_rect; + + texture->get_rect_region(rect, src_rect, rect, src_rect); + + VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, draw_center, modulate); } void StyleBoxTexture::set_draw_center(bool p_draw) { diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d08fc2634e..d4732281be 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1367,3 +1367,471 @@ CubeMap::~CubeMap() { BIND_CONSTANT( CUBEMAP_FRONT ); BIND_CONSTANT( CUBEMAP_BACK ); */ +/////////////////////////// + +void CurveTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_max", "max"), &CurveTexture::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &CurveTexture::get_max); + + ClassDB::bind_method(D_METHOD("set_min", "min"), &CurveTexture::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &CurveTexture::get_min); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); + + ClassDB::bind_method(D_METHOD("set_points", "points"), &CurveTexture::set_points); + ClassDB::bind_method(D_METHOD("get_points"), &CurveTexture::get_points); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min", PROPERTY_HINT_RANGE, "-1024,1024"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max", PROPERTY_HINT_RANGE, "-1024,1024"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); +} +void CurveTexture::set_max(float p_max) { + + max = p_max; + emit_changed(); +} +float CurveTexture::get_max() const { + + return max; +} + +void CurveTexture::set_min(float p_min) { + + min = p_min; + emit_changed(); +} +float CurveTexture::get_min() const { + + return min; +} +void CurveTexture::set_width(int p_width) { + + ERR_FAIL_COND(p_width < 32 || p_width > 4096); + width = p_width; + if (points.size()) + set_points(points); +} +int CurveTexture::get_width() const { + + return width; +} + +static void _plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d, float *p_heights, bool *p_useds, int p_width, float p_min, float p_max) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx; + int newx; + float lasty; + float newy; + int ntimes; + int i, j; + + int xmax = p_width; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } + + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1]); + geometry[1][1] = (p_b[1]); + geometry[2][1] = (p_c[1]); + geometry[3][1] = (p_d[1]); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; + tmp2[0][1] = 0; + tmp2[0][2] = 0; + tmp2[0][3] = 1; + tmp2[1][0] = d3; + tmp2[1][1] = d2; + tmp2[1][2] = d; + tmp2[1][3] = 0; + tmp2[2][0] = 6 * d3; + tmp2[2][1] = 2 * d2; + tmp2[2][2] = 0; + tmp2[2][3] = 0; + tmp2[3][0] = 6 * d3; + tmp2[3][1] = 0; + tmp2[3][2] = 0; + tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + lastx = CLAMP(x, 0, xmax); + lasty = y; + + p_heights[lastx] = lasty; + p_useds[lastx] = true; + + /* loop over the curve */ + for (i = 0; i < ntimes; i++) { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP((Math::round(x)), 0, xmax); + newy = CLAMP(y, p_min, p_max); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) { + p_useds[newx] = true; + p_heights[newx] = newy; + } + + lastx = newx; + lasty = newy; + } +} + +void CurveTexture::set_points(const PoolVector<Vector2> &p_points) { + + points = p_points; + + PoolVector<uint8_t> data; + PoolVector<bool> used; + data.resize(width * sizeof(float)); + used.resize(width); + { + PoolVector<uint8_t>::Write wd8 = data.write(); + float *wd = (float *)wd8.ptr(); + PoolVector<bool>::Write wu = used.write(); + int pc = p_points.size(); + PoolVector<Vector2>::Read pr = p_points.read(); + + for (int i = 0; i < width; i++) { + wd[i] = 0.0; + wu[i] = false; + } + + Vector2 prev = Vector2(0, 0); + Vector2 prev2 = Vector2(0, 0); + + for (int i = -1; i < pc; i++) { + + Vector2 next; + Vector2 next2; + if (i + 1 >= pc) { + next = Vector2(1, 0); + } else { + next = Vector2(pr[i + 1].x, pr[i + 1].y); + } + + if (i + 2 >= pc) { + next2 = Vector2(1, 0); + } else { + next2 = Vector2(pr[i + 2].x, pr[i + 2].y); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2, prev, next, next2, wd, wu.ptr(), width, min, max); + + prev2 = prev; + prev = next; + } + } + + Image image(width, 1, false, Image::FORMAT_RF, data); + + VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(texture, image); + + emit_changed(); +} + +PoolVector<Vector2> CurveTexture::get_points() const { + + return points; +} + +RID CurveTexture::get_rid() const { + + return texture; +} + +CurveTexture::CurveTexture() { + + max = 1; + min = 0; + width = 2048; + texture = VS::get_singleton()->texture_create(); +} +CurveTexture::~CurveTexture() { + VS::get_singleton()->free(texture); +} +////////////////// + +//setter and getter names for property serialization +#define COLOR_RAMP_GET_OFFSETS "get_offsets" +#define COLOR_RAMP_GET_COLORS "get_colors" +#define COLOR_RAMP_SET_OFFSETS "set_offsets" +#define COLOR_RAMP_SET_COLORS "set_colors" + +GradientTexture::GradientTexture() { + //Set initial color ramp transition from black to white + points.resize(2); + points[0].color = Color(0, 0, 0, 1); + points[0].offset = 0; + points[1].color = Color(1, 1, 1, 1); + points[1].offset = 1; + is_sorted = true; + update_pending = false; + width = 2048; + + texture = VS::get_singleton()->texture_create(); + _queue_update(); +} + +GradientTexture::~GradientTexture() { + VS::get_singleton()->free(texture); +} + +void GradientTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &GradientTexture::add_point); + ClassDB::bind_method(D_METHOD("remove_point", "offset", "color"), &GradientTexture::remove_point); + + ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &GradientTexture::set_offset); + ClassDB::bind_method(D_METHOD("get_offset", "point"), &GradientTexture::get_offset); + + ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &GradientTexture::set_color); + ClassDB::bind_method(D_METHOD("get_color", "point"), &GradientTexture::get_color); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width); + + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &GradientTexture::get_color_at_offset); + + ClassDB::bind_method(D_METHOD("get_point_count"), &GradientTexture::get_points_count); + + ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update); + + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &GradientTexture::set_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &GradientTexture::get_offsets); + + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &GradientTexture::set_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &GradientTexture::get_colors); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "width"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); +} + +void GradientTexture::_queue_update() { + + if (update_pending) + return; + + call_deferred("_update"); +} + +void GradientTexture::_update() { + + update_pending = false; + + PoolVector<uint8_t> data; + data.resize(width * 4); + { + PoolVector<uint8_t>::Write wd8 = data.write(); + for (int i = 0; i < width; i++) { + float ofs = float(i) / (width - 1); + + Color color = get_color_at_offset(ofs); + wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255)); + wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255)); + wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255)); + wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255)); + } + } + + Image image(width, 1, false, Image::FORMAT_RGBA8, data); + + VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RGBA8, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(texture, image); + + emit_changed(); +} + +void GradientTexture::set_width(int p_width) { + + width = p_width; + _queue_update(); +} +int GradientTexture::get_width() const { + + return width; +} + +Vector<float> GradientTexture::get_offsets() const { + Vector<float> offsets; + offsets.resize(points.size()); + for (int i = 0; i < points.size(); i++) { + offsets[i] = points[i].offset; + } + return offsets; +} + +Vector<Color> GradientTexture::get_colors() const { + Vector<Color> colors; + colors.resize(points.size()); + for (int i = 0; i < points.size(); i++) { + colors[i] = points[i].color; + } + return colors; +} + +void GradientTexture::set_offsets(const Vector<float> &p_offsets) { + points.resize(p_offsets.size()); + for (int i = 0; i < points.size(); i++) { + points[i].offset = p_offsets[i]; + } + is_sorted = false; + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_colors(const Vector<Color> &p_colors) { + if (points.size() < p_colors.size()) + is_sorted = false; + points.resize(p_colors.size()); + for (int i = 0; i < points.size(); i++) { + points[i].color = p_colors[i]; + } + emit_changed(); + _queue_update(); +} + +Vector<GradientTexture::Point> &GradientTexture::get_points() { + return points; +} + +void GradientTexture::add_point(float p_offset, const Color &p_color) { + + Point p; + p.offset = p_offset; + p.color = p_color; + is_sorted = false; + points.push_back(p); + + emit_changed(); + _queue_update(); +} + +void GradientTexture::remove_point(int p_index) { + + ERR_FAIL_INDEX(p_index, points.size()); + ERR_FAIL_COND(points.size() <= 2); + points.remove(p_index); + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_points(Vector<GradientTexture::Point> &p_points) { + points = p_points; + is_sorted = false; + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_offset(int pos, const float offset) { + if (points.size() <= pos) + points.resize(pos + 1); + points[pos].offset = offset; + is_sorted = false; + emit_changed(); + _queue_update(); +} + +float GradientTexture::get_offset(int pos) const { + if (points.size() > pos) + return points[pos].offset; + return 0; //TODO: Maybe throw some error instead? +} + +void GradientTexture::set_color(int pos, const Color &color) { + if (points.size() <= pos) { + points.resize(pos + 1); + is_sorted = false; + } + points[pos].color = color; + emit_changed(); + _queue_update(); +} + +Color GradientTexture::get_color(int pos) const { + if (points.size() > pos) + return points[pos].color; + return Color(0, 0, 0, 1); //TODO: Maybe throw some error instead? +} + +int GradientTexture::get_points_count() const { + return points.size(); +} diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 0092fee836..52e5fdd161 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -394,6 +394,44 @@ VARIANT_ENUM_CAST(CubeMap::Flags); VARIANT_ENUM_CAST(CubeMap::Side); VARIANT_ENUM_CAST(CubeMap::Storage); +class CurveTexture : public Texture { + + GDCLASS(CurveTexture, Texture); + RES_BASE_EXTENSION("cvtex"); + +private: + RID texture; + PoolVector<Vector2> points; + float min, max; + int width; + +protected: + static void _bind_methods(); + +public: + void set_max(float p_max); + float get_max() const; + + void set_min(float p_min); + float get_min() const; + + void set_width(int p_width); + int get_width() const; + + void set_points(const PoolVector<Vector2> &p_points); + PoolVector<Vector2> get_points() const; + + virtual RID get_rid() const; + + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return false; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + CurveTexture(); + ~CurveTexture(); +}; /* enum CubeMapSide { @@ -408,4 +446,107 @@ VARIANT_ENUM_CAST(CubeMap::Storage); */ //VARIANT_ENUM_CAST( Texture::CubeMapSide ); +class GradientTexture : public Texture { + GDCLASS(GradientTexture, Texture); + +public: + struct Point { + + float offset; + Color color; + bool operator<(const Point &p_ponit) const { + return offset < p_ponit.offset; + } + }; + +private: + Vector<Point> points; + bool is_sorted; + bool update_pending; + RID texture; + int width; + + void _queue_update(); + void _update(); + +protected: + static void _bind_methods(); + +public: + void add_point(float p_offset, const Color &p_color); + void remove_point(int p_index); + + void set_points(Vector<Point> &points); + Vector<Point> &get_points(); + + void set_offset(int pos, const float offset); + float get_offset(int pos) const; + + void set_color(int pos, const Color &color); + Color get_color(int pos) const; + + void set_offsets(const Vector<float> &offsets); + Vector<float> get_offsets() const; + + void set_colors(const Vector<Color> &colors); + Vector<Color> get_colors() const; + + void set_width(int p_width); + int get_width() const; + + virtual RID get_rid() const { return texture; } + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return true; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { + + if (points.empty()) + return Color(0, 0, 0, 1); + + if (!is_sorted) { + points.sort(); + is_sorted = true; + } + + //binary search + int low = 0; + int high = points.size() - 1; + int middle; + + while (low <= high) { + middle = (low + high) / 2; + Point &point = points[middle]; + if (point.offset > p_offset) { + high = middle - 1; //search low end of array + } else if (point.offset < p_offset) { + low = middle + 1; //search high end of array + } else { + return point.color; + } + } + + //return interpolated value + if (points[middle].offset > p_offset) { + middle--; + } + int first = middle; + int second = middle + 1; + if (second >= points.size()) + return points[points.size() - 1].color; + if (first < 0) + return points[0].color; + Point &pointFirst = points[first]; + Point &pointSecond = points[second]; + return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + } + + int get_points_count() const; + + GradientTexture(); + virtual ~GradientTexture(); +}; + #endif diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 3e128379ae..13fbac3417 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -125,7 +125,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::STRING, pre + "name")); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial")); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset")); @@ -159,16 +159,16 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const { return tile_map[p_id].texture; } -void TileSet::tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material) { +void TileSet::tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].material = p_material; emit_changed(); } -Ref<CanvasItemMaterial> TileSet::tile_get_material(int p_id) const { +Ref<ShaderMaterial> TileSet::tile_get_material(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<CanvasItemMaterial>()); + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<ShaderMaterial>()); return tile_map[p_id].material; } @@ -403,8 +403,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name); ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture:Texture"), &TileSet::tile_set_texture); ClassDB::bind_method(D_METHOD("tile_get_texture:Texture", "id"), &TileSet::tile_get_texture); - ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material:CanvasItemMaterial"), &TileSet::tile_set_material); - ClassDB::bind_method(D_METHOD("tile_get_material:CanvasItemMaterial", "id"), &TileSet::tile_get_material); + ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material:ShaderMaterial"), &TileSet::tile_set_material); + ClassDB::bind_method(D_METHOD("tile_get_material:ShaderMaterial", "id"), &TileSet::tile_get_material); ClassDB::bind_method(D_METHOD("tile_set_texture_offset", "id", "texture_offset"), &TileSet::tile_set_texture_offset); ClassDB::bind_method(D_METHOD("tile_get_texture_offset", "id"), &TileSet::tile_get_texture_offset); ClassDB::bind_method(D_METHOD("tile_set_shape_offset", "id", "shape_offset"), &TileSet::tile_set_shape_offset); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 53f68d00a5..4c8adb760f 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -51,7 +51,7 @@ class TileSet : public Resource { Ref<OccluderPolygon2D> occluder; Vector2 navigation_polygon_offset; Ref<NavigationPolygon> navigation_polygon; - Ref<CanvasItemMaterial> material; + Ref<ShaderMaterial> material; Color modulate; // Default modulate for back-compat @@ -92,8 +92,8 @@ public: void tile_set_shape(int p_id, const Ref<Shape2D> &p_shape); Ref<Shape2D> tile_get_shape(int p_id) const; - void tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material); - Ref<CanvasItemMaterial> tile_get_material(int p_id) const; + void tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material); + Ref<ShaderMaterial> tile_get_material(int p_id) const; void tile_set_modulate(int p_id, const Color &p_color); Color tile_get_modulate(int p_id) const; diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index f0a33e0d3b..d4a5429c02 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -32,6 +32,9 @@ SceneStringNames *SceneStringNames::singleton = NULL; SceneStringNames::SceneStringNames() { + _estimate_cost = StaticCString::create("_estimate_cost"); + _compute_cost = StaticCString::create("_compute_cost"); + resized = StaticCString::create("resized"); dot = StaticCString::create("."); doubledot = StaticCString::create(".."); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 8900bbe1d9..3ca006daba 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -49,6 +49,9 @@ class SceneStringNames { public: _FORCE_INLINE_ static SceneStringNames *get_singleton() { return singleton; } + StringName _estimate_cost; + StringName _compute_cost; + StringName resized; StringName dot; StringName doubledot; |