diff options
171 files changed, 12401 insertions, 2588 deletions
@@ -35,7 +35,7 @@ Official binaries for the Godot editor and the export templates can be found #### Compiling from source -[See the official docs](http://docs.godotengine.org/en/latest/reference/_compiling.html) +[See the official docs](http://docs.godotengine.org/en/latest/development/compiling/) for compilation instructions for every supported platform. ### Community @@ -52,7 +52,7 @@ on Freenode. The official documentation is hosted on [ReadTheDocs](http://docs.godotengine.org). It is maintained by the Godot community in its own [GitHub repository](https://github.com/godotengine/godot-docs). -The [class reference](http://docs.godotengine.org/en/latest/classes/_classes.html) +The [class reference](http://docs.godotengine.org/en/latest/classes/) is also accessible from within the engine. The official demos are maintained in their own [GitHub repository](https://github.com/godotengine/godot-demo-projects) diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 4cc2edd1c3..47432b1e97 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -149,8 +149,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { unzFile pkg = unzOpen2(packages[file.package].filename.utf8().get_data(), &io); ERR_FAIL_COND_V(!pkg, NULL); int unz_err = unzGoToFilePos(pkg, &file.file_pos); - ERR_FAIL_COND_V(unz_err != UNZ_OK, NULL); - if (unzOpenCurrentFile(pkg) != UNZ_OK) { + if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) { unzClose(pkg); ERR_FAIL_V(NULL); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 9dd9b044a2..974ed64267 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -172,6 +172,7 @@ Error PCKPacker::flush(bool p_verbose) { printf("\n"); file->close(); + memdelete(buf); return OK; }; diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 110185c2d2..c82a40f30d 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -28,6 +28,8 @@ /*************************************************************************/ #include "a_star.h" #include "geometry.h" +#include "scene/scene_string_names.h" +#include "script_language.h" int AStar::get_available_point_id() const { @@ -187,7 +189,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { Point *n = begin_point->neighbours[i]; n->prev_point = begin_point; - n->distance = n->pos.distance_to(begin_point->pos); + n->distance = _compute_cost(n->id, begin_point->id); n->distance *= n->weight_scale; n->last_pass = pass; open_list.add(&n->list); @@ -215,7 +217,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { Point *p = E->self(); real_t cost = p->distance; - cost += p->pos.distance_to(end_point->pos); + cost += _estimate_cost(p->id, end_point->id); cost *= p->weight_scale; if (cost < least_cost) { @@ -233,7 +235,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { Point *e = p->neighbours[i]; - real_t distance = p->pos.distance_to(e->pos) + p->distance; + real_t distance = _compute_cost(p->id, e->id) + p->distance; distance *= e->weight_scale; if (e->last_pass == pass) { @@ -274,6 +276,20 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { return found_route; } +float AStar::_estimate_cost(int p_from_id, int p_to_id) { + if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) + return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id); + + return points[p_from_id]->pos.distance_to(points[p_to_id]->pos); +} + +float AStar::_compute_cost(int p_from_id, int p_to_id) { + if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) + return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id); + + return points[p_from_id]->pos.distance_to(points[p_to_id]->pos); +} + PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { ERR_FAIL_COND_V(!points.has(p_from_id), PoolVector<Vector3>()); @@ -395,6 +411,9 @@ void AStar::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path); ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar::get_id_path); + + BIND_VMETHOD(MethodInfo("_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); + BIND_VMETHOD(MethodInfo("_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); } AStar::AStar() { diff --git a/core/math/a_star.h b/core/math/a_star.h index 2ac855737c..43c9c4457a 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -93,6 +93,9 @@ class AStar : public Reference { protected: static void _bind_methods(); + virtual float _estimate_cost(int p_from_id, int p_to_id); + virtual float _compute_cost(int p_from_id, int p_to_id); + public: int get_available_point_id() const; diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp index 8f942c423f..77cff6a052 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -61,6 +61,10 @@ Vector2 Vector2::normalized() const { return v; } +bool Vector2::is_normalized() const { + return Math::isequal_approx(length(), (real_t)1.0); +} + real_t Vector2::distance_to(const Vector2 &p_vector2) const { return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y)); @@ -274,13 +278,23 @@ Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, c */ } -Vector2 Vector2::slide(const Vector2 &p_vec) const { +// slide returns the component of the vector along the given plane, specified by its normal vector. +Vector2 Vector2::slide(const Vector2 &p_n) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector2()); +#endif + return *this - p_n * this->dot(p_n); +} - return p_vec - *this * this->dot(p_vec); +Vector2 Vector2::bounce(const Vector2 &p_n) const { + return -reflect(p_n); } -Vector2 Vector2::reflect(const Vector2 &p_vec) const { - return p_vec - *this * this->dot(p_vec) * 2.0; +Vector2 Vector2::reflect(const Vector2 &p_n) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector2()); +#endif + return 2.0 * p_n * this->dot(p_n) - *this; } bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { diff --git a/core/math/math_2d.h b/core/math/math_2d.h index af6437d7f1..50ebcb845f 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -82,6 +82,7 @@ struct Vector2 { void normalize(); Vector2 normalized() const; + bool is_normalized() const; real_t length() const; real_t length_squared() const; @@ -106,6 +107,7 @@ struct Vector2 { Vector2 cubic_interpolate_soft(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; Vector2 slide(const Vector2 &p_vec) const; + Vector2 bounce(const Vector2 &p_vec) const; Vector2 reflect(const Vector2 &p_vec) const; Vector2 operator+(const Vector2 &p_v) const; diff --git a/core/math/transform.h b/core/math/transform.h index e307aba129..64b4b23aa0 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -229,27 +229,4 @@ _FORCE_INLINE_ Rect3 Transform::xform_inv(const Rect3 &p_aabb) const { return ret; } -#ifdef OPTIMIZED_TRANSFORM_IMPL_OVERRIDE - -#else - -struct OptimizedTransform { - - Transform transform; - - _FORCE_INLINE_ void invert() { transform.invert(); } - _FORCE_INLINE_ void affine_invert() { transform.affine_invert(); } - _FORCE_INLINE_ Vector3 xform(const Vector3 &p_vec) const { return transform.xform(p_vec); }; - _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_vec) const { return transform.xform_inv(p_vec); }; - _FORCE_INLINE_ OptimizedTransform operator*(const OptimizedTransform &p_ot) const { return OptimizedTransform(transform * p_ot.transform); } - _FORCE_INLINE_ Transform get_transform() const { return transform; } - _FORCE_INLINE_ void set_transform(const Transform &p_transform) { transform = p_transform; } - - OptimizedTransform(const Transform &p_transform) { - transform = p_transform; - } -}; - -#endif - #endif diff --git a/core/math/vector3.h b/core/math/vector3.h index 951380e898..8550ae7009 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -107,6 +107,7 @@ struct Vector3 { _FORCE_INLINE_ real_t angle_to(const Vector3 &p_b) const; _FORCE_INLINE_ Vector3 slide(const Vector3 &p_vec) const; + _FORCE_INLINE_ Vector3 bounce(const Vector3 &p_vec) const; _FORCE_INLINE_ Vector3 reflect(const Vector3 &p_vec) const; /* Operators */ @@ -400,14 +401,23 @@ void Vector3::zero() { x = y = z = 0; } -Vector3 Vector3::slide(const Vector3 &p_vec) const { - - return p_vec - *this * this->dot(p_vec); +// slide returns the component of the vector along the given plane, specified by its normal vector. +Vector3 Vector3::slide(const Vector3 &p_n) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector3()); +#endif + return *this - p_n * this->dot(p_n); } -Vector3 Vector3::reflect(const Vector3 &p_vec) const { +Vector3 Vector3::bounce(const Vector3 &p_n) const { + return -reflect(p_n); +} - return p_vec - *this * this->dot(p_vec) * 2.0; +Vector3 Vector3::reflect(const Vector3 &p_n) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V(p_n.is_normalized() == false, Vector3()); +#endif + return 2.0 * p_n * this->dot(p_n) - *this; } #endif diff --git a/core/os/os.h b/core/os/os.h index 46e57e5186..0febfb70cf 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -177,6 +177,10 @@ public: virtual void set_borderless_window(int p_borderless) {} virtual bool get_borderless_window() { return 0; } + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; }; + virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }; + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { return ERR_UNAVAILABLE; }; + virtual void set_keep_screen_on(bool p_enabled); virtual bool is_keep_screen_on() const; virtual void set_low_processor_usage_mode(bool p_enabled); diff --git a/core/script_language.h b/core/script_language.h index 6c37074639..88584e4ef9 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -43,7 +43,7 @@ typedef void (*ScriptEditRequestFunction)(const String &p_path); class ScriptServer { enum { - MAX_LANGUAGES = 4 + MAX_LANGUAGES = 16 }; static ScriptLanguage *_languages[MAX_LANGUAGES]; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 758500a873..9c435ea0e5 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -340,6 +340,7 @@ struct _VariantCall { VCALL_LOCALMEM0R(Vector2, aspect); VCALL_LOCALMEM1R(Vector2, dot); VCALL_LOCALMEM1R(Vector2, slide); + VCALL_LOCALMEM1R(Vector2, bounce); VCALL_LOCALMEM1R(Vector2, reflect); VCALL_LOCALMEM0R(Vector2, angle); //VCALL_LOCALMEM1R(Vector2,cross); @@ -377,6 +378,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(Vector3, distance_squared_to); VCALL_LOCALMEM1R(Vector3, angle_to); VCALL_LOCALMEM1R(Vector3, slide); + VCALL_LOCALMEM1R(Vector3, bounce); VCALL_LOCALMEM1R(Vector3, reflect); VCALL_LOCALMEM0R(Plane, normalized); @@ -1438,8 +1440,9 @@ void register_variant_methods() { ADDFUNC1(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray()); ADDFUNC0(VECTOR2, REAL, Vector2, aspect, varray()); ADDFUNC1(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "vec", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "vec", varray()); + ADDFUNC1(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray()); + ADDFUNC1(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray()); + ADDFUNC1(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray()); //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); ADDFUNC0(VECTOR2, VECTOR2, Vector2, abs, varray()); ADDFUNC1(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray()); @@ -1475,8 +1478,9 @@ void register_variant_methods() { ADDFUNC1(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray()); ADDFUNC1(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray()); ADDFUNC1(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "by", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "by", varray()); + ADDFUNC1(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray()); + ADDFUNC1(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray()); + ADDFUNC1(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray()); ADDFUNC0(PLANE, PLANE, Plane, normalized, varray()); ADDFUNC0(PLANE, VECTOR3, Plane, center, varray()); diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 67e4673ad6..733854a15e 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -755,7 +755,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, Image::Format format = Image::FORMAT_MAX; for (int i = 0; i < Image::FORMAT_MAX; i++) { - if (Image::get_format_name(format) == sformat) { + if (Image::get_format_name(Image::Format(i)) == sformat) { format = Image::Format(i); } } diff --git a/doc/base/classes.xml b/doc/base/classes.xml index f3d73deaf0..5bb85aedc1 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -21836,6 +21836,8 @@ </argument> <argument index="3" name="max_bounces" type="int" default="4"> </argument> + <argument index="4" name="floor_max_angle" type="float" default="0.785398"> + </argument> <description> </description> </method> @@ -21846,6 +21848,7 @@ </argument> <description> Move the body to the given position. This is not a teleport, and the body will stop if there is an obstacle. The returned vector is how much movement was remaining before being stopped. + [code]floor_max_angle[/code] is in radians (default is pi/4), and filters which obstacles should be considered as floors/cellings instead of walls. </description> </method> <method name="revert_motion"> @@ -46992,6 +46995,15 @@ do_property]. Returns the ratio of X to Y. </description> </method> + <method name="bounce"> + <return type="Vector2"> + </return> + <argument index="0" name="n" type="Vector2"> + </argument> + <description> + Bounce returns the vector "bounced off" from the given plane, specified by its normal vector. + </description> + </method> <method name="clamped"> <return type="Vector2"> </return> @@ -47084,10 +47096,10 @@ do_property]. <method name="reflect"> <return type="Vector2"> </return> - <argument index="0" name="vec" type="Vector2"> + <argument index="0" name="n" type="Vector2"> </argument> <description> - Like "slide", but reflects the Vector instead of continuing along the wall. + Reflects the vector along the given plane, specified by its normal vector. </description> </method> <method name="rotated"> @@ -47102,10 +47114,10 @@ do_property]. <method name="slide"> <return type="Vector2"> </return> - <argument index="0" name="vec" type="Vector2"> + <argument index="0" name="n" type="Vector2"> </argument> <description> - Slides the vector by the other vector. + Slide returns the component of the vector along the given plane, specified by its normal vector. </description> </method> <method name="snapped"> @@ -47178,6 +47190,15 @@ do_property]. <description> </description> </method> + <method name="bounce"> + <return type="Vector3"> + </return> + <argument index="0" name="n" type="Vector3"> + </argument> + <description> + Bounce returns the vector "bounced off" from the given plane, specified by its normal vector. + </description> + </method> <method name="ceil"> <return type="Vector3"> </return> @@ -47308,10 +47329,10 @@ do_property]. <method name="reflect"> <return type="Vector3"> </return> - <argument index="0" name="by" type="Vector3"> + <argument index="0" name="n" type="Vector3"> </argument> <description> - Like "slide", but reflects the Vector instead of continuing along the wall. + Reflects the vector along the given plane, specified by its normal vector. </description> </method> <method name="rotated"> @@ -47328,10 +47349,10 @@ do_property]. <method name="slide"> <return type="Vector3"> </return> - <argument index="0" name="by" type="Vector3"> + <argument index="0" name="n" type="Vector3"> </argument> <description> - Slides the vector along a wall. + Slide returns the component of the vector along the given plane, specified by its normal vector. </description> </method> <method name="snapped"> diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py index 78f39fc7ec..1386e91ce1 100755 --- a/doc/tools/doc_status.py +++ b/doc/tools/doc_status.py @@ -206,7 +206,7 @@ class ClassStatus: output['overall'] = (description_progress + items_progress).to_colored_string('{percent}%', '{pad_percent}{s}') if self.name.startswith('Total'): - output['url'] = color('url', 'http://docs.godotengine.org/en/latest/classes/_classes.html') + output['url'] = color('url', 'http://docs.godotengine.org/en/latest/classes/') if flags['s']: output['comment'] = color('part_good', 'ALL OK') else: diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 3f54f887da..fcac0a3e05 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -8699,7 +8699,7 @@ void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item, CanvasIte } } -void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material, Shader *shader) { +void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material, Shader *shader) { if (canvas_shader.bind()) rebind_texpixel_size = true; @@ -8748,7 +8748,7 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *mater uses_texpixel_size = shader->uses_texpixel_size; } -void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItemMaterial *material, Shader *shader) { +void RasterizerGLES2::_canvas_item_setup_shader_uniforms(ShaderMaterial *material, Shader *shader) { //this can be optimized.. int tex_id = 1; @@ -8925,7 +8925,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list, int p_z, cons //begin rect CanvasItem *material_owner = ci->material_owner ? ci->material_owner : ci; - CanvasItemMaterial *material = material_owner->material; + ShaderMaterial *material = material_owner->material; if (material != canvas_last_material || rebind_shader) { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index 9aeb3af61a..f45b51ae57 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -1224,7 +1224,7 @@ class RasterizerGLES2 : public Rasterizer { bool uses_texpixel_size; bool rebind_texpixel_size; Transform canvas_transform; - CanvasItemMaterial *canvas_last_material; + ShaderMaterial *canvas_last_material; bool canvas_texscreen_used; Vector2 normal_flip; _FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2 &p_flip); @@ -1288,8 +1288,8 @@ class RasterizerGLES2 : public Rasterizer { template <bool use_normalmap> _FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item, CanvasItem *current_clip, bool &reclip); - _FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItemMaterial *material, Shader *p_shader); - _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItemMaterial *material, Shader *p_shader); + _FORCE_INLINE_ void _canvas_item_setup_shader_params(ShaderMaterial *material, Shader *p_shader); + _FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(ShaderMaterial *material, Shader *p_shader); public: /* TEXTURE API */ diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 26d13bad89..43fff5a1b1 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -535,49 +535,49 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur //top left DSTRECT(np->rect.pos.x, np->rect.pos.y, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); - SRCRECT(0, 0, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); + SRCRECT(np->source.pos.x, np->source.pos.y, np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //top right - DSTRECT(np->rect.pos.x + np->rect.size.x - np->margin[MARGIN_RIGHT], np->rect.pos.y, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(texture->width - np->margin[MARGIN_RIGHT], 0, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); + DSTRECT(np->rect.pos.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.pos.y, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); + SRCRECT(np->source.pos.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.pos.y, np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //bottom right - DSTRECT(np->rect.pos.x + np->rect.size.x - np->margin[MARGIN_RIGHT], np->rect.pos.y + np->rect.size.y - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); - SRCRECT(texture->width - np->margin[MARGIN_RIGHT], texture->height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); + DSTRECT(np->rect.pos.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.pos.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); + SRCRECT(np->source.pos.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.pos.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //bottom left - DSTRECT(np->rect.pos.x, np->rect.pos.y + np->rect.size.y - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); - SRCRECT(0, texture->height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); + DSTRECT(np->rect.pos.x, np->rect.pos.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); + SRCRECT(np->source.pos.x, np->source.pos.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->margin[MARGIN_LEFT], np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //top DSTRECT(np->rect.pos.x + np->margin[MARGIN_LEFT], np->rect.pos.y, np->rect.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(np->margin[MARGIN_LEFT], 0, texture->width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); + SRCRECT(np->source.pos.x + np->margin[MARGIN_LEFT], np->source.pos.y, np->source.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //bottom - DSTRECT(np->rect.pos.x + np->margin[MARGIN_LEFT], np->rect.pos.y + np->rect.size.y - np->margin[MARGIN_BOTTOM], np->rect.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); - SRCRECT(np->margin[MARGIN_LEFT], texture->height - np->margin[MARGIN_BOTTOM], texture->width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); + DSTRECT(np->rect.pos.x + np->margin[MARGIN_LEFT], np->rect.pos.y + np->rect.size.height - np->margin[MARGIN_BOTTOM], np->rect.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]); + SRCRECT(np->source.pos.x + np->margin[MARGIN_LEFT], np->source.pos.y + np->source.size.height - np->margin[MARGIN_BOTTOM], np->source.size.width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //left DSTRECT(np->rect.pos.x, np->rect.pos.y + np->margin[MARGIN_TOP], np->margin[MARGIN_LEFT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(0, np->margin[MARGIN_TOP], np->margin[MARGIN_LEFT], texture->height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); + SRCRECT(np->source.pos.x, np->source.pos.y + np->margin[MARGIN_TOP], np->margin[MARGIN_LEFT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); //right DSTRECT(np->rect.pos.x + np->rect.size.width - np->margin[MARGIN_RIGHT], np->rect.pos.y + np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(texture->width - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], texture->height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); + SRCRECT(np->source.pos.x + np->source.size.width - np->margin[MARGIN_RIGHT], np->source.pos.y + np->margin[MARGIN_TOP], np->margin[MARGIN_RIGHT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); if (np->draw_center) { //center DSTRECT(np->rect.pos.x + np->margin[MARGIN_LEFT], np->rect.pos.y + np->margin[MARGIN_TOP], np->rect.size.x - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->rect.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); - SRCRECT(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP], texture->width - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], texture->height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); + SRCRECT(np->source.pos.x + np->margin[MARGIN_LEFT], np->source.pos.y + np->margin[MARGIN_TOP], np->source.size.x - np->margin[MARGIN_LEFT] - np->margin[MARGIN_RIGHT], np->source.size.height - np->margin[MARGIN_TOP] - np->margin[MARGIN_BOTTOM]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -687,7 +687,7 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item, Item *cur } #if 0 -void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItemMaterial *material,Shader* shader) { +void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material,Shader* shader) { if (canvas_shader.bind()) rebind_texpixel_size=true; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index d3936801dd..4353d82eec 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1283,6 +1283,35 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { } } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); + + glBindVertexArray(s->instancing_array_id); // use the instancing array ID + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //modify the buffer + + int stride = sizeof(float) * 4 * 6; + + //transform + + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 3); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 4); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 5); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + 0); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, ((uint8_t *)NULL) + sizeof(float) * 4 * 2); + glVertexAttribDivisor(12, 1); + + } break; } } @@ -1451,6 +1480,30 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { restore_tex = false; } } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = static_cast<RasterizerStorageGLES3::Particles *>(e->owner); + RasterizerStorageGLES3::Surface *s = static_cast<RasterizerStorageGLES3::Surface *>(e->geometry); + + if (!particles->use_local_coords) //not using local coordinates? then clear transform.. + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, Transform()); + + int amount = particles->amount; + + if (s->index_array_len > 0) { + + glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); + + storage->info.render_vertices_count += s->index_array_len * amount; + + } else { + + glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); + + storage->info.render_vertices_count += s->array_len * amount; + } + + } break; } } @@ -1556,61 +1609,6 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform } } -void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance, const Transform &p_view_transform, const CameraMatrix &p_projection) { - - if (p_instance->billboard || p_instance->billboard_y || p_instance->depth_scale) { - - Transform xf = p_instance->transform; - if (p_instance->depth_scale) { - - if (p_projection.matrix[3][3]) { - //orthogonal matrix, try to do about the same - //with viewport size - //real_t w = Math::abs( 1.0/(2.0*(p_projection.matrix[0][0])) ); - real_t h = Math::abs(1.0 / (2.0 * p_projection.matrix[1][1])); - float sc = (h * 2.0); //consistent with Y-fov - xf.basis.scale(Vector3(sc, sc, sc)); - } else { - //just scale by depth - real_t sc = Plane(p_view_transform.origin, -p_view_transform.get_basis().get_axis(2)).distance_to(xf.origin); - xf.basis.scale(Vector3(sc, sc, sc)); - } - } - - if (p_instance->billboard && storage->frame.current_rt) { - - Vector3 scale = xf.basis.get_scale(); - - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), -p_view_transform.get_basis().get_axis(1)); - } else { - xf.set_look_at(xf.origin, xf.origin + p_view_transform.get_basis().get_axis(2), p_view_transform.get_basis().get_axis(1)); - } - - xf.basis.scale(scale); - } - - if (p_instance->billboard_y && storage->frame.current_rt) { - - Vector3 scale = xf.basis.get_scale(); - Vector3 look_at = p_view_transform.get_origin(); - look_at.y = 0.0; - Vector3 look_at_norm = look_at.normalized(); - - if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP]) { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, -1.0, 0.0)); - } else { - xf.set_look_at(xf.origin, xf.origin + look_at_norm, Vector3(0.0, 1.0, 0.0)); - } - xf.basis.scale(scale); - } - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, xf); - - } else { - state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, p_instance->transform); - } -} - void RasterizerSceneGLES3::_set_cull(bool p_front, bool p_reverse_cull) { bool front = p_front; @@ -1677,6 +1675,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS, true); //by default unshaded (easier to set) bool first = true; + bool prev_use_instancing = false; storage->info.render_object_count += p_element_count; @@ -1804,10 +1803,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } } + bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES; - - if ((prev_base_type == VS::INSTANCE_MULTIMESH) != (e->instance->base_type == VS::INSTANCE_MULTIMESH)) { - state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, e->instance->base_type == VS::INSTANCE_MULTIMESH); + if (use_instancing != prev_use_instancing) { + state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, use_instancing); rebind = true; } @@ -1820,7 +1819,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ if (skeleton.is_valid()) { RasterizerStorageGLES3::Skeleton *sk = storage->skeleton_owner.getornull(skeleton); glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); - glBindTexture(GL_TEXTURE_2D,sk->texture); + glBindTexture(GL_TEXTURE_2D, sk->texture); } } @@ -1835,8 +1834,6 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ } } - - if (!(e->sort_key & RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) { _setup_light(e, p_view_transform); } @@ -1850,8 +1847,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ _set_cull(e->sort_key & RenderList::SORT_KEY_MIRROR_FLAG, p_reverse_cull); state.scene_shader.set_uniform(SceneShaderGLES3::NORMAL_MULT, e->instance->mirror ? -1.0 : 1.0); - - _setup_transform(e->instance, p_view_transform, p_projection); + state.scene_shader.set_uniform(SceneShaderGLES3::WORLD_TRANSFORM, e->instance->transform); _render_geometry(e); @@ -1861,6 +1857,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_ prev_owner = e->owner; prev_shading = shading; prev_skeleton = skeleton; + prev_use_instancing = use_instancing; first = false; } @@ -1930,7 +1927,7 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo if (has_blend_alpha || (has_base_alpha && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) return; //bye - if (!m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + if (!m->shader->spatial.writes_modelview_or_projection && !m->shader->spatial.uses_vertex && !m->shader->spatial.uses_discard && m->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //shader does not use discard and does not write a vertex position, use generic material if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) m = storage->material_owner.getptr(default_material_twosided); @@ -2730,6 +2727,30 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p case VS::INSTANCE_IMMEDIATE: { } break; + case VS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getptr(inst->base); + ERR_CONTINUE(!particles); + + for (int i = 0; i < particles->draw_passes.size(); i++) { + + RID pmesh = particles->draw_passes[i]; + if (!pmesh.is_valid()) + continue; + RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.get(pmesh); + if (!mesh) + continue; //mesh not assigned + + int ssize = mesh->surfaces.size(); + + for (int j = 0; j < ssize; j++) { + + RasterizerStorageGLES3::Surface *s = mesh->surfaces[j]; + _add_geometry(s, inst, particles, -1, p_shadow); + } + } + + } break; } } } @@ -4419,13 +4440,14 @@ void RasterizerSceneGLES3::initialize() { state.scene_shader.init(); - default_shader = storage->shader_create(VS::SHADER_SPATIAL); + default_shader = storage->shader_create(); + storage->shader_set_code(default_shader, "shader_type spatial;\n"); default_material = storage->material_create(); storage->material_set_shader(default_material, default_shader); - default_shader_twosided = storage->shader_create(VS::SHADER_SPATIAL); + default_shader_twosided = storage->shader_create(); default_material_twosided = storage->material_create(); - storage->shader_set_code(default_shader_twosided, "render_mode cull_disabled;\n"); + storage->shader_set_code(default_shader_twosided, "shader_type spatial; render_mode cull_disabled;\n"); storage->material_set_shader(default_material_twosided, default_shader_twosided); glGenBuffers(1, &state.scene_ubo); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b27bce726f..68da532824 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -691,7 +691,6 @@ public: _FORCE_INLINE_ void _set_cull(bool p_front, bool p_reverse_cull); _FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material *p_material, bool p_alpha_pass); - _FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance, const Transform &p_view_transform, const CameraMatrix &p_projection); _FORCE_INLINE_ void _setup_geometry(RenderList::Element *e); _FORCE_INLINE_ void _render_geometry(RenderList::Element *e); _FORCE_INLINE_ void _setup_light(RenderList::Element *e, const Transform &p_view_transform); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 4fcd09ed58..d6c8b3b35b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1338,12 +1338,12 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in /* SHADER API */ -RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode) { +RID RasterizerStorageGLES3::shader_create() { Shader *shader = memnew(Shader); - shader->mode = p_mode; + shader->mode = VS::SHADER_SPATIAL; + shader->shader = &scene->state.scene_shader; RID rid = shader_owner.make_rid(shader); - shader_set_mode(rid, p_mode); _shader_make_dirty(shader); shader->self = rid; @@ -1358,22 +1358,30 @@ void RasterizerStorageGLES3::_shader_make_dirty(Shader *p_shader) { _shader_dirty_list.add(&p_shader->dirty_list); } -void RasterizerStorageGLES3::shader_set_mode(RID p_shader, VS::ShaderMode p_mode) { +void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) { - ERR_FAIL_INDEX(p_mode, VS::SHADER_MAX); Shader *shader = shader_owner.get(p_shader); ERR_FAIL_COND(!shader); - if (shader->custom_code_id && p_mode == shader->mode) - return; + shader->code = p_code; + + String mode_string = ShaderLanguage::get_shader_type(p_code); + VS::ShaderMode mode; - if (shader->custom_code_id) { + if (mode_string == "canvas_item") + mode = VS::SHADER_CANVAS_ITEM; + else if (mode_string == "particles") + mode = VS::SHADER_PARTICLES; + else + mode = VS::SHADER_SPATIAL; + + if (shader->custom_code_id && mode != shader->mode) { shader->shader->free_custom_shader(shader->custom_code_id); shader->custom_code_id = 0; } - shader->mode = p_mode; + shader->mode = mode; ShaderGLES3 *shaders[VS::SHADER_MAX] = { &scene->state.scene_shader, @@ -1382,25 +1390,12 @@ void RasterizerStorageGLES3::shader_set_mode(RID p_shader, VS::ShaderMode p_mode }; - shader->shader = shaders[p_mode]; - - shader->custom_code_id = shader->shader->create_custom_shader(); - - _shader_make_dirty(shader); -} -VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { - - const Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader, VS::SHADER_MAX); - - return shader->mode; -} -void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String &p_code) { + shader->shader = shaders[mode]; - Shader *shader = shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); + if (shader->custom_code_id == 0) { + shader->custom_code_id = shader->shader->create_custom_shader(); + } - shader->code = p_code; _shader_make_dirty(shader); } String RasterizerStorageGLES3::shader_get_code(RID p_shader) const { @@ -1453,6 +1448,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->spatial.ontop = false; p_shader->spatial.uses_sss = false; p_shader->spatial.uses_vertex = false; + p_shader->spatial.writes_modelview_or_projection = false; shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD); shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX); @@ -1477,6 +1473,9 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_scene.usage_flag_pointers["SSS_STRENGTH"] = &p_shader->spatial.uses_sss; shaders.actions_scene.usage_flag_pointers["DISCARD"] = &p_shader->spatial.uses_discard; + shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; + shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection; + actions = &shaders.actions_scene; actions->uniforms = &p_shader->uniforms; @@ -4861,6 +4860,8 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); + particles->amount = p_amount; + int floats = p_amount * 24; float *data = memnew_arr(float, floats); @@ -4868,17 +4869,25 @@ void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) data[i] = 0; } - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + for (int i = 0; i < 2; i++) { - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[1]); - glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + glBindVertexArray(particles->particle_vaos[i]); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[i]); + glBufferData(GL_ARRAY_BUFFER, floats * sizeof(float), data, GL_DYNAMIC_DRAW); + + for (int i = 0; i < 6; i++) { + glEnableVertexAttribArray(i); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + } + } + + glBindVertexArray(0); particles->prev_ticks = 0; particles->phase = 0; particles->prev_phase = 0; + particles->clear = true; memdelete_arr(data); } @@ -4927,41 +4936,29 @@ void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles particles->use_local_coords = p_enable; } -void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { - - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - particles->process_material = p_material; -} - -void RasterizerStorageGLES3::particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape) { +void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_shape = p_shape; + particles->fixed_fps = p_fps; } -void RasterizerStorageGLES3::particles_set_emission_sphere_radius(RID p_particles, float p_radius) { - Particles *particles = particles_owner.getornull(p_particles); - ERR_FAIL_COND(!particles); - - particles->emission_sphere_radius = p_radius; -} -void RasterizerStorageGLES3::particles_set_emission_box_extents(RID p_particles, const Vector3 &p_extents) { +void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_box_extents = p_extents; + particles->fractional_delta = p_enable; } -void RasterizerStorageGLES3::particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points) { + +void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->emission_points = p_points; + particles->process_material = p_material; } void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) { @@ -4972,26 +4969,30 @@ void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, VS::Parti particles->draw_order = p_order; } -void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_count) { +void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_passes) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->draw_passes.resize(p_count); + particles->draw_passes.resize(p_passes); } -void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles, int p_pass, RID p_material) { + +void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); - particles->draw_passes[p_pass].material = p_material; + particles->draw_passes[p_pass] = p_mesh; } -void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) { + +void RasterizerStorageGLES3::particles_request_process(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_pass, particles->draw_passes.size()); - particles->draw_passes[p_pass].mesh = p_mesh; + + if (!particles->particle_element.in_list()) { + particle_update_list.add(&particles->particle_element); + } } Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { @@ -5002,10 +5003,86 @@ Rect3 RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) { return particles->computed_aabb; } +Rect3 RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const { + + const Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles, Rect3()); + + return Rect3(Vector3(-1, -1, -1), Vector3(2, 2, 2)); +} + +void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform &p_transform) { + + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + + particles->emission_transform = p_transform; +} + +void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_delta) { + + float new_phase = Math::fmod((float)particles->phase + (p_delta / particles->lifetime), (float)1.0); + + if (particles->clear) { + particles->cycle_number = 0; + } else if (new_phase < particles->phase) { + particles->cycle_number++; + } + + shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); + shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase); + particles->phase = new_phase; + + shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear); + if (particles->use_local_coords) + shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform()); + else + shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, particles->emission_transform); + + glUniform1ui(shaders.particles.get_uniform(ParticlesShaderGLES3::CYCLE), particles->cycle_number); + + particles->clear = false; + + glBindVertexArray(particles->particle_vaos[0]); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + + // GLint size = 0; + // glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS, 0, particles->amount); + glEndTransformFeedback(); + + SWAP(particles->particle_buffers[0], particles->particle_buffers[1]); + SWAP(particles->particle_vaos[0], particles->particle_vaos[1]); + + glBindVertexArray(0); + /* //debug particles :D + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); + + float *data = (float *)glMapBufferRange(GL_ARRAY_BUFFER, 0, particles->amount * 16 * 6, GL_MAP_READ_BIT); + for (int i = 0; i < particles->amount; i++) { + int ofs = i * 24; + print_line(itos(i) + ":"); + print_line("\tColor: " + Color(data[ofs + 0], data[ofs + 1], data[ofs + 2], data[ofs + 3])); + print_line("\tVelocity: " + Vector3(data[ofs + 4], data[ofs + 5], data[ofs + 6])); + print_line("\tActive: " + itos(data[ofs + 7])); + print_line("\tCustom: " + Color(data[ofs + 8], data[ofs + 9], data[ofs + 10], data[ofs + 11])); + print_line("\tXF X: " + Color(data[ofs + 12], data[ofs + 13], data[ofs + 14], data[ofs + 15])); + print_line("\tXF Y: " + Color(data[ofs + 16], data[ofs + 17], data[ofs + 18], data[ofs + 19])); + print_line("\tXF Z: " + Color(data[ofs + 20], data[ofs + 21], data[ofs + 22], data[ofs + 23])); + } + + glUnmapBuffer(GL_ARRAY_BUFFER); + glBindBuffer(GL_ARRAY_BUFFER, 0); + //*/ +} + void RasterizerStorageGLES3::update_particles() { glEnable(GL_RASTERIZER_DISCARD); - glBindVertexArray(0); while (particle_update_list.first()) { @@ -5068,38 +5145,61 @@ void RasterizerStorageGLES3::update_particles() { } } - shaders.particles.bind(); - - shaders.particles.set_uniform(ParticlesShaderGLES3::ORIGIN, particles->origin); - - float new_phase = Math::fmod((float)particles->phase + (frame.delta / particles->lifetime), (float)1.0); + shaders.particles.set_conditional(ParticlesShaderGLES3::USE_FRACTIONAL_DELTA, particles->fractional_delta); - shaders.particles.set_uniform(ParticlesShaderGLES3::SYSTEM_PHASE, new_phase); - shaders.particles.set_uniform(ParticlesShaderGLES3::PREV_SYSTEM_PHASE, particles->phase); - particles->phase = new_phase; + shaders.particles.bind(); shaders.particles.set_uniform(ParticlesShaderGLES3::TOTAL_PARTICLES, particles->amount); - shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, 0.0); + shaders.particles.set_uniform(ParticlesShaderGLES3::TIME, Color(frame.time[0], frame.time[1], frame.time[2], frame.time[3])); shaders.particles.set_uniform(ParticlesShaderGLES3::EXPLOSIVENESS, particles->explosiveness); - shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, frame.delta); + shaders.particles.set_uniform(ParticlesShaderGLES3::LIFETIME, particles->lifetime); shaders.particles.set_uniform(ParticlesShaderGLES3::GRAVITY, particles->gravity); shaders.particles.set_uniform(ParticlesShaderGLES3::ATTRACTOR_COUNT, 0); + shaders.particles.set_uniform(ParticlesShaderGLES3::EMITTING, particles->emitting); + shaders.particles.set_uniform(ParticlesShaderGLES3::RANDOMNESS, particles->randomness); - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particles->particle_buffers[1]); + if (particles->clear && particles->pre_process_time > 0.0) { - for (int i = 0; i < 6; i++) { - glEnableVertexAttribArray(i); - glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4 * 6, ((uint8_t *)0) + (i * 16)); + float frame_time; + if (particles->fixed_fps > 0) + frame_time = 1.0 / particles->fixed_fps; + else + frame_time = 1.0 / 30.0; + + float delta = particles->pre_process_time; + if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 + delta = 0.1; + } + float todo = delta; + + while (todo >= frame_time) { + _particles_process(particles, frame_time); + todo -= frame_time; + } } - glBeginTransformFeedback(GL_POINTS); - glDrawArrays(GL_POINTS, 0, particles->amount); - glEndTransformFeedback(); + if (particles->fixed_fps > 0) { + float frame_time = 1.0 / particles->fixed_fps; + float delta = frame.delta; + if (delta > 0.1) { //avoid recursive stalls if fps goes below 10 + delta = 0.1; + } else if (delta <= 0.0) { //unlikely but.. + delta = 0.001; + } + float todo = particles->frame_remainder + delta; - particle_update_list.remove(particle_update_list.first()); + while (todo >= frame_time) { + _particles_process(particles, frame_time); + todo -= frame_time; + } + + particles->frame_remainder = todo; + + } else { + _particles_process(particles, frame.delta); + } - SWAP(particles->particle_buffers[0], particles->particle_buffers[1]); + particle_update_list.remove(particle_update_list.first()); } glDisable(GL_RASTERIZER_DISCARD); @@ -5143,6 +5243,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base, RasterizerScene inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_PARTICLES: { + inst = particles_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -5182,6 +5286,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base, RasterizerSc inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; + case VS::INSTANCE_PARTICLES: { + inst = particles_owner.getornull(p_base); + ERR_FAIL_COND(!inst); + } break; case VS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); @@ -5856,6 +5964,10 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { return VS::INSTANCE_IMMEDIATE; } + if (particles_owner.owns(p_rid)) { + return VS::INSTANCE_PARTICLES; + } + if (light_owner.owns(p_rid)) { return VS::INSTANCE_LIGHT; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 50617b8124..e376c2c0bb 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -408,6 +408,7 @@ public: bool uses_vertex; bool uses_discard; bool uses_sss; + bool writes_modelview_or_projection; } spatial; @@ -433,10 +434,7 @@ public: mutable RID_Owner<Shader> shader_owner; - virtual RID shader_create(VS::ShaderMode p_mode = VS::SHADER_SPATIAL); - - virtual void shader_set_mode(RID p_shader, VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; + virtual RID shader_create(); virtual void shader_set_code(RID p_shader, const String &p_code); virtual String shader_get_code(RID p_shader) const; @@ -778,7 +776,7 @@ public: Skeleton() : update_list(this) { - size=0; + size = 0; use_2d = false; texture = 0; @@ -987,7 +985,7 @@ public: /* PARTICLES */ - struct Particles : public Instantiable { + struct Particles : public GeometryOwner { bool emitting; int amount; @@ -1000,23 +998,14 @@ public: bool use_local_coords; RID process_material; - VS::ParticlesEmissionShape emission_shape; - float emission_sphere_radius; - Vector3 emission_box_extents; - PoolVector<Vector3> emission_points; - GLuint emission_point_texture; - VS::ParticlesDrawOrder draw_order; - struct DrawPass { - RID mesh; - RID material; - }; - Vector<DrawPass> draw_passes; + Vector<RID> draw_passes; Rect3 computed_aabb; GLuint particle_buffers[2]; + GLuint particle_vaos[2]; SelfList<Particles> particle_element; @@ -1024,10 +1013,19 @@ public: float prev_phase; uint64_t prev_ticks; - Transform origin; + uint32_t cycle_number; + + int fixed_fps = 0; + bool fractional_delta; + float frame_remainder; + + bool clear; + + Transform emission_transform; Particles() : particle_element(this) { + cycle_number = 0; emitting = false; amount = 0; lifetime = 1.0; @@ -1035,23 +1033,26 @@ public: explosiveness = 0.0; randomness = 0.0; use_local_coords = true; + fixed_fps = 0; + fractional_delta = false; + frame_remainder = 0; draw_order = VS::PARTICLES_DRAW_ORDER_INDEX; - emission_shape = VS::PARTICLES_EMSSION_POINT; - emission_sphere_radius = 1.0; - emission_box_extents = Vector3(1, 1, 1); - emission_point_texture = 0; particle_buffers[0] = 0; particle_buffers[1] = 0; prev_ticks = 0; + clear = true; + glGenBuffers(2, particle_buffers); + glGenVertexArrays(2, particle_vaos); } ~Particles() { glDeleteBuffers(2, particle_buffers); + glDeleteVertexArrays(2, particle_vaos); } }; @@ -1073,19 +1074,20 @@ public: virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity); virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); virtual void particles_set_process_material(RID p_particles, RID p_material); - - virtual void particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape); - virtual void particles_set_emission_sphere_radius(RID p_particles, float p_radius); - virtual void particles_set_emission_box_extents(RID p_particles, const Vector3 &p_extents); - virtual void particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points); + virtual void particles_set_fixed_fps(RID p_particles, int p_fps); + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable); virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order); virtual void particles_set_draw_passes(RID p_particles, int p_count); - virtual void particles_set_draw_pass_material(RID p_particles, int p_pass, RID p_material); virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh); + virtual void particles_request_process(RID p_particles); virtual Rect3 particles_get_current_aabb(RID p_particles); + virtual Rect3 particles_get_aabb(RID p_particles) const; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform); + void _particles_process(Particles *p_particles, float p_delta); /* INSTANCE */ diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 48ca86ebe2..b9d50caa10 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -91,6 +91,16 @@ static String _prestr(SL::DataPrecision p_pres) { return ""; } +static String _qualstr(SL::ArgumentQualifier p_qual) { + + switch (p_qual) { + case SL::ARGUMENT_QUALIFIER_IN: return ""; + case SL::ARGUMENT_QUALIFIER_OUT: return "out "; + case SL::ARGUMENT_QUALIFIER_INOUT: return "inout "; + } + return ""; +} + static String _opstr(SL::Operator p_op) { return SL::get_operator_text(p_op); @@ -175,6 +185,21 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo return text; } break; + case SL::TYPE_MAT2: + case SL::TYPE_MAT3: + case SL::TYPE_MAT4: { + + String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += f2sp0(p_values[i].real); + } + text += ")"; + return text; + + } break; default: ERR_FAIL_V(String()); } } @@ -194,6 +219,7 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri for (Set<StringName>::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { + print_line(String(p_node->functions[fidx].name) + " uses function: " + String(E->get())); if (added.has(E->get())) { continue; //was added already } @@ -219,7 +245,7 @@ void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode *p_node, const Stri if (i > 0) header += ", "; - header += _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); + header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); } header += ")\n"; @@ -383,6 +409,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener if (fnode->name == "vertex") { + print_line("vertex uses functions: " + itos(pnode->functions[i].uses_function.size())); _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); r_gen_code.vertex = function_code["vertex"]; } @@ -482,6 +509,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener case SL::OP_ASSIGN_BIT_AND: case SL::OP_ASSIGN_BIT_OR: case SL::OP_ASSIGN_BIT_XOR: + if (onode->arguments[0]->type == SL::Node::TYPE_VARIABLE) { + SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; + if (p_actions.write_flag_pointers.has(vnode->name)) { + *p_actions.write_flag_pointers[vnode->name] = true; + } + } code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions); break; case SL::OP_BIT_INVERT: @@ -524,6 +557,23 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } code += ")"; } break; + case SL::OP_INDEX: { + + code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions); + code += "["; + code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions); + code += "]"; + + } break; + case SL::OP_SELECT_IF: { + + code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions); + code += "?"; + code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions); + code += ":"; + code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions); + + } break; default: { code = "(" + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions) + ")"; @@ -546,10 +596,10 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { - if (cfnode->blocks.size()) { - code = "return " + _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions); + if (cfnode->expressions.size()) { + code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions) + ";"; } else { - code = "return"; + code = "return;"; } } @@ -566,7 +616,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { - Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode)); + Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); if (err != OK) { #if 1 @@ -648,7 +698,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; + actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; @@ -686,6 +738,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["DISCARD"] = "_discard"; //actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; + actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; @@ -701,16 +754,17 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; + actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS_MOTION\n"; actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[VS::SHADER_SPATIAL].render_mode_defines["skip_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["skip_default_transform"] = "#define SKIP_TRANSFORM_USED\n"; /* PARTICLES SHADER */ - actions[VS::SHADER_PARTICLES].renames["COLOR"] = "color"; + actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "active"; @@ -719,13 +773,15 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; actions[VS::SHADER_PARTICLES].renames["TIME"] = "time"; actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; - actions[VS::SHADER_PARTICLES].renames["DELTA"] = "delta"; - actions[VS::SHADER_PARTICLES].renames["SEED"] = "seed"; - actions[VS::SHADER_PARTICLES].renames["ORIGIN"] = "origin"; + actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; + actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; + actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; + actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; + actions[VS::SHADER_SPATIAL].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; vertex_name = "vertex"; fragment_name = "fragment"; diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h index 44d6b3a349..17e0eee157 100644 --- a/drivers/gles3/shader_compiler_gles3.h +++ b/drivers/gles3/shader_compiler_gles3.h @@ -41,6 +41,7 @@ public: Map<StringName, Pair<int *, int> > render_mode_values; Map<StringName, bool *> render_mode_flags; Map<StringName, bool *> usage_flag_pointers; + Map<StringName, bool *> write_flag_pointers; Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms; }; diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index e72f12cc5e..347b15d639 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -22,16 +22,21 @@ struct Attractor { #define MAX_ATTRACTORS 64 -uniform mat4 origin; +uniform bool emitting; uniform float system_phase; uniform float prev_system_phase; -uniform float total_particles; +uniform int total_particles; uniform float explosiveness; +uniform float randomness; uniform vec4 time; uniform float delta; uniform vec3 gravity; uniform int attractor_count; uniform Attractor attractors[MAX_ATTRACTORS]; +uniform bool clear; +uniform uint cycle; +uniform float lifetime; +uniform mat4 emission_transform; out highp vec4 out_color; //tfb: @@ -53,52 +58,116 @@ MATERIAL_UNIFORMS #endif +uint hash(uint x) { + + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); + x = (x >> uint(16)) ^ x; + return x; +} + + void main() { bool apply_forces=true; bool apply_velocity=true; + vec3 current_gravity = gravity; + float local_delta=delta; float mass = 1.0; - float restart_phase = float(gl_InstanceID)/total_particles; - restart_phase*= explosiveness; + float restart_phase = float(gl_VertexID)/float(total_particles); + + if (randomness>0.0) { + uint seed = cycle; + if (restart_phase >= system_phase) { + seed-=uint(1); + } + seed*=uint(total_particles); + seed+=uint(gl_VertexID); + float random = float(hash(seed) % uint(65536)) / 65536.0; + restart_phase+=randomness * random * 1.0 / float(total_particles); + } + + restart_phase*= (1.0-explosiveness); bool restart=false; - bool active = out_velocity_active.a > 0.5; + bool active = velocity_active.a > 0.5; if (system_phase > prev_system_phase) { - restart = prev_system_phase < restart_phase && system_phase >= restart_phase; + if (prev_system_phase < restart_phase && system_phase >= restart_phase) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } + } else { - restart = prev_system_phase < restart_phase || system_phase >= restart_phase; + if (prev_system_phase < restart_phase) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (1.0 - restart_phase + system_phase) * lifetime; +#endif + } else if (system_phase >= restart_phase) { + restart=true; +#ifdef USE_FRACTIONAL_DELTA + local_delta = (system_phase - restart_phase) * lifetime; +#endif + } } - if (restart) { - active=true; + uint current_cycle = cycle; + + if (system_phase < restart_phase) { + current_cycle-=uint(1); } - out_color=color; - out_velocity_active=velocity_active; - out_custom=custom; + uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID); - mat4 xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + if (restart) { + active=emitting; + } + mat4 xform; - out_rot_active=rot_active; +#if defined(ENABLE_KEEP_DATA) + if (clear) { +#else + if (clear || restart) { +#endif + out_color=vec4(1.0); + out_velocity_active=vec4(0.0); + out_custom=vec4(0.0); + if (!restart) + active=false; + + xform = mat4( + vec4(1.0,0.0,0.0,0.0), + vec4(0.0,1.0,0.0,0.0), + vec4(0.0,0.0,1.0,0.0), + vec4(0.0,0.0,0.0,1.0) + ); + } else { + out_color=color; + out_velocity_active=velocity_active; + out_custom=custom; + xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + } if (active) { //execute shader { - VERTEX_SHADER_CODE +VERTEX_SHADER_CODE } #if !defined(DISABLE_FORCE) - { + if (true) { - vec3 force = gravity; + vec3 force = current_gravity; for(int i=0;i<attractor_count;i++) { - vec3 rel_vec = out_pos_lifetime.xyz - attractors[i].pos; + vec3 rel_vec = xform[3].xyz - attractors[i].pos; float dist = rel_vec.length(); if (attractors[i].radius < dist) continue; @@ -119,17 +188,19 @@ void main() { } } - out_velocity_seed.xyz += force * delta; + out_velocity_active.xyz += force * local_delta; } #endif #if !defined(DISABLE_VELOCITY) - { + if (true) { - out_pos_lifetime.xyz += out_velocity_seed.xyz * delta; + xform[3].xyz += out_velocity_active.xyz * local_delta; } #endif + } else { + xform=mat4(0.0); } xform = transpose(xform); @@ -162,6 +233,6 @@ MATERIAL_UNIFORMS void main() { { - FRAGMENT_SHADER_CODE +FRAGMENT_SHADER_CODE } } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index ffc41e611b..43a391631f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -52,6 +52,10 @@ layout(location=9) in highp vec4 instance_xform1; layout(location=10) in highp vec4 instance_xform2; layout(location=11) in lowp vec4 instance_color; +#if defined(ENABLE_INSTANCE_CUSTOM) +layout(location=12) in highp vec4 instance_custom_data; +#endif + #endif layout(std140) uniform SceneData { //ubo:0 @@ -157,9 +161,21 @@ out highp vec4 position_interp; void main() { highp vec4 vertex = vertex_attrib; // vec4(vertex_attrib.xyz * data_attrib.x,1.0); - highp mat4 modelview = camera_inverse_matrix * world_transform; + + mat4 world_matrix = world_transform; + + +#ifdef USE_INSTANCING + + { + highp mat4 m=mat4(instance_xform0,instance_xform1,instance_xform2,vec4(0.0,0.0,0.0,1.0)); + world_matrix = world_matrix * transpose(m); + } +#endif + vec3 normal = normal_attrib * normal_mult; + #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) vec3 tangent = tangent_attrib.xyz; tangent*=normal_mult; @@ -168,6 +184,10 @@ void main() { #if defined(ENABLE_COLOR_INTERP) color_interp = color_attrib; +#if defined(USE_INSTANCING) + color_interp *= instance_color; +#endif + #endif #ifdef USE_SKELETON @@ -215,40 +235,12 @@ void main() { } #endif -#ifdef USE_INSTANCING - - { - highp mat3x4 m=mat3x4(instance_xform0,instance_xform1,instance_xform2); - vertex.xyz = vertex * m; - normal = vec4(normal,0.0) * m; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) - tangent.xyz = vec4(tangent.xyz,0.0) * mn; -#endif -#if defined(ENABLE_COLOR_INTERP) - color_interp*=instance_color; -#endif - } -#endif //USE_INSTANCING - -#if !defined(SKIP_TRANSFORM_USED) - - vertex = modelview * vertex; - normal = normalize((modelview * vec4(normal,0.0)).xyz); -#endif - -#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) -# if !defined(SKIP_TRANSFORM_USED) - - tangent=normalize((modelview * vec4(tangent,0.0)).xyz); -# endif vec3 binormal = normalize( cross(normal,tangent) * binormalf ); #endif - - - #if defined(ENABLE_UV_INTERP) uv_interp = uv_attrib; #endif @@ -257,16 +249,45 @@ void main() { uv2_interp = uv2_attrib; #endif +#if defined(USE_INSTANCING) && defined(ENABLE_INSTANCE_CUSTOM) + vec4 instance_custom = instance_custom_data; +#else + vec4 instance_custom = vec4(0.0); +#endif + + highp mat4 modelview = camera_inverse_matrix * world_matrix; + highp mat4 local_projection = projection_matrix; + +//defines that make writing custom shaders easier +#define projection_matrix local_projection +#define world_transform world_matrix { VERTEX_SHADER_CODE } + + + +#if !defined(SKIP_TRANSFORM_USED) + + vertex = modelview * vertex; + normal = normalize((modelview * vec4(normal,0.0)).xyz); +#endif + + vertex_interp = vertex.xyz; normal_interp = normal; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY) + +#if !defined(SKIP_TRANSFORM_USED) + + tangent = normalize((modelview * vec4(tangent,0.0)).xyz); + binormal = normalize((modelview * vec4(binormal,0.0)).xyz); + +#endif tangent_interp = tangent; binormal_interp = binormal; #endif diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index e2a544b676..ea765e8f8a 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -54,6 +54,7 @@ #endif #include "global_config.h" #include <assert.h> +#include <dlfcn.h> #include <errno.h> #include <poll.h> #include <signal.h> @@ -435,6 +436,36 @@ String OS_Unix::get_locale() const { return locale; } +Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle) { + p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW); + if (!p_library_handle) { + ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + dlerror()); + ERR_FAIL_V(ERR_CANT_OPEN); + } + return OK; +} + +Error OS_Unix::close_dynamic_library(void *p_library_handle) { + if (dlclose(p_library_handle)) { + return FAILED; + } + return OK; +} + +Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { + const char *error; + dlerror(); // Clear existing errors + + p_symbol_handle = dlsym(p_library_handle, p_name.utf8().get_data()); + + error = dlerror(); + if (error != NULL) { + ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + error); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } + return OK; +} + Error OS_Unix::set_cwd(const String &p_cwd) { if (chdir(p_cwd.utf8().get_data()) != 0) diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 3ac4f46109..ff259ab0f0 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -82,6 +82,10 @@ public: //virtual VideoMode get_video_mode() const; //virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const; + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle); + virtual Error close_dynamic_library(void *p_library_handle); + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle); + virtual Error set_cwd(const String &p_cwd); virtual String get_name(); diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index b188a5760b..032e200775 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -789,7 +789,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const } else { uint64_t import_mt = FileAccess::get_modified_time(path + ".import"); - print_line(itos(import_mt) + " vs " + itos(p_dir->files[i]->import_modified_time)); + //print_line(itos(import_mt) + " vs " + itos(p_dir->files[i]->import_modified_time)); if (import_mt != p_dir->files[i]->import_modified_time) { print_line("REIMPORT: import modified changed, reimport"); reimport = true; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 18c16af5af..72f26a5230 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -73,7 +73,9 @@ #include "plugins/collision_shape_2d_editor_plugin.h" #include "plugins/color_ramp_editor_plugin.h" #include "plugins/cube_grid_theme_editor_plugin.h" +#include "plugins/curve_editor_plugin.h" #include "plugins/gi_probe_editor_plugin.h" +#include "plugins/gradient_texture_editor_plugin.h" #include "plugins/item_list_editor_plugin.h" #include "plugins/light_occluder_2d_editor_plugin.h" #include "plugins/line_2d_editor_plugin.h" @@ -1088,7 +1090,7 @@ void EditorNode::_dialog_action(String p_file) { GlobalConfig::get_singleton()->set("application/main_scene", p_file); GlobalConfig::get_singleton()->save(); - //would be nice to show the project manager opened with the hilighted field.. + //would be nice to show the project manager opened with the highlighted field.. } break; case FILE_SAVE_OPTIMIZED: { @@ -5681,7 +5683,7 @@ EditorNode::EditorNode() { overridden_default_layout = -1; default_layout.instance(); default_layout->set_value(docks_section, "dock_3", TTR("FileSystem")); - default_layout->set_value(docks_section, "dock_5", TTR("Scene")); + default_layout->set_value(docks_section, "dock_5", TTR("Scene") + "," + TTR("Import")); default_layout->set_value(docks_section, "dock_6", TTR("Inspector") + "," + TTR("Node")); for (int i = 0; i < DOCK_SLOT_MAX / 2; i++) @@ -5909,7 +5911,7 @@ EditorNode::EditorNode() { //add_editor_plugin( memnew( MeshLibraryEditorPlugin(this) ) ); //add_editor_plugin( memnew( StreamEditorPlugin(this) ) ); add_editor_plugin(memnew(StyleBoxEditorPlugin(this))); - //add_editor_plugin( memnew( ParticlesEditorPlugin(this) ) ); + add_editor_plugin(memnew(ParticlesEditorPlugin(this))); add_editor_plugin(memnew(ResourcePreloaderEditorPlugin(this))); add_editor_plugin(memnew(ItemListEditorPlugin(this))); //add_editor_plugin( memnew( RichTextEditorPlugin(this) ) ); @@ -5929,7 +5931,9 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(LightOccluder2DEditorPlugin(this))); add_editor_plugin(memnew(NavigationPolygonEditorPlugin(this))); add_editor_plugin(memnew(ColorRampEditorPlugin(this))); + add_editor_plugin(memnew(GradientTextureEditorPlugin(this))); add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this))); + add_editor_plugin(memnew(CurveTextureEditorPlugin(this))); add_editor_plugin(memnew(TextureEditorPlugin(this))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); //add_editor_plugin( memnew( MaterialEditorPlugin(this) ) ); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index fe1f984f39..3e0a2c712a 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1101,7 +1101,7 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) { folder_options->add_item(TTR("Expand all"), FOLDER_EXPAND_ALL); folder_options->add_item(TTR("Collapse all"), FOLDER_COLLAPSE_ALL); - folder_options->set_pos(files->get_global_pos() + p_pos); + folder_options->set_pos(tree->get_global_pos() + p_pos); folder_options->popup(); } diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 93614fb511..95baacb9e7 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -364,7 +364,7 @@ Error ColladaImport::_create_material(const String &p_target) { ERR_FAIL_COND_V(!collada.state.effect_map.has(src_mat.instance_effect), ERR_INVALID_PARAMETER); Collada::Effect &effect = collada.state.effect_map[src_mat.instance_effect]; - Ref<FixedSpatialMaterial> material = memnew(FixedSpatialMaterial); + Ref<SpatialMaterial> material = memnew(SpatialMaterial); if (src_mat.name != "") material->set_name(src_mat.name); @@ -381,15 +381,15 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<Texture> texture = ResourceLoader::load(texfile, "Texture"); if (texture.is_valid()) { - material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, texture); + material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture); material->set_albedo(Color(1, 1, 1, 1)); - //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1,1)); + //material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,Color(1,1,1,1)); } else { missing_textures.push_back(texfile.get_file()); } } } else { - //material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,effect.diffuse.color); + //material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,effect.diffuse.color); } // SPECULAR @@ -401,11 +401,11 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<Texture> texture = ResourceLoader::load(texfile, "Texture"); if (texture.is_valid()) { - material->set_texture(FixedSpatialMaterial::TEXTURE_SPECULAR, texture); + material->set_texture(SpatialMaterial::TEXTURE_SPECULAR, texture); material->set_specular(Color(1, 1, 1, 1)); - //material->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,texture); - //material->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,Color(1,1,1,1)); + //material->set_texture(SpatialMaterial::PARAM_SPECULAR,texture); + //material->set_parameter(SpatialMaterial::PARAM_SPECULAR,Color(1,1,1,1)); } else { missing_textures.push_back(texfile.get_file()); } @@ -424,18 +424,18 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<Texture> texture = ResourceLoader::load(texfile, "Texture"); if (texture.is_valid()) { - material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION, true); - material->set_texture(FixedSpatialMaterial::TEXTURE_EMISSION, texture); + material->set_feature(SpatialMaterial::FEATURE_EMISSION, true); + material->set_texture(SpatialMaterial::TEXTURE_EMISSION, texture); material->set_emission(Color(1, 1, 1, 1)); - //material->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,Color(1,1,1,1)); + //material->set_parameter(SpatialMaterial::PARAM_EMISSION,Color(1,1,1,1)); } else { missing_textures.push_back(texfile.get_file()); } } } else { if (effect.emission.color != Color()) { - material->set_feature(FixedSpatialMaterial::FEATURE_EMISSION, true); + material->set_feature(SpatialMaterial::FEATURE_EMISSION, true); material->set_emission(effect.emission.color); } } @@ -449,11 +449,11 @@ Error ColladaImport::_create_material(const String &p_target) { Ref<Texture> texture = ResourceLoader::load(texfile, "Texture"); if (texture.is_valid()) { - material->set_feature(FixedSpatialMaterial::FEATURE_NORMAL_MAPPING, true); - material->set_texture(FixedSpatialMaterial::TEXTURE_NORMAL, texture); + material->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true); + material->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture); //material->set_emission(Color(1,1,1,1)); - //material->set_texture(FixedSpatialMaterial::PARAM_NORMAL,texture); + //material->set_texture(SpatialMaterial::PARAM_NORMAL,texture); } else { //missing_textures.push_back(texfile.get_file()); } @@ -464,9 +464,9 @@ Error ColladaImport::_create_material(const String &p_target) { material->set_roughness(roughness); if (effect.double_sided) { - material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); + material->set_cull_mode(SpatialMaterial::CULL_DISABLED); } - material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, effect.unshaded); + material->set_flag(SpatialMaterial::FLAG_UNSHADED, effect.unshaded); material_cache[p_target] = material; return OK; @@ -1000,7 +1000,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<Mesh> &p_mesh, c { - Ref<FixedSpatialMaterial> material; + Ref<SpatialMaterial> material; //find material Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 8a78376f13..3aa412bd5c 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -157,7 +157,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> memdelete(p_node); return NULL; } - +#if 0 if (p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); @@ -177,18 +177,18 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for (int i = 0; i < m->get_surface_count(); i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { //fm->set_flag(Material::FLAG_UNSHADED,true); //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); - //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + //fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } } } } - +#endif if (p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); @@ -199,19 +199,19 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> for (int i = 0; i < m->get_surface_count(); i++) { - Ref<FixedSpatialMaterial> mat = m->surface_get_material(i); + Ref<SpatialMaterial> mat = m->surface_get_material(i); if (!mat.is_valid()) continue; if (_teststr(mat->get_name(), "alpha")) { - mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); mat->set_name(_fixstr(mat->get_name(), "alpha")); } if (_teststr(mat->get_name(), "vcol")) { - mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); mat->set_name(_fixstr(mat->get_name(), "vcol")); } } @@ -242,7 +242,7 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } } } - +#if 0 if (p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); @@ -277,12 +277,12 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for (int i = 0; i < m->get_surface_count(); i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { //fm->set_flag(Material::FLAG_UNSHADED,true); //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); - //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + //fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } } @@ -290,6 +290,8 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> } } } + +#endif #if 0 if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) { @@ -325,12 +327,12 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } }*/ @@ -687,16 +689,16 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Mesh> for (int i = 0; i < mesh->get_surface_count(); i++) { - Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i); + Ref<SpatialMaterial> fm = mesh->surface_get_material(i); if (fm.is_valid()) { String name = fm->get_name(); /* if (_teststr(name,"alpha")) { - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); name=_fixstr(name,"alpha"); } if (_teststr(name,"vcol")) { - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY,true); name=_fixstr(name,"vcol"); }*/ fm->set_name(name); diff --git a/editor/io_plugins/editor_scene_import_plugin.cpp b/editor/io_plugins/editor_scene_import_plugin.cpp index 52a554f6d1..1fd7078135 100644 --- a/editor/io_plugins/editor_scene_import_plugin.cpp +++ b/editor/io_plugins/editor_scene_import_plugin.cpp @@ -1408,7 +1408,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) { - if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/diffuse" || E->get().name=="textures/detail" || E->get().name=="textures/emission")) { + if (E->get().type==Variant::OBJECT && res->cast_to<SpatialMaterial>() && (E->get().name=="textures/diffuse" || E->get().name=="textures/detail" || E->get().name=="textures/emission")) { Ref<ImageTexture> tex =res->get(E->get().name); if (tex.is_valid()) { @@ -1416,7 +1416,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag image_map.insert(tex,TEXTURE_ROLE_DIFFUSE); } - } else if (E->get().type==Variant::OBJECT && res->cast_to<FixedSpatialMaterial>() && (E->get().name=="textures/normal")) { + } else if (E->get().type==Variant::OBJECT && res->cast_to<SpatialMaterial>() && (E->get().name=="textures/normal")) { Ref<ImageTexture> tex =res->get(E->get().name); if (tex.is_valid()) { @@ -1424,7 +1424,7 @@ void EditorSceneImportPlugin::_find_resources(const Variant& p_var, Map<Ref<Imag image_map.insert(tex,TEXTURE_ROLE_NORMALMAP); /* if (p_flags&SCENE_FLAG_CONVERT_NORMALMAPS_TO_XY) - res->cast_to<FixedSpatialMaterial>()->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_XY_NORMALMAP,true); + res->cast_to<SpatialMaterial>()->set_fixed_flag(SpatialMaterial::FLAG_USE_XY_NORMALMAP,true); */ } @@ -1532,12 +1532,12 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { //fm->set_flag(Material::FLAG_UNSHADED,true); //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); - //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + //fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } } @@ -1555,18 +1555,18 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh> for(int i=0;i<m->get_surface_count();i++) { - Ref<FixedSpatialMaterial> mat = m->surface_get_material(i); + Ref<SpatialMaterial> mat = m->surface_get_material(i); if (!mat.is_valid()) continue; if (p_flags&SCENE_FLAG_DETECT_ALPHA && _teststr(mat->get_name(),"alpha")) { - //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + //mat->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); //mat->set_name(_fixstr(mat->get_name(),"alpha")); } if (p_flags&SCENE_FLAG_DETECT_VCOLOR && _teststr(mat->get_name(),"vcol")) { - //mat->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true); + //mat->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY,true); //mat->set_name(_fixstr(mat->get_name(),"vcol")); } @@ -1641,12 +1641,12 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { //fm->set_flag(Material::FLAG_UNSHADED,true); //fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); //fm->set_depth_draw_mode(Material::DEPTH_DRAW_NEVER); - //fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + //fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } } @@ -1689,12 +1689,12 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh> Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { - Ref<FixedSpatialMaterial> fm = m->surface_get_material(i); + Ref<SpatialMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); } } }*/ @@ -2062,16 +2062,16 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh> for(int i=0;i<mesh->get_surface_count();i++) { - Ref<FixedSpatialMaterial> fm = mesh->surface_get_material(i); + Ref<SpatialMaterial> fm = mesh->surface_get_material(i); if (fm.is_valid()) { String name = fm->get_name(); /* if (_teststr(name,"alpha")) { - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA,true); name=_fixstr(name,"alpha"); } if (_teststr(name,"vcol")) { - fm->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY,true); + fm->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY,true); name=_fixstr(name,"vcol"); }*/ fm->set_name(name); diff --git a/editor/io_plugins/editor_scene_importer_fbxconv.cpp b/editor/io_plugins/editor_scene_importer_fbxconv.cpp index a2fe4a649b..12a88c3eb6 100644 --- a/editor/io_plugins/editor_scene_importer_fbxconv.cpp +++ b/editor/io_plugins/editor_scene_importer_fbxconv.cpp @@ -483,29 +483,29 @@ void EditorSceneImporterFBXConv::_parse_materials(State& state) { ERR_CONTINUE(!material.has("id")); String id = _id(material["id"]); - Ref<FixedSpatialMaterial> mat = memnew( FixedSpatialMaterial ); + Ref<SpatialMaterial> mat = memnew( SpatialMaterial ); if (material.has("diffuse")) { - mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,_get_color(material["diffuse"])); + mat->set_parameter(SpatialMaterial::PARAM_DIFFUSE,_get_color(material["diffuse"])); } if (material.has("specular")) { - mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR,_get_color(material["specular"])); + mat->set_parameter(SpatialMaterial::PARAM_SPECULAR,_get_color(material["specular"])); } if (material.has("emissive")) { - mat->set_parameter(FixedSpatialMaterial::PARAM_EMISSION,_get_color(material["emissive"])); + mat->set_parameter(SpatialMaterial::PARAM_EMISSION,_get_color(material["emissive"])); } if (material.has("shininess")) { float exp = material["shininess"]; - mat->set_parameter(FixedSpatialMaterial::PARAM_SPECULAR_EXP,exp); + mat->set_parameter(SpatialMaterial::PARAM_SPECULAR_EXP,exp); } if (material.has("opacity")) { - Color c = mat->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE); + Color c = mat->get_parameter(SpatialMaterial::PARAM_DIFFUSE); c.a=material["opacity"]; - mat->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,c); + mat->set_parameter(SpatialMaterial::PARAM_DIFFUSE,c); } @@ -537,15 +537,15 @@ void EditorSceneImporterFBXConv::_parse_materials(State& state) { String type=texture["type"]; if (type=="DIFFUSE") - mat->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,tex); + mat->set_texture(SpatialMaterial::PARAM_DIFFUSE,tex); else if (type=="SPECULAR") - mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR,tex); + mat->set_texture(SpatialMaterial::PARAM_SPECULAR,tex); else if (type=="SHININESS") - mat->set_texture(FixedSpatialMaterial::PARAM_SPECULAR_EXP,tex); + mat->set_texture(SpatialMaterial::PARAM_SPECULAR_EXP,tex); else if (type=="NORMAL") - mat->set_texture(FixedSpatialMaterial::PARAM_NORMAL,tex); + mat->set_texture(SpatialMaterial::PARAM_NORMAL,tex); else if (type=="EMISSIVE") - mat->set_texture(FixedSpatialMaterial::PARAM_EMISSION,tex); + mat->set_texture(SpatialMaterial::PARAM_EMISSION,tex); } } diff --git a/editor/plugins/baked_light_baker.cpp b/editor/plugins/baked_light_baker.cpp index de2b78b8dd..3db54978e1 100644 --- a/editor/plugins/baked_light_baker.cpp +++ b/editor/plugins/baked_light_baker.cpp @@ -144,18 +144,18 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m MeshMaterial mm; - Ref<FixedSpatialMaterial> fm = mat; + Ref<SpatialMaterial> fm = mat; if (fm.is_valid()) { //fixed route - mm.diffuse.color=fm->get_parameter(FixedSpatialMaterial::PARAM_DIFFUSE); + mm.diffuse.color=fm->get_parameter(SpatialMaterial::PARAM_DIFFUSE); if (linear_color) mm.diffuse.color=mm.diffuse.color.to_linear(); - mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_DIFFUSE)); - mm.specular.color=fm->get_parameter(FixedSpatialMaterial::PARAM_SPECULAR); + mm.diffuse.tex=_get_mat_tex(fm->get_texture(SpatialMaterial::PARAM_DIFFUSE)); + mm.specular.color=fm->get_parameter(SpatialMaterial::PARAM_SPECULAR); if (linear_color) mm.specular.color=mm.specular.color.to_linear(); - mm.specular.tex=_get_mat_tex(fm->get_texture(FixedSpatialMaterial::PARAM_SPECULAR)); + mm.specular.tex=_get_mat_tex(fm->get_texture(SpatialMaterial::PARAM_SPECULAR)); } else { mm.diffuse.color=Color(1,1,1,1); diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 62426a7699..c0599bf26e 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -571,25 +571,25 @@ CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) { imgeom->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001))); - line_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial )); + 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,Color(1,1,1)); + 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,Color(1,1,1)); - handle_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial )); + handle_material = Ref<SpatialMaterial>( memnew( SpatialMaterial )); handle_material->set_flag(Material::FLAG_UNSHADED, true); - handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true); - handle_material->set_parameter(FixedSpatialMaterial::PARAM_DIFFUSE,Color(1,1,1)); - handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); - handle_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_COLOR_ARRAY, false); + handle_material->set_fixed_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); + handle_material->set_parameter(SpatialMaterial::PARAM_DIFFUSE,Color(1,1,1)); + handle_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); + handle_material->set_fixed_flag(SpatialMaterial::FLAG_USE_COLOR_ARRAY, false); Ref<Texture> handle=editor->get_gui_base()->get_icon("Editor3DHandle","EditorIcons"); handle_material->set_point_size(handle->get_width()); - handle_material->set_texture(FixedSpatialMaterial::PARAM_DIFFUSE,handle); + handle_material->set_texture(SpatialMaterial::PARAM_DIFFUSE,handle); pointsm = memnew( MeshInstance ); imgeom->add_child(pointsm); diff --git a/editor/plugins/collision_polygon_editor_plugin.h b/editor/plugins/collision_polygon_editor_plugin.h index ace8c3429f..d033fbf2ed 100644 --- a/editor/plugins/collision_polygon_editor_plugin.h +++ b/editor/plugins/collision_polygon_editor_plugin.h @@ -62,8 +62,8 @@ class CollisionPolygonEditor : public HBoxContainer { ToolButton *button_edit; - Ref<FixedSpatialMaterial> line_material; - Ref<FixedSpatialMaterial> handle_material; + Ref<SpatialMaterial> line_material; + Ref<SpatialMaterial> handle_material; EditorNode *editor; Panel *panel; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp new file mode 100644 index 0000000000..52edc75bc0 --- /dev/null +++ b/editor/plugins/curve_editor_plugin.cpp @@ -0,0 +1,519 @@ +#include "curve_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "os/keyboard.h" +#include "spatial_editor_plugin.h" +void CurveTextureEdit::_gui_input(const InputEvent &p_event) { + + if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) { + + points.remove(grabbed); + grabbed = -1; + update(); + emit_signal("curve_changed"); + accept_event(); + } + + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) { + + update(); + Ref<Font> font = get_font("font", "Label"); + + int font_h = font->get_height(); + + Vector2 size = get_size(); + size.y -= font_h; + + Point2 p = Vector2(p_event.mouse_button.x, p_event.mouse_button.y) / size; + p.y = CLAMP(1.0 - p.y, 0, 1) * (max - min) + min; + grabbed = -1; + grabbing = true; + + for (int i = 0; i < points.size(); i++) { + + Vector2 ps = p * get_size(); + Vector2 pt = Vector2(points[i].offset, points[i].height) * get_size(); + if (ps.distance_to(pt) < 4) { + grabbed = i; + } + } + + //grab or select + if (grabbed != -1) { + return; + } + //insert + + Point np; + np.offset = p.x; + np.height = p.y; + + points.push_back(np); + points.sort(); + for (int i = 0; i < points.size(); i++) { + if (points[i].offset == p.x && points[i].height == p.y) { + grabbed = i; + break; + } + } + + emit_signal("curve_changed"); + } + + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) { + + if (grabbing) { + grabbing = false; + emit_signal("curve_changed"); + } + update(); + } + + if (p_event.type == InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) { + + Ref<Font> font = get_font("font", "Label"); + int font_h = font->get_height(); + Vector2 size = get_size(); + size.y -= font_h; + + Point2 p = Vector2(p_event.mouse_motion.x, p_event.mouse_motion.y) / size; + p.y = CLAMP(1.0 - p.y, 0, 1) * (max - min) + min; + p.x = CLAMP(p.x, 0.0, 1.0); + + bool valid = true; + + for (int i = 0; i < points.size(); i++) { + + if (points[i].offset == p.x && points[i].height == p.y && i != grabbed) { + valid = false; + } + } + + if (!valid) + return; + + points[grabbed].offset = p.x; + points[grabbed].height = p.y; + + points.sort(); + for (int i = 0; i < points.size(); i++) { + if (points[i].offset == p.x && points[i].height == p.y) { + grabbed = i; + break; + } + } + + emit_signal("curve_changed"); + + update(); + } +} + +void CurveTextureEdit::_plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d) { + + Ref<Font> font = get_font("font", "Label"); + + int font_h = font->get_height(); + + 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, lasty; + int newx, newy; + int ntimes; + int i, j; + + int xmax = get_size().x; + int ymax = get_size().y - font_h; + + int vsplits = 4; + + int zero_ofs = (1.0 - (0.0 - min) / (max - min)) * ymax; + + draw_line(Vector2(0, zero_ofs), Vector2(xmax, zero_ofs), Color(0.8, 0.8, 0.8, 0.15), 2.0); + + for (int i = 0; i <= vsplits; i++) { + float fofs = float(i) / vsplits; + int yofs = fofs * ymax; + draw_line(Vector2(xmax, yofs), Vector2(xmax - 4, yofs), Color(0.8, 0.8, 0.8, 0.8), 2.0); + + String text = rtos((1.0 - fofs) * (max - min) + min); + int ppos = text.find("."); + if (ppos != -1) { + if (text.length() > ppos + 2) + text = text.substr(0, ppos + 2); + } + + int size = font->get_string_size(text).x; + int xofs = xmax - size - 4; + yofs -= font_h / 2; + + if (yofs < 2) { + yofs = 2; + } else if (yofs + font_h > ymax - 2) { + yofs = ymax - font_h - 2; + } + + draw_string(font, Vector2(xofs, yofs + font->get_ascent()), text, Color(0.8, 0.8, 0.8, 1)); + } + + /* 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] - min) / (max - min) * ymax); + geometry[1][1] = ((p_b[1] - min) / (max - min) * ymax); + geometry[2][1] = ((p_c[1] - min) / (max - min) * ymax); + geometry[3][1] = ((p_d[1] - min) / (max - min) * ymax); + + /* 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 = CLAMP(y, 0, ymax); + + /* if (fix255) + { + cd->curve[cd->outline][lastx] = lasty; + } + else + { + cd->curve_ptr[cd->outline][lastx] = lasty; + if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax); + } +*/ + /* 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((Math::round(y)), 0, ymax); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) { +#if 0 + if(fix255) + { + /* use fixed array size (for the curve graph) */ + cd->curve[cd->outline][newx] = newy; + } + else + { + /* use dynamic allocated curve_ptr (for the real curve) */ + cd->curve_ptr[cd->outline][newx] = newy; + + if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy); + } +#endif + draw_line(Vector2(lastx, ymax - lasty), Vector2(newx, ymax - newy), Color(0.8, 0.8, 0.8, 0.8), 2.0); + } + + lastx = newx; + lasty = newy; + } + + int splits = 8; + + draw_line(Vector2(0, ymax - 1), Vector2(xmax, ymax - 1), Color(0.8, 0.8, 0.8, 0.3), 2.0); + + for (int i = 0; i <= splits; i++) { + float fofs = float(i) / splits; + draw_line(Vector2(fofs * xmax, ymax), Vector2(fofs * xmax, ymax - 2), Color(0.8, 0.8, 0.8, 0.8), 2.0); + + String text = rtos(fofs); + int size = font->get_string_size(text).x; + int ofs = fofs * xmax - size * 0.5; + if (ofs < 2) { + ofs = 2; + } else if (ofs + size > xmax - 2) { + ofs = xmax - size - 2; + } + + draw_string(font, Vector2(ofs, ymax + font->get_ascent()), text, Color(0.8, 0.8, 0.8, 1)); + } +} + +void CurveTextureEdit::_notification(int p_what) { + + if (p_what == NOTIFICATION_DRAW) { + + Ref<Font> font = get_font("font", "Label"); + + int font_h = font->get_height(); + + draw_style_box(get_stylebox("bg", "Tree"), Rect2(Point2(), get_size())); + + int w = get_size().x; + int h = get_size().y; + + Vector2 prev = Vector2(0, 0); + Vector2 prev2 = Vector2(0, 0); + + for (int i = -1; i < points.size(); i++) { + + Vector2 next; + Vector2 next2; + if (i + 1 >= points.size()) { + next = Vector2(1, 0); + } else { + next = Vector2(points[i + 1].offset, points[i + 1].height); + } + + if (i + 2 >= points.size()) { + next2 = Vector2(1, 0); + } else { + next2 = Vector2(points[i + 2].offset, points[i + 2].height); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2, prev, next, next2); + + prev2 = prev; + prev = next; + } + + Vector2 size = get_size(); + size.y -= font_h; + for (int i = 0; i < points.size(); i++) { + + Color col = i == grabbed ? Color(1, 0.0, 0.0, 0.9) : Color(1, 1, 1, 0.8); + + float h = (points[i].height - min) / (max - min); + draw_rect(Rect2(Vector2(points[i].offset, 1.0 - h) * size - Vector2(2, 2), Vector2(5, 5)), col); + } + + /* if (grabbed!=-1) { + + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } +*/ + if (has_focus()) { + + draw_line(Vector2(-1, -1), Vector2(w + 1, -1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(w + 1, -1), Vector2(w + 1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); + } + } +} + +Size2 CurveTextureEdit::get_minimum_size() const { + + return Vector2(64, 64); +} + +void CurveTextureEdit::set_range(float p_min, float p_max) { + max = p_max; + min = p_min; + update(); +} + +void CurveTextureEdit::set_points(const Vector<Vector2> &p_points) { + + points.clear(); + for (int i = 0; i < p_points.size(); i++) { + Point p; + p.offset = p_points[i].x; + p.height = p_points[i].y; + points.push_back(p); + } + + points.sort(); + update(); +} + +Vector<Vector2> CurveTextureEdit::get_points() const { + Vector<Vector2> ret; + for (int i = 0; i < points.size(); i++) + ret.push_back(Vector2(points[i].offset, points[i].height)); + return ret; +} + +void CurveTextureEdit::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_gui_input"), &CurveTextureEdit::_gui_input); + + ADD_SIGNAL(MethodInfo("curve_changed")); +} + +CurveTextureEdit::CurveTextureEdit() { + + grabbed = -1; + grabbing = false; + max = 1; + min = 0; + set_focus_mode(FOCUS_ALL); +} + +void CurveTextureEditorPlugin::_curve_settings_changed() { + + if (!curve_texture_ref.is_valid()) + return; + curve_editor->set_points(Variant(curve_texture_ref->get_points())); + curve_editor->set_range(curve_texture_ref->get_min(), curve_texture_ref->get_max()); +} + +CurveTextureEditorPlugin::CurveTextureEditorPlugin(EditorNode *p_node) { + + editor = p_node; + curve_editor = memnew(CurveTextureEdit); + + curve_button = editor->add_bottom_panel_item("CurveTexture", curve_editor); + + curve_button->hide(); + curve_editor->set_custom_minimum_size(Size2(100, 128 * EDSCALE)); + curve_editor->hide(); + curve_editor->connect("curve_changed", this, "curve_changed"); +} + +void CurveTextureEditorPlugin::edit(Object *p_object) { + + if (curve_texture_ref.is_valid()) { + curve_texture_ref->disconnect("changed", this, "_curve_settings_changed"); + } + CurveTexture *curve_texture = p_object->cast_to<CurveTexture>(); + if (!curve_texture) + return; + curve_texture_ref = Ref<CurveTexture>(curve_texture); + curve_editor->set_points(Variant(curve_texture_ref->get_points())); + curve_editor->set_range(curve_texture_ref->get_min(), curve_texture_ref->get_max()); + if (!curve_texture_ref->is_connected("changed", this, "_curve_settings_changed")) { + curve_texture_ref->connect("changed", this, "_curve_settings_changed"); + } +} + +bool CurveTextureEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("CurveTexture"); +} + +void CurveTextureEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + curve_button->show(); + editor->make_bottom_panel_item_visible(curve_editor); + + } else { + + curve_button->hide(); + if (curve_editor->is_visible_in_tree()) + editor->hide_bottom_panel(); + } +} + +void CurveTextureEditorPlugin::_curve_changed() { + + if (curve_texture_ref.is_valid()) { + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + Vector<Vector2> points = curve_editor->get_points(); + PoolVector<Vector2> ppoints = Variant(points); + + ur->create_action(TTR("Modify Curve"), UndoRedo::MERGE_ENDS); + ur->add_do_method(this, "undo_redo_curve_texture", ppoints); + ur->add_undo_method(this, "undo_redo_curve_texture", curve_texture_ref->get_points()); + ur->commit_action(); + } +} + +void CurveTextureEditorPlugin::_undo_redo_curve_texture(const PoolVector<Vector2> &points) { + + curve_texture_ref->set_points(points); + curve_editor->set_points(Variant(curve_texture_ref->get_points())); + curve_editor->update(); +} + +CurveTextureEditorPlugin::~CurveTextureEditorPlugin() { +} + +void CurveTextureEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("curve_changed"), &CurveTextureEditorPlugin::_curve_changed); + ClassDB::bind_method(D_METHOD("_curve_settings_changed"), &CurveTextureEditorPlugin::_curve_settings_changed); + ClassDB::bind_method(D_METHOD("undo_redo_curve_texture", "points"), &CurveTextureEditorPlugin::_undo_redo_curve_texture); +} diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h new file mode 100644 index 0000000000..e98cec2727 --- /dev/null +++ b/editor/plugins/curve_editor_plugin.h @@ -0,0 +1,66 @@ +#ifndef CURVE_EDITOR_PLUGIN_H +#define CURVE_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" + +class CurveTextureEdit : public Control { + + GDCLASS(CurveTextureEdit, Control); + + struct Point { + + float offset; + float height; + bool operator<(const Point &p_ponit) const { + return offset < p_ponit.offset; + } + }; + + bool grabbing; + int grabbed; + Vector<Point> points; + float max, min; + + void _plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d); + +protected: + void _gui_input(const InputEvent &p_event); + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_range(float p_min, float p_max); + void set_points(const Vector<Vector2> &p_points); + Vector<Vector2> get_points() const; + virtual Size2 get_minimum_size() const; + CurveTextureEdit(); +}; + +class CurveTextureEditorPlugin : public EditorPlugin { + + GDCLASS(CurveTextureEditorPlugin, EditorPlugin); + + CurveTextureEdit *curve_editor; + Ref<CurveTexture> curve_texture_ref; + EditorNode *editor; + ToolButton *curve_button; + +protected: + static void _bind_methods(); + void _curve_changed(); + void _undo_redo_curve_texture(const PoolVector<Vector2> &points); + void _curve_settings_changed(); + +public: + virtual String get_name() const { return "CurveTexture"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + CurveTextureEditorPlugin(EditorNode *p_node); + ~CurveTextureEditorPlugin(); +}; + +#endif // CURVE_EDITOR_PLUGIN_H diff --git a/editor/plugins/gradient_texture_editor_plugin.cpp b/editor/plugins/gradient_texture_editor_plugin.cpp new file mode 100644 index 0000000000..1e82a1105a --- /dev/null +++ b/editor/plugins/gradient_texture_editor_plugin.cpp @@ -0,0 +1,504 @@ +#include "gradient_texture_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "spatial_editor_plugin.h" + +#include "os/keyboard.h" +#include "scene/resources/default_theme/theme_data.h" +#define POINT_WIDTH 8 + +GradientTextureEdit::GradientTextureEdit() { + grabbed = -1; + grabbing = false; + set_focus_mode(FOCUS_ALL); + + popup = memnew(PopupPanel); + picker = memnew(ColorPicker); + popup->add_child(picker); + + add_child(popup); + + checker = Ref<ImageTexture>(memnew(ImageTexture)); + checker->create_from_image(Image(checker_bg_png), ImageTexture::FLAG_REPEAT); +} + +int GradientTextureEdit::_get_point_from_pos(int x) { + int result = -1; + int total_w = get_size().width - get_size().height - 3; + for (int i = 0; i < points.size(); i++) { + //Check if we clicked at point + if (ABS(x - points[i].offset * total_w + 1) < (POINT_WIDTH / 2 + 1)) { + result = i; + } + } + return result; +} + +void GradientTextureEdit::_show_color_picker() { + if (grabbed == -1) + return; + Size2 ms = Size2(350, picker->get_combined_minimum_size().height + 10); + picker->set_pick_color(points[grabbed].color); + popup->set_pos(get_global_pos() - Vector2(ms.width - get_size().width, ms.height)); + popup->set_size(ms); + popup->popup(); +} + +GradientTextureEdit::~GradientTextureEdit() { +} + +void GradientTextureEdit::_gui_input(const InputEvent &p_event) { + + if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) { + + points.remove(grabbed); + grabbed = -1; + grabbing = false; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + + //Show color picker on double click. + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.doubleclick && p_event.mouse_button.pressed) { + grabbed = _get_point_from_pos(p_event.mouse_button.x); + _show_color_picker(); + accept_event(); + } + + //Delete point on right click + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 2 && p_event.mouse_button.pressed) { + grabbed = _get_point_from_pos(p_event.mouse_button.x); + if (grabbed != -1) { + points.remove(grabbed); + grabbed = -1; + grabbing = false; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + } + + //Hold alt key to duplicate selected color + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed && p_event.key.mod.alt) { + + int x = p_event.mouse_button.x; + grabbed = _get_point_from_pos(x); + + if (grabbed != -1) { + int total_w = get_size().width - get_size().height - 3; + GradientTexture::Point newPoint = points[grabbed]; + newPoint.offset = CLAMP(x / float(total_w), 0, 1); + + points.push_back(newPoint); + points.sort(); + for (int i = 0; i < points.size(); ++i) { + if (points[i].offset == newPoint.offset) { + grabbed = i; + break; + } + } + + emit_signal("ramp_changed"); + update(); + } + } + + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width - get_size().height - 3; + + //Check if color selector was clicked. + if (x > total_w + 3) { + _show_color_picker(); + return; + } + + grabbing = true; + + grabbed = _get_point_from_pos(x); + //grab or select + if (grabbed != -1) { + return; + } + + //insert + GradientTexture::Point newPoint; + newPoint.offset = CLAMP(x / float(total_w), 0, 1); + + GradientTexture::Point prev; + GradientTexture::Point next; + + int pos = -1; + for (int i = 0; i < points.size(); i++) { + if (points[i].offset < newPoint.offset) + pos = i; + } + + if (pos == -1) { + + prev.color = Color(0, 0, 0); + prev.offset = 0; + if (points.size()) { + next = points[0]; + } else { + next.color = Color(1, 1, 1); + next.offset = 1.0; + } + } else { + + if (pos == points.size() - 1) { + next.color = Color(1, 1, 1); + next.offset = 1.0; + } else { + next = points[pos + 1]; + } + prev = points[pos]; + } + + newPoint.color = prev.color.linear_interpolate(next.color, (newPoint.offset - prev.offset) / (next.offset - prev.offset)); + + points.push_back(newPoint); + points.sort(); + for (int i = 0; i < points.size(); i++) { + if (points[i].offset == newPoint.offset) { + grabbed = i; + break; + } + } + + emit_signal("ramp_changed"); + } + + if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) { + + if (grabbing) { + grabbing = false; + emit_signal("ramp_changed"); + } + update(); + } + + if (p_event.type == InputEvent::MOUSE_MOTION && grabbing) { + + int total_w = get_size().width - get_size().height - 3; + + int x = p_event.mouse_motion.x; + float newofs = CLAMP(x / float(total_w), 0, 1); + + //Snap to nearest point if holding shift + if (p_event.key.mod.shift) { + float snap_treshhold = 0.03; + float smallest_ofs = snap_treshhold; + bool founded = false; + int nearest_point; + for (int i = 0; i < points.size(); ++i) { + if (i != grabbed) { + float temp_ofs = ABS(points[i].offset - newofs); + if (temp_ofs < smallest_ofs) { + smallest_ofs = temp_ofs; + nearest_point = i; + if (founded) + break; + founded = true; + } + } + } + if (founded) { + if (points[nearest_point].offset < newofs) + newofs = points[nearest_point].offset + 0.00001; + else + newofs = points[nearest_point].offset - 0.00001; + newofs = CLAMP(newofs, 0, 1); + } + } + + bool valid = true; + for (int i = 0; i < points.size(); i++) { + + if (points[i].offset == newofs && i != grabbed) { + valid = false; + } + } + + if (!valid) + return; + + points[grabbed].offset = newofs; + + points.sort(); + for (int i = 0; i < points.size(); i++) { + if (points[i].offset == newofs) { + grabbed = i; + break; + } + } + + emit_signal("ramp_changed"); + + update(); + } +} + +void GradientTextureEdit::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + if (!picker->is_connected("color_changed", this, "_color_changed")) { + picker->connect("color_changed", this, "_color_changed"); + } + } + if (p_what == NOTIFICATION_DRAW) { + + int w = get_size().x; + int h = get_size().y; + + if (w == 0 || h == 0) + return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size + + int total_w = get_size().width - get_size().height - 3; + + //Draw checker pattern for ramp + _draw_checker(0, 0, total_w, h); + + //Draw color ramp + GradientTexture::Point prev; + prev.offset = 0; + if (points.size() == 0) + prev.color = Color(0, 0, 0); //Draw black rectangle if we have no points + else + prev.color = points[0].color; //Extend color of first point to the beginning. + + for (int i = -1; i < points.size(); i++) { + + GradientTexture::Point next; + //If there is no next point + if (i + 1 == points.size()) { + if (points.size() == 0) + next.color = Color(0, 0, 0); //Draw black rectangle if we have no points + else + next.color = points[i].color; //Extend color of last point to the end. + next.offset = 1; + } else { + next = points[i + 1]; + } + + if (prev.offset == next.offset) { + prev = next; + continue; + } + + Vector<Vector2> points; + Vector<Color> colors; + points.push_back(Vector2(prev.offset * total_w, h)); + points.push_back(Vector2(prev.offset * total_w, 0)); + points.push_back(Vector2(next.offset * total_w, 0)); + points.push_back(Vector2(next.offset * total_w, h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points, colors, Vector<Point2>()); + prev = next; + } + + //Draw point markers + for (int i = 0; i < points.size(); i++) { + + Color col = i == grabbed ? Color(1, 0.0, 0.0, 0.9) : points[i].color.contrasted(); + col.a = 0.9; + + draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col); + draw_rect(Rect2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2, POINT_WIDTH, h / 2), Color(0.6, 0.6, 0.6, i == grabbed ? 0.9 : 0.4)); + draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h - 1), col); + draw_line(Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h - 1), col); + draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h / 2), col); + draw_line(Vector2(points[i].offset * total_w - POINT_WIDTH / 2, h - 1), Vector2(points[i].offset * total_w + POINT_WIDTH / 2, h - 1), col); + } + + //Draw "button" for color selector + _draw_checker(total_w + 3, 0, h, h); + if (grabbed != -1) { + //Draw with selection color + draw_rect(Rect2(total_w + 3, 0, h, h), points[grabbed].color); + } else { + //if no color selected draw grey color with 'X' on top. + draw_rect(Rect2(total_w + 3, 0, h, h), Color(0.5, 0.5, 0.5, 1)); + draw_line(Vector2(total_w + 3, 0), Vector2(total_w + 3 + h, h), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + 3, h), Vector2(total_w + 3 + h, 0), Color(1, 1, 1, 0.6)); + } + + //Draw borders around color ramp if in focus + if (has_focus()) { + + draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); + draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6)); + } + } +} + +void GradientTextureEdit::_draw_checker(int x, int y, int w, int h) { + //Draw it with polygon to insert UVs for scale + Vector<Vector2> backPoints; + backPoints.push_back(Vector2(x, y)); + backPoints.push_back(Vector2(x, y + h)); + backPoints.push_back(Vector2(x + w, y + h)); + backPoints.push_back(Vector2(x + w, y)); + Vector<Color> colorPoints; + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + colorPoints.push_back(Color(1, 1, 1, 1)); + Vector<Vector2> uvPoints; + //Draw checker pattern pixel-perfect and scale it by 2. + uvPoints.push_back(Vector2(x, y)); + uvPoints.push_back(Vector2(x, y + h * .5f / checker->get_height())); + uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y + h * .5f / checker->get_height())); + uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y)); + draw_polygon(backPoints, colorPoints, uvPoints, checker); +} + +Size2 GradientTextureEdit::get_minimum_size() const { + + return Vector2(0, 16); +} + +void GradientTextureEdit::_color_changed(const Color &p_color) { + + if (grabbed == -1) + return; + points[grabbed].color = p_color; + update(); + emit_signal("ramp_changed"); +} + +void GradientTextureEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) { + + ERR_FAIL_COND(p_offsets.size() != p_colors.size()); + points.clear(); + for (int i = 0; i < p_offsets.size(); i++) { + GradientTexture::Point p; + p.offset = p_offsets[i]; + p.color = p_colors[i]; + points.push_back(p); + } + + points.sort(); + update(); +} + +Vector<float> GradientTextureEdit::get_offsets() const { + Vector<float> ret; + for (int i = 0; i < points.size(); i++) + ret.push_back(points[i].offset); + return ret; +} + +Vector<Color> GradientTextureEdit::get_colors() const { + Vector<Color> ret; + for (int i = 0; i < points.size(); i++) + ret.push_back(points[i].color); + return ret; +} + +void GradientTextureEdit::set_points(Vector<GradientTexture::Point> &p_points) { + if (points.size() != p_points.size()) + grabbed = -1; + points.clear(); + points = p_points; +} + +Vector<GradientTexture::Point> &GradientTextureEdit::get_points() { + return points; +} + +void GradientTextureEdit::_bind_methods() { + ClassDB::bind_method(D_METHOD("_gui_input"), &GradientTextureEdit::_gui_input); + ClassDB::bind_method(D_METHOD("_color_changed"), &GradientTextureEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); +} + +GradientTextureEditorPlugin::GradientTextureEditorPlugin(EditorNode *p_node) { + + editor = p_node; + ramp_editor = memnew(GradientTextureEdit); + + gradient_button = editor->add_bottom_panel_item("GradientTexture", ramp_editor); + + gradient_button->hide(); + ramp_editor->set_custom_minimum_size(Size2(100, 100 * EDSCALE)); + ramp_editor->hide(); + ramp_editor->connect("ramp_changed", this, "ramp_changed"); +} + +void GradientTextureEditorPlugin::edit(Object *p_object) { + + GradientTexture *gradient_texture = p_object->cast_to<GradientTexture>(); + if (!gradient_texture) + return; + gradient_texture_ref = Ref<GradientTexture>(gradient_texture); + ramp_editor->set_points(gradient_texture_ref->get_points()); +} + +bool GradientTextureEditorPlugin::handles(Object *p_object) const { + + return p_object->is_class("GradientTexture"); +} + +void GradientTextureEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + gradient_button->show(); + editor->make_bottom_panel_item_visible(ramp_editor); + + } else { + + gradient_button->hide(); + if (ramp_editor->is_visible_in_tree()) + editor->hide_bottom_panel(); + } +} + +void GradientTextureEditorPlugin::_ramp_changed() { + + if (gradient_texture_ref.is_valid()) { + + UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); + + //Not sure if I should convert this data to PoolVector + Vector<float> new_offsets = ramp_editor->get_offsets(); + Vector<Color> new_colors = ramp_editor->get_colors(); + Vector<float> old_offsets = gradient_texture_ref->get_offsets(); + Vector<Color> old_colors = gradient_texture_ref->get_colors(); + + if (old_offsets.size() != new_offsets.size()) + ur->create_action(TTR("Add/Remove Color Ramp Point")); + else + ur->create_action(TTR("Modify Color Ramp"), UndoRedo::MERGE_ENDS); + ur->add_do_method(this, "undo_redo_gradient_texture", new_offsets, new_colors); + ur->add_undo_method(this, "undo_redo_gradient_texture", old_offsets, old_colors); + ur->commit_action(); + + //gradient_texture_ref->set_points(ramp_editor->get_points()); + } +} + +void GradientTextureEditorPlugin::_undo_redo_gradient_texture(const Vector<float> &offsets, + const Vector<Color> &colors) { + + gradient_texture_ref->set_offsets(offsets); + gradient_texture_ref->set_colors(colors); + ramp_editor->set_points(gradient_texture_ref->get_points()); + ramp_editor->update(); +} + +GradientTextureEditorPlugin::~GradientTextureEditorPlugin() { +} + +void GradientTextureEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("ramp_changed"), &GradientTextureEditorPlugin::_ramp_changed); + ClassDB::bind_method(D_METHOD("undo_redo_gradient_texture", "offsets", "colors"), &GradientTextureEditorPlugin::_undo_redo_gradient_texture); +} diff --git a/editor/plugins/gradient_texture_editor_plugin.h b/editor/plugins/gradient_texture_editor_plugin.h new file mode 100644 index 0000000000..5af828f17c --- /dev/null +++ b/editor/plugins/gradient_texture_editor_plugin.h @@ -0,0 +1,69 @@ +#ifndef GRADIENT_TEXTURE_EDITOR_PLUGIN_H +#define GRADIENT_TEXTURE_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/resources/texture.h" + +class GradientTextureEdit : public Control { + + GDCLASS(GradientTextureEdit, Control); + + PopupPanel *popup; + ColorPicker *picker; + + Ref<ImageTexture> checker; + + bool grabbing; + int grabbed; + Vector<GradientTexture::Point> points; + + void _draw_checker(int x, int y, int w, int h); + void _color_changed(const Color &p_color); + int _get_point_from_pos(int x); + void _show_color_picker(); + +protected: + void _gui_input(const InputEvent &p_event); + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors); + Vector<float> get_offsets() const; + Vector<Color> get_colors() const; + void set_points(Vector<GradientTexture::Point> &p_points); + Vector<GradientTexture::Point> &get_points(); + virtual Size2 get_minimum_size() const; + + GradientTextureEdit(); + virtual ~GradientTextureEdit(); +}; + +class GradientTextureEditorPlugin : public EditorPlugin { + + GDCLASS(GradientTextureEditorPlugin, EditorPlugin); + + bool _2d; + Ref<GradientTexture> gradient_texture_ref; + GradientTextureEdit *ramp_editor; + EditorNode *editor; + ToolButton *gradient_button; + +protected: + static void _bind_methods(); + void _ramp_changed(); + void _undo_redo_gradient_texture(const Vector<float> &offsets, const Vector<Color> &colors); + +public: + virtual String get_name() const { return "GradientTexture"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + GradientTextureEditorPlugin(EditorNode *p_node); + ~GradientTextureEditorPlugin(); +}; + +#endif // GRADIENT_TEXTURE_EDITOR_PLUGIN_H diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index fd26674a0e..9624030246 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -27,30 +27,24 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#if 0 #include "particles_editor_plugin.h" #include "editor/plugins/spatial_editor_plugin.h" #include "io/resource_loader.h" -#include "servers/visual/particle_system_sw.h" - void ParticlesEditor::_node_removed(Node *p_node) { - if(p_node==node) { - node=NULL; + if (p_node == node) { + node = NULL; hide(); } - } - -void ParticlesEditor::_resource_seleted(const String& p_res) { +void ParticlesEditor::_resource_seleted(const String &p_res) { //print_line("selected resource path: "+p_res); } -void ParticlesEditor::_node_selected(const NodePath& p_path){ - +void ParticlesEditor::_node_selected(const NodePath &p_path) { Node *sel = get_node(p_path); if (!sel) @@ -66,12 +60,11 @@ void ParticlesEditor::_node_selected(const NodePath& p_path){ geometry = vi->get_faces(VisualInstance::FACES_SOLID); - if (geometry.size()==0) { + if (geometry.size() == 0) { err_dialog->set_text(TTR("Node does not contain geometry (faces).")); err_dialog->popup_centered_minsize(); return; - } Transform geom_xform = node->get_global_transform().affine_inverse() * vi->get_global_transform(); @@ -79,20 +72,17 @@ void ParticlesEditor::_node_selected(const NodePath& p_path){ int gc = geometry.size(); PoolVector<Face3>::Write w = geometry.write(); - - for(int i=0;i<gc;i++) { - for(int j=0;j<3;j++) { - w[i].vertex[j] = geom_xform.xform( w[i].vertex[j] ); + for (int i = 0; i < gc; i++) { + for (int j = 0; j < 3; j++) { + w[i].vertex[j] = geom_xform.xform(w[i].vertex[j]); } } - w = PoolVector<Face3>::Write(); - emission_dialog->popup_centered(Size2(300,130)); + emission_dialog->popup_centered(Size2(300, 130)); } - /* void ParticlesEditor::_populate() { @@ -112,74 +102,77 @@ void ParticlesEditor::_populate() { void ParticlesEditor::_notification(int p_notification) { - if (p_notification==NOTIFICATION_ENTER_TREE) { - options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons")); - + if (p_notification == NOTIFICATION_ENTER_TREE) { + options->set_icon(options->get_popup()->get_icon("Particles", "EditorIcons")); } } - void ParticlesEditor::_menu_option(int p_option) { - - switch(p_option) { + switch (p_option) { case MENU_OPTION_GENERATE_AABB: { - +#if 0 Transform globalizer = node->get_global_transform(); ParticleSystemSW pssw; - for(int i=0;i<VS::PARTICLE_VAR_MAX;i++) { + for (int i = 0; i < VS::PARTICLE_VAR_MAX; i++) { - pssw.particle_vars[i]=node->get_variable((Particles::Variable)i); - pssw.particle_randomness[i]=node->get_randomness((Particles::Variable)i); + pssw.particle_vars[i] = node->get_variable((Particles::Variable)i); + pssw.particle_randomness[i] = node->get_randomness((Particles::Variable)i); } - pssw.emission_half_extents=node->get_emission_half_extents(); - pssw.emission_points=node->get_emission_points(); - pssw.emission_base_velocity=node->get_emission_base_velocity(); - pssw.amount=node->get_amount(); - pssw.gravity_normal=node->get_gravity_normal(); - pssw.emitting=true; - pssw.height_from_velocity=node->has_height_from_velocity(); - pssw.color_phase_count=1; - + pssw.emission_half_extents = node->get_emission_half_extents(); + pssw.emission_points = node->get_emission_points(); + pssw.emission_base_velocity = node->get_emission_base_velocity(); + pssw.amount = node->get_amount(); + pssw.gravity_normal = node->get_gravity_normal(); + pssw.emitting = true; + pssw.height_from_velocity = node->has_height_from_velocity(); + pssw.color_phase_count = 1; ParticleSystemProcessSW pp; - float delta=0.01; - float lifetime=pssw.particle_vars[VS::PARTICLE_LIFETIME]; - + float delta = 0.01; + float lifetime = pssw.particle_vars[VS::PARTICLE_LIFETIME]; Transform localizer = globalizer.affine_inverse(); AABB aabb; - for(float t=0;t<lifetime;t+=delta) { + for (float t = 0; t < lifetime; t += delta) { - pp.process(&pssw,globalizer,delta); - for(int i=0;i<pp.particle_data.size();i++) { + pp.process(&pssw, globalizer, delta); + for (int i = 0; i < pp.particle_data.size(); i++) { Vector3 p = localizer.xform(pp.particle_data[i].pos); - if (t==0 && i==0) - aabb.pos=p; + if (t == 0 && i == 0) + aabb.pos = p; else aabb.expand_to(p); } } - aabb.grow_by( aabb.get_longest_axis_size()*0.2); + aabb.grow_by(aabb.get_longest_axis_size() * 0.2); node->set_visibility_aabb(aabb); - - +#endif } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH: { - + Ref<ParticlesMaterial> material = node->get_process_material(); + if (material.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + return; + } emission_file_dialog->popup_centered_ratio(); } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { -/* + Ref<ParticlesMaterial> material = node->get_process_material(); + if (material.is_null()) { + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + return; + } + /* Node *root = get_scene()->get_root_node(); ERR_FAIL_COND(!root); EditorNode *en = root->cast_to<EditorNode>(); @@ -192,50 +185,50 @@ void ParticlesEditor::_menu_option(int p_option) { } } - void ParticlesEditor::edit(Particles *p_particles) { - node=p_particles; - + node = p_particles; } void ParticlesEditor::_generate_emission_points() { /// hacer codigo aca - PoolVector<Vector3> points; + PoolVector<float> points; + bool use_normals = emission_fill->get_selected() == 1; + PoolVector<float> normals; - if (emission_fill->get_selected()==0) { + if (emission_fill->get_selected() < 2) { - float area_accum=0; - Map<float,int> triangle_area_map; - print_line("geometry size: "+itos(geometry.size())); + float area_accum = 0; + Map<float, int> triangle_area_map; + print_line("geometry size: " + itos(geometry.size())); - for(int i=0;i<geometry.size();i++) { + for (int i = 0; i < geometry.size(); i++) { float area = geometry[i].get_area(); - if (area<CMP_EPSILON) + if (area < CMP_EPSILON) continue; - triangle_area_map[area_accum]=i; - area_accum+=area; + triangle_area_map[area_accum] = i; + area_accum += area; } - if (!triangle_area_map.size() || area_accum==0) { + if (!triangle_area_map.size() || area_accum == 0) { err_dialog->set_text(TTR("Faces contain no area!")); err_dialog->popup_centered_minsize(); return; } - int emissor_count=emission_amount->get_val(); + int emissor_count = emission_amount->get_value(); - for(int i=0;i<emissor_count;i++) { + for (int i = 0; i < emissor_count; i++) { - float areapos = Math::random(0,area_accum); + float areapos = Math::random(0.0f, area_accum); - Map<float,int>::Element *E = triangle_area_map.find_closest(areapos); + Map<float, int>::Element *E = triangle_area_map.find_closest(areapos); ERR_FAIL_COND(!E) int index = E->get(); - ERR_FAIL_INDEX(index,geometry.size()); + ERR_FAIL_INDEX(index, geometry.size()); // ok FINALLY get face Face3 face = geometry[index]; @@ -243,13 +236,22 @@ void ParticlesEditor::_generate_emission_points() { Vector3 pos = face.get_random_point_inside(); - points.push_back(pos); + points.push_back(pos.x); + points.push_back(pos.y); + points.push_back(pos.z); + + if (use_normals) { + Vector3 normal = face.get_plane().normal; + normals.push_back(normal.x); + normals.push_back(normal.y); + normals.push_back(normal.z); + } } } else { int gcount = geometry.size(); - if (gcount==0) { + if (gcount == 0) { err_dialog->set_text(TTR("No faces!")); err_dialog->popup_centered_minsize(); @@ -258,32 +260,32 @@ void ParticlesEditor::_generate_emission_points() { PoolVector<Face3>::Read r = geometry.read(); - AABB aabb; + Rect3 aabb; - for(int i=0;i<gcount;i++) { + for (int i = 0; i < gcount; i++) { - for(int j=0;j<3;j++) { + for (int j = 0; j < 3; j++) { - if (i==0 && j==0) - aabb.pos=r[i].vertex[j]; + if (i == 0 && j == 0) + aabb.pos = r[i].vertex[j]; else aabb.expand_to(r[i].vertex[j]); } } - int emissor_count=emission_amount->get_val(); + int emissor_count = emission_amount->get_value(); - for(int i=0;i<emissor_count;i++) { + for (int i = 0; i < emissor_count; i++) { - int attempts=5; + int attempts = 5; - for(int j=0;j<attempts;j++) { + for (int j = 0; j < attempts; j++) { Vector3 dir; - dir[Math::rand()%3]=1.0; - Vector3 ofs = Vector3(1,1,1)-dir; - ofs=(Vector3(1,1,1)-dir)*Vector3(Math::randf(),Math::randf(),Math::randf())*aabb.size; - ofs+=aabb.pos; + dir[Math::rand() % 3] = 1.0; + Vector3 ofs = Vector3(1, 1, 1) - dir; + ofs = (Vector3(1, 1, 1) - dir) * Vector3(Math::randf(), Math::randf(), Math::randf()) * aabb.size; + ofs += aabb.pos; Vector3 ofsv = ofs + aabb.size * dir; @@ -291,135 +293,172 @@ void ParticlesEditor::_generate_emission_points() { ofs -= dir; ofsv += dir; - float max=-1e7,min=1e7; + float max = -1e7, min = 1e7; - for(int k=0;k<gcount;k++) { + for (int k = 0; k < gcount; k++) { - const Face3& f3 = r[k]; + const Face3 &f3 = r[k]; Vector3 res; - if (f3.intersects_segment(ofs,ofsv,&res)) { + if (f3.intersects_segment(ofs, ofsv, &res)) { - res-=ofs; + res -= ofs; float d = dir.dot(res); - if (d<min) - min=d; - if (d>max) - max=d; - + if (d < min) + min = d; + if (d > max) + max = d; } } - - if (max<min) + if (max < min) continue; //lost attempt - float val = min + (max-min)*Math::randf(); + float val = min + (max - min) * Math::randf(); Vector3 point = ofs + dir * val; - points.push_back(point); + points.push_back(point.x); + points.push_back(point.y); + points.push_back(point.z); break; } } } - //print_line("point count: "+itos(points.size())); - node->set_emission_points(points); + int point_count = points.size() / 3; + + int w = 2048; + int h = (point_count / 2048) + 1; + PoolVector<uint8_t> point_img; + point_img.resize(w * h * 3 * sizeof(float)); + + { + PoolVector<uint8_t>::Write iw = point_img.write(); + zeromem(iw.ptr(), w * h * 3 * sizeof(float)); + PoolVector<float>::Read r = points.read(); + copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3); + } + + Image image(w, h, false, Image::FORMAT_RGBF, point_img); + + Ref<ImageTexture> tex; + tex.instance(); + tex->create_from_image(image, Texture::FLAG_FILTER); + + Ref<ParticlesMaterial> material = node->get_process_material(); + ERR_FAIL_COND(material.is_null()); + + if (use_normals) { + + material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); + material->set_emission_point_count(point_count); + material->set_emission_point_texture(tex); + + PoolVector<uint8_t> point_img2; + point_img2.resize(w * h * 3 * sizeof(float)); + + { + PoolVector<uint8_t>::Write iw = point_img2.write(); + zeromem(iw.ptr(), w * h * 3 * sizeof(float)); + PoolVector<float>::Read r = normals.read(); + copymem(iw.ptr(), r.ptr(), point_count * sizeof(float) * 3); + } + + Image image2(w, h, false, Image::FORMAT_RGBF, point_img2); + + Ref<ImageTexture> tex2; + tex2.instance(); + tex2->create_from_image(image2, Texture::FLAG_FILTER); + + material->set_emission_normal_texture(tex2); + } else { + + material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); + material->set_emission_point_count(point_count); + material->set_emission_point_texture(tex); + } + + //print_line("point count: "+itos(points.size())); + //node->set_emission_points(points); } void ParticlesEditor::_bind_methods() { - ClassDB::bind_method("_menu_option",&ParticlesEditor::_menu_option); - ClassDB::bind_method("_resource_seleted",&ParticlesEditor::_resource_seleted); - ClassDB::bind_method("_node_selected",&ParticlesEditor::_node_selected); - ClassDB::bind_method("_generate_emission_points",&ParticlesEditor::_generate_emission_points); + ClassDB::bind_method("_menu_option", &ParticlesEditor::_menu_option); + ClassDB::bind_method("_resource_seleted", &ParticlesEditor::_resource_seleted); + ClassDB::bind_method("_node_selected", &ParticlesEditor::_node_selected); + ClassDB::bind_method("_generate_emission_points", &ParticlesEditor::_generate_emission_points); //ClassDB::bind_method("_populate",&ParticlesEditor::_populate); - } ParticlesEditor::ParticlesEditor() { - particles_editor_hb = memnew ( HBoxContainer ); + particles_editor_hb = memnew(HBoxContainer); SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); - options = memnew( MenuButton ); + options = memnew(MenuButton); particles_editor_hb->add_child(options); particles_editor_hb->hide(); options->set_text("Particles"); - options->get_popup()->add_item(TTR("Generate AABB"),MENU_OPTION_GENERATE_AABB); + options->get_popup()->add_item(TTR("Generate AABB"), MENU_OPTION_GENERATE_AABB); options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Create Emitter From Mesh"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH); - options->get_popup()->add_item(TTR("Create Emitter From Node"),MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE); - options->get_popup()->add_item(TTR("Clear Emitter"),MENU_OPTION_CLEAR_EMISSION_VOLUME); + options->get_popup()->add_item(TTR("Create Emission Points From Mesh"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_MESH); + options->get_popup()->add_item(TTR("Create Emission Points From Node"), MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE); + // options->get_popup()->add_item(TTR("Clear Emitter"), MENU_OPTION_CLEAR_EMISSION_VOLUME); - options->get_popup()->connect("id_pressed", this,"_menu_option"); + options->get_popup()->connect("id_pressed", this, "_menu_option"); - emission_dialog = memnew( ConfirmationDialog ); + emission_dialog = memnew(ConfirmationDialog); emission_dialog->set_title(TTR("Create Emitter")); add_child(emission_dialog); - Label *l = memnew(Label); - l->set_pos(Point2(5,5)); - l->set_text(TTR("Emission Positions:")); - emission_dialog->add_child(l); - + VBoxContainer *emd_vb = memnew(VBoxContainer); + emission_dialog->add_child(emd_vb); - emission_amount = memnew( SpinBox ); - emission_amount->set_anchor(MARGIN_RIGHT,ANCHOR_END); - emission_amount->set_begin( Point2(20,23)); - emission_amount->set_end( Point2(5,25)); + emission_amount = memnew(SpinBox); emission_amount->set_min(1); - emission_amount->set_max(65536); - emission_amount->set_val(512); - emission_dialog->add_child(emission_amount); - emission_dialog->get_ok()->set_text(TTR("Create")); - emission_dialog->connect("confirmed",this,"_generate_emission_points"); - - l = memnew(Label); - l->set_pos(Point2(5,50)); - l->set_text(TTR("Emission Fill:")); - emission_dialog->add_child(l); - - emission_fill = memnew( OptionButton ); - emission_fill->set_anchor(MARGIN_RIGHT,ANCHOR_END); - emission_fill->set_begin( Point2(20,70)); - emission_fill->set_end( Point2(5,75)); - emission_fill->add_item(TTR("Surface")); + emission_amount->set_max(100000); + emission_amount->set_value(512); + emd_vb->add_margin_child(TTR("Emission Points:"), emission_amount); + + emission_fill = memnew(OptionButton); + emission_fill->add_item(TTR("Surface Points")); + emission_fill->add_item(TTR("Surface Points+Normal (Directed)")); emission_fill->add_item(TTR("Volume")); - emission_dialog->add_child(emission_fill); + emd_vb->add_margin_child(TTR("Emission Source: "), emission_fill); + + emission_dialog->get_ok()->set_text(TTR("Create")); + emission_dialog->connect("confirmed", this, "_generate_emission_points"); - err_dialog = memnew( ConfirmationDialog ); + err_dialog = memnew(ConfirmationDialog); //err_dialog->get_cancel()->hide(); add_child(err_dialog); - - emission_file_dialog = memnew( EditorFileDialog ); + emission_file_dialog = memnew(EditorFileDialog); add_child(emission_file_dialog); - emission_file_dialog->connect("file_selected",this,"_resource_seleted"); - emission_tree_dialog = memnew( SceneTreeDialog ); + emission_file_dialog->connect("file_selected", this, "_resource_seleted"); + emission_tree_dialog = memnew(SceneTreeDialog); add_child(emission_tree_dialog); - emission_tree_dialog->connect("selected",this,"_node_selected"); + emission_tree_dialog->connect("selected", this, "_node_selected"); List<String> extensions; - ResourceLoader::get_recognized_extensions_for_type("Mesh",&extensions); + ResourceLoader::get_recognized_extensions_for_type("Mesh", &extensions); emission_file_dialog->clear_filters(); - for(int i=0;i<extensions.size();i++) { + for (int i = 0; i < extensions.size(); i++) { - emission_file_dialog->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); + emission_file_dialog->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } emission_file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE); //options->set_anchor(MARGIN_LEFT,Control::ANCHOR_END); //options->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END); - } - void ParticlesEditorPlugin::edit(Object *p_object) { particles_editor->edit(p_object->cast_to<Particles>()); @@ -427,7 +466,7 @@ void ParticlesEditorPlugin::edit(Object *p_object) { bool ParticlesEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("Particles"); + return p_object->is_class("Particles"); } void ParticlesEditorPlugin::make_visible(bool p_visible) { @@ -440,21 +479,16 @@ void ParticlesEditorPlugin::make_visible(bool p_visible) { particles_editor->hide(); particles_editor->edit(NULL); } - } ParticlesEditorPlugin::ParticlesEditorPlugin(EditorNode *p_node) { - editor=p_node; - particles_editor = memnew( ParticlesEditor ); + editor = p_node; + particles_editor = memnew(ParticlesEditor); editor->get_viewport()->add_child(particles_editor); particles_editor->hide(); } - -ParticlesEditorPlugin::~ParticlesEditorPlugin() -{ +ParticlesEditorPlugin::~ParticlesEditorPlugin() { } - -#endif diff --git a/editor/plugins/particles_editor_plugin.h b/editor/plugins/particles_editor_plugin.h index 420e20d641..b3394d879e 100644 --- a/editor/plugins/particles_editor_plugin.h +++ b/editor/plugins/particles_editor_plugin.h @@ -37,17 +37,16 @@ /** @author Juan Linietsky <reduzio@gmail.com> */ -#if 0 + class ParticlesEditor : public Control { - GDCLASS(ParticlesEditor, Control ); + GDCLASS(ParticlesEditor, Control); Panel *panel; MenuButton *options; HBoxContainer *particles_editor_hb; Particles *node; - EditorFileDialog *emission_file_dialog; SceneTreeDialog *emission_tree_dialog; @@ -57,9 +56,6 @@ class ParticlesEditor : public Control { SpinBox *emission_amount; OptionButton *emission_fill; - - - enum Menu { MENU_OPTION_GENERATE_AABB, @@ -72,35 +68,33 @@ class ParticlesEditor : public Control { PoolVector<Face3> geometry; void _generate_emission_points(); - void _resource_seleted(const String& p_res); - void _node_selected(const NodePath& p_path); + void _resource_seleted(const String &p_res); + void _node_selected(const NodePath &p_path); void _menu_option(int); void _populate(); -friend class ParticlesEditorPlugin; + friend class ParticlesEditorPlugin; protected: - void _notification(int p_notification); void _node_removed(Node *p_node); static void _bind_methods(); -public: +public: void edit(Particles *p_particles); ParticlesEditor(); }; class ParticlesEditorPlugin : public EditorPlugin { - GDCLASS( ParticlesEditorPlugin, EditorPlugin ); + GDCLASS(ParticlesEditorPlugin, EditorPlugin); ParticlesEditor *particles_editor; EditorNode *editor; public: - virtual String get_name() const { return "Particles"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_node); @@ -109,8 +103,6 @@ public: ParticlesEditorPlugin(EditorNode *p_node); ~ParticlesEditorPlugin(); - }; #endif // PARTICLES_EDITOR_PLUGIN_H -#endif diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 0b3587bc5e..6fcda001ee 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -530,16 +530,16 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { editor=p_node; singleton=this; - path_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial )); - path_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) ); - path_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); + path_material = Ref<SpatialMaterial>( memnew( SpatialMaterial )); + path_material->set_parameter( SpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) ); + path_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); path_material->set_line_width(3); path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); path_material->set_flag(Material::FLAG_UNSHADED,true); - path_thin_material = Ref<FixedSpatialMaterial>( memnew( FixedSpatialMaterial )); - path_thin_material->set_parameter( FixedSpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) ); - path_thin_material->set_fixed_flag(FixedSpatialMaterial::FLAG_USE_ALPHA, true); + path_thin_material = Ref<SpatialMaterial>( memnew( SpatialMaterial )); + path_thin_material->set_parameter( SpatialMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) ); + path_thin_material->set_fixed_flag(SpatialMaterial::FLAG_USE_ALPHA, true); path_thin_material->set_line_width(1); path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); path_thin_material->set_flag(Material::FLAG_UNSHADED,true); diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 9d0f6eb9f2..131cf11ef8 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -78,8 +78,8 @@ public: Path *get_edited_path() { return path; } static PathEditorPlugin* singleton; - Ref<FixedSpatialMaterial> path_material; - Ref<FixedSpatialMaterial> path_thin_material; + Ref<SpatialMaterial> path_material; + Ref<SpatialMaterial> path_thin_material; virtual bool forward_spatial_gui_input(Camera* p_camera,const InputEvent& p_event); //virtual bool forward_gui_input(const InputEvent& p_event) { return collision_polygon_editor->forward_gui_input(p_event); } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 11dfb7b910..37782ed173 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -137,14 +137,35 @@ void ShaderTextEditor::_load_theme_settings() { }*/ } +void ShaderTextEditor::_check_shader_mode() { + + String type = ShaderLanguage::get_shader_type(get_text_edit()->get_text()); + + print_line("type is: " + type); + Shader::Mode mode; + + if (type == "canvas_item") { + mode = Shader::MODE_CANVAS_ITEM; + } else if (type == "particles") { + mode = Shader::MODE_PARTICLES; + } else { + mode = Shader::MODE_SPATIAL; + } + + if (shader->get_mode() != mode) { + shader->set_code(get_text_edit()->get_text()); + _load_theme_settings(); + } +} + void ShaderTextEditor::_code_complete_script(const String &p_code, List<String> *r_options) { - print_line("code complete"); + _check_shader_mode(); ShaderLanguage sl; String calltip; - Error err = sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), r_options, calltip); + Error err = sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip); if (calltip != "") { get_text_edit()->set_code_hint(calltip); @@ -153,13 +174,15 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<String> void ShaderTextEditor::_validate_script() { + _check_shader_mode(); + String code = get_text_edit()->get_text(); //List<StringName> params; //shader->get_param_list(¶ms); ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode()))); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types()); if (err != OK) { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 4a56c14ecb..14caf4ab49 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -44,6 +44,8 @@ class ShaderTextEditor : public CodeTextEditor { Ref<Shader> shader; + void _check_shader_mode(); + protected: static void _bind_methods(); virtual void _load_theme_settings(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index c00652bc35..5e0901f9be 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -524,7 +524,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hil return false; if (get_selected_count() == 0) { if (p_hilite_only) - spatial_editor->select_gizmo_hilight_axis(-1); + spatial_editor->select_gizmo_highlight_axis(-1); return false; } @@ -558,7 +558,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hil if (p_hilite_only) { - spatial_editor->select_gizmo_hilight_axis(col_axis); + spatial_editor->select_gizmo_highlight_axis(col_axis); } else { //handle rotate @@ -598,7 +598,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hil if (p_hilite_only) { - spatial_editor->select_gizmo_hilight_axis(col_axis + 3); + spatial_editor->select_gizmo_highlight_axis(col_axis + 3); } else { //handle rotate _edit.mode = TRANSFORM_ROTATE; @@ -610,7 +610,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hil } if (p_hilite_only) - spatial_editor->select_gizmo_hilight_axis(-1); + spatial_editor->select_gizmo_highlight_axis(-1); return false; } @@ -1069,7 +1069,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { spatial_editor->set_over_gizmo_handle(selected_handle); spatial_editor->get_selected()->update_gizmo(); if (selected_handle != -1) - spatial_editor->select_gizmo_hilight_axis(-1); + spatial_editor->select_gizmo_highlight_axis(-1); } } } @@ -2229,7 +2229,7 @@ SpatialEditorSelectedItem::~SpatialEditorSelectedItem() { VisualServer::get_singleton()->free(sbox_instance); } -void SpatialEditor::select_gizmo_hilight_axis(int p_axis) { +void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { for (int i = 0; i < 3; i++) { @@ -2329,12 +2329,12 @@ void SpatialEditor::_generate_selection_box() { st->add_vertex(b); } - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); - mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); mat->set_albedo(Color(1, 1, 1)); - mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); - mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); st->set_material(mat); selection_box = st->commit(); } @@ -2888,12 +2888,12 @@ void SpatialEditor::_init_indicators() { { indicator_mat.instance(); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - //indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP,true); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + //indicator_mat->set_flag(SpatialMaterial::FLAG_ONTOP,true); + indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - indicator_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); PoolVector<Color> grid_colors[3]; PoolVector<Vector3> grid_points[3]; @@ -2980,7 +2980,7 @@ void SpatialEditor::_init_indicators() { cursor_points.push_back(Vector3(0, 0, -cs)); cursor_material.instance(); cursor_material->set_albedo(Color(0, 1, 1)); - cursor_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + cursor_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); Array d; d.resize(VS::ARRAY_MAX); @@ -3000,10 +3000,10 @@ void SpatialEditor::_init_indicators() { float gizmo_alph = EditorSettings::get_singleton()->get("editors/3d/manipulator_gizmo_opacity"); - gizmo_hl = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - gizmo_hl->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true); - gizmo_hl->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + gizmo_hl = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + gizmo_hl->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + gizmo_hl->set_flag(SpatialMaterial::FLAG_ONTOP, true); + gizmo_hl->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); gizmo_hl->set_albedo(Color(1, 1, 1, gizmo_alph + 0.2f)); for (int i = 0; i < 3; i++) { @@ -3011,10 +3011,10 @@ void SpatialEditor::_init_indicators() { move_gizmo[i] = Ref<Mesh>(memnew(Mesh)); rotate_gizmo[i] = Ref<Mesh>(memnew(Mesh)); - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); - mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true); - mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + mat->set_flag(SpatialMaterial::FLAG_ONTOP, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); Color col; col[i] = 1.0; col.a = gizmo_alph; diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index e0d2a38956..0dedd6ce6d 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -323,8 +323,8 @@ private: bool grid_enabled; Ref<Mesh> move_gizmo[3], rotate_gizmo[3]; - Ref<FixedSpatialMaterial> gizmo_color[3]; - Ref<FixedSpatialMaterial> gizmo_hl; + Ref<SpatialMaterial> gizmo_color[3]; + Ref<SpatialMaterial> gizmo_hl; int over_gizmo_handle; @@ -333,8 +333,8 @@ private: RID indicators_instance; RID cursor_mesh; RID cursor_instance; - Ref<FixedSpatialMaterial> indicator_mat; - Ref<FixedSpatialMaterial> cursor_material; + Ref<SpatialMaterial> indicator_mat; + Ref<SpatialMaterial> cursor_material; /* struct Selected { @@ -484,7 +484,7 @@ public: void update_transform_gizmo(); - void select_gizmo_hilight_axis(int p_axis); + void select_gizmo_highlight_axis(int p_axis); void set_custom_camera(Node *p_camera) { custom_camera = p_camera; } void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo = p_undo_redo; } diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 6dee151d99..2ae6f6a3d7 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -58,7 +58,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me Sprite *mi = child->cast_to<Sprite>(); Ref<Texture> texture = mi->get_texture(); - Ref<CanvasItemMaterial> material = mi->get_material(); + Ref<ShaderMaterial> material = mi->get_material(); if (texture.is_null()) continue; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index cc26769939..f2a79a2f47 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -3846,8 +3846,8 @@ void PropertyEditor::_item_edited() { } break; case Variant::BOOL: { - _edit_set(name, item->is_checked(1), refresh_all); item->set_tooltip(1, item->is_checked(1) ? "True" : "False"); + _edit_set(name, item->is_checked(1), refresh_all); } break; case Variant::INT: case Variant::REAL: { diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 3310405ae9..5f0bc8841b 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -1113,6 +1113,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope tree->set_anchor(MARGIN_BOTTOM, ANCHOR_END); tree->set_begin(Point2(0, p_label ? 18 : 0)); tree->set_end(Point2(0, 0)); + tree->add_constant_override("button_margin", 0); add_child(tree); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index d1a8aa62e5..47c89419a0 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -359,20 +359,28 @@ ScriptCreateDialog::ScriptCreateDialog() { language_menu = memnew(OptionButton); vb->add_margin_child(TTR("Language"), language_menu); + int default_lang = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { - language_menu->add_item(ScriptServer::get_language(i)->get_name()); + String lang = ScriptServer::get_language(i)->get_name(); + language_menu->add_item(lang); + if (lang == "GDScript") { + default_lang = i; + } } editor_settings = EditorSettings::get_singleton(); String last_selected_language = editor_settings->get_project_metadata("script_setup", "last_selected_language", ""); - if (last_selected_language != "") - for (int i = 0; i < language_menu->get_item_count(); i++) + if (last_selected_language != "") { + for (int i = 0; i < language_menu->get_item_count(); i++) { if (language_menu->get_item_text(i) == last_selected_language) { language_menu->select(i); break; - } else - language_menu->select(0); + } + } + } else { + language_menu->select(default_lang); + } language_menu->connect("item_selected", this, "_lang_changed"); diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 8a24ed2b2f..385de3fa18 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -70,10 +70,6 @@ void EditorSpatialGizmo::Instance::create_instance(Spatial *p_base) { instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); VS::get_singleton()->instance_attach_object_instance_ID(instance, p_base->get_instance_ID()); - if (billboard) - VS::get_singleton()->instance_geometry_set_flag(instance, VS::INSTANCE_FLAG_BILLBOARD, true); - if (unscaled) - VS::get_singleton()->instance_geometry_set_flag(instance, VS::INSTANCE_FLAG_DEPH_SCALE, true); if (skeleton.is_valid()) VS::get_singleton()->instance_attach_skeleton(instance, skeleton); if (extra_margin) @@ -228,7 +224,6 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi Array a; a.resize(VS::ARRAY_MAX); a[VS::ARRAY_VERTEX] = p_handles; - print_line("handles?: " + itos(p_handles.size())); PoolVector<Color> colors; { colors.resize(p_handles.size()); @@ -243,7 +238,10 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi } a[VS::ARRAY_COLOR] = colors; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, a); - mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material); + if (p_billboard) + mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material_billboard); + else + mesh->surface_set_material(0, SpatialEditorGizmos::singleton->handle2_material); if (p_billboard) { float md = 0; @@ -390,7 +388,7 @@ bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_p Transform t = spatial_node->get_global_transform(); t.orthonormalize(); if (billboard_handle) { - t.set_look_at(t.origin, t.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); + t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); } float min_d = 1e20; @@ -452,7 +450,7 @@ bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_p const Vector3 *vptr = collision_segments.ptr(); Transform t = spatial_node->get_global_transform(); if (billboard_handle) { - t.set_look_at(t.origin, t.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); + t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); } Vector3 cp; @@ -504,7 +502,7 @@ bool EditorSpatialGizmo::intersect_ray(const Camera *p_camera, const Point2 &p_p Transform gt = spatial_node->get_global_transform(); if (billboard_handle) { - gt.set_look_at(gt.origin, gt.origin + p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); + gt.set_look_at(gt.origin, gt.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1)); } Transform ai = gt.affine_inverse(); @@ -777,7 +775,7 @@ void LightSpatialGizmo::redraw() { points.push_back(Vector3(b.x, b.y, 0)); } - add_lines(points, SpatialEditorGizmos::singleton->light_material, true); + add_lines(points, SpatialEditorGizmos::singleton->light_material_omni, true); add_collision_segments(points); add_unscaled_billboard(SpatialEditorGizmos::singleton->light_material_omni_icon, 0.05); @@ -2994,24 +2992,24 @@ Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) { return Ref<SpatialEditorGizmo>(); } -Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_line_material(const Color &p_base_color) { +Ref<SpatialMaterial> SpatialEditorGizmos::create_line_material(const Color &p_base_color) { - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); line_material->set_line_width(3.0); - line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); - //line_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - //->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + //line_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + //->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); line_material->set_albedo(p_base_color); return line_material; } -Ref<FixedSpatialMaterial> SpatialEditorGizmos::create_solid_material(const Color &p_base_color) { +Ref<SpatialMaterial> SpatialEditorGizmos::create_solid_material(const Color &p_base_color) { - Ref<FixedSpatialMaterial> line_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - line_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - line_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + Ref<SpatialMaterial> line_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + line_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + line_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); line_material->set_albedo(p_base_color); return line_material; @@ -3021,58 +3019,65 @@ SpatialEditorGizmos::SpatialEditorGizmos() { singleton = this; - handle_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - handle_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + handle_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + handle_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); handle_material->set_albedo(Color(0.8, 0.8, 0.8)); + handle_material_billboard = handle_material->duplicate(); + handle_material_billboard->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); - handle2_material = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - handle2_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - handle2_material->set_flag(FixedSpatialMaterial::FLAG_USE_POINT_SIZE, true); + handle2_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + handle2_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + handle2_material->set_flag(SpatialMaterial::FLAG_USE_POINT_SIZE, true); handle_t = SpatialEditor::get_singleton()->get_icon("Editor3DHandle", "EditorIcons"); handle2_material->set_point_size(handle_t->get_width()); - handle2_material->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, handle_t); + handle2_material->set_texture(SpatialMaterial::TEXTURE_ALBEDO, handle_t); handle2_material->set_albedo(Color(1, 1, 1)); - handle2_material->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); - handle2_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - handle2_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + handle2_material->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); + handle2_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + handle2_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + handle2_material_billboard = handle2_material->duplicate(); + handle2_material_billboard->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); light_material = create_line_material(Color(1, 1, 0.2)); - - light_material_omni_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - light_material_omni_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - light_material_omni_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - light_material_omni_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - light_material_omni_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + light_material_omni = create_line_material(Color(1, 1, 0.2)); + light_material_omni->set_billboard_mode(SpatialMaterial::BILLBOARD_ENABLED); + + light_material_omni_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + light_material_omni_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + light_material_omni_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + light_material_omni_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + light_material_omni_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); light_material_omni_icon->set_albedo(Color(1, 1, 1, 0.9)); - light_material_omni_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); - - light_material_directional_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - light_material_directional_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - light_material_directional_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - light_material_directional_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - light_material_directional_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + light_material_omni_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoLight", "EditorIcons")); + light_material_omni_icon->set_flag(SpatialMaterial::FLAG_FIXED_SIZE, true); + + light_material_directional_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + light_material_directional_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + light_material_directional_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + light_material_directional_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + light_material_directional_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); light_material_directional_icon->set_albedo(Color(1, 1, 1, 0.9)); - light_material_directional_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); + light_material_directional_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoDirectionalLight", "EditorIcons")); camera_material = create_line_material(Color(1.0, 0.5, 1.0)); navmesh_edge_material = create_line_material(Color(0.1, 0.8, 1.0)); navmesh_solid_material = create_solid_material(Color(0.1, 0.8, 1.0, 0.4)); - navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); - navmesh_edge_material->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); - navmesh_solid_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); + navmesh_edge_material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); + navmesh_edge_material->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); + navmesh_solid_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); navmesh_edge_material_disabled = create_line_material(Color(1.0, 0.8, 0.1)); navmesh_solid_material_disabled = create_solid_material(Color(1.0, 0.8, 0.1, 0.4)); - navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); - navmesh_edge_material_disabled->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); - navmesh_solid_material_disabled->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); + navmesh_edge_material_disabled->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, false); + navmesh_edge_material_disabled->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, false); + navmesh_solid_material_disabled->set_cull_mode(SpatialMaterial::CULL_DISABLED); skeleton_material = create_line_material(Color(0.6, 1.0, 0.3)); - skeleton_material->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - skeleton_material->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - skeleton_material->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true); - skeleton_material->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); + skeleton_material->set_cull_mode(SpatialMaterial::CULL_DISABLED); + skeleton_material->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + skeleton_material->set_flag(SpatialMaterial::FLAG_ONTOP, true); + skeleton_material->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); //position 3D Shared mesh @@ -3095,11 +3100,11 @@ SpatialEditorGizmos::SpatialEditorGizmos() { cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); cursor_colors.push_back(Color(0.5, 0.5, 1, 0.7)); - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); - mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); mat->set_line_width(3); Array d; d.resize(VS::ARRAY_MAX); @@ -3119,11 +3124,11 @@ SpatialEditorGizmos::SpatialEditorGizmos() { cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); cursor_colors.push_back(Color(0.5, 0.5, 0.5, 0.7)); - Ref<FixedSpatialMaterial> mat = memnew(FixedSpatialMaterial); - mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); - mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + Ref<SpatialMaterial> mat = memnew(SpatialMaterial); + mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); mat->set_line_width(3); Array d; d.resize(VS::ARRAY_MAX); @@ -3133,13 +3138,13 @@ SpatialEditorGizmos::SpatialEditorGizmos() { listener_line_mesh->surface_set_material(0, mat); } - sample_player_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - sample_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - sample_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - sample_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - sample_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + sample_player_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + sample_player_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + sample_player_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + sample_player_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + sample_player_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); sample_player_icon->set_albedo(Color(1, 1, 1, 0.9)); - sample_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons")); + sample_player_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoSpatialSamplePlayer", "EditorIcons")); room_material = create_line_material(Color(1.0, 0.6, 0.9)); portal_material = create_line_material(Color(1.0, 0.8, 0.6)); @@ -3152,29 +3157,29 @@ SpatialEditorGizmos::SpatialEditorGizmos() { gi_probe_material_internal = create_line_material(Color(0.5, 0.8, 0.3, 0.1)); joint_material = create_line_material(Color(0.6, 0.8, 1.0)); - stream_player_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - stream_player_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - stream_player_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - stream_player_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - stream_player_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + stream_player_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + stream_player_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + stream_player_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + stream_player_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + stream_player_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); stream_player_icon->set_albedo(Color(1, 1, 1, 0.9)); - stream_player_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer", "EditorIcons")); + stream_player_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoSpatialStreamPlayer", "EditorIcons")); - visibility_notifier_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - visibility_notifier_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - visibility_notifier_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - visibility_notifier_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - visibility_notifier_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + visibility_notifier_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + visibility_notifier_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + visibility_notifier_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + visibility_notifier_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + visibility_notifier_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); visibility_notifier_icon->set_albedo(Color(1, 1, 1, 0.9)); - visibility_notifier_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("Visible", "EditorIcons")); + visibility_notifier_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("Visible", "EditorIcons")); - listener_icon = Ref<FixedSpatialMaterial>(memnew(FixedSpatialMaterial)); - listener_icon->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - listener_icon->set_cull_mode(FixedSpatialMaterial::CULL_DISABLED); - listener_icon->set_depth_draw_mode(FixedSpatialMaterial::DEPTH_DRAW_DISABLED); - listener_icon->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + listener_icon = Ref<SpatialMaterial>(memnew(SpatialMaterial)); + listener_icon->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + listener_icon->set_cull_mode(SpatialMaterial::CULL_DISABLED); + listener_icon->set_depth_draw_mode(SpatialMaterial::DEPTH_DRAW_DISABLED); + listener_icon->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); listener_icon->set_albedo(Color(1, 1, 1, 0.9)); - listener_icon->set_texture(FixedSpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons")); + listener_icon->set_texture(SpatialMaterial::TEXTURE_ALBEDO, SpatialEditor::get_singleton()->get_icon("GizmoListener", "EditorIcons")); { diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h index 76564c5a99..a47a134975 100644 --- a/editor/spatial_editor_gizmos.h +++ b/editor/spatial_editor_gizmos.h @@ -399,38 +399,41 @@ public: class SpatialEditorGizmos { public: - Ref<FixedSpatialMaterial> create_line_material(const Color &p_base_color); - Ref<FixedSpatialMaterial> create_solid_material(const Color &p_base_color); - Ref<FixedSpatialMaterial> handle2_material; - Ref<FixedSpatialMaterial> handle_material; - Ref<FixedSpatialMaterial> light_material; - Ref<FixedSpatialMaterial> light_material_omni_icon; - Ref<FixedSpatialMaterial> light_material_directional_icon; - Ref<FixedSpatialMaterial> camera_material; - Ref<FixedSpatialMaterial> skeleton_material; - Ref<FixedSpatialMaterial> reflection_probe_material; - Ref<FixedSpatialMaterial> reflection_probe_material_internal; - Ref<FixedSpatialMaterial> gi_probe_material; - Ref<FixedSpatialMaterial> gi_probe_material_internal; - Ref<FixedSpatialMaterial> room_material; - Ref<FixedSpatialMaterial> portal_material; - Ref<FixedSpatialMaterial> raycast_material; - Ref<FixedSpatialMaterial> visibility_notifier_material; - Ref<FixedSpatialMaterial> car_wheel_material; - Ref<FixedSpatialMaterial> joint_material; - - Ref<FixedSpatialMaterial> navmesh_edge_material; - Ref<FixedSpatialMaterial> navmesh_solid_material; - Ref<FixedSpatialMaterial> navmesh_edge_material_disabled; - Ref<FixedSpatialMaterial> navmesh_solid_material_disabled; - - Ref<FixedSpatialMaterial> listener_icon; - - Ref<FixedSpatialMaterial> sample_player_icon; - Ref<FixedSpatialMaterial> stream_player_icon; - Ref<FixedSpatialMaterial> visibility_notifier_icon; - - Ref<FixedSpatialMaterial> shape_material; + Ref<SpatialMaterial> create_line_material(const Color &p_base_color); + Ref<SpatialMaterial> create_solid_material(const Color &p_base_color); + Ref<SpatialMaterial> handle2_material; + Ref<SpatialMaterial> handle2_material_billboard; + Ref<SpatialMaterial> handle_material; + Ref<SpatialMaterial> handle_material_billboard; + Ref<SpatialMaterial> light_material; + Ref<SpatialMaterial> light_material_omni; + Ref<SpatialMaterial> light_material_omni_icon; + Ref<SpatialMaterial> light_material_directional_icon; + Ref<SpatialMaterial> camera_material; + Ref<SpatialMaterial> skeleton_material; + Ref<SpatialMaterial> reflection_probe_material; + Ref<SpatialMaterial> reflection_probe_material_internal; + Ref<SpatialMaterial> gi_probe_material; + Ref<SpatialMaterial> gi_probe_material_internal; + Ref<SpatialMaterial> room_material; + Ref<SpatialMaterial> portal_material; + Ref<SpatialMaterial> raycast_material; + Ref<SpatialMaterial> visibility_notifier_material; + Ref<SpatialMaterial> car_wheel_material; + Ref<SpatialMaterial> joint_material; + + Ref<SpatialMaterial> navmesh_edge_material; + Ref<SpatialMaterial> navmesh_solid_material; + Ref<SpatialMaterial> navmesh_edge_material_disabled; + Ref<SpatialMaterial> navmesh_solid_material_disabled; + + Ref<SpatialMaterial> listener_icon; + + Ref<SpatialMaterial> sample_player_icon; + Ref<SpatialMaterial> stream_player_icon; + Ref<SpatialMaterial> visibility_notifier_icon; + + Ref<SpatialMaterial> shape_material; Ref<Texture> handle_t; Ref<Mesh> pos3d_mesh; diff --git a/main/input_default.cpp b/main/input_default.cpp index 131e9e3b90..0a5d06c0d3 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -485,12 +485,27 @@ void InputDefault::warp_mouse_pos(const Vector2 &p_to) { Point2i InputDefault::warp_mouse_motion(const InputEventMouseMotion &p_motion, const Rect2 &p_rect) { - const Point2i rel_warped(Math::fmod(p_motion.relative_x, p_rect.size.x), Math::fmod(p_motion.relative_y, p_rect.size.y)); + // The relative distance reported for the next event after a warp is in the boundaries of the + // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod() + // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation + // and the subsequent event, the reported relative distance will be less than the size of the rect + // and thus fmod() will be disabled for handling the situation. + // And due to this mouse warping mechanism being stateless, we need to apply some heuristics to + // detect the warp: if the relative distance is greater than the half of the size of the relevant rect + // (checked per each axis), it will be considered as the consequence of a former pointer warp. + + const Point2i rel_sgn(p_motion.relative_x >= 0.0f ? 1 : -1, p_motion.relative_y >= 0.0 ? 1 : -1); + const Size2i warp_margin = p_rect.size * 0.5f; + const Point2i rel_warped( + Math::fmod(p_motion.relative_x + rel_sgn.x * warp_margin.x, p_rect.size.x) - rel_sgn.x * warp_margin.x, + Math::fmod(p_motion.relative_y + rel_sgn.y * warp_margin.y, p_rect.size.y) - rel_sgn.y * warp_margin.y); + const Point2i pos_local = Point2i(p_motion.global_x, p_motion.global_y) - p_rect.pos; const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y)); if (pos_warped != pos_local) { OS::get_singleton()->warp_mouse_pos(pos_warped + p_rect.pos); } + return rel_warped; } diff --git a/main/tests/test_shader_lang.cpp b/main/tests/test_shader_lang.cpp index 4ca09fe656..74b4f0dd81 100644 --- a/main/tests/test_shader_lang.cpp +++ b/main/tests/test_shader_lang.cpp @@ -323,8 +323,10 @@ MainLoop *test() { Set<String> rm; rm.insert("popo"); + Set<String> types; + types.insert("spatial"); - Error err = sl.compile(code, dt, rm); + Error err = sl.compile(code, dt, rm, types); if (err) { diff --git a/modules/cscript/SCsub b/modules/cscript/SCsub deleted file mode 100644 index 0882406761..0000000000 --- a/modules/cscript/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -env.add_source_files(env.modules_sources, "*.cpp") - -Export('env') diff --git a/modules/cscript/godot_c.cpp b/modules/cscript/godot_c.cpp deleted file mode 100644 index f754f2bb21..0000000000 --- a/modules/cscript/godot_c.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************/ -/* godot_c.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "godot_c.h" diff --git a/modules/cscript/godot_c.h b/modules/cscript/godot_c.h deleted file mode 100644 index 58acbf8bf9..0000000000 --- a/modules/cscript/godot_c.h +++ /dev/null @@ -1,567 +0,0 @@ -/*************************************************************************/ -/* godot_c.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef GODOT_C_H -#define GODOT_C_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(GDAPI_BUILT_IN) || !defined(WINDOWS_ENABLED) -#define GDAPI -#elif defined(GDAPI_EXPORTS) -#define GDAPI __declspec(dllexport) -#else -#define GDAPI __declspec(dllimport) -#endif - -#define GODOT_API_VERSION 1 - -typedef int godot_bool; - -#define GODOT_FALSE 0 -#define GODOT_TRUE 1 - -////// Image - -#define GODOT_IMAGE_FORMAT_GRAYSCALE 0 -#define GODOT_IMAGE_FORMAT_INTENSITY 1 -#define GODOT_IMAGE_FORMAT_GRAYSCALE_ALPHA 2 -#define GODOT_IMAGE_FORMAT_RGB 3 -#define GODOT_IMAGE_FORMAT_RGBA 4 -#define GODOT_IMAGE_FORMAT_INDEXED 5 -#define GODOT_IMAGE_FORMAT_INDEXED_ALPHA 6 -#define GODOT_IMAGE_FORMAT_YUV_422 7 -#define GODOT_IMAGE_FORMAT_YUV_444 8 -#define GODOT_IMAGE_FORMAT_BC1 9 -#define GODOT_IMAGE_FORMAT_BC2 10 -#define GODOT_IMAGE_FORMAT_BC3 11 -#define GODOT_IMAGE_FORMAT_BC4 12 -#define GODOT_IMAGE_FORMAT_BC5 13 -#define GODOT_IMAGE_FORMAT_PVRTC2 14 -#define GODOT_IMAGE_FORMAT_PVRTC2_ALPHA 15 -#define GODOT_IMAGE_FORMAT_PVRTC4 16 -#define GODOT_IMAGE_FORMAT_PVRTC4_ALPHA 17 -#define GODOT_IMAGE_FORMAT_ETC 18 -#define GODOT_IMAGE_FORMAT_ATC 19 -#define GODOT_IMAGE_FORMAT_ATC_ALPHA_EXPLICIT 20 -#define GODOT_IMAGE_FORMAT_ATC_ALPHA_INTERPOLATED 21 - -typedef void *godot_image; - -godot_image GDAPI godot_image_create_empty(); -godot_image GDAPI godot_image_create(int p_width, int p_height, int p_format, int p_use_mipmaps); -godot_image GDAPI godot_image_create_with_data(int p_width, int p_height, int p_format, int p_use_mipmaps, unsigned char *p_buffer); -int GDAPI godot_image_get_width(godot_image p_image); -int GDAPI godot_image_get_height(godot_image p_image); -int GDAPI godot_image_get_format(godot_image p_image); -int GDAPI godot_image_get_mipmap_count(godot_image p_image); -godot_image GDAPI godot_image_copy(godot_image p_image); -void GDAPI godot_image_free(godot_image p_image); - -////// RID - -typedef void *godot_rid; - -godot_rid GDAPI godot_rid_create(); -godot_rid GDAPI godot_rid_copy(godot_rid p_rid); -void GDAPI godot_rid_free(godot_rid p_rid); - -////// Variant (forward declared) - -typedef void *godot_variant; - -////// Dictionary - -typedef void *godot_dictionary; - -godot_dictionary GDAPI godot_dictionary_create(); -void GDAPI godot_dictionary_has(godot_dictionary p_dictionary, godot_variant p_key); -godot_variant GDAPI godot_dictionary_get(godot_dictionary p_dictionary, godot_variant p_key); -void GDAPI godot_dictionary_insert(godot_dictionary p_dictionary, godot_variant p_key, godot_variant p_value); -void GDAPI godot_dictionary_remove(godot_dictionary p_dictionary, godot_variant p_key); -void GDAPI godot_dictionary_clear(godot_dictionary p_dictionary); -int GDAPI godot_dictionary_get_size(godot_dictionary p_dictionary); -void GDAPI godot_dictionary_get_keys(godot_dictionary p_dictionary, godot_variant *p_keys); -godot_dictionary GDAPI godot_dictionary_copy(godot_dictionary p_dictionary); -void GDAPI godot_dictionary_free(godot_dictionary p_dictionary); - -////// Array - -typedef void *godot_array; - -godot_array GDAPI godot_array_create(); -godot_variant GDAPI godot_array_get(godot_array p_array, int p_index); -void GDAPI godot_array_set(godot_array p_array, int p_index, godot_variant p_value); -void GDAPI godot_array_resize(godot_array p_array, int p_size); -void GDAPI godot_array_insert(godot_array p_array, int p_position, godot_variant p_value); -void GDAPI godot_array_remove(godot_array p_array, int p_position); -void GDAPI godot_array_clear(godot_array p_array); -int GDAPI godot_array_get_size(godot_array p_array); -int GDAPI godot_array_find(godot_array p_array, godot_variant p_value, int p_from_pos = -1); -godot_array GDAPI godot_array_copy(godot_array p_array); -void GDAPI godot_array_free(godot_array p_array); - -////// InputEvent - -#define INPUT_EVENT_BUTTON_LEFT 1 -#define INPUT_EVENT_BUTTON_RIGHT 2 -#define INPUT_EVENT_BUTTON_MIDDLE 3 -#define INPUT_EVENT_BUTTON_WHEEL_UP 4 -#define INPUT_EVENT_BUTTON_WHEEL_DOWN 5 -#define INPUT_EVENT_BUTTON_WHEEL_LEFT 6 -#define INPUT_EVENT_BUTTON_WHEEL_RIGHT 7 -#define INPUT_EVENT_BUTTON_MASK_LEFT (1 << (INPUT_EVENT_BUTTON_LEFT - 1)) -#define INPUT_EVENT_BUTTON_MASK_RIGHT (1 << (INPUT_EVENT_BUTTON_RIGHT - 1)) -#define INPUT_EVENT_BUTTON_MASK_MIDDLE (1 << (INPUT_EVENT_BUTTON_MIDDLE - 1)) - -#define INPUT_EVENT_TYPE_NONE 0 -#define INPUT_EVENT_TYPE_KEY 1 -#define INPUT_EVENT_TYPE_MOUSE_MOTION 2 -#define INPUT_EVENT_TYPE_MOUSE_BUTTON 3 -#define INPUT_EVENT_TYPE_JOYPAD_MOTION 4 -#define INPUT_EVENT_TYPE_JOYPAD_BUTTON 5 -#define INPUT_EVENT_TYPE_SCREEN_TOUCH 6 -#define INPUT_EVENT_TYPE_SCREEN_DRAG 7 -#define INPUT_EVENT_TYPE_ACTION 8 - -typedef void *godot_input_event; - -godot_input_event GDAPI godot_input_event_create(); -godot_input_event GDAPI godot_input_event_copy(godot_input_event p_input_event); -void GDAPI godot_input_event_free(godot_input_event p_input_event); - -int GDAPI godot_input_event_get_type(godot_input_event p_event); -int GDAPI godot_input_event_get_device(godot_input_event p_event); - -godot_bool GDAPI godot_input_event_mod_has_alt(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mod_has_ctrl(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mod_has_command(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mod_has_shift(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mod_has_meta(godot_input_event p_event); - -int GDAPI godot_input_event_key_get_scancode(godot_input_event p_event); -int GDAPI godot_input_event_key_get_unicode(godot_input_event p_event); -godot_bool GDAPI godot_input_event_key_is_pressed(godot_input_event p_event); -godot_bool GDAPI godot_input_event_key_is_echo(godot_input_event p_event); - -int GDAPI godot_input_event_mouse_get_x(godot_input_event p_event); -int GDAPI godot_input_event_mouse_get_y(godot_input_event p_event); -int GDAPI godot_input_event_mouse_get_global_x(godot_input_event p_event); -int GDAPI godot_input_event_mouse_get_global_y(godot_input_event p_event); -int GDAPI godot_input_event_mouse_get_button_mask(godot_input_event p_event); - -int GDAPI godot_input_event_mouse_button_get_button_index(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mouse_button_is_pressed(godot_input_event p_event); -godot_bool GDAPI godot_input_event_mouse_button_is_doubleclick(godot_input_event p_event); - -int GDAPI godot_input_event_mouse_motion_get_relative_x(godot_input_event p_event); -int GDAPI godot_input_event_mouse_motion_get_relative_y(godot_input_event p_event); - -int GDAPI godot_input_event_mouse_motion_get_speed_x(godot_input_event p_event); -int GDAPI godot_input_event_mouse_motion_get_speed_y(godot_input_event p_event); - -int GDAPI godot_input_event_joypad_motion_get_axis(godot_input_event p_event); -float GDAPI godot_input_event_joypad_motion_get_axis_value(godot_input_event p_event); - -int GDAPI godot_input_event_joypad_button_get_button_index(godot_input_event p_event); -godot_bool GDAPI godot_input_event_joypad_button_is_pressed(godot_input_event p_event); -float GDAPI godot_input_event_joypad_button_get_pressure(godot_input_event p_event); - -int GDAPI godot_input_event_screen_touch_get_index(godot_input_event p_event); -int GDAPI godot_input_event_screen_touch_get_x(godot_input_event p_event); -int GDAPI godot_input_event_screen_touch_get_y(godot_input_event p_event); -int GDAPI godot_input_event_screen_touch_is_pressed(godot_input_event p_event); - -int GDAPI godot_input_event_screen_drag_get_index(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_x(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_y(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_relative_x(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_relative_y(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_speed_x(godot_input_event p_event); -int GDAPI godot_input_event_screen_drag_get_speed_y(godot_input_event p_event); - -int GDAPI godot_input_event_is_action(godot_input_event p_event, char *p_action); -int GDAPI godot_input_event_is_action_pressed(godot_input_event p_event, char *p_action); - -////// ByteArray - -typedef void *godot_byte_array; - -godot_byte_array GDAPI godot_byte_array_create(); -godot_byte_array GDAPI godot_byte_array_copy(godot_byte_array p_byte_array); -void GDAPI godot_byte_array_free(godot_byte_array p_byte_array); - -int GDAPI godot_byte_array_get_size(godot_byte_array p_byte_array); -unsigned char GDAPI godot_byte_array_get(godot_byte_array p_byte_array, int p_index); -void GDAPI godot_byte_array_set(godot_byte_array p_byte_array, int p_index, unsigned char p_value); -void GDAPI godot_byte_array_remove(godot_byte_array p_byte_array, int p_index); -void GDAPI godot_byte_array_clear(godot_byte_array p_byte_array); - -typedef void *godot_byte_array_lock; - -godot_byte_array_lock GDAPI godot_byte_array_get_lock(godot_byte_array p_byte_array); -unsigned char GDAPI *godot_byte_array_lock_get_pointer(godot_byte_array_lock p_byte_array_lock); -void GDAPI godot_byte_array_lock_free(godot_byte_array_lock p_byte_array_lock); - -godot_image GDAPI godot_image_create_with_array(int p_width, int p_height, int p_format, int p_use_mipmaps, godot_array p_array); -godot_byte_array GDAPI godot_image_get_data(godot_image p_image); - -////// IntArray - -typedef void *godot_int_array; - -godot_int_array GDAPI godot_int_array_create(); -godot_int_array GDAPI godot_int_array_copy(godot_int_array p_int_array); -void GDAPI godot_int_array_free(godot_int_array p_int_array); - -int GDAPI godot_int_array_get_size(godot_int_array p_int_array); -int GDAPI godot_int_array_get(godot_int_array p_int_array, int p_index); -void GDAPI godot_int_array_set(godot_int_array p_int_array, int p_index, int p_value); -void GDAPI godot_int_array_remove(godot_int_array p_int_array, int p_index); -void GDAPI godot_int_array_clear(godot_int_array p_int_array); - -typedef void *godot_int_array_lock; - -godot_int_array_lock GDAPI godot_int_array_get_lock(godot_int_array p_int_array); -int GDAPI *godot_int_array_lock_get_pointer(godot_int_array_lock p_int_array_lock); -void GDAPI godot_int_array_lock_free(godot_int_array_lock p_int_array_lock); - -////// RealArray - -typedef void *godot_real_array; - -godot_real_array GDAPI godot_real_array_create(); -godot_real_array GDAPI godot_real_array_copy(godot_real_array p_real_array); -void GDAPI godot_real_array_free(godot_real_array p_real_array); - -int GDAPI godot_real_array_get_size(godot_real_array p_real_array); -float GDAPI godot_real_array_get(godot_real_array p_real_array, int p_index); -void GDAPI godot_real_array_set(godot_real_array p_real_array, int p_index, float p_value); -void GDAPI godot_real_array_remove(godot_real_array p_real_array, int p_index); -void GDAPI godot_real_array_clear(godot_real_array p_real_array); - -typedef void *godot_real_array_lock; - -godot_real_array_lock GDAPI godot_real_array_get_lock(godot_real_array p_real_array); -float GDAPI *godot_real_array_lock_get_pointer(godot_real_array_lock p_real_array_lock); -void GDAPI godot_real_array_lock_free(godot_real_array_lock p_real_array_lock); - -////// StringArray - -typedef void *godot_string_array; - -godot_string_array GDAPI godot_string_array_create(); -godot_string_array GDAPI godot_string_array_copy(godot_string_array p_string_array); -void GDAPI godot_string_array_free(godot_string_array p_string_array); - -int GDAPI godot_string_array_get_size(godot_string_array p_string_array); -int GDAPI godot_string_array_get(godot_string_array p_string_array, int p_index, unsigned char *p_string, int p_max_len); -void GDAPI godot_string_array_set(godot_string_array p_string_array, int p_index, unsigned char *p_string); -void GDAPI godot_string_array_remove(godot_string_array p_string_array, int p_index); -void GDAPI godot_string_array_clear(godot_string_array p_string_array); - -////// Vector2Array - -typedef void *godot_vector2_array; - -godot_vector2_array GDAPI godot_vector2_array_create(); -godot_vector2_array GDAPI godot_vector2_array_copy(godot_vector2_array p_vector2_array); -void GDAPI godot_vector2_array_free(godot_vector2_array p_vector2_array); - -int GDAPI godot_vector2_array_get_size(godot_vector2_array p_vector2_array); -int GDAPI godot_vector2_array_get_stride(godot_vector2_array p_vector2_array); -void GDAPI godot_vector2_array_get(godot_vector2_array p_vector2_array, int p_index, float *p_vector2); -void GDAPI godot_vector2_array_set(godot_vector2_array p_vector2_array, int p_index, float *p_vector2); -void GDAPI godot_vector2_array_remove(godot_vector2_array p_vector2_array, int p_index); -void GDAPI godot_vector2_array_clear(godot_vector2_array p_vector2_array); - -typedef void *godot_vector2_array_lock; - -godot_vector2_array_lock GDAPI godot_vector2_array_get_lock(godot_vector2_array p_vector2_array); -float GDAPI *godot_vector2_array_lock_get_pointer(godot_vector2_array_lock p_vector2_array_lock); -void GDAPI godot_vector2_array_lock_free(godot_vector2_array_lock p_vector2_array_lock); - -////// Vector3Array - -typedef void *godot_vector3_array; - -godot_vector3_array GDAPI godot_vector3_array_create(); -godot_vector3_array GDAPI godot_vector3_array_copy(godot_vector3_array p_vector3_array); -void GDAPI godot_vector3_array_free(godot_vector3_array p_vector3_array); - -int GDAPI godot_vector3_array_get_size(godot_vector3_array p_vector3_array); -int GDAPI godot_vector3_array_get_stride(godot_vector3_array p_vector3_array); -void GDAPI godot_vector3_array_get(godot_vector3_array p_vector3_array, int p_index, float *p_vector3); -void GDAPI godot_vector3_array_set(godot_vector3_array p_vector3_array, int p_index, float *p_vector3); -void GDAPI godot_vector3_array_remove(godot_vector3_array p_vector3_array, int p_index); -void GDAPI godot_vector3_array_clear(godot_vector3_array p_vector3_array); - -typedef void *godot_vector3_array_lock; - -godot_vector3_array_lock GDAPI godot_vector3_array_get_lock(godot_vector3_array p_vector3_array); -float GDAPI *godot_vector3_array_lock_get_pointer(godot_vector3_array_lock p_vector3_array_lock); -void GDAPI godot_vector3_array_lock_free(godot_vector3_array_lock p_vector3_array_lock); - -////// ColorArray - -typedef void *godot_color_array; - -godot_color_array GDAPI godot_color_array_create(); -godot_color_array GDAPI godot_color_array_copy(godot_color_array p_color_array); -void GDAPI godot_color_array_free(godot_color_array p_color_array); - -int GDAPI godot_color_array_get_size(godot_color_array p_color_array); -int GDAPI godot_color_array_get_stride(godot_color_array p_color_array); -void GDAPI godot_color_array_get(godot_color_array p_color_array, int p_index, float *p_color); -void GDAPI godot_color_array_set(godot_color_array p_color_array, int p_index, float *p_color); -void GDAPI godot_color_array_remove(godot_color_array p_color_array, int p_index); -void GDAPI godot_color_array_clear(godot_color_array p_color_array); - -typedef void *godot_color_array_lock; - -godot_color_array_lock GDAPI godot_color_array_get_lock(godot_color_array p_color_array); -float GDAPI *godot_color_array_lock_get_pointer(godot_color_array_lock p_color_array_lock); -void GDAPI godot_color_array_lock_free(godot_color_array_lock p_color_array_lock); - -////// Instance (forward declared) - -typedef void *godot_instance; - -////// Variant - -#define GODOT_VARIANT_NIL 0 -#define GODOT_VARIANT_BOOL 1 -#define GODOT_VARIANT_INT 2 -#define GODOT_VARIANT_REAL 3 -#define GODOT_VARIANT_STRING 4 -#define GODOT_VARIANT_VECTOR2 5 -#define GODOT_VARIANT_RECT2 6 -#define GODOT_VARIANT_VECTOR3 7 -#define GODOT_VARIANT_MATRIX32 8 -#define GODOT_VARIANT_PLANE 9 -#define GODOT_VARIANT_QUAT 10 -#define GODOT_VARIANT_AABB 11 -#define GODOT_VARIANT_MATRIX3 12 -#define GODOT_VARIANT_TRANSFORM 13 -#define GODOT_VARIANT_COLOR 14 -#define GODOT_VARIANT_IMAGE 15 -#define GODOT_VARIANT_NODE_PATH 16 -#define GODOT_VARIANT_RID 17 -#define GODOT_VARIANT_OBJECT 18 -#define GODOT_VARIANT_INPUT_EVENT 19 -#define GODOT_VARIANT_DICTIONARY 20 -#define GODOT_VARIANT_ARRAY 21 -#define GODOT_VARIANT_BYTE_ARRAY 22 -#define GODOT_VARIANT_INT_ARRAY 23 -#define GODOT_VARIANT_REAL_ARRAY 24 -#define GODOT_VARIANT_STRING_ARRAY 25 -#define GODOT_VARIANT_VECTOR2_ARRAY 26 -#define GODOT_VARIANT_VECTOR3_ARRAY 27 -#define GODOT_VARIANT_COLOR_ARRAY 28 -#define GODOT_VARIANT_MAX 29 - -godot_variant *godot_variant_new(); - -int GDAPI godot_variant_get_type(godot_variant p_variant); - -void GDAPI godot_variant_set_null(godot_variant p_variant); -void GDAPI godot_variant_set_bool(godot_variant p_variant, godot_bool p_bool); -void GDAPI godot_variant_set_int(godot_variant p_variant, int p_int); -void GDAPI godot_variant_set_float(godot_variant p_variant, int p_float); -void GDAPI godot_variant_set_string(godot_variant p_variant, char *p_string); -void GDAPI godot_variant_set_vector2(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_rect2(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_vector3(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_matrix32(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_plane(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_aabb(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_matrix3(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_transform(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_color(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_set_image(godot_variant p_variant, godot_image *p_image); -void GDAPI godot_variant_set_node_path(godot_variant p_variant, char *p_path); -void GDAPI godot_variant_set_rid(godot_variant p_variant, char *p_path); -void GDAPI godot_variant_set_instance(godot_variant p_variant, godot_instance p_instance); -void GDAPI godot_variant_set_input_event(godot_variant p_variant, godot_input_event p_instance); -void GDAPI godot_variant_set_dictionary(godot_variant p_variant, godot_dictionary p_dictionary); -void GDAPI godot_variant_set_array(godot_variant p_variant, godot_array p_array); -void GDAPI godot_variant_set_byte_array(godot_variant p_variant, godot_byte_array p_array); -void GDAPI godot_variant_set_int_array(godot_variant p_variant, godot_byte_array p_array); -void GDAPI godot_variant_set_string_array(godot_variant p_variant, godot_string_array p_array); -void GDAPI godot_variant_set_vector2_array(godot_variant p_variant, godot_vector2_array p_array); -void GDAPI godot_variant_set_vector3_array(godot_variant p_variant, godot_vector3_array p_array); -void GDAPI godot_variant_set_color_array(godot_variant p_variant, godot_color_array p_array); - -godot_bool GDAPI godot_variant_get_bool(godot_variant p_variant); -int GDAPI godot_variant_get_int(godot_variant p_variant); -float GDAPI godot_variant_get_float(godot_variant p_variant); -int GDAPI godot_variant_get_string(godot_variant p_variant, char *p_string, int p_bufsize); -void GDAPI godot_variant_get_vector2(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_rect2(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_vector3(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_matrix32(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_plane(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_aabb(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_matrix3(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_transform(godot_variant p_variant, float *p_elems); -void GDAPI godot_variant_get_color(godot_variant p_variant, float *p_elems); -godot_image GDAPI *godot_variant_get_image(godot_variant p_variant); -int GDAPI godot_variant_get_node_path(godot_variant p_variant, char *p_path, int p_bufsize); -godot_rid GDAPI godot_variant_get_rid(godot_variant p_variant); -godot_instance GDAPI godot_variant_get_instance(godot_variant p_variant); -void GDAPI godot_variant_get_input_event(godot_variant p_variant, godot_input_event); -void GDAPI godot_variant_get_dictionary(godot_variant p_variant, godot_dictionary); -godot_array GDAPI godot_variant_get_array(godot_variant p_variant); -godot_byte_array GDAPI godot_variant_get_byte_array(godot_variant p_variant); -godot_byte_array GDAPI godot_variant_get_int_array(godot_variant p_variant); -godot_string_array GDAPI godot_variant_get_string_array(godot_variant p_variant); -godot_vector2_array GDAPI godot_variant_get_vector2_array(godot_variant p_variant); -godot_vector3_array GDAPI godot_variant_get_vector3_array(godot_variant p_variant); -godot_color_array GDAPI godot_variant_get_color_array(godot_variant p_variant); - -void GDAPI godot_variant_delete(godot_variant p_variant); - -////// Class -/// - -char GDAPI **godot_class_get_list(); //get list of classes in array to array of strings, must be freed, use godot_list_free() - -int GDAPI godot_class_get_base(char *p_class, char *p_base, int p_max_len); -int GDAPI godot_class_get_name(char *p_class, char *p_base, int p_max_len); - -char GDAPI **godot_class_get_method_list(char *p_class); //free with godot_list_free() -int GDAPI godot_class_method_get_argument_count(char *p_class, char *p_method); -int GDAPI godot_class_method_get_argument_type(char *p_class, char *p_method, int p_argument); -godot_variant GDAPI godot_class_method_get_argument_default_value(char *p_class, char *p_method, int p_argument); - -char GDAPI **godot_class_get_constant_list(char *p_class); //free with godot_list_free() -int GDAPI godot_class_constant_get_value(char *p_class, char *p_constant); - -////// Instance - -typedef int godot_call_error; - -#define GODOT_CALL_OK -#define GODOT_CALL_ERROR_WRONG_ARGUMENTS -#define GODOT_CALL_ERROR_INVALID_INSTANCE - -godot_instance GDAPI godot_instance_new(char *p_class); -int GDAPI godot_instance_get_class(godot_instance p_instance, char *p_class, int p_max_len); - -typedef struct { - char *name; - int hint; - char *hint_string; - int usage; -} godot_property_info; - -godot_call_error GDAPI godot_instance_call(godot_instance p_instance, char *p_method, ...); -godot_call_error GDAPI godot_instance_call_ret(godot_instance p_instance, godot_variant r_return, char *p_method, ...); -godot_bool GDAPI godot_instance_set(godot_instance p_instance, char *p_prop, godot_variant p_value); -godot_variant GDAPI godot_instance_get(godot_instance p_instance, char *p_prop); - -#define GODOT_PROPERTY_HINT_NONE 0 ///< no hint provided. -#define GODOT_PROPERTY_HINT_RANGE 1 ///< hint_text = "min,max,step,slider; //slider is optional" -#define GODOT_PROPERTY_HINT_EXP_RANGE 2 ///< hint_text = "min,max,step", exponential edit -#define GODOT_PROPERTY_HINT_ENUM 3 ///< hint_text= "val1,val2,val3,etc" -#define GODOT_PROPERTY_HINT_EXP_EASING 4 /// exponential easing function (Math::ease) -#define GODOT_PROPERTY_HINT_LENGTH 5 ///< hint_text= "length" (as integer) -#define GODOT_PROPERTY_HINT_SPRITE_FRAME 6 -#define GODOT_PROPERTY_HINT_KEY_ACCEL 7 ///< hint_text= "length" (as integer) -#define GODOT_PROPERTY_HINT_FLAGS 8 ///< hint_text= "flag1,flag2,etc" (as bit flags) -#define GODOT_PROPERTY_HINT_ALL_FLAGS 9 -#define GODOT_PROPERTY_HINT_FILE 10 ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," -#define GODOT_PROPERTY_HINT_DIR 11 ///< a directort path must be passed -#define GODOT_PROPERTY_HINT_GLOBAL_FILE 12 ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," -#define GODOT_PROPERTY_HINT_GLOBAL_DIR 13 ///< a directort path must be passed -#define GODOT_PROPERTY_HINT_RESOURCE_TYPE 14 ///< a resource object type -#define GODOT_PROPERTY_HINT_MULTILINE_TEXT 15 ///< used for string properties that can contain multiple lines -#define GODOT_PROPERTY_HINT_COLOR_NO_ALPHA 16 ///< used for ignoring alpha component when editing a color -#define GODOT_PROPERTY_HINT_IMAGE_COMPRESS_LOSSY 17 -#define GODOT_PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS 18 -#define GODOT_PROPERTY_HINT_OBJECT_ID 19 - -#define GODOT_PROPERTY_USAGE_STORAGE 1 -#define GODOT_PROPERTY_USAGE_EDITOR 2 -#define GODOT_PROPERTY_USAGE_NETWORK 4 -#define GODOT_PROPERTY_USAGE_EDITOR_HELPER 8 -#define GODOT_PROPERTY_USAGE_CHECKABLE 16 //used for editing global variables -#define GODOT_PROPERTY_USAGE_CHECKED 32 //used for editing global variables -#define GODOT_PROPERTY_USAGE_INTERNATIONALIZED 64 //hint for internationalized strings -#define GODOT_PROPERTY_USAGE_BUNDLE 128 //used for optimized bundles -#define GODOT_PROPERTY_USAGE_CATEGORY 256 -#define GODOT_PROPERTY_USAGE_STORE_IF_NONZERO 512 //only store if nonzero -#define GODOT_PROPERTY_USAGE_STORE_IF_NONONE 1024 //only store if false -#define GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE 2048 -#define GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED 4096 -#define GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE 8192 -#define GODOT_PROPERTY_USAGE_STORE_IF_NULL 16384 -#define GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER 32768 - -#define GODOT_PROPERTY_USAGE_DEFAULT GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK -#define GODOT_PROPERTY_USAGE_DEFAULT_INTL GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK | GODOT_PROPERTY_USAGE_INTERNATIONALIZED -#define GODOT_PROPERTY_USAGE_NOEDITOR GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_NETWORK - -godot_property_info GDAPI **godot_instance_get_property_list(godot_instance p_instance); -void GDAPI godot_instance_free_property_list(godot_instance p_instance, godot_property_info **p_list); - -void GDAPI godot_list_free(char **p_name); //helper to free all the class list - -////// Script API - -typedef void *(godot_script_instance_func)(godot_instance); //passed an instance, return a pointer to your userdata -typedef void(godot_script_free_func)(godot_instance, void *); //passed an instance, please free your userdata - -void GDAPI godot_script_register(char *p_base, char *p_name, godot_script_instance_func p_instance_func, godot_script_free_func p_free_func); -void GDAPI godot_script_unregister(char *p_name); - -typedef GDAPI godot_variant(godot_script_func)(godot_instance, void *, godot_variant *, int); //instance,userdata,arguments,argument count. Return something or NULL. Arguments must not be freed. - -void GDAPI godot_script_add_function(char *p_name, char *p_function_name, godot_script_func p_func); -void GDAPI godot_script_add_validated_function(char *p_name, char *p_function_name, godot_script_func p_func, int *p_arg_types, int p_arg_count, godot_variant *p_default_args, int p_default_arg_count); - -typedef void(godot_set_property_func)(godot_instance, void *, godot_variant); //instance,userdata,value. Value must not be freed. -typedef godot_variant(godot_get_property_func)(godot_instance, void *); //instance,userdata. Return a value or NULL. - -void GDAPI godot_script_add_property(char *p_name, char *p_path, godot_set_property_func p_set_func, godot_get_property_func p_get_func); -void GDAPI godot_script_add_listed_property(char *p_name, char *p_path, godot_set_property_func p_set_func, godot_get_property_func p_get_func, int p_type, int p_hint, char *p_hint_string, int p_usage); - -////// System Functions - -//using these will help Godot track how much memory is in use in debug mode -void GDAPI *godot_alloc(int p_bytes); -void GDAPI *godot_realloc(void *p_ptr, int p_bytes); -void GDAPI godot_free(void *p_ptr); - -#ifdef __cplusplus -} -#endif - -#endif // GODOT_C_H diff --git a/modules/dlscript/SCsub b/modules/dlscript/SCsub new file mode 100644 index 0000000000..ac13319a1d --- /dev/null +++ b/modules/dlscript/SCsub @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.modules_sources, "*.cpp") +env.add_source_files(env.modules_sources, "godot/*.cpp") + +env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN']) + +if "platform" in env and env["platform"] == "x11": # there has to be a better solution? + env.Append(LINKFLAGS=["-rdynamic"]) +env.use_ptrcall = True + +Export('env') diff --git a/modules/dlscript/api_generator.cpp b/modules/dlscript/api_generator.cpp new file mode 100644 index 0000000000..c8e38ca9a3 --- /dev/null +++ b/modules/dlscript/api_generator.cpp @@ -0,0 +1,394 @@ +#include "api_generator.h" + +#ifdef TOOLS_ENABLED + +#include "class_db.h" +#include "core/global_config.h" +#include "os/file_access.h" + +// helper stuff + +static Error save_file(const String &p_path, const List<String> &p_content) { + + FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE); + + ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE); + + for (const List<String>::Element *e = p_content.front(); e != NULL; e = e->next()) { + file->store_string(e->get()); + } + + file->close(); + + return OK; +} + +// helper stuff end + +struct MethodAPI { + String method_name; + String return_type; + + List<String> argument_types; + List<String> argument_names; + + Map<int, Variant> default_arguments; + + int argument_count; + bool has_varargs; + bool is_editor; + bool is_noscript; + bool is_const; + bool is_reverse; + bool is_virtual; + bool is_from_script; +}; + +struct PropertyAPI { + String name; + String getter; + String setter; + String type; +}; + +struct ConstantAPI { + String constant_name; + int constant_value; +}; + +struct SignalAPI { + String name; + List<String> argument_types; + List<String> argument_names; + Map<int, Variant> default_arguments; +}; + +struct ClassAPI { + String class_name; + String super_class_name; + + ClassDB::APIType api_type; + + bool is_singleton; + bool is_instanciable; + // @Unclear + bool is_creatable; + // @Unclear + bool memory_own; + + List<MethodAPI> methods; + List<PropertyAPI> properties; + List<ConstantAPI> constants; + List<SignalAPI> signals_; +}; + +/* + * Reads the entire Godot API to a list + */ +List<ClassAPI> generate_c_api_classes() { + + List<ClassAPI> api; + + List<StringName> classes; + ClassDB::get_class_list(&classes); + + for (List<StringName>::Element *e = classes.front(); e != NULL; e = e->next()) { + StringName class_name = e->get(); + + ClassAPI class_api; + class_api.api_type = ClassDB::get_api_type(e->get()); + class_api.class_name = class_name; + class_api.super_class_name = ClassDB::get_parent_class(class_name); + { + String name = class_name; + if (name.begins_with("_")) { + name.remove(0); + } + class_api.is_singleton = GlobalConfig::get_singleton()->has_singleton(name); + } + class_api.is_instanciable = !class_api.is_singleton && ClassDB::can_instance(class_name); + + { + bool is_reference = false; + List<StringName> inheriters; + ClassDB::get_inheriters_from_class("Reference", &inheriters); + is_reference = inheriters.find(class_name) < 0; + // @Unclear + class_api.memory_own = !class_api.is_singleton && is_reference; + } + + // constants + { + List<String> constant; + ClassDB::get_integer_constant_list(class_name, &constant, true); + for (List<String>::Element *c = constant.front(); c != NULL; c = c->next()) { + ConstantAPI constant_api; + constant_api.constant_name = c->get(); + constant_api.constant_value = ClassDB::get_integer_constant(class_name, c->get()); + + class_api.constants.push_back(constant_api); + } + } + + // signals + { + List<MethodInfo> signals_; + ClassDB::get_signal_list(class_name, &signals_, true); + + for (int i = 0; i < signals_.size(); i++) { + SignalAPI signal; + + MethodInfo method_info = signals_[i]; + signal.name = method_info.name; + + for (int j = 0; j < method_info.arguments.size(); j++) { + PropertyInfo argument = method_info.arguments[j]; + String type; + String name = argument.name; + + if (argument.name.find(":") != -1) { + type = argument.name.get_slice(":", 1); + name = argument.name.get_slice(":", 0); + } else if (argument.hint == PROPERTY_HINT_RESOURCE_TYPE) { + type = argument.hint_string; + } else if (argument.type == Variant::NIL) { + type = "Variant"; + } else { + type = Variant::get_type_name(argument.type); + } + + signal.argument_names.push_back(name); + signal.argument_types.push_back(type); + } + + Vector<Variant> default_arguments = method_info.default_arguments; + + int default_start = signal.argument_names.size() - default_arguments.size(); + + for (int j = 0; j < default_arguments.size(); j++) { + signal.default_arguments[default_start + j] = default_arguments[j]; + } + + class_api.signals_.push_back(signal); + } + } + + //properties + { + List<PropertyInfo> properties; + ClassDB::get_property_list(class_name, &properties, true); + + for (List<PropertyInfo>::Element *p = properties.front(); p != NULL; p = p->next()) { + PropertyAPI property_api; + + property_api.name = p->get().name; + property_api.getter = ClassDB::get_property_getter(class_name, p->get().name); + property_api.setter = ClassDB::get_property_setter(class_name, p->get().name); + + if (p->get().name.find(":") != -1) { + property_api.type = p->get().name.get_slice(":", 1); + property_api.name = p->get().name.get_slice(":", 0); + } else if (p->get().hint == PROPERTY_HINT_RESOURCE_TYPE) { + property_api.type = p->get().hint_string; + } else if (p->get().type == Variant::NIL) { + property_api.type = "Variant"; + } else { + property_api.type = Variant::get_type_name(p->get().type); + } + + if (!property_api.setter.empty() || !property_api.getter.empty()) { + class_api.properties.push_back(property_api); + } + } + } + + //methods + { + List<MethodInfo> methods; + ClassDB::get_method_list(class_name, &methods, true); + + for (List<MethodInfo>::Element *m = methods.front(); m != NULL; m = m->next()) { + MethodAPI method_api; + MethodBind *method_bind = ClassDB::get_method(class_name, m->get().name); + MethodInfo &method_info = m->get(); + + //method name + method_api.method_name = m->get().name; + //method return type + if (method_bind && method_bind->get_return_type() != StringName()) { + method_api.return_type = method_bind->get_return_type(); + } else if (method_api.method_name.find(":") != -1) { + method_api.return_type = method_api.method_name.get_slice(":", 1); + method_api.method_name = method_api.method_name.get_slice(":", 0); + } else if (m->get().return_val.type != Variant::NIL) { + method_api.return_type = m->get().return_val.hint == PROPERTY_HINT_RESOURCE_TYPE ? m->get().return_val.hint_string : Variant::get_type_name(m->get().return_val.type); + } else { + method_api.return_type = "void"; + } + + method_api.argument_count = method_info.arguments.size(); + method_api.has_varargs = method_bind && method_bind->is_vararg(); + + // Method flags + if (method_info.flags) { + const uint32_t flags = method_info.flags; + method_api.is_editor = flags & METHOD_FLAG_EDITOR; + method_api.is_noscript = flags & METHOD_FLAG_NOSCRIPT; + method_api.is_const = flags & METHOD_FLAG_CONST; + method_api.is_reverse = flags & METHOD_FLAG_REVERSE; + method_api.is_virtual = flags & METHOD_FLAG_VIRTUAL; + method_api.is_from_script = flags & METHOD_FLAG_FROM_SCRIPT; + } + + method_api.is_virtual = method_api.is_virtual || method_api.method_name[0] == '_'; + + // method argument name and type + + for (int i = 0; i < method_api.argument_count; i++) { + String arg_name; + String arg_type; + PropertyInfo arg_info = method_info.arguments[i]; + + arg_name = arg_info.name; + + if (arg_info.name.find(":") != -1) { + arg_type = arg_info.name.get_slice(":", 1); + arg_name = arg_info.name.get_slice(":", 0); + } else if (arg_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { + arg_type = arg_info.hint_string; + } else if (arg_info.type == Variant::NIL) { + arg_type = "Variant"; + } else { + arg_type = Variant::get_type_name(arg_info.type); + } + + method_api.argument_names.push_back(arg_name); + method_api.argument_types.push_back(arg_type); + + if (method_bind && method_bind->has_default_argument(i)) { + method_api.default_arguments[i] = method_bind->get_default_argument(i); + } + } + + class_api.methods.push_back(method_api); + } + } + + api.push_back(class_api); + } + + return api; +} + +/* + * Generates the JSON source from the API in p_api + */ +static List<String> generate_c_api_json(const List<ClassAPI> &p_api) { + + // I'm sorry for the \t mess + + List<String> source; + + source.push_back("[\n"); + + for (const List<ClassAPI>::Element *c = p_api.front(); c != NULL; c = c->next()) { + ClassAPI api = c->get(); + + source.push_back("\t{\n"); + + source.push_back("\t\t\"name\": \"" + api.class_name + "\",\n"); + source.push_back("\t\t\"base_class\": \"" + api.super_class_name + "\",\n"); + source.push_back(String("\t\t\"api_type\": \"") + (api.api_type == ClassDB::API_CORE ? "core" : (api.api_type == ClassDB::API_EDITOR ? "tools" : "none")) + "\",\n"); + source.push_back(String("\t\t\"singleton\": ") + (api.is_singleton ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\"instanciable\": ") + (api.is_instanciable ? "true" : "false") + ",\n"); + // @Unclear + // source.push_back(String("\t\t\"createable\": ") + (api.is_creatable ? "true" : "false") + ",\n"); + + source.push_back("\t\t\"constants\": {\n"); + for (List<ConstantAPI>::Element *e = api.constants.front(); e; e = e->next()) { + source.push_back("\t\t\t\"" + e->get().constant_name + "\": " + String::num_int64(e->get().constant_value) + (e->next() ? "," : "") + "\n"); + } + source.push_back("\t\t},\n"); + + source.push_back("\t\t\"properties\": [\n"); + for (List<PropertyAPI>::Element *e = api.properties.front(); e; e = e->next()) { + source.push_back("\t\t\t{\n"); + source.push_back("\t\t\t\t\"name\": \"" + e->get().name + "\",\n"); + source.push_back("\t\t\t\t\"type\": \"" + e->get().type + "\",\n"); + source.push_back("\t\t\t\t\"getter\": \"" + e->get().getter + "\",\n"); + source.push_back("\t\t\t\t\"setter\": \"" + e->get().setter + "\"\n"); + source.push_back(String("\t\t\t}") + (e->next() ? "," : "") + "\n"); + } + source.push_back("\t\t],\n"); + + source.push_back("\t\t\"signals\": [\n"); + for (List<SignalAPI>::Element *e = api.signals_.front(); e; e = e->next()) { + source.push_back("\t\t\t{\n"); + source.push_back("\t\t\t\t\"name\": \"" + e->get().name + "\",\n"); + source.push_back("\t\t\t\t\"arguments\": [\n"); + for (int i = 0; i < e->get().argument_names.size(); i++) { + source.push_back("\t\t\t\t\t{\n"); + source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n"); + source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n"); + source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n"); + source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n"); + } + source.push_back("\t\t\t\t]\n"); + source.push_back(String("\t\t\t}") + (e->next() ? "," : "") + "\n"); + } + source.push_back("\t\t],\n"); + + source.push_back("\t\t\"methods\": [\n"); + for (List<MethodAPI>::Element *e = api.methods.front(); e; e = e->next()) { + source.push_back("\t\t\t{\n"); + source.push_back("\t\t\t\t\"name\": \"" + e->get().method_name + "\",\n"); + source.push_back("\t\t\t\t\"return_type\": \"" + e->get().return_type + "\",\n"); + source.push_back(String("\t\t\t\t\"is_editor\": ") + (e->get().is_editor ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"is_noscript\": ") + (e->get().is_noscript ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"is_const\": ") + (e->get().is_const ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"is_reverse\": ") + (e->get().is_reverse ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"is_virtual\": ") + (e->get().is_virtual ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"has_varargs\": ") + (e->get().has_varargs ? "true" : "false") + ",\n"); + source.push_back(String("\t\t\t\t\"is_from_script\": ") + (e->get().is_from_script ? "true" : "false") + ",\n"); + source.push_back("\t\t\t\t\"arguments\": [\n"); + for (int i = 0; i < e->get().argument_names.size(); i++) { + source.push_back("\t\t\t\t\t{\n"); + source.push_back("\t\t\t\t\t\t\"name\": \"" + e->get().argument_names[i] + "\",\n"); + source.push_back("\t\t\t\t\t\t\"type\": \"" + e->get().argument_types[i] + "\",\n"); + source.push_back("\t\t\t\t\t\t\"default_value\": \"" + (e->get().default_arguments.has(i) ? (String)e->get().default_arguments[i] : "") + "\"\n"); + source.push_back(String("\t\t\t\t\t}") + ((i < e->get().argument_names.size() - 1) ? "," : "") + "\n"); + } + source.push_back("\t\t\t\t]\n"); + source.push_back(String("\t\t\t}") + (e->next() ? "," : "") + "\n"); + } + source.push_back("\t\t]\n"); + + source.push_back(String("\t}") + (c->next() ? "," : "") + "\n"); + } + + source.push_back("]"); + + return source; +} + +// + +#endif + +/* + * Saves the whole Godot API to a JSON file located at + * p_path + */ +Error generate_c_api(const String &p_path) { + +#ifndef TOOLS_ENABLED + return ERR_BUG; +#else + + List<ClassAPI> api = generate_c_api_classes(); + + List<String> json_source = generate_c_api_json(api); + + return save_file(p_path, json_source); +#endif +} diff --git a/modules/dlscript/api_generator.h b/modules/dlscript/api_generator.h new file mode 100644 index 0000000000..4a8354e9d6 --- /dev/null +++ b/modules/dlscript/api_generator.h @@ -0,0 +1,9 @@ +#ifndef API_GENERATOR_H +#define API_GENERATOR_H + +#include "core/ustring.h" +#include "typedefs.h" + +Error generate_c_api(const String &p_path); + +#endif // API_GENERATOR_H diff --git a/modules/cscript/config.py b/modules/dlscript/config.py index 5698a37295..9f57b9bb74 100644 --- a/modules/cscript/config.py +++ b/modules/dlscript/config.py @@ -5,4 +5,4 @@ def can_build(platform): def configure(env): - pass + env.use_ptrcall = True diff --git a/modules/dlscript/dl_script.cpp b/modules/dlscript/dl_script.cpp new file mode 100644 index 0000000000..449d7b4b17 --- /dev/null +++ b/modules/dlscript/dl_script.cpp @@ -0,0 +1,1120 @@ +/*************************************************************************/ +/* dl_script.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "dl_script.h" + +#include "global_config.h" +#include "global_constants.h" +#include "io/file_access_encrypted.h" +#include "os/file_access.h" +#include "os/os.h" + +#include "scene/resources/scene_format_text.h" + +#ifdef TOOLS_ENABLED +// #include "editor/editor_import_export.h" +#endif + +#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) +#include "api_generator.h" +#endif + +// Script + +bool DLScript::can_instance() const { +#ifdef DLSCRIPT_EDITOR_FEATURES + return script_data || (!is_tool() && !ScriptServer::is_scripting_enabled()); +#else + // allow defaultlibrary without editor features + if (!library.is_valid()) { + String path = GLOBAL_GET("dlscript/default_dllibrary"); + + RES lib = ResourceLoader::load(path); + + if (lib.is_valid() && lib->cast_to<DLLibrary>()) { + return true; + } + } + + return script_data; +#endif + //return script_data || (!tool && !ScriptServer::is_scripting_enabled()); + // change to true enable in editor stuff. +} + +Ref<Script> DLScript::get_base_script() const { + Ref<DLScript> base_script; + base_script->library = library; + base_script->script_data = script_data; + base_script->script_name = script_data->base; + return base_script; +} + +StringName DLScript::get_instance_base_type() const { + return script_data->base_native_type; +} + +ScriptInstance *DLScript::instance_create(Object *p_this) { + +#ifdef TOOLS_ENABLED + +// find a good way to initialize stuff in the editor +#ifdef DLSCRIPT_EDITOR_FEATURES + if (!ScriptServer::is_scripting_enabled() && !is_tool()) { + // placeholder, for nodes. But for tools we want the real thing + + PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(DLScriptLanguage::singleton, Ref<Script>((Script *)this), p_this)); + placeholders.insert(sins); + + List<PropertyInfo> pinfo; + Map<StringName, Variant> values; + + if (!library.is_valid()) + return sins; + + if (!library->library_handle) { + Error err = library->_initialize_handle(true); + if (err != OK) { + return sins; + } + } + + if (!script_data) { + script_data = library->get_script_data(script_name); + } + if (script_data) + script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); + + if (script_data) { + for (Map<StringName, DLScriptData::Property>::Element *E = script_data->properties.front(); E; E = E->next()) { + + PropertyInfo p = E->get().info; + p.name = String(E->key()); + pinfo.push_back(p); + values[p.name] = E->get().default_value; + } + } + + sins->update(pinfo, values); + + return sins; + } +#endif + +#endif + + if (!library.is_valid()) { + String path = GLOBAL_GET("dlscript/default_dllibrary"); + + RES lib = ResourceLoader::load(path); + + if (lib.is_valid() && lib->cast_to<DLLibrary>()) { + set_library(lib); + } + } + + DLInstance *new_instance = memnew(DLInstance); + + new_instance->owner = p_this; + new_instance->script = Ref<DLScript>(this); + +#ifndef DLSCRIPT_EDITOR_FEATURES + if (!ScriptServer::is_scripting_enabled()) { + new_instance->userdata = 0; + } else { + new_instance->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); + } +#else + new_instance->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); +#endif + + instances.insert(p_this); + return new_instance; +} + +bool DLScript::instance_has(const Object *p_this) const { + return instances.has((Object *)p_this); // TODO +} + +bool DLScript::has_source_code() const { + return false; +} + +String DLScript::get_source_code() const { + return ""; +} + +Error DLScript::reload(bool p_keep_state) { + return FAILED; +} + +bool DLScript::has_method(const StringName &p_method) const { + if (!script_data) + return false; + DLScriptData *data = script_data; + + while (data) { + if (data->methods.has(p_method)) + return true; + + data = data->base_data; + } + + return false; +} + +MethodInfo DLScript::get_method_info(const StringName &p_method) const { + if (!script_data) + return MethodInfo(); + DLScriptData *data = script_data; + + while (data) { + if (data->methods.has(p_method)) + return data->methods[p_method].info; + + data = data->base_data; + } + + ERR_FAIL_COND_V(!script_data->methods.has(p_method), MethodInfo()); + return MethodInfo(); +} + +void DLScript::get_script_method_list(List<MethodInfo> *p_list) const { + if (!script_data) return; + + Set<MethodInfo> methods; + DLScriptData *data = script_data; + + while (data) { + for (Map<StringName, DLScriptData::Method>::Element *E = data->methods.front(); E; E = E->next()) { + methods.insert(E->get().info); + } + data = data->base_data; + } + + for (Set<MethodInfo>::Element *E = methods.front(); E; E = E->next()) { + p_list->push_back(E->get()); + } +} + +void DLScript::get_script_property_list(List<PropertyInfo> *p_list) const { + if (!script_data) return; + + Set<PropertyInfo> properties; + DLScriptData *data = script_data; + + while (data) { + for (Map<StringName, DLScriptData::Property>::Element *E = data->properties.front(); E; E = E->next()) { + properties.insert(E->get().info); + } + data = data->base_data; + } + + for (Set<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { + p_list->push_back(E->get()); + } +} + +bool DLScript::get_property_default_value(const StringName &p_property, Variant &r_value) const { + if (!script_data) return false; + + DLScriptData *data = script_data; + + while (data) { + if (data->properties.has(p_property)) { + r_value = data->properties[p_property].default_value; + return true; + } + + data = data->base_data; + } + + return false; +} + +bool DLScript::is_tool() const { + ERR_FAIL_COND_V(!script_data, false); + return script_data->is_tool; +} + +String DLScript::get_node_type() const { + return ""; // ? +} + +ScriptLanguage *DLScript::get_language() const { + return DLScriptLanguage::singleton; +} + +bool DLScript::has_script_signal(const StringName &p_signal) const { + if (!script_data) + return false; + + DLScriptData *data = script_data; + + while (data) { + if (data->signals_.has(p_signal)) { + return true; + } + + data = data->base_data; + } + + return false; +} + +void DLScript::get_script_signal_list(List<MethodInfo> *r_signals) const { + if (!script_data) + return; + + Set<MethodInfo> signals_; + DLScriptData *data = script_data; + + while (data) { + + for (Map<StringName, DLScriptData::Signal>::Element *S = data->signals_.front(); S; S = S->next()) { + signals_.insert(S->get().signal); + } + + data = data->base_data; + } + + for (Set<MethodInfo>::Element *E = signals_.front(); E; E = E->next()) { + r_signals->push_back(E->get()); + } +} + +Ref<DLLibrary> DLScript::get_library() const { + return library; +} + +void DLScript::set_library(Ref<DLLibrary> p_library) { + library = p_library; + +#ifdef TOOLS_ENABLED + if (!ScriptServer::is_scripting_enabled()) + return; +#endif + if (library.is_valid()) { + Error initalize_status = library->_initialize_handle(!ScriptServer::is_scripting_enabled()); + ERR_FAIL_COND(initalize_status != OK); + if (script_name) { + script_data = library->get_script_data(script_name); + ERR_FAIL_COND(!script_data); + } + } +} + +StringName DLScript::get_script_name() const { + return script_name; +} + +void DLScript::set_script_name(StringName p_script_name) { + script_name = p_script_name; + + if (library.is_valid()) { + script_data = library->get_script_data(script_name); + ERR_FAIL_COND(!script_data); + } +} + +void DLScript::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_library"), &DLScript::get_library); + ClassDB::bind_method(D_METHOD("set_library", "library"), &DLScript::set_library); + ClassDB::bind_method(D_METHOD("get_script_name"), &DLScript::get_script_name); + ClassDB::bind_method(D_METHOD("set_script_name", "script_name"), &DLScript::set_script_name); + + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "DLLibrary"), "set_library", "get_library"); + ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "script_name"), "set_script_name", "get_script_name"); +} + +DLScript::DLScript() { + script_data = NULL; +} + +DLScript::~DLScript() { + //hmm +} + +// Library + +DLLibrary *DLLibrary::currently_initialized_library = NULL; + +DLLibrary *DLLibrary::get_currently_initialized_library() { + return currently_initialized_library; +} + +static const char *_dl_platforms_info[] = { + "|unix|so|Unix", + "unix|x11|so|X11", + "unix|server|so|Server", + "unix|android|so|Android", + "unix|blackberry|so|Blackberry 10", + "unix|haiku|so|Haiku", // Right? + "|mac|dynlib|Mac", + "mac|ios|dynlib|iOS", + "mac|osx|dynlib|OSX", + "|html5|js|HTML5", + "|windows|dll|Windows", + "windows|uwp|dll|UWP", + NULL // Finishing condition +}; + +void DLLibrary::set_platform_file(StringName p_platform, String p_file) { + if (p_file.empty()) { + platform_files.erase(p_platform); + } else { + platform_files[p_platform] = p_file; + } +} + +String DLLibrary::get_platform_file(StringName p_platform) const { + if (platform_files.has(p_platform)) { + return platform_files[p_platform]; + } else { + return ""; + } +} + +Error DLLibrary::_initialize_handle(bool p_in_editor) { + _THREAD_SAFE_METHOD_ + + void *_library_handle; + + // Get the file + + const String platform_name = OS::get_singleton()->get_name(); + String platform_file(""); + char **platform_info = (char **)_dl_platforms_info; + + if (platform_files.has(platform_name.to_lower())) { + platform_file = platform_files[platform_name.to_lower()]; + } + + while (*platform_info) { + String platform_info_string(*platform_info); + + if (platform_name == platform_info_string.get_slicec('|', 3)) { + String platform_key = platform_info_string.get_slicec('|', 1); + String fallback_platform_key = platform_info_string.get_slicec('|', 0); + + if (platform_files.has(platform_key)) { + platform_file = platform_files[platform_key]; + } else if (!fallback_platform_key.empty() && platform_files.has(fallback_platform_key)) { + platform_file = platform_files[fallback_platform_key]; + } else { + return ERR_UNAVAILABLE; + } + } + platform_info++; + } + ERR_FAIL_COND_V(platform_file == "", ERR_DOES_NOT_EXIST); + + library_path = GlobalConfig::get_singleton()->globalize_path(platform_file); + + if (DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) { + *this = *DLScriptLanguage::get_singleton()->get_library_dllibrary(library_path); + return OK; + } + + // Open the file + + Error error; + error = OS::get_singleton()->open_dynamic_library(library_path, _library_handle); + if (error) return error; + ERR_FAIL_COND_V(!_library_handle, ERR_BUG); + + // Get the method + + void *library_init; + error = OS::get_singleton()->get_dynamic_library_symbol_handle(_library_handle, DLScriptLanguage::get_init_symbol_name(), library_init); + if (error) return error; + ERR_FAIL_COND_V(!library_init, ERR_BUG); + + DLLibrary::currently_initialized_library = this; + + void (*library_init_fpointer)(godot_dlscript_init_options *) = (void (*)(godot_dlscript_init_options *))library_init; + + godot_dlscript_init_options options; + + options.in_editor = p_in_editor; + options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); + options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); + options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE); + + library_init_fpointer(&options); // Catch errors? + /*{ + ERR_EXPLAIN("Couldn't initialize library"); + ERR_FAIL_V(ERR_SCRIPT_FAILED); + }*/ + + DLLibrary::currently_initialized_library = NULL; + library_handle = _library_handle; + + DLScriptLanguage::get_singleton()->set_library_initialized(library_path, this); + + return OK; +} + +Error DLLibrary::_free_handle(bool p_in_editor) { + ERR_FAIL_COND_V(!library_handle, ERR_BUG); + + if (!DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) { + OS::get_singleton()->close_dynamic_library(library_handle); + library_handle = 0; + return OK; + } + + Error error = OK; + void *library_terminate; + error = OS::get_singleton()->get_dynamic_library_symbol_handle(library_handle, DLScriptLanguage::get_terminate_symbol_name(), library_terminate); + if (error) + return OK; // no terminate? okay, not that important lol + + void (*library_terminate_pointer)(godot_dlscript_terminate_options *) = (void (*)(godot_dlscript_terminate_options *))library_terminate; + + godot_dlscript_terminate_options options; + options.in_editor = p_in_editor; + + library_terminate_pointer(&options); + + DLScriptLanguage::get_singleton()->set_library_uninitialized(library_path); + + OS::get_singleton()->close_dynamic_library(library_handle); + library_handle = 0; + + return OK; +} + +void DLLibrary::_register_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) { + ERR_FAIL_COND(scripts.has(p_name)); + + DLScriptData *s = memnew(DLScriptData); + s->base = p_base; + s->create_func = p_instance_func; + s->destroy_func = p_destroy_func; + Map<StringName, DLScriptData *>::Element *E = scripts.find(p_base); + if (E) { + s->base_data = E->get(); + s->base_native_type = s->base_data->base_native_type; + } else { + if (!ClassDB::class_exists(p_base)) { + memdelete(s); + ERR_EXPLAIN("Invalid base for registered type '" + p_name + "'"); + ERR_FAIL(); + } + s->base_native_type = p_base; + } + + scripts.insert(p_name, s); +} + +void DLLibrary::_register_tool_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func) { + ERR_FAIL_COND(scripts.has(p_name)); + + DLScriptData *s = memnew(DLScriptData); + s->base = p_base; + s->create_func = p_instance_func; + s->destroy_func = p_destroy_func; + s->is_tool = true; + Map<StringName, DLScriptData *>::Element *E = scripts.find(p_base); + if (E) { + s->base_data = E->get(); + s->base_native_type = s->base_data->base_native_type; + } else { + if (!ClassDB::class_exists(p_base)) { + memdelete(s); + ERR_EXPLAIN("Invalid base for registered type '" + p_name + "'"); + ERR_FAIL(); + } + s->base_native_type = p_base; + } + + scripts.insert(p_name, s); +} + +void DLLibrary::_register_script_method(const StringName p_name, const StringName p_method, godot_method_attributes p_attr, godot_instance_method p_func, MethodInfo p_info) { + ERR_FAIL_COND(!scripts.has(p_name)); + + p_info.name = p_method; + DLScriptData::Method method; + + method = DLScriptData::Method(p_func, p_info, p_attr.rpc_type); + + scripts[p_name]->methods.insert(p_method, method); +} + +void DLLibrary::_register_script_property(const StringName p_name, const String p_path, godot_property_attributes *p_attr, godot_property_set_func p_setter, godot_property_get_func p_getter) { + ERR_FAIL_COND(!scripts.has(p_name)); + + DLScriptData::Property p; + + PropertyInfo pi; + pi.name = p_path; + + if (p_attr != NULL) { + pi = PropertyInfo((Variant::Type)p_attr->type, p_path, (PropertyHint)p_attr->hint, *(String *)&p_attr->hint_string, p_attr->usage); + + p = DLScriptData::Property(p_setter, p_getter, pi, *(Variant *)&p_attr->default_value, p_attr->rset_type); + } + + scripts[p_name]->properties.insert(p_path, p); +} + +void DLLibrary::_register_script_signal(const StringName p_name, const godot_signal *p_signal) { + ERR_FAIL_COND(!scripts.has(p_name)); + ERR_FAIL_COND(!p_signal); + + DLScriptData::Signal signal; + + signal.signal.name = *(String *)&p_signal->name; + + { + List<PropertyInfo> arguments; + for (int i = 0; i < p_signal->num_args; i++) { + PropertyInfo info; + godot_signal_argument attrib = p_signal->args[i]; + + String *name = (String *)&attrib.name; + info.name = *name; + info.type = (Variant::Type)attrib.type; + info.hint = (PropertyHint)attrib.hint; + info.hint_string = *(String *)&attrib.hint_string; + info.usage = attrib.usage; + + arguments.push_back(info); + } + + signal.signal.arguments = arguments; + } + + { + Vector<Variant> default_arguments; + for (int i = 0; i < p_signal->num_default_args; i++) { + Variant *v; + godot_signal_argument attrib = p_signal->args[i]; + + v = (Variant *)&attrib.default_value; + + default_arguments.push_back(*v); + } + + signal.signal.default_arguments = default_arguments; + } + + scripts[p_name]->signals_.insert(*(String *)&p_signal->name, signal); +} + +DLScriptData *DLLibrary::get_script_data(const StringName p_name) { + + if (!scripts.has(p_name)) { + if (DLScriptLanguage::get_singleton()->is_library_initialized(library_path)) { + _update_library(*DLScriptLanguage::get_singleton()->get_library_dllibrary(library_path)); + } + ERR_FAIL_COND_V(!scripts.has(p_name), NULL); + } + + return scripts[p_name]; +} + +bool DLLibrary::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + if (name.begins_with("platform/")) { + set_platform_file(name.get_slice("/", 1), p_value); + return true; + } + return false; +} + +bool DLLibrary::_get(const StringName &p_name, Variant &r_ret) const { + String name = p_name; + if (name.begins_with("platform/")) { + r_ret = get_platform_file(name.get_slice("/", 1)); + return true; + } + return false; +} + +void DLLibrary::_get_property_list(List<PropertyInfo> *p_list) const { + char **platform_info = (char **)_dl_platforms_info; + + Set<String> registered_platform_names; + { + List<StringName> ep; + // ep.push_back("X11"); + // EditorImportExport::get_singleton()->get_export_platforms(&ep); + for (List<StringName>::Element *E = ep.front(); E; E = E->next()) { + registered_platform_names.insert(String(E->get()).to_lower()); + } + } + + while (*platform_info) { + String platform_info_string(*platform_info); + String fallback_platform_key = platform_info_string.get_slicec('|', 0); + String platform_key = platform_info_string.get_slicec('|', 1); + String platform_extension = platform_info_string.get_slicec('|', 2); + String platform_name = platform_info_string.get_slicec('|', 3); + + registered_platform_names.erase(platform_name); + + if (fallback_platform_key.empty()) { + p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension)); + + } else { + if (platform_files.has(platform_key)) { + p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED)); + } else { + p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_key, PROPERTY_HINT_FILE, "*." + platform_extension, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CHECKABLE)); + } + } + platform_info++; + } + + while (registered_platform_names.size()) { + const String platform_name = registered_platform_names.front()->get(); + registered_platform_names.erase(platform_name); + p_list->push_back(PropertyInfo(Variant::STRING, "platform/" + platform_name.to_lower(), PROPERTY_HINT_FILE, "*")); + } +} + +void DLLibrary::_notification(int what) { + // TODO +} + +void DLLibrary::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_platform_file", "platform", "file"), &DLLibrary::set_platform_file); + ClassDB::bind_method(D_METHOD("get_platform_file", "platform"), &DLLibrary::get_platform_file); +} + +DLLibrary::DLLibrary() { + library_handle = NULL; +} + +DLLibrary::~DLLibrary() { + + for (Map<StringName, DLScriptData *>::Element *E = scripts.front(); E; E = E->next()) { + for (Map<StringName, DLScriptData::Method>::Element *M = E->get()->methods.front(); M; M = M->next()) { + if (M->get().method.free_func) { + M->get().method.free_func(M->get().method.method_data); + } + } + memdelete(E->get()); + } + + if (library_handle) { + bool in_editor = false; +#ifdef TOOLS_ENABLED + in_editor = !ScriptServer::is_scripting_enabled(); +#endif + _free_handle(in_editor); + } +} + +// Instance + +bool DLInstance::set(const StringName &p_name, const Variant &p_value) { + if (!script->script_data) + return false; + if (script->script_data->properties.has(p_name)) { + script->script_data->properties[p_name].setter.set_func((godot_object *)owner, script->script_data->properties[p_name].setter.method_data, userdata, *(godot_variant *)&p_value); + return true; + } + return false; +} + +bool DLInstance::get(const StringName &p_name, Variant &r_ret) const { + if (!script->script_data) + return false; + if (script->script_data->properties.has(p_name)) { + godot_variant value = script->script_data->properties[p_name].getter.get_func((godot_object *)owner, script->script_data->properties[p_name].getter.method_data, userdata); + r_ret = *(Variant *)&value; + return true; + } + return false; +} + +void DLInstance::get_property_list(List<PropertyInfo> *p_properties) const { + script->get_script_property_list(p_properties); + // TODO: dynamic properties +} + +Variant::Type DLInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { + if (script->script_data->properties.has(p_name)) { + *r_is_valid = true; + return script->script_data->properties[p_name].info.type; + } + *r_is_valid = false; + return Variant::NIL; +} + +void DLInstance::get_method_list(List<MethodInfo> *p_list) const { + script->get_script_method_list(p_list); +} + +bool DLInstance::has_method(const StringName &p_method) const { + return script->has_method(p_method); +} + +Variant DLInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + // TODO: validated methods & errors + + DLScriptData *data_ptr = script->script_data; + while (data_ptr) { + Map<StringName, DLScriptData::Method>::Element *E = data_ptr->methods.find(p_method); + if (E) { + godot_variant result = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); + return *(Variant *)&result; + } + data_ptr = data_ptr->base_data; + } + r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); +} + +void DLInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { + // TODO: validated methods & errors + + DLScriptData *data_ptr = script->script_data; + while (data_ptr) { + Map<StringName, DLScriptData::Method>::Element *E = data_ptr->methods.find(p_method); + if (E) { + E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); + } + data_ptr = data_ptr->base_data; + } +} + +void DLInstance::_ml_call_reversed(DLScriptData *data_ptr, const StringName &p_method, const Variant **p_args, int p_argcount) { + // TODO: validated methods & errors + + if (data_ptr->base_data) + _ml_call_reversed(data_ptr->base_data, p_method, p_args, p_argcount); + + // Variant::CallError ce; + + Map<StringName, DLScriptData::Method>::Element *E = data_ptr->methods.find(p_method); + if (E) { + E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args); + } +} + +void DLInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { + if (script.ptr() && script->script_data) { + _ml_call_reversed(script->script_data, p_method, p_args, p_argcount); + } +} + +void DLInstance::notification(int p_notification) { + Variant value = p_notification; + const Variant *args[1] = { &value }; + call_multilevel(DLScriptLanguage::singleton->strings._notification, args, 1); +} + +Ref<Script> DLInstance::get_script() const { + return script; +} + +ScriptLanguage *DLInstance::get_language() { + return DLScriptLanguage::singleton; +} + +ScriptInstance::RPCMode DLInstance::get_rpc_mode(const StringName &p_method) const { + DLScriptData::Method m = script->script_data->methods[p_method]; + switch (m.rpc_mode) { + case GODOT_METHOD_RPC_MODE_DISABLED: + return RPC_MODE_DISABLED; + case GODOT_METHOD_RPC_MODE_REMOTE: + return RPC_MODE_REMOTE; + case GODOT_METHOD_RPC_MODE_SYNC: + return RPC_MODE_SYNC; + case GODOT_METHOD_RPC_MODE_MASTER: + return RPC_MODE_MASTER; + case GODOT_METHOD_RPC_MODE_SLAVE: + return RPC_MODE_SLAVE; + default: + return RPC_MODE_DISABLED; + } +} + +ScriptInstance::RPCMode DLInstance::get_rset_mode(const StringName &p_variable) const { + DLScriptData::Property p = script->script_data->properties[p_variable]; + switch (p.rset_mode) { + case GODOT_METHOD_RPC_MODE_DISABLED: + return RPC_MODE_DISABLED; + case GODOT_METHOD_RPC_MODE_REMOTE: + return RPC_MODE_REMOTE; + case GODOT_METHOD_RPC_MODE_SYNC: + return RPC_MODE_SYNC; + case GODOT_METHOD_RPC_MODE_MASTER: + return RPC_MODE_MASTER; + case GODOT_METHOD_RPC_MODE_SLAVE: + return RPC_MODE_SLAVE; + default: + return RPC_MODE_DISABLED; + } +} + +DLInstance::DLInstance() { + owner = NULL; + userdata = NULL; +} + +DLInstance::~DLInstance() { + if (script.is_valid()) { + if (owner) { + script->instances.erase(owner); + } + if (!script->script_data) + return; + script->script_data->destroy_func.destroy_func((godot_object *)owner, script->script_data->destroy_func.method_data, userdata); + if (script->script_data->destroy_func.free_func) + script->script_data->destroy_func.free_func(script->script_data->destroy_func.method_data); + if (script->script_data->create_func.free_func) + script->script_data->create_func.free_func(script->script_data->create_func.method_data); + } +} + +// Language + +DLScriptLanguage *DLScriptLanguage::singleton = NULL; + +String DLScriptLanguage::get_name() const { + return "DLScript"; +} + +bool DLScriptLanguage::is_library_initialized(const String &p_path) { + + return initialized_libraries.has(p_path); +} + +void DLScriptLanguage::set_library_initialized(const String &p_path, DLLibrary *p_dllibrary) { + + initialized_libraries[p_path] = p_dllibrary; +} + +DLLibrary *DLScriptLanguage::get_library_dllibrary(const String &p_path) { + + return initialized_libraries[p_path]; +} + +void DLScriptLanguage::set_library_uninitialized(const String &p_path) { + + initialized_libraries.erase(p_path); +} + +void DLScriptLanguage::init() { + // TODO: Expose globals + GLOBAL_DEF("dlscript/default_dllibrary", ""); + PropertyInfo prop_info(Variant::STRING, "dlscript/default_dllibrary", PROPERTY_HINT_FILE, "tres,res,dllib"); + GlobalConfig::get_singleton()->set_custom_property_info("dlscript/default_dllibrary", prop_info); + +// generate bindings +#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) + + List<String> args = OS::get_singleton()->get_cmdline_args(); + + List<String>::Element *E = args.find("--dlscript-generate-json-api"); + + if (E && E->next()) { + if (generate_c_api(E->next()->get()) != OK) { + ERR_PRINT("Failed to generate C API\n"); + } + } +#endif +} + +String DLScriptLanguage::get_type() const { + return "DLScript"; +} + +String DLScriptLanguage::get_extension() const { + return "dl"; +} + +Error DLScriptLanguage::execute_file(const String &p_path) { + return OK; // ?? +} + +void DLScriptLanguage::finish() { + // cleanup is for noobs +} + +// scons doesn't want to link in the api source so we need to call a dummy function to cause it to link +extern "C" void _api_anchor(); + +void DLScriptLanguage::_compile_dummy_for_the_api() { + _api_anchor(); +} + +Ref<Script> DLScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const { + DLScript *src = memnew(DLScript); + src->set_script_name(p_class_name); + return Ref<DLScript>(src); +} + +bool DLScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { + return false; // TODO +} + +Script *DLScriptLanguage::create_script() const { + DLScript *scr = memnew(DLScript); + return scr; +} + +bool DLScriptLanguage::has_named_classes() const { + return true; +} + +int DLScriptLanguage::find_function(const String &p_function, const String &p_code) const { + return -1; // No source code! +} + +String DLScriptLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const { + return ""; // No source code! +} + +void DLScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) { + // TODO TODO TODO +} + +// TODO: Any debugging? (research) +String DLScriptLanguage::debug_get_error() const { + return ""; +} + +int DLScriptLanguage::debug_get_stack_level_count() const { + return 1; // ? +} + +int DLScriptLanguage::debug_get_stack_level_line(int p_level) const { + return -1; +} + +String DLScriptLanguage::debug_get_stack_level_function(int p_level) const { + return "[native code]"; // ? +} + +String DLScriptLanguage::debug_get_stack_level_source(int p_level) const { + return ""; +} + +void DLScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} + +void DLScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} + +String DLScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { + return ""; // ?? +} + +void DLScriptLanguage::reload_all_scripts() { + // @Todo +} + +void DLScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) { + // @Todo + OS::get_singleton()->print("reload tool scripts\n"); +} + +void DLScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("dl"); // Container file format +} + +void DLScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const { +} + +void DLScriptLanguage::get_public_constants(List<Pair<String, Variant> > *p_constants) const { +} + +// TODO: all profilling +void DLScriptLanguage::profiling_start() { +} + +void DLScriptLanguage::profiling_stop() { +} + +int DLScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { + return 0; +} + +int DLScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { + return 0; +} + +void DLScriptLanguage::frame() { +} + +String DLScriptLanguage::get_init_symbol_name() { + return "godot_dlscript_init"; // TODO: Maybe make some internal function which would do the actual stuff +} + +String DLScriptLanguage::get_terminate_symbol_name() { + return "godot_dlscript_terminate"; +} + +DLScriptLanguage::DLScriptLanguage() { + ERR_FAIL_COND(singleton); + strings._notification = StringName("_notification"); + singleton = this; + initialized_libraries = Map<String, DLLibrary *>(); +} + +DLScriptLanguage::~DLScriptLanguage() { + singleton = NULL; +} + +RES ResourceFormatLoaderDLScript::load(const String &p_path, const String &p_original_path, Error *r_error) { + ResourceFormatLoaderText rsflt; + return rsflt.load(p_path, p_original_path, r_error); +} + +void ResourceFormatLoaderDLScript::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("dl"); +} +bool ResourceFormatLoaderDLScript::handles_type(const String &p_type) const { + return (p_type == "Script" || p_type == "DLScript"); +} +String ResourceFormatLoaderDLScript::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (el == "dl") + return "DLScript"; + return ""; +} + +Error ResourceFormatSaverDLScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + ResourceFormatSaverText rfst; + return rfst.save(p_path, p_resource, p_flags); +} + +bool ResourceFormatSaverDLScript::recognize(const RES &p_resource) const { + return p_resource->cast_to<DLScript>() != NULL; +} + +void ResourceFormatSaverDLScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + if (p_resource->cast_to<DLScript>()) { + p_extensions->push_back("dl"); + } +} diff --git a/modules/dlscript/dl_script.h b/modules/dlscript/dl_script.h new file mode 100644 index 0000000000..497208c832 --- /dev/null +++ b/modules/dlscript/dl_script.h @@ -0,0 +1,404 @@ +/*************************************************************************/ +/* dl_script.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef DL_SCRIPT_H +#define DL_SCRIPT_H + +#include "io/resource_loader.h" +#include "io/resource_saver.h" +#include "os/thread_safe.h" +#include "resource.h" +#include "script_language.h" +#include "self_list.h" + +#include "godot.h" + +#ifdef TOOLS_ENABLED +// #define DLSCRIPT_EDITOR_FEATURES +#endif + +struct DLScriptData { + /* typedef void* (InstanceFunc)(godot_object* instance); + typedef void (DestroyFunc)(godot_object* instance,void* userdata); + typedef godot_variant (MethodFunc)(godot_object *instance, void *userdata, void *method_data, int arg_count,godot_variant **args); + typedef void (MethodDataFreeFunc)(void *method_data); + typedef void (SetterFunc)(godot_object* instance,void* userdata,godot_variant value); + typedef godot_variant (GetterFunc)(godot_object* instance,void* userdata);*/ + + struct Method { + godot_instance_method method; + MethodInfo info; + int rpc_mode; + + Method() { + } + Method(godot_instance_method p_method, MethodInfo p_info, int p_rpc_mode) { + method = p_method; + info = p_info; + rpc_mode = p_rpc_mode; + } + }; + struct Property { + godot_property_set_func setter; + godot_property_get_func getter; + PropertyInfo info; + Variant default_value; + int rset_mode; + + Property() { + } + Property(godot_property_set_func p_setter, godot_property_get_func p_getter) { + setter = p_setter; + getter = p_getter; + } + Property(godot_property_set_func p_setter, godot_property_get_func p_getter, PropertyInfo p_info, Variant p_default_value, int p_rset_mode) { + setter = p_setter; + getter = p_getter; + info = p_info; + default_value = p_default_value; + rset_mode = p_rset_mode; + } + }; + + struct Signal { + MethodInfo signal; + }; + + Map<StringName, Method> methods; + Map<StringName, Property> properties; + Map<StringName, Signal> signals_; // QtCreator doesn't like the name signals + StringName base; + StringName base_native_type; + DLScriptData *base_data; + godot_instance_create_func create_func; + godot_instance_destroy_func destroy_func; + + bool is_tool; + + DLScriptData() { + base = StringName(); + base_data = NULL; + is_tool = false; + } + DLScriptData(StringName p_base, godot_instance_create_func p_instance, godot_instance_destroy_func p_free) { + base = p_base; + base_data = NULL; + create_func = p_instance; + destroy_func = p_free; + is_tool = false; + } +}; + +class DLLibrary; + +class DLScript : public Script { + + GDCLASS(DLScript, Script); + + Ref<DLLibrary> library; + StringName script_name; + StringName base_native_type; + Set<Object *> instances; + DLScriptData *script_data; + +#ifdef TOOLS_ENABLED + Set<PlaceHolderScriptInstance *> placeholders; +// void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); +// virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); +#endif + + friend class DLInstance; + friend class DLScriptLanguage; + +protected: + static void _bind_methods(); + +public: + virtual bool can_instance() const; + + virtual Ref<Script> get_base_script() const; //for script inheritance + + virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so + virtual ScriptInstance *instance_create(Object *p_this); + virtual bool instance_has(const Object *p_this) const; + + virtual bool has_source_code() const; + virtual String get_source_code() const; + virtual void set_source_code(const String &p_code) {} + virtual Error reload(bool p_keep_state = false); + + virtual bool has_method(const StringName &p_method) const; + virtual MethodInfo get_method_info(const StringName &p_method) const; + + virtual bool is_tool() const; + + virtual String get_node_type() const; + + virtual ScriptLanguage *get_language() const; + + virtual bool has_script_signal(const StringName &p_signal) const; + virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; + + virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const; + + virtual void update_exports() {} //editor tool + virtual void get_script_method_list(List<MethodInfo> *p_list) const; + virtual void get_script_property_list(List<PropertyInfo> *p_list) const; + + Ref<DLLibrary> get_library() const; + void set_library(Ref<DLLibrary> p_library); + + StringName get_script_name() const; + void set_script_name(StringName p_script_name); + + DLScript(); + ~DLScript(); +}; + +class DLLibrary : public Resource { + _THREAD_SAFE_CLASS_ + + GDCLASS(DLLibrary, Resource); + OBJ_SAVE_TYPE(DLLibrary); + + Map<StringName, String> platform_files; + void *library_handle; + String library_path; + static DLLibrary *currently_initialized_library; + Map<StringName, DLScriptData *> scripts; + +protected: + friend class DLScript; + _FORCE_INLINE_ void _update_library(const DLLibrary &p_other) { + platform_files = p_other.platform_files; + library_handle = p_other.library_handle; + library_path = p_other.library_path; + scripts = p_other.scripts; + } + + Error _initialize_handle(bool p_in_editor = false); + + Error _free_handle(bool p_in_editor = false); + + DLScriptData *get_script_data(const StringName p_name); + + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + static DLLibrary *get_currently_initialized_library(); + + void _register_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func); + void _register_tool_script(const StringName p_name, const StringName p_base, godot_instance_create_func p_instance_func, godot_instance_destroy_func p_destroy_func); + void _register_script_method(const StringName p_name, const StringName p_method, godot_method_attributes p_attr, godot_instance_method p_func, MethodInfo p_info); + void _register_script_property(const StringName p_name, const String p_path, godot_property_attributes *p_attr, godot_property_set_func p_setter, godot_property_get_func p_getter); + void _register_script_signal(const StringName p_name, const godot_signal *p_signal); + + void set_platform_file(StringName p_platform, String p_file); + String get_platform_file(StringName p_platform) const; + + DLLibrary(); + ~DLLibrary(); +}; + +class DLInstance : public ScriptInstance { + friend class DLScript; + + Object *owner; + Ref<DLScript> script; + void *userdata; + + void _ml_call_reversed(DLScriptData *data_ptr, const StringName &p_method, const Variant **p_args, int p_argcount); + +public: + _FORCE_INLINE_ Object *get_owner() { return owner; } + + _FORCE_INLINE_ void *get_userdata() { return userdata; } + + virtual bool set(const StringName &p_name, const Variant &p_value); + virtual bool get(const StringName &p_name, Variant &r_ret) const; + virtual void get_property_list(List<PropertyInfo> *p_properties) const; + virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; + + virtual void get_method_list(List<MethodInfo> *p_list) const; + virtual bool has_method(const StringName &p_method) const; + virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); + virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); + virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); + + Variant debug_get_member_by_index(int p_idx) const { return Variant(); } + + virtual void notification(int p_notification); + + virtual Ref<Script> get_script() const; + + virtual ScriptLanguage *get_language(); + + void set_path(const String &p_path); + + void reload_members(); + + virtual RPCMode get_rpc_mode(const StringName &p_method) const; + virtual RPCMode get_rset_mode(const StringName &p_variable) const; + + DLInstance(); + ~DLInstance(); +}; + +class DLScriptLanguage : public ScriptLanguage { + friend class DLScript; + friend class DLInstance; + + static DLScriptLanguage *singleton; + + Variant *_global_array; // @Unused necessary? + Vector<Variant> global_array; // @Unused necessary? + Map<StringName, int> globals; // @Unused necessary? + + // @Unused necessary? + void _add_global(const StringName &p_name, const Variant &p_value); + + Mutex *lock; + + SelfList<DLScript>::List script_list; + + Map<String, DLLibrary *> initialized_libraries; + + bool profiling; + uint64_t script_frame_time; + + struct { + + StringName _notification; + + } strings; + +public: + _FORCE_INLINE_ static DLScriptLanguage *get_singleton() { return singleton; } + + virtual String get_name() const; + + bool is_library_initialized(const String &p_path); + void set_library_initialized(const String &p_path, DLLibrary *p_dllibrary); + DLLibrary *get_library_dllibrary(const String &p_path); + void set_library_uninitialized(const String &p_path); + + /* LANGUAGE FUNCTIONS */ + virtual void init(); + virtual String get_type() const; + virtual String get_extension() const; + virtual Error execute_file(const String &p_path); + virtual void finish(); + + /* EDITOR FUNCTIONS */ + + virtual void get_reserved_words(List<String> *p_words) const {}; + virtual void get_comment_delimiters(List<String> *p_delimiters) const {}; + virtual void get_string_delimiters(List<String> *p_delimiters) const {}; + virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; + virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const; + virtual Script *create_script() const; + virtual bool has_named_classes() const; + virtual int find_function(const String &p_function, const String &p_code) const; + virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; + + virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; } + + virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } + + virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {}; + virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); + + /* MULTITHREAD FUNCTIONS */ + + //some VMs need to be notified of thread creation/exiting to allocate a stack + virtual void thread_enter() {} + virtual void thread_exit() {} + + /* DEBUGGER FUNCTIONS */ + + virtual String debug_get_error() const; + virtual int debug_get_stack_level_count() const; + virtual int debug_get_stack_level_line(int p_level) const; + virtual String debug_get_stack_level_function(int p_level) const; + virtual String debug_get_stack_level_source(int p_level) const; + virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1){}; + virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); + virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); + virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1); + + virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } + + virtual void reload_all_scripts(); + virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload); + /* LOADER FUNCTIONS */ + + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual void get_public_functions(List<MethodInfo> *p_functions) const; + virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const; + + /* PROFILLER FUNCTIONS */ + + virtual void profiling_start(); + virtual void profiling_stop(); + + virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); + virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); + + virtual void frame(); + + static String get_init_symbol_name(); + static String get_terminate_symbol_name(); + + /* HACKER FUNCTIONS */ + void _compile_dummy_for_the_api(); + + DLScriptLanguage(); + ~DLScriptLanguage(); +}; + +class ResourceFormatLoaderDLScript : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class ResourceFormatSaverDLScript : public ResourceFormatSaver { + virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); + virtual bool recognize(const RES &p_resource) const; + virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; +}; + +// ugly, but hey + +#endif // DL_SCRIPT_H diff --git a/modules/dlscript/godot.cpp b/modules/dlscript/godot.cpp new file mode 100644 index 0000000000..9a488ad612 --- /dev/null +++ b/modules/dlscript/godot.cpp @@ -0,0 +1,198 @@ +/*************************************************************************/ +/* godot_c.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "godot.h" + +#include "class_db.h" +#include "dl_script.h" +#include "global_config.h" +#include "variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern "C" void _string_api_anchor(); +extern "C" void _vector2_api_anchor(); +extern "C" void _rect2_api_anchor(); +extern "C" void _vector3_api_anchor(); +extern "C" void _transform2d_api_anchor(); +extern "C" void _plane_api_anchor(); +extern "C" void _quat_api_anchor(); +extern "C" void _basis_api_anchor(); +extern "C" void _rect3_api_anchor(); +extern "C" void _transform_api_anchor(); +extern "C" void _color_api_anchor(); +extern "C" void _image_api_anchor(); +extern "C" void _node_path_api_anchor(); +extern "C" void _rid_api_anchor(); +extern "C" void _input_event_api_anchor(); +extern "C" void _dictionary_api_anchor(); +extern "C" void _array_api_anchor(); +extern "C" void _pool_arrays_api_anchor(); +extern "C" void _variant_api_anchor(); + +void _api_anchor() { + + _string_api_anchor(); + _vector2_api_anchor(); + _rect2_api_anchor(); + _vector3_api_anchor(); + _transform2d_api_anchor(); + _plane_api_anchor(); + _quat_api_anchor(); + _rect3_api_anchor(); + _basis_api_anchor(); + _transform_api_anchor(); + _color_api_anchor(); + _image_api_anchor(); + _node_path_api_anchor(); + _rid_api_anchor(); + _input_event_api_anchor(); + _dictionary_api_anchor(); + _array_api_anchor(); + _pool_arrays_api_anchor(); + _variant_api_anchor(); +} + +extern "C++" { +template <class a, class b> +_FORCE_INLINE_ a memcast(b v) { + return *((a *)&v); +} +} + +void GDAPI godot_object_destroy(godot_object *p_o) { + memdelete((Object *)p_o); +} + +// Singleton API + +godot_object GDAPI *godot_global_get_singleton(char *p_name) { + return (godot_object *)GlobalConfig::get_singleton()->get_singleton_object(String(p_name)); +} // result shouldn't be freed + +// MethodBind API + +godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname) { + + MethodBind *mb = ClassDB::get_method(StringName(p_classname), StringName(p_methodname)); + // MethodBind *mb = ClassDB::get_method("Node", "get_name"); + return (godot_method_bind *)mb; +} + +void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) { + + MethodBind *mb = (MethodBind *)p_method_bind; + Object *o = (Object *)p_instance; + mb->ptrcall(o, p_args, p_ret); +} + +// @Todo +/* +void GDAPI godot_method_bind_varcall(godot_method_bind *p_method_bind) +{ + +} +*/ + +// Script API + +void GDAPI godot_script_register_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { + DLLibrary *library = DLLibrary::get_currently_initialized_library(); + if (!library) { + ERR_EXPLAIN("Attempt to register script after initializing library!"); + ERR_FAIL(); + } + library->_register_script(p_name, p_base, p_create_func, p_destroy_func); +} + +void GDAPI godot_script_register_tool_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) { + DLLibrary *library = DLLibrary::get_currently_initialized_library(); + if (!library) { + ERR_EXPLAIN("Attempt to register script after initializing library!"); + ERR_FAIL(); + } + library->_register_tool_script(p_name, p_base, p_create_func, p_destroy_func); +} + +void GDAPI godot_script_register_method(const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) { + DLLibrary *library = DLLibrary::get_currently_initialized_library(); + if (!library) { + ERR_EXPLAIN("Attempt to register script after initializing library!"); + ERR_FAIL(); + } + library->_register_script_method(p_name, p_function_name, p_attr, p_method, MethodInfo()); +} + +void GDAPI godot_script_register_property(const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) { + DLLibrary *library = DLLibrary::get_currently_initialized_library(); + if (!library) { + ERR_EXPLAIN("Attempt to register script after initializing library!"); + ERR_FAIL(); + } + + library->_register_script_property(p_name, p_path, p_attr, p_set_func, p_get_func); +} + +void GDAPI godot_script_register_signal(const char *p_name, const godot_signal *p_signal) { + DLLibrary *library = DLLibrary::get_currently_initialized_library(); + if (!library) { + ERR_EXPLAIN("Attempt to register script after initializing library!"); + ERR_FAIL(); + } + + library->_register_script_signal(p_name, p_signal); +} + +void GDAPI *godot_dlinstance_get_userdata(godot_object *p_instance) { + Object *instance = (Object *)p_instance; + if (!instance) + return NULL; + if (instance->get_script_instance() && instance->get_script_instance()->get_language() == DLScriptLanguage::get_singleton()) { + return ((DLInstance *)instance->get_script_instance())->get_userdata(); + } + return NULL; +} + +// System functions +void GDAPI *godot_alloc(int p_bytes) { + return memalloc(p_bytes); +} + +void GDAPI *godot_realloc(void *p_ptr, int p_bytes) { + return memrealloc(p_ptr, p_bytes); +} + +void GDAPI godot_free(void *p_ptr) { + memfree(p_ptr); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot.h b/modules/dlscript/godot.h new file mode 100644 index 0000000000..75f1f47ed1 --- /dev/null +++ b/modules/dlscript/godot.h @@ -0,0 +1,389 @@ +/*************************************************************************/ +/* godot_c.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GODOT_C_H +#define GODOT_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef GDAPI_BUILT_IN +#define GDAPI_EXPORT +#endif + +#if !defined(_WIN32) && !defined(_MSC_VER) +#define GDAPI +#elif defined(GDAPI_EXPORT) +#define GDAPI __declspec(dllexport) +#else +#define GDAPI __declspec(dllimport) +#endif + +#include <stdbool.h> +#include <stdint.h> + +#define GODOT_API_VERSION 1 + +////// Error + +typedef enum godot_error { + GODOT_OK, + GODOT_FAILED, ///< Generic fail error + GODOT_ERR_UNAVAILABLE, ///< What is requested is unsupported/unavailable + GODOT_ERR_UNCONFIGURED, ///< The object being used hasnt been properly set up yet + GODOT_ERR_UNAUTHORIZED, ///< Missing credentials for requested resource + GODOT_ERR_PARAMETER_RANGE_ERROR, ///< Parameter given out of range (5) + GODOT_ERR_OUT_OF_MEMORY, ///< Out of memory + GODOT_ERR_FILE_NOT_FOUND, + GODOT_ERR_FILE_BAD_DRIVE, + GODOT_ERR_FILE_BAD_PATH, + GODOT_ERR_FILE_NO_PERMISSION, // (10) + GODOT_ERR_FILE_ALREADY_IN_USE, + GODOT_ERR_FILE_CANT_OPEN, + GODOT_ERR_FILE_CANT_WRITE, + GODOT_ERR_FILE_CANT_READ, + GODOT_ERR_FILE_UNRECOGNIZED, // (15) + GODOT_ERR_FILE_CORRUPT, + GODOT_ERR_FILE_MISSING_DEPENDENCIES, + GODOT_ERR_FILE_EOF, + GODOT_ERR_CANT_OPEN, ///< Can't open a resource/socket/file + GODOT_ERR_CANT_CREATE, // (20) + GODOT_ERR_QUERY_FAILED, + GODOT_ERR_ALREADY_IN_USE, + GODOT_ERR_LOCKED, ///< resource is locked + GODOT_ERR_TIMEOUT, + GODOT_ERR_CANT_CONNECT, // (25) + GODOT_ERR_CANT_RESOLVE, + GODOT_ERR_CONNECTION_ERROR, + GODOT_ERR_CANT_AQUIRE_RESOURCE, + GODOT_ERR_CANT_FORK, + GODOT_ERR_INVALID_DATA, ///< Data passed is invalid (30) + GODOT_ERR_INVALID_PARAMETER, ///< Parameter passed is invalid + GODOT_ERR_ALREADY_EXISTS, ///< When adding, item already exists + GODOT_ERR_DOES_NOT_EXIST, ///< When retrieving/erasing, it item does not exist + GODOT_ERR_DATABASE_CANT_READ, ///< database is full + GODOT_ERR_DATABASE_CANT_WRITE, ///< database is full (35) + GODOT_ERR_COMPILATION_FAILED, + GODOT_ERR_METHOD_NOT_FOUND, + GODOT_ERR_LINK_FAILED, + GODOT_ERR_SCRIPT_FAILED, + GODOT_ERR_CYCLIC_LINK, // (40) + GODOT_ERR_INVALID_DECLARATION, + GODOT_ERR_DUPLICATE_SYMBOL, + GODOT_ERR_PARSE_ERROR, + GODOT_ERR_BUSY, + GODOT_ERR_SKIP, // (45) + GODOT_ERR_HELP, ///< user requested help!! + GODOT_ERR_BUG, ///< a bug in the software certainly happened, due to a double check failing or unexpected behavior. + GODOT_ERR_PRINTER_ON_FIRE, /// the parallel port printer is engulfed in flames + GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD, ///< shit happens, has never been used, though + GODOT_ERR_WTF = GODOT_ERR_OMFG_THIS_IS_VERY_VERY_BAD ///< short version of the above +} godot_error; + +////// bool + +typedef bool godot_bool; + +#define GODOT_TRUE 1 +#define GODOT_FALSE 0 + +/////// int + +typedef int godot_int; + +/////// real + +typedef float godot_real; + +/////// Object (forward declared) +typedef void godot_object; + +/////// String + +#include "godot/godot_string.h" + +////// Vector2 + +#include "godot/godot_vector2.h" + +////// Rect2 + +#include "godot/godot_rect2.h" + +////// Vector3 + +#include "godot/godot_vector3.h" + +////// Transform2D + +#include "godot/godot_transform2d.h" + +/////// Plane + +#include "godot/godot_plane.h" + +/////// Quat + +#include "godot/godot_quat.h" + +/////// Rect3 + +#include "godot/godot_rect3.h" + +/////// Basis + +#include "godot/godot_basis.h" + +/////// Transform + +#include "godot/godot_transform.h" + +/////// Color + +#include "godot/godot_color.h" + +/////// Image + +#include "godot/godot_image.h" + +/////// NodePath + +#include "godot/godot_node_path.h" + +/////// RID + +#include "godot/godot_rid.h" + +/////// InputEvent + +#include "godot/godot_input_event.h" + +/////// Dictionary + +#include "godot/godot_dictionary.h" + +/////// Array + +#include "godot/godot_array.h" + +// single API file for Pool*Array +#include "godot/godot_pool_arrays.h" + +void GDAPI godot_object_destroy(godot_object *p_o); + +////// Variant + +#include "godot/godot_variant.h" + +////// Singleton API + +godot_object GDAPI *godot_global_get_singleton(char *p_name); // result shouldn't be freed + +////// MethodBind API + +typedef struct godot_method_bind { + uint8_t _dont_touch_that[1]; // TODO +} godot_method_bind; + +godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname); +void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret); + +////// Script API + +typedef struct godot_dlscript_init_options { + godot_bool in_editor; + uint64_t core_api_hash; + uint64_t editor_api_hash; + uint64_t no_api_hash; +} godot_dlscript_init_options; + +typedef struct godot_dlscript_terminate_options { + godot_bool in_editor; +} godot_dlscript_terminate_options; + +typedef enum godot_method_rpc_mode { + GODOT_METHOD_RPC_MODE_DISABLED, + GODOT_METHOD_RPC_MODE_REMOTE, + GODOT_METHOD_RPC_MODE_SYNC, + GODOT_METHOD_RPC_MODE_MASTER, + GODOT_METHOD_RPC_MODE_SLAVE, +} godot_method_rpc_mode; + +typedef struct godot_method_attributes { + godot_method_rpc_mode rpc_type; +} godot_method_attributes; + +typedef enum godot_property_hint { + GODOT_PROPERTY_HINT_NONE, ///< no hint provided. + GODOT_PROPERTY_HINT_RANGE, ///< hint_text = "min,max,step,slider; //slider is optional" + GODOT_PROPERTY_HINT_EXP_RANGE, ///< hint_text = "min,max,step", exponential edit + GODOT_PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc" + GODOT_PROPERTY_HINT_EXP_EASING, /// exponential easing funciton (Math::ease) + GODOT_PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer) + GODOT_PROPERTY_HINT_SPRITE_FRAME, + GODOT_PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer) + GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags) + GODOT_PROPERTY_HINT_LAYERS_2D_RENDER, + GODOT_PROPERTY_HINT_LAYERS_2D_PHYSICS, + GODOT_PROPERTY_HINT_LAYERS_3D_RENDER, + GODOT_PROPERTY_HINT_LAYERS_3D_PHYSICS, + GODOT_PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," + GODOT_PROPERTY_HINT_DIR, ///< a directort path must be passed + GODOT_PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc," + GODOT_PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed + GODOT_PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type + GODOT_PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines + GODOT_PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color + GODOT_PROPERTY_HINT_IMAGE_COMPRESS_LOSSY, + GODOT_PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS, + GODOT_PROPERTY_HINT_OBJECT_ID, + GODOT_PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose + GODOT_PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts) + GODOT_PROPERTY_HINT_METHOD_OF_VARIANT_TYPE, ///< a method of a type + GODOT_PROPERTY_HINT_METHOD_OF_BASE_TYPE, ///< a method of a base type + GODOT_PROPERTY_HINT_METHOD_OF_INSTANCE, ///< a method of an instance + GODOT_PROPERTY_HINT_METHOD_OF_SCRIPT, ///< a method of a script & base + GODOT_PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, ///< a property of a type + GODOT_PROPERTY_HINT_PROPERTY_OF_BASE_TYPE, ///< a property of a base type + GODOT_PROPERTY_HINT_PROPERTY_OF_INSTANCE, ///< a property of an instance + GODOT_PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base + GODOT_PROPERTY_HINT_MAX, +} godot_property_hint; + +typedef enum godot_property_usage_flags { + + GODOT_PROPERTY_USAGE_STORAGE = 1, + GODOT_PROPERTY_USAGE_EDITOR = 2, + GODOT_PROPERTY_USAGE_NETWORK = 4, + GODOT_PROPERTY_USAGE_EDITOR_HELPER = 8, + GODOT_PROPERTY_USAGE_CHECKABLE = 16, //used for editing global variables + GODOT_PROPERTY_USAGE_CHECKED = 32, //used for editing global variables + GODOT_PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings + GODOT_PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor + GODOT_PROPERTY_USAGE_CATEGORY = 256, + GODOT_PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero + GODOT_PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false + GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE = 2048, + GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED = 4096, + GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE = 8192, + GODOT_PROPERTY_USAGE_STORE_IF_NULL = 16384, + GODOT_PROPERTY_USAGE_ANIMATE_AS_TRIGGER = 32768, + GODOT_PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED = 65536, + + GODOT_PROPERTY_USAGE_DEFAULT = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK, + GODOT_PROPERTY_USAGE_DEFAULT_INTL = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_EDITOR | GODOT_PROPERTY_USAGE_NETWORK | GODOT_PROPERTY_USAGE_INTERNATIONALIZED, + GODOT_PROPERTY_USAGE_NOEDITOR = GODOT_PROPERTY_USAGE_STORAGE | GODOT_PROPERTY_USAGE_NETWORK, +} godot_property_usage_flags; + +typedef struct godot_property_attributes { + godot_method_rpc_mode rset_type; + + godot_int type; + godot_property_hint hint; + godot_string hint_string; + godot_property_usage_flags usage; + godot_variant default_value; +} godot_property_attributes; + +typedef struct godot_instance_create_func { + // instance pointer, method_data - return user data + void *(*create_func)(godot_object *, void *); + void *method_data; + void (*free_func)(void *); +} godot_script_instance_func; + +typedef struct godot_instance_destroy_func { + // instance pointer, method data, user data + void (*destroy_func)(godot_object *, void *, void *); + void *method_data; + void (*free_func)(void *); +} godot_instance_destroy_func; + +void GDAPI godot_script_register_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); + +void GDAPI godot_script_register_tool_class(const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func); + +typedef struct godot_instance_method { + // instance pointer, method data, user data, num args, args - return result as varaint + godot_variant (*method)(godot_object *, void *, void *, int, godot_variant **); + void *method_data; + void (*free_func)(void *); +} godot_instance_method; + +void GDAPI godot_script_register_method(const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method); + +typedef struct godot_property_set_func { + // instance pointer, method data, user data, value + void (*set_func)(godot_object *, void *, void *, godot_variant); + void *method_data; + void (*free_func)(void *); +} godot_property_set_func; + +typedef struct godot_property_get_func { + // instance pointer, method data, user data, value + godot_variant (*get_func)(godot_object *, void *, void *); + void *method_data; + void (*free_func)(void *); +} godot_property_get_func; + +void GDAPI godot_script_register_property(const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func); + +typedef struct godot_signal_argument { + godot_string name; + godot_int type; + godot_property_hint hint; + godot_string hint_string; + godot_property_usage_flags usage; + godot_variant default_value; +} godot_signal_argument; + +typedef struct godot_signal { + godot_string name; + int num_args; + godot_signal_argument *args; + int num_default_args; + godot_variant *default_args; +} godot_signal; + +void GDAPI godot_script_register_signal(const char *p_name, const godot_signal *p_signal); + +void GDAPI *godot_dlinstance_get_userdata(godot_object *p_instance); + +////// System Functions + +//using these will help Godot track how much memory is in use in debug mode +void GDAPI *godot_alloc(int p_bytes); +void GDAPI *godot_realloc(void *p_ptr, int p_bytes); +void GDAPI godot_free(void *p_ptr); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_C_H diff --git a/modules/dlscript/godot/godot_array.cpp b/modules/dlscript/godot/godot_array.cpp new file mode 100644 index 0000000000..21ad97ca78 --- /dev/null +++ b/modules/dlscript/godot/godot_array.cpp @@ -0,0 +1,271 @@ +#include "godot_array.h" + +#include "core/array.h" +#include "core/os/memory.h" + +#include "core/color.h" +#include "core/dvector.h" + +#include "core/variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _array_api_anchor() { +} + +void GDAPI godot_array_new(godot_array *p_arr) { + Array *a = (Array *)p_arr; + memnew_placement(a, Array); +} + +void GDAPI godot_array_new_pool_color_array(godot_array *p_arr, const godot_pool_color_array *p_pca) { + Array *a = (Array *)p_arr; + PoolVector<Color> *pca = (PoolVector<Color> *)p_pca; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_vector3_array(godot_array *p_arr, const godot_pool_vector3_array *p_pv3a) { + Array *a = (Array *)p_arr; + PoolVector<Vector3> *pca = (PoolVector<Vector3> *)p_pv3a; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_vector2_array(godot_array *p_arr, const godot_pool_vector2_array *p_pv2a) { + Array *a = (Array *)p_arr; + PoolVector<Vector2> *pca = (PoolVector<Vector2> *)p_pv2a; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_string_array(godot_array *p_arr, const godot_pool_string_array *p_psa) { + Array *a = (Array *)p_arr; + PoolVector<String> *pca = (PoolVector<String> *)p_psa; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_real_array(godot_array *p_arr, const godot_pool_real_array *p_pra) { + Array *a = (Array *)p_arr; + PoolVector<godot_real> *pca = (PoolVector<godot_real> *)p_pra; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_int_array(godot_array *p_arr, const godot_pool_int_array *p_pia) { + Array *a = (Array *)p_arr; + PoolVector<godot_int> *pca = (PoolVector<godot_int> *)p_pia; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_new_pool_byte_array(godot_array *p_arr, const godot_pool_byte_array *p_pba) { + Array *a = (Array *)p_arr; + PoolVector<uint8_t> *pca = (PoolVector<uint8_t> *)p_pba; + memnew_placement(a, Array); + a->resize(pca->size()); + + for (size_t i = 0; i < a->size(); i++) { + Variant v = pca->operator[](i); + a->operator[](i) = v; + } +} + +void GDAPI godot_array_set(godot_array *p_arr, const godot_int p_idx, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->operator[](p_idx) = *val; +} + +godot_variant GDAPI *godot_array_get(godot_array *p_arr, const godot_int p_idx) { + Array *a = (Array *)p_arr; + return (godot_variant *)&a->operator[](p_idx); +} + +void GDAPI godot_array_append(godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->append(*val); +} + +void GDAPI godot_array_clear(godot_array *p_arr) { + Array *a = (Array *)p_arr; + a->clear(); +} + +godot_int GDAPI godot_array_count(godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + return a->count(*val); +} + +godot_bool GDAPI godot_array_empty(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + return a->empty(); +} + +void GDAPI godot_array_erase(godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->erase(*val); +} + +godot_variant GDAPI godot_array_front(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = a->front(); + return v; +} + +godot_variant GDAPI godot_array_back(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = a->back(); + return v; +} + +godot_int GDAPI godot_array_find(const godot_array *p_arr, const godot_variant *p_what, const godot_int p_from) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_what; + return a->find(*val, p_from); +} + +godot_int GDAPI godot_array_find_last(const godot_array *p_arr, const godot_variant *p_what) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_what; + return a->find_last(*val); +} + +godot_bool GDAPI godot_array_has(const godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + return a->has(*val); +} + +uint32_t GDAPI godot_array_hash(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + return a->hash(); +} + +void GDAPI godot_array_insert(godot_array *p_arr, const godot_int p_pos, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->insert(p_pos, *val); +} + +void GDAPI godot_array_invert(godot_array *p_arr) { + Array *a = (Array *)p_arr; + a->invert(); +} + +godot_bool GDAPI godot_array_is_shared(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + return false; // @Todo how do I do it? +} + +godot_variant GDAPI godot_array_pop_back(godot_array *p_arr) { + Array *a = (Array *)p_arr; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = a->pop_back(); + return v; +} + +godot_variant GDAPI godot_array_pop_front(godot_array *p_arr) { + Array *a = (Array *)p_arr; + godot_variant v; + Variant *val = (Variant *)&v; + memnew_placement(val, Variant); + *val = a->pop_front(); + return v; +} + +void GDAPI godot_array_push_back(godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->push_back(*val); +} + +void GDAPI godot_array_push_front(godot_array *p_arr, const godot_variant *p_value) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_value; + a->push_front(*val); +} + +void GDAPI godot_array_remove(godot_array *p_arr, const godot_int p_idx) { + Array *a = (Array *)p_arr; + a->remove(p_idx); +} + +void GDAPI godot_array_resize(godot_array *p_arr, const godot_int p_size) { + Array *a = (Array *)p_arr; + a->resize(p_size); +} + +godot_int GDAPI godot_array_rfind(const godot_array *p_arr, const godot_variant *p_what, const godot_int p_from) { + Array *a = (Array *)p_arr; + Variant *val = (Variant *)p_what; + return a->rfind(*val, p_from); +} + +godot_int GDAPI godot_array_size(const godot_array *p_arr) { + Array *a = (Array *)p_arr; + return a->size(); +} + +void GDAPI godot_array_sort(godot_array *p_arr) { + Array *a = (Array *)p_arr; + a->sort(); +} + +void GDAPI godot_array_sort_custom(godot_array *p_arr, godot_object *p_obj, const godot_string *p_func) { + Array *a = (Array *)p_arr; + String *func = (String *)p_func; + a->sort_custom((Object *)p_obj, *func); +} + +void GDAPI godot_array_destroy(godot_array *p_arr) { + ((Array *)p_arr)->~Array(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_array.h b/modules/dlscript/godot/godot_array.h new file mode 100644 index 0000000000..544e95a2ed --- /dev/null +++ b/modules/dlscript/godot/godot_array.h @@ -0,0 +1,88 @@ +#ifndef GODOT_DLSCRIPT_ARRAY_H +#define GODOT_DLSCRIPT_ARRAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_ARRAY_TYPE_DEFINED +typedef struct godot_array { + uint8_t _dont_touch_that[8]; +} godot_array; +#endif + +#include "../godot.h" + +#include "godot_pool_arrays.h" +#include "godot_variant.h" + +void GDAPI godot_array_new(godot_array *p_arr); +void GDAPI godot_array_new_pool_color_array(godot_array *p_arr, const godot_pool_color_array *p_pca); +void GDAPI godot_array_new_pool_vector3_array(godot_array *p_arr, const godot_pool_vector3_array *p_pv3a); +void GDAPI godot_array_new_pool_vector2_array(godot_array *p_arr, const godot_pool_vector2_array *p_pv2a); +void GDAPI godot_array_new_pool_string_array(godot_array *p_arr, const godot_pool_string_array *p_psa); +void GDAPI godot_array_new_pool_real_array(godot_array *p_arr, const godot_pool_real_array *p_pra); +void GDAPI godot_array_new_pool_int_array(godot_array *p_arr, const godot_pool_int_array *p_pia); +void GDAPI godot_array_new_pool_byte_array(godot_array *p_arr, const godot_pool_byte_array *p_pba); + +void GDAPI godot_array_set(godot_array *p_arr, const godot_int p_idx, const godot_variant *p_value); + +godot_variant GDAPI *godot_array_get(godot_array *p_arr, const godot_int p_idx); + +void GDAPI godot_array_append(godot_array *p_arr, const godot_variant *p_value); + +void GDAPI godot_array_clear(godot_array *p_arr); + +godot_int GDAPI godot_array_count(godot_array *p_arr, const godot_variant *p_value); + +godot_bool GDAPI godot_array_empty(const godot_array *p_arr); + +void GDAPI godot_array_erase(godot_array *p_arr, const godot_variant *p_value); + +godot_variant GDAPI godot_array_front(const godot_array *p_arr); + +godot_variant GDAPI godot_array_back(const godot_array *p_arr); + +godot_int GDAPI godot_array_find(const godot_array *p_arr, const godot_variant *p_what, const godot_int p_from); + +godot_int GDAPI godot_array_find_last(const godot_array *p_arr, const godot_variant *p_what); + +godot_bool GDAPI godot_array_has(const godot_array *p_arr, const godot_variant *p_value); + +uint32_t GDAPI godot_array_hash(const godot_array *p_arr); + +void GDAPI godot_array_insert(godot_array *p_arr, const godot_int p_pos, const godot_variant *p_value); + +void GDAPI godot_array_invert(godot_array *p_arr); + +godot_bool GDAPI godot_array_is_shared(const godot_array *p_arr); + +godot_variant GDAPI godot_array_pop_back(godot_array *p_arr); + +godot_variant GDAPI godot_array_pop_front(godot_array *p_arr); + +void GDAPI godot_array_push_back(godot_array *p_arr, const godot_variant *p_value); + +void GDAPI godot_array_push_front(godot_array *p_arr, const godot_variant *p_value); + +void GDAPI godot_array_remove(godot_array *p_arr, const godot_int p_idx); + +void GDAPI godot_array_resize(godot_array *p_arr, const godot_int p_size); + +godot_int GDAPI godot_array_rfind(const godot_array *p_arr, const godot_variant *p_what, const godot_int p_from); + +godot_int GDAPI godot_array_size(const godot_array *p_arr); + +void GDAPI godot_array_sort(godot_array *p_arr); + +void GDAPI godot_array_sort_custom(godot_array *p_arr, godot_object *p_obj, const godot_string *p_func); + +void GDAPI godot_array_destroy(godot_array *p_arr); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_ARRAY_H diff --git a/modules/dlscript/godot/godot_basis.cpp b/modules/dlscript/godot/godot_basis.cpp new file mode 100644 index 0000000000..813a531de5 --- /dev/null +++ b/modules/dlscript/godot/godot_basis.cpp @@ -0,0 +1,58 @@ +#include "godot_basis.h" + +#include "math/matrix3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _basis_api_anchor() { +} + +void GDAPI godot_basis_new(godot_basis *p_basis) { + Basis *basis = (Basis *)p_basis; + *basis = Basis(); +} + +void GDAPI godot_basis_new_with_euler_quat(godot_basis *p_basis, const godot_quat *p_euler) { + Basis *basis = (Basis *)p_basis; + Quat *euler = (Quat *)p_euler; + *basis = Basis(*euler); +} + +void GDAPI godot_basis_new_with_euler(godot_basis *p_basis, const godot_vector3 *p_euler) { + Basis *basis = (Basis *)p_basis; + Vector3 *euler = (Vector3 *)p_euler; + *basis = Basis(*euler); +} + +godot_quat GDAPI godot_basis_as_quat(const godot_basis *p_basis) { + const Basis *basis = (const Basis *)p_basis; + godot_quat quat; + Quat *p_quat = (Quat *)&quat; + *p_quat = basis->operator Quat(); + return quat; +} + +godot_vector3 GDAPI godot_basis_get_euler(const godot_basis *p_basis) { + const Basis *basis = (const Basis *)p_basis; + godot_vector3 euler; + Vector3 *p_euler = (Vector3 *)&euler; + *p_euler = basis->get_euler(); + return euler; +} + +/* + * p_elements is a pointer to an array of 3 (!!) vector3 + */ +void GDAPI godot_basis_get_elements(godot_basis *p_basis, godot_vector3 *p_elements) { + Basis *basis = (Basis *)p_basis; + Vector3 *elements = (Vector3 *)p_elements; + elements[0] = basis->elements[0]; + elements[1] = basis->elements[1]; + elements[2] = basis->elements[2]; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_basis.h b/modules/dlscript/godot/godot_basis.h new file mode 100644 index 0000000000..43efd65ea2 --- /dev/null +++ b/modules/dlscript/godot/godot_basis.h @@ -0,0 +1,34 @@ +#ifndef GODOT_DLSCRIPT_BASIS_H +#define GODOT_DLSCRIPT_BASIS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_BASIS_TYPE_DEFINED +typedef struct godot_basis { + uint8_t _dont_touch_that[36]; +} godot_basis; +#endif + +#include "../godot.h" + +void GDAPI godot_basis_new(godot_basis *p_basis); +void GDAPI godot_basis_new_with_euler_quat(godot_basis *p_basis, const godot_quat *p_euler); +void GDAPI godot_basis_new_with_euler(godot_basis *p_basis, const godot_vector3 *p_euler); + +godot_quat GDAPI godot_basis_as_quat(const godot_basis *p_basis); +godot_vector3 GDAPI godot_basis_get_euler(const godot_basis *p_basis); + +/* + * p_elements is a pointer to an array of 3 (!!) vector3 + */ +void GDAPI godot_basis_get_elements(godot_basis *p_basis, godot_vector3 *p_elements); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_BASIS_H diff --git a/modules/dlscript/godot/godot_color.cpp b/modules/dlscript/godot/godot_color.cpp new file mode 100644 index 0000000000..7e49565d40 --- /dev/null +++ b/modules/dlscript/godot/godot_color.cpp @@ -0,0 +1,34 @@ +#include "godot_color.h" + +#include "color.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _color_api_anchor() { +} + +void GDAPI godot_color_new(godot_color *p_color) { + Color *color = (Color *)p_color; + *color = Color(); +} + +void GDAPI godot_color_new_rgba(godot_color *p_color, const godot_real r, const godot_real g, const godot_real b, const godot_real a) { + Color *color = (Color *)p_color; + *color = Color(r, g, b, a); +} + +uint32_t GDAPI godot_color_get_32(const godot_color *p_color) { + const Color *color = (const Color *)p_color; + return color->to_32(); +} + +float GDAPI *godot_color_index(godot_color *p_color, const godot_int idx) { + Color *color = (Color *)p_color; + return &color->operator[](idx); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_color.h b/modules/dlscript/godot/godot_color.h new file mode 100644 index 0000000000..72e16a2c5a --- /dev/null +++ b/modules/dlscript/godot/godot_color.h @@ -0,0 +1,29 @@ +#ifndef GODOT_DLSCRIPT_COLOR_H +#define GODOT_DLSCRIPT_COLOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_COLOR_TYPE_DEFINED +typedef struct godot_color { + uint8_t _dont_touch_that[16]; +} godot_color; +#endif + +#include "../godot.h" + +void GDAPI godot_color_new(godot_color *p_color); +void GDAPI godot_color_new_rgba(godot_color *p_color, const godot_real r, const godot_real g, const godot_real b, const godot_real a); + +uint32_t GDAPI godot_color_get_32(const godot_color *p_color); + +float GDAPI *godot_color_index(godot_color *p_color, const godot_int idx); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_COLOR_H diff --git a/modules/dlscript/godot/godot_dictionary.cpp b/modules/dlscript/godot/godot_dictionary.cpp new file mode 100644 index 0000000000..9147b17307 --- /dev/null +++ b/modules/dlscript/godot/godot_dictionary.cpp @@ -0,0 +1,109 @@ +#include "godot_dictionary.h" + +#include "core/dictionary.h" + +#include "core/os/memory.h" + +#include "core/io/json.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _dictionary_api_anchor() { +} + +void GDAPI godot_dictionary_new(godot_dictionary *p_dict) { + Dictionary *dict = (Dictionary *)p_dict; + memnew_placement(dict, Dictionary); +} + +void GDAPI godot_dictionary_clear(godot_dictionary *p_dict) { + Dictionary *dict = (Dictionary *)p_dict; + dict->clear(); +} + +godot_bool GDAPI godot_dictionary_empty(const godot_dictionary *p_dict) { + const Dictionary *dict = (const Dictionary *)p_dict; + return dict->empty(); +} + +void GDAPI godot_dictionary_erase(godot_dictionary *p_dict, const godot_variant *p_key) { + Dictionary *dict = (Dictionary *)p_dict; + Variant *key = (Variant *)p_key; + dict->erase(*key); +} + +godot_bool GDAPI godot_dictionary_has(const godot_dictionary *p_dict, const godot_variant *p_key) { + const Dictionary *dict = (const Dictionary *)p_dict; + const Variant *key = (const Variant *)p_key; + return dict->has(*key); +} + +godot_bool GDAPI godot_dictionary_has_all(const godot_dictionary *p_dict, const godot_array *p_keys) { + const Dictionary *dict = (const Dictionary *)p_dict; + const Array *keys = (const Array *)p_keys; + return dict->has_all(*keys); +} + +uint32_t GDAPI godot_dictionary_hash(const godot_dictionary *p_dict) { + const Dictionary *dict = (const Dictionary *)p_dict; + return dict->hash(); +} + +godot_array GDAPI godot_dictionary_keys(const godot_dictionary *p_dict) { + godot_array a; + godot_array_new(&a); + const Dictionary *dict = (const Dictionary *)p_dict; + Array *array = (Array *)&a; + *array = dict->keys(); + return a; +} + +godot_int GDAPI godot_dictionary_parse_json(godot_dictionary *p_dict, const godot_string *p_json) { + Dictionary *dict = (Dictionary *)p_dict; + const String *json = (const String *)p_json; + Variant ret; + int err_line; + String err_str; + int err = (int)JSON::parse(*json, ret, err_str, err_line); + *dict = ret; + return err; +} + +godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_dict, const godot_variant *p_key) { + Dictionary *dict = (Dictionary *)p_dict; + Variant *key = (Variant *)p_key; + return (godot_variant *)&dict->operator[](*key); +} + +godot_int GDAPI godot_dictionary_size(const godot_dictionary *p_dict) { + const Dictionary *dict = (const Dictionary *)p_dict; + return dict->size(); +} + +godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_dict) { + const Dictionary *dict = (const Dictionary *)p_dict; + godot_string str; + godot_string_new(&str); + String *s = (String *)&str; + *s = JSON::print(Variant(*dict)); + return str; +} + +godot_array GDAPI godot_dictionary_values(const godot_dictionary *p_dict) { + godot_array a; + godot_array_new(&a); + const Dictionary *dict = (const Dictionary *)p_dict; + Array *array = (Array *)&a; + *array = dict->values(); + return a; +} + +void GDAPI godot_dictionary_destroy(godot_dictionary *p_dict) { + ((Dictionary *)p_dict)->~Dictionary(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_dictionary.h b/modules/dlscript/godot/godot_dictionary.h new file mode 100644 index 0000000000..5f86cbca5a --- /dev/null +++ b/modules/dlscript/godot/godot_dictionary.h @@ -0,0 +1,51 @@ +#ifndef GODOT_DLSCRIPT_DICTIONARY_H +#define GODOT_DLSCRIPT_DICTIONARY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_DICITIONARY_TYPE_DEFINED +typedef struct godot_dictionary { + uint8_t _dont_touch_that[8]; +} godot_dictionary; +#endif + +#include "godot_array.h" +#include "godot_variant.h" + +void GDAPI godot_dictionary_new(godot_dictionary *p_dict); + +void GDAPI godot_dictionary_clear(godot_dictionary *p_dict); + +godot_bool GDAPI godot_dictionary_empty(const godot_dictionary *p_dict); + +void GDAPI godot_dictionary_erase(godot_dictionary *p_dict, const godot_variant *p_key); + +godot_bool GDAPI godot_dictionary_has(const godot_dictionary *p_dict, const godot_variant *p_key); + +godot_bool GDAPI godot_dictionary_has_all(const godot_dictionary *p_dict, const godot_array *p_keys); + +uint32_t GDAPI godot_dictionary_hash(const godot_dictionary *p_dict); + +godot_array GDAPI godot_dictionary_keys(const godot_dictionary *p_dict); + +godot_int GDAPI godot_dictionary_parse_json(godot_dictionary *p_dict, const godot_string *p_json); + +godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_dict, const godot_variant *p_key); + +godot_int GDAPI godot_dictionary_size(const godot_dictionary *p_dict); + +godot_string GDAPI godot_dictionary_to_json(const godot_dictionary *p_dict); + +godot_array GDAPI godot_dictionary_values(const godot_dictionary *p_dict); + +void GDAPI godot_dictionary_destroy(godot_dictionary *p_dict); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_DICTIONARY_H diff --git a/modules/dlscript/godot/godot_image.cpp b/modules/dlscript/godot/godot_image.cpp new file mode 100644 index 0000000000..362d1aa3e6 --- /dev/null +++ b/modules/dlscript/godot/godot_image.cpp @@ -0,0 +1,85 @@ +#include "godot_image.h" + +#include "image.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _image_api_anchor() { +} + +#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) + +void GDAPI godot_image_new(godot_image *p_img) { + Image *img = (Image *)p_img; + memnew_placement_custom(img, Image, Image()); +} + +void GDAPI godot_image_new_with_png_jpg(godot_image *p_img, const uint8_t *p_mem_png_jpg, int p_len) { + Image *img = (Image *)p_img; + memnew_placement_custom(img, Image, Image(p_mem_png_jpg, p_len)); +} + +void GDAPI godot_image_new_with_xpm(godot_image *p_img, const char **p_xpm) { + Image *img = (Image *)p_img; + memnew_placement_custom(img, Image, Image(p_xpm)); +} + +void GDAPI godot_image_new_with_size_format(godot_image *p_img, int p_width, int p_height, bool p_use_mipmaps, godot_image_format p_format) { + Image *img = (Image *)p_img; + memnew_placement_custom(img, Image, Image(p_width, p_height, p_use_mipmaps, (Image::Format)p_format)); +} + +void GDAPI godot_image_new_with_size_format_data(godot_image *p_img, int p_width, int p_height, bool p_use_mipmaps, godot_image_format p_format, godot_pool_byte_array *p_data) { + Image *img = (Image *)p_img; + PoolVector<uint8_t> *data = (PoolVector<uint8_t> *)p_data; + memnew_placement_custom(img, Image, Image(p_width, p_height, p_use_mipmaps, (Image::Format)p_format, *data)); +} + +godot_pool_byte_array GDAPI godot_image_get_data(godot_image *p_img) { + Image *img = (Image *)p_img; + PoolVector<uint8_t> cpp_data = img->get_data(); + godot_pool_byte_array *data = (godot_pool_byte_array *)&cpp_data; + return *data; +} + +godot_error GDAPI godot_image_load(godot_image *p_img, const godot_string *p_path) { + Image *img = (Image *)p_img; + String *path = (String *)p_path; + return (godot_error)img->load(*path); +} + +godot_error GDAPI godot_image_save_png(godot_image *p_img, const godot_string *p_path) { + Image *img = (Image *)p_img; + String *path = (String *)p_path; + return (godot_error)img->save_png(*path); +} + +int GDAPI godot_image_get_width(const godot_image *p_img) { + Image *img = (Image *)p_img; + return img->get_width(); +} + +int GDAPI godot_image_get_height(const godot_image *p_img) { + Image *img = (Image *)p_img; + return img->get_height(); +} + +godot_bool GDAPI godot_image_has_mipmaps(const godot_image *p_img) { + Image *img = (Image *)p_img; + return img->has_mipmaps(); +} + +int GDAPI godot_image_get_mipmap_count(const godot_image *p_img) { + Image *img = (Image *)p_img; + return img->get_mipmap_count(); +} + +void GDAPI godot_image_destroy(godot_image *p_img) { + ((Image *)p_img)->~Image(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_image.h b/modules/dlscript/godot/godot_image.h new file mode 100644 index 0000000000..78593f21a7 --- /dev/null +++ b/modules/dlscript/godot/godot_image.h @@ -0,0 +1,95 @@ +#ifndef GODOT_DLSCRIPT_IMAGE_H +#define GODOT_DLSCRIPT_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_IMAGE_TYPE_DEFINED +typedef struct godot_image { + uint8_t _dont_touch_that[32]; +} godot_image; +#endif + +#include "godot_pool_arrays.h" + +#include "../godot.h" + +// This is a copypasta of the C++ enum inside the Image class +// There's no neat way of automatically updating the C enum / using the C++ enum directly +// if somebody knows a way feel free to open a PR or open an issue (or ask for Karroffel or bojidar-bg on IRC) + +enum godot_image_format { + + GODOT_IMAGE_FORMAT_L8, //luminance + GODOT_IMAGE_FORMAT_LA8, //luminance-alpha + GODOT_IMAGE_FORMAT_R8, + GODOT_IMAGE_FORMAT_RG8, + GODOT_IMAGE_FORMAT_RGB8, + GODOT_IMAGE_FORMAT_RGBA8, + GODOT_IMAGE_FORMAT_RGB565, //16 bit + GODOT_IMAGE_FORMAT_RGBA4444, + GODOT_IMAGE_FORMAT_RGBA5551, + GODOT_IMAGE_FORMAT_RF, //float + GODOT_IMAGE_FORMAT_RGF, + GODOT_IMAGE_FORMAT_RGBF, + GODOT_IMAGE_FORMAT_RGBAF, + GODOT_IMAGE_FORMAT_RH, //half float + GODOT_IMAGE_FORMAT_RGH, + GODOT_IMAGE_FORMAT_RGBH, + GODOT_IMAGE_FORMAT_RGBAH, + GODOT_IMAGE_FORMAT_DXT1, //s3tc bc1 + GODOT_IMAGE_FORMAT_DXT3, //bc2 + GODOT_IMAGE_FORMAT_DXT5, //bc3 + GODOT_IMAGE_FORMAT_ATI1, //bc4 + GODOT_IMAGE_FORMAT_ATI2, //bc5 + GODOT_IMAGE_FORMAT_BPTC_RGBA, //btpc bc6h + GODOT_IMAGE_FORMAT_BPTC_RGBF, //float / + GODOT_IMAGE_FORMAT_BPTC_RGBFU, //unsigned float + GODOT_IMAGE_FORMAT_PVRTC2, //pvrtc + GODOT_IMAGE_FORMAT_PVRTC2A, + GODOT_IMAGE_FORMAT_PVRTC4, + GODOT_IMAGE_FORMAT_PVRTC4A, + GODOT_IMAGE_FORMAT_ETC, //etc1 + GODOT_IMAGE_FORMAT_ETC2_R11, //etc2 + GODOT_IMAGE_FORMAT_ETC2_R11S, //signed, NOT srgb. + GODOT_IMAGE_FORMAT_ETC2_RG11, + GODOT_IMAGE_FORMAT_ETC2_RG11S, + GODOT_IMAGE_FORMAT_ETC2_RGB8, + GODOT_IMAGE_FORMAT_ETC2_RGBA8, + GODOT_IMAGE_FORMAT_ETC2_RGB8A1, + GODOT_IMAGE_FORMAT_MAX +}; +typedef enum godot_image_format godot_image_format; + +void GDAPI godot_image_new(godot_image *p_img); +// p_len can be -1 +void GDAPI godot_image_new_with_png_jpg(godot_image *p_img, const uint8_t *p_mem_png_jpg, int p_len); +void GDAPI godot_image_new_with_xpm(godot_image *p_img, const char **p_xpm); + +void GDAPI godot_image_new_with_size_format(godot_image *p_img, int p_width, int p_height, bool p_use_mipmaps, godot_image_format p_format); +void GDAPI godot_image_new_with_size_format_data(godot_image *p_img, int p_width, int p_height, bool p_use_mipmaps, godot_image_format p_format, godot_pool_byte_array *p_data); + +godot_pool_byte_array GDAPI godot_image_get_data(godot_image *p_img); + +godot_error GDAPI godot_image_load(godot_image *p_img, const godot_string *p_path); +godot_error GDAPI godot_image_save_png(godot_image *p_img, const godot_string *p_path); + +int GDAPI godot_image_get_width(const godot_image *p_img); +int GDAPI godot_image_get_height(const godot_image *p_img); +godot_bool GDAPI godot_image_has_mipmaps(const godot_image *p_img); +int GDAPI godot_image_get_mipmap_count(const godot_image *p_img); + +// @Incomplete +// I think it's too complex for the binding authors to implement the image class anew, so we should definitely +// export all methods here. That takes a while so it's on my @Todo list + +void GDAPI godot_image_destroy(godot_image *p_img); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_IMAGE_H diff --git a/modules/dlscript/godot/godot_input_event.cpp b/modules/dlscript/godot/godot_input_event.cpp new file mode 100644 index 0000000000..b50ed8a22d --- /dev/null +++ b/modules/dlscript/godot/godot_input_event.cpp @@ -0,0 +1,280 @@ +#include "godot_input_event.h" + +#include "os/input_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _input_event_api_anchor() { +} + +void GDAPI godot_input_event_new(godot_input_event *p_ie) { + InputEvent *ie = (InputEvent *)p_ie; + *ie = InputEvent(); +} + +godot_bool GDAPI godot_input_event_is_pressed(const godot_input_event *p_ie) { + const InputEvent *ie = (const InputEvent *)p_ie; + return ie->is_pressed(); +} + +godot_bool GDAPI godot_input_event_is_action(const godot_input_event *p_ie, const godot_string *p_action) { + const InputEvent *ie = (const InputEvent *)p_ie; + const String *action = (const String *)p_action; + return ie->is_action(*action); +} + +godot_bool GDAPI godot_input_event_is_action_pressed(const godot_input_event *p_ie, const godot_string *p_action) { + const InputEvent *ie = (const InputEvent *)p_ie; + const String *action = (const String *)p_action; + return ie->is_action_pressed(*action); +} + +godot_bool GDAPI godot_input_event_is_action_released(const godot_input_event *p_ie, const godot_string *p_action) { + const InputEvent *ie = (const InputEvent *)p_ie; + const String *action = (const String *)p_action; + return ie->is_action_released(*action); +} + +godot_bool GDAPI godot_input_event_is_echo(const godot_input_event *p_ie) { + const InputEvent *ie = (const InputEvent *)p_ie; + return ie->is_echo(); +} + +void GDAPI godot_input_event_set_as_action(godot_input_event *p_ie, const godot_string *p_action, const godot_bool p_pressed) { + InputEvent *ie = (InputEvent *)p_ie; + const String *action = (const String *)p_action; + return ie->set_as_action(*action, p_pressed); +} + +godot_string GDAPI godot_input_event_as_string(const godot_input_event *p_ie) { + const InputEvent *ie = (const InputEvent *)p_ie; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = (String)*ie; + return str; +} + +uint32_t GDAPI *godot_input_event_get_id(godot_input_event *p_ie) { + InputEvent *ie = (InputEvent *)p_ie; + return &ie->ID; +} + +godot_input_event_type GDAPI *godot_input_event_get_type(godot_input_event *p_ie) { + InputEvent *ie = (InputEvent *)p_ie; + return (godot_input_event_type *)&ie->type; +} + +godot_int GDAPI *godot_input_event_get_device(godot_input_event *p_ie) { + InputEvent *ie = (InputEvent *)p_ie; + return &ie->device; +} + +static InputModifierState *_get_mod_for_type(InputEvent *ie) { + switch (ie->type) { + case InputEvent::MOUSE_BUTTON: + return &ie->mouse_button.mod; + case InputEvent::MOUSE_MOTION: + return &ie->mouse_motion.mod; + case InputEvent::KEY: + return &ie->key.mod; + default: + return 0; + } +} + +godot_bool GDAPI *godot_input_event_mod_get_alt(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + InputModifierState *mod = _get_mod_for_type(ie); + return &mod->alt; +} + +godot_bool GDAPI *godot_input_event_mod_get_ctrl(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + InputModifierState *mod = _get_mod_for_type(ie); + return &mod->control; +} + +godot_bool GDAPI *godot_input_event_mod_get_command(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + InputModifierState *mod = _get_mod_for_type(ie); + return &mod->command; +} + +godot_bool GDAPI *godot_input_event_mod_get_shift(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + InputModifierState *mod = _get_mod_for_type(ie); + return &mod->shift; +} + +godot_bool GDAPI *godot_input_event_mod_get_meta(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + InputModifierState *mod = _get_mod_for_type(ie); + return &mod->meta; +} + +uint32_t GDAPI *godot_input_event_key_get_scancode(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->key.scancode; +} + +uint32_t GDAPI *godot_input_event_key_get_unicode(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->key.unicode; +} + +godot_bool GDAPI *godot_input_event_key_get_pressed(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->key.pressed; +} + +godot_bool GDAPI *godot_input_event_key_get_echo(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->key.echo; +} + +float GDAPI *godot_input_event_mouse_get_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.x; +} + +float GDAPI *godot_input_event_mouse_get_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.y; +} + +float GDAPI *godot_input_event_mouse_get_global_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.global_x; +} + +float GDAPI *godot_input_event_mouse_get_global_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.global_y; +} + +godot_int GDAPI *godot_input_event_mouse_get_button_mask(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.button_mask; +} + +godot_int GDAPI *godot_input_event_mouse_button_get_button_index(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.button_index; +} + +godot_bool GDAPI *godot_input_event_mouse_button_get_pressed(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.pressed; +} + +godot_bool GDAPI *godot_input_event_mouse_button_get_doubleclick(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_button.doubleclick; +} + +float GDAPI *godot_input_event_mouse_motion_get_relative_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_motion.relative_x; +} + +float GDAPI *godot_input_event_mouse_motion_get_relative_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_motion.relative_y; +} + +float GDAPI *godot_input_event_mouse_motion_get_speed_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_motion.speed_x; +} + +float GDAPI *godot_input_event_mouse_motion_get_speed_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->mouse_motion.speed_y; +} + +godot_int GDAPI *godot_input_event_joypad_motion_get_axis(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->joy_motion.axis; +} + +float GDAPI *godot_input_event_joypad_motion_get_axis_value(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->joy_motion.axis_value; +} + +godot_int GDAPI *godot_input_event_joypad_button_get_button_index(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->joy_button.button_index; +} + +godot_bool GDAPI *godot_input_event_joypad_button_get_pressed(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->joy_button.pressed; +} + +float GDAPI *godot_input_event_joypad_button_get_pressure(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->joy_button.pressure; +} + +godot_int GDAPI *godot_input_event_screen_touch_get_index(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_touch.index; +} + +float GDAPI *godot_input_event_screen_touch_get_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_touch.x; +} + +float GDAPI *godot_input_event_screen_touch_get_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_touch.y; +} + +godot_bool GDAPI *godot_input_event_screen_touch_get_pressed(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_touch.pressed; +} + +godot_int GDAPI *godot_input_event_screen_drag_get_index(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.index; +} + +float GDAPI *godot_input_event_screen_drag_get_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.x; +} + +float GDAPI *godot_input_event_screen_drag_get_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.y; +} + +float GDAPI *godot_input_event_screen_drag_get_relative_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.relative_x; +} + +float GDAPI *godot_input_event_screen_drag_get_relative_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.relative_y; +} + +float GDAPI *godot_input_event_screen_drag_get_speed_x(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.speed_x; +} + +float GDAPI *godot_input_event_screen_drag_get_speed_y(godot_input_event *p_event) { + InputEvent *ie = (InputEvent *)p_event; + return &ie->screen_drag.speed_y; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_input_event.h b/modules/dlscript/godot/godot_input_event.h new file mode 100644 index 0000000000..bfda18bf7c --- /dev/null +++ b/modules/dlscript/godot/godot_input_event.h @@ -0,0 +1,206 @@ +#ifndef GODOT_DLSCRIPT_INPUT_EVENT_H +#define GODOT_DLSCRIPT_INPUT_EVENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_INPUT_EVENT_TYPE_DEFINED +typedef struct godot_input_event { + uint8_t _dont_touch_that[56]; +} godot_input_event; +#endif + +enum godot_input_event_type { + GODOT_INPUT_EVENT_TYPE_NONE, + GODOT_INPUT_EVENT_TYPE_KEY, + GODOT_INPUT_EVENT_TYPE_MOUSE_MOTION, + GODOT_INPUT_EVENT_TYPE_MOUSE_BUTTON, + GODOT_INPUT_EVENT_TYPE_JOYPAD_MOTION, + GODOT_INPUT_EVENT_TYPE_JOYPAD_BUTTON, + GODOT_INPUT_EVENT_TYPE_SCREEN_TOUCH, + GODOT_INPUT_EVENT_TYPE_SCREEN_DRAG, + GODOT_INPUT_EVENT_TYPE_ACTION, + GODOT_INPUT_EVENT_TYPE_TYPE_MAX +}; +typedef enum godot_input_event_type godot_input_event_type; + +enum { + GODOT_BUTTON_LEFT = 1, + GODOT_BUTTON_RIGHT = 2, + GODOT_BUTTON_MIDDLE = 3, + GODOT_BUTTON_WHEEL_UP = 4, + GODOT_BUTTON_WHEEL_DOWN = 5, + GODOT_BUTTON_WHEEL_LEFT = 6, + GODOT_BUTTON_WHEEL_RIGHT = 7, + GODOT_BUTTON_MASK_LEFT = (1 << (GODOT_BUTTON_LEFT - 1)), + GODOT_BUTTON_MASK_RIGHT = (1 << (GODOT_BUTTON_RIGHT - 1)), + GODOT_BUTTON_MASK_MIDDLE = (1 << (GODOT_BUTTON_MIDDLE - 1)), + +}; + +enum { + + GODOT_JOY_BUTTON_0 = 0, + GODOT_JOY_BUTTON_1 = 1, + GODOT_JOY_BUTTON_2 = 2, + GODOT_JOY_BUTTON_3 = 3, + GODOT_JOY_BUTTON_4 = 4, + GODOT_JOY_BUTTON_5 = 5, + GODOT_JOY_BUTTON_6 = 6, + GODOT_JOY_BUTTON_7 = 7, + GODOT_JOY_BUTTON_8 = 8, + GODOT_JOY_BUTTON_9 = 9, + GODOT_JOY_BUTTON_10 = 10, + GODOT_JOY_BUTTON_11 = 11, + GODOT_JOY_BUTTON_12 = 12, + GODOT_JOY_BUTTON_13 = 13, + GODOT_JOY_BUTTON_14 = 14, + GODOT_JOY_BUTTON_15 = 15, + GODOT_JOY_BUTTON_MAX = 16, + + GODOT_JOY_L = GODOT_JOY_BUTTON_4, + GODOT_JOY_R = GODOT_JOY_BUTTON_5, + GODOT_JOY_L2 = GODOT_JOY_BUTTON_6, + GODOT_JOY_R2 = GODOT_JOY_BUTTON_7, + GODOT_JOY_L3 = GODOT_JOY_BUTTON_8, + GODOT_JOY_R3 = GODOT_JOY_BUTTON_9, + GODOT_JOY_SELECT = GODOT_JOY_BUTTON_10, + GODOT_JOY_START = GODOT_JOY_BUTTON_11, + GODOT_JOY_DPAD_UP = GODOT_JOY_BUTTON_12, + GODOT_JOY_DPAD_DOWN = GODOT_JOY_BUTTON_13, + GODOT_JOY_DPAD_LEFT = GODOT_JOY_BUTTON_14, + GODOT_JOY_DPAD_RIGHT = GODOT_JOY_BUTTON_15, + + // a little history about game controllers (who copied who) + + GODOT_JOY_SNES_B = GODOT_JOY_BUTTON_0, + GODOT_JOY_SNES_A = GODOT_JOY_BUTTON_1, + GODOT_JOY_SNES_Y = GODOT_JOY_BUTTON_2, + GODOT_JOY_SNES_X = GODOT_JOY_BUTTON_3, + + GODOT_JOY_SONY_CIRCLE = GODOT_JOY_SNES_A, + GODOT_JOY_SONY_X = GODOT_JOY_SNES_B, + GODOT_JOY_SONY_SQUARE = GODOT_JOY_SNES_Y, + GODOT_JOY_SONY_TRIANGLE = GODOT_JOY_SNES_X, + + GODOT_JOY_SEGA_B = GODOT_JOY_SNES_A, + GODOT_JOY_SEGA_A = GODOT_JOY_SNES_B, + GODOT_JOY_SEGA_X = GODOT_JOY_SNES_Y, + GODOT_JOY_SEGA_Y = GODOT_JOY_SNES_X, + + GODOT_JOY_XBOX_B = GODOT_JOY_SEGA_B, + GODOT_JOY_XBOX_A = GODOT_JOY_SEGA_A, + GODOT_JOY_XBOX_X = GODOT_JOY_SEGA_X, + GODOT_JOY_XBOX_Y = GODOT_JOY_SEGA_Y, + + GODOT_JOY_DS_A = GODOT_JOY_SNES_A, + GODOT_JOY_DS_B = GODOT_JOY_SNES_B, + GODOT_JOY_DS_X = GODOT_JOY_SNES_X, + GODOT_JOY_DS_Y = GODOT_JOY_SNES_Y, + + GODOT_JOY_WII_C = GODOT_JOY_BUTTON_5, + GODOT_JOY_WII_Z = GODOT_JOY_BUTTON_6, + + GODOT_JOY_WII_MINUS = GODOT_JOY_BUTTON_9, + GODOT_JOY_WII_PLUS = GODOT_JOY_BUTTON_10, + + // end of history + + GODOT_JOY_AXIS_0 = 0, + GODOT_JOY_AXIS_1 = 1, + GODOT_JOY_AXIS_2 = 2, + GODOT_JOY_AXIS_3 = 3, + GODOT_JOY_AXIS_4 = 4, + GODOT_JOY_AXIS_5 = 5, + GODOT_JOY_AXIS_6 = 6, + GODOT_JOY_AXIS_7 = 7, + GODOT_JOY_AXIS_MAX = 8, + + GODOT_JOY_ANALOG_0_X = GODOT_JOY_AXIS_0, + GODOT_JOY_ANALOG_0_Y = GODOT_JOY_AXIS_1, + + GODOT_JOY_ANALOG_1_X = GODOT_JOY_AXIS_2, + GODOT_JOY_ANALOG_1_Y = GODOT_JOY_AXIS_3, + + GODOT_JOY_ANALOG_2_X = GODOT_JOY_AXIS_4, + GODOT_JOY_ANALOG_2_Y = GODOT_JOY_AXIS_5, + + GODOT_JOY_ANALOG_L2 = GODOT_JOY_AXIS_6, + GODOT_JOY_ANALOG_R2 = GODOT_JOY_AXIS_7, +}; + +#include "../godot.h" + +void GDAPI godot_input_event_new(godot_input_event *p_ie); + +godot_bool GDAPI godot_input_event_is_pressed(const godot_input_event *p_ie); +godot_bool GDAPI godot_input_event_is_action(const godot_input_event *p_ie, const godot_string *p_action); +godot_bool GDAPI godot_input_event_is_action_pressed(const godot_input_event *p_ie, const godot_string *p_action); +godot_bool GDAPI godot_input_event_is_action_released(const godot_input_event *p_ie, const godot_string *p_action); +godot_bool GDAPI godot_input_event_is_echo(const godot_input_event *p_ie); +void GDAPI godot_input_event_set_as_action(godot_input_event *p_ie, const godot_string *p_action, const godot_bool p_pressed); + +godot_string GDAPI godot_input_event_as_string(const godot_input_event *p_ie); + +// Note: +// We're returning pointers to the fields in the unions. +// This is because I'm too lazy to write setter functions + +uint32_t GDAPI *godot_input_event_get_id(godot_input_event *p_ie); +godot_input_event_type GDAPI *godot_input_event_get_type(godot_input_event *p_ie); +godot_int GDAPI *godot_input_event_get_device(godot_input_event *p_ie); + +godot_bool GDAPI *godot_input_event_mod_get_alt(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mod_get_ctrl(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mod_get_command(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mod_get_shift(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mod_get_meta(godot_input_event *p_event); + +uint32_t GDAPI *godot_input_event_key_get_scancode(godot_input_event *p_event); +uint32_t GDAPI *godot_input_event_key_get_unicode(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_key_get_pressed(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_key_get_echo(godot_input_event *p_event); + +float GDAPI *godot_input_event_mouse_get_x(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_get_y(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_get_global_x(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_get_global_y(godot_input_event *p_event); +godot_int GDAPI *godot_input_event_mouse_get_button_mask(godot_input_event *p_event); + +godot_int GDAPI *godot_input_event_mouse_button_get_button_index(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mouse_button_get_pressed(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_mouse_button_get_doubleclick(godot_input_event *p_event); + +float GDAPI *godot_input_event_mouse_motion_get_relative_x(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_motion_get_relative_y(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_motion_get_speed_x(godot_input_event *p_event); +float GDAPI *godot_input_event_mouse_motion_get_speed_y(godot_input_event *p_event); + +godot_int GDAPI *godot_input_event_joypad_motion_get_axis(godot_input_event *p_event); +float GDAPI *godot_input_event_joypad_motion_get_axis_value(godot_input_event *p_event); + +godot_int GDAPI *godot_input_event_joypad_button_get_button_index(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_joypad_button_get_pressed(godot_input_event *p_event); +float GDAPI *godot_input_event_joypad_button_get_pressure(godot_input_event *p_event); + +godot_int GDAPI *godot_input_event_screen_touch_get_index(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_touch_get_x(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_touch_get_y(godot_input_event *p_event); +godot_bool GDAPI *godot_input_event_screen_touch_get_pressed(godot_input_event *p_event); + +godot_int GDAPI *godot_input_event_screen_drag_get_index(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_x(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_y(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_relative_x(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_relative_y(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_speed_x(godot_input_event *p_event); +float GDAPI *godot_input_event_screen_drag_get_speed_y(godot_input_event *p_event); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_INPUT_EVENT_H diff --git a/modules/dlscript/godot/godot_node_path.cpp b/modules/dlscript/godot/godot_node_path.cpp new file mode 100644 index 0000000000..8b79175e44 --- /dev/null +++ b/modules/dlscript/godot/godot_node_path.cpp @@ -0,0 +1,91 @@ +#include "godot_node_path.h" + +#include "path_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _node_path_api_anchor() { +} + +#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) + +// @Bug ? +// Do I need to memnew_placement when returning strings? + +void GDAPI godot_node_path_new(godot_node_path *p_np, const godot_string *p_from) { + NodePath *np = (NodePath *)p_np; + String *from = (String *)p_from; + memnew_placement_custom(np, NodePath, NodePath(*from)); +} + +void GDAPI godot_node_path_copy(godot_node_path *p_np, const godot_node_path *p_from) { + NodePath *np = (NodePath *)p_np; + NodePath *from = (NodePath *)p_from; + *np = *from; +} + +godot_string GDAPI godot_node_path_get_name(const godot_node_path *p_np, const godot_int p_idx) { + const NodePath *np = (const NodePath *)p_np; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = np->get_name(p_idx); + return str; +} + +godot_int GDAPI godot_node_path_get_name_count(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + return np->get_name_count(); +} + +godot_string GDAPI godot_node_path_get_property(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = np->get_property(); + return str; +} + +godot_string GDAPI godot_node_path_get_subname(const godot_node_path *p_np, const godot_int p_idx) { + const NodePath *np = (const NodePath *)p_np; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = np->get_subname(p_idx); + return str; +} + +godot_int GDAPI godot_node_path_get_subname_count(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + return np->get_subname_count(); +} + +godot_bool GDAPI godot_node_path_is_absolute(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + return np->is_absolute(); +} + +godot_bool GDAPI godot_node_path_is_empty(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + return np->is_empty(); +} + +godot_string GDAPI godot_node_path_as_string(const godot_node_path *p_np) { + const NodePath *np = (const NodePath *)p_np; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = *np; + return str; +} + +void GDAPI godot_node_path_destroy(godot_node_path *p_np) { + ((NodePath *)p_np)->~NodePath(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_node_path.h b/modules/dlscript/godot/godot_node_path.h new file mode 100644 index 0000000000..04f1e70c1d --- /dev/null +++ b/modules/dlscript/godot/godot_node_path.h @@ -0,0 +1,39 @@ +#ifndef GODOT_DLSCRIPT_NODE_PATH_H +#define GODOT_DLSCRIPT_NODE_PATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_NODE_PATH_TYPE_DEFINED +typedef struct godot_node_path { + uint8_t _dont_touch_that[8]; +} godot_node_path; +#endif + +#include "../godot.h" + +void GDAPI godot_node_path_new(godot_node_path *p_np, const godot_string *p_from); +void GDAPI godot_node_path_copy(godot_node_path *p_np, const godot_node_path *p_from); + +godot_string GDAPI godot_node_path_get_name(const godot_node_path *p_np, const godot_int p_idx); +godot_int GDAPI godot_node_path_get_name_count(const godot_node_path *p_np); + +godot_string GDAPI godot_node_path_get_property(const godot_node_path *p_np); +godot_string GDAPI godot_node_path_get_subname(const godot_node_path *p_np, const godot_int p_idx); +godot_int GDAPI godot_node_path_get_subname_count(const godot_node_path *p_np); + +godot_bool GDAPI godot_node_path_is_absolute(const godot_node_path *p_np); +godot_bool GDAPI godot_node_path_is_empty(const godot_node_path *p_np); + +godot_string GDAPI godot_node_path_as_string(const godot_node_path *p_np); + +void GDAPI godot_node_path_destroy(godot_node_path *p_np); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_NODE_PATH_H diff --git a/modules/dlscript/godot/godot_plane.cpp b/modules/dlscript/godot/godot_plane.cpp new file mode 100644 index 0000000000..883aeb6282 --- /dev/null +++ b/modules/dlscript/godot/godot_plane.cpp @@ -0,0 +1,48 @@ +#include "godot_plane.h" + +#include "math/plane.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _plane_api_anchor() { +} + +void GDAPI godot_plane_new(godot_plane *p_pl) { + Plane *pl = (Plane *)p_pl; + *pl = Plane(); +} + +void GDAPI godot_plane_new_with_normal(godot_plane *p_pl, const godot_vector3 *p_normal, const godot_real p_d) { + Plane *pl = (Plane *)p_pl; + const Vector3 *normal = (const Vector3 *)p_normal; + *pl = Plane(*normal, p_d); +} + +void GDAPI godot_plane_set_normal(godot_plane *p_pl, const godot_vector3 *p_normal) { + Plane *pl = (Plane *)p_pl; + const Vector3 *normal = (const Vector3 *)p_normal; + pl->set_normal(*normal); +} + +godot_vector3 godot_plane_get_normal(const godot_plane *p_pl) { + const Plane *pl = (const Plane *)p_pl; + const Vector3 normal = pl->get_normal(); + godot_vector3 *v3 = (godot_vector3 *)&normal; + return *v3; +} + +void GDAPI godot_plane_set_d(godot_plane *p_pl, const godot_real p_d) { + Plane *pl = (Plane *)p_pl; + pl->d = p_d; +} + +godot_real GDAPI godot_plane_get_d(const godot_plane *p_pl) { + const Plane *pl = (const Plane *)p_pl; + return pl->d; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_plane.h b/modules/dlscript/godot/godot_plane.h new file mode 100644 index 0000000000..1323ef4075 --- /dev/null +++ b/modules/dlscript/godot/godot_plane.h @@ -0,0 +1,37 @@ +#ifndef GODOT_DLSCRIPT_PLANE_H +#define GODOT_DLSCRIPT_PLANE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_PLANE_TYPE_DEFINED +typedef struct godot_plane { + uint8_t _dont_touch_that[16]; +} godot_plane; +#endif + +#include "godot_vector3.h" + +void GDAPI godot_plane_new(godot_plane *p_pl); +void GDAPI godot_plane_new_with_normal(godot_plane *p_pl, const godot_vector3 *p_normal, const godot_real p_d); + +// @Incomplete +// These are additional valid constructors +// _FORCE_INLINE_ Plane(const Vector3 &p_normal, real_t p_d); +// _FORCE_INLINE_ Plane(const Vector3 &p_point, const Vector3& p_normal); +// _FORCE_INLINE_ Plane(const Vector3 &p_point1, const Vector3 &p_point2,const Vector3 &p_point3,ClockDirection p_dir = CLOCKWISE); + +void GDAPI godot_plane_set_normal(godot_plane *p_pl, const godot_vector3 *p_normal); +godot_vector3 GDAPI godot_plane_get_normal(const godot_plane *p_pl); + +godot_real GDAPI godot_plane_get_d(const godot_plane *p_pl); +void GDAPI godot_plane_set_d(godot_plane *p_pl, const godot_real p_d); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_PLANE_H diff --git a/modules/dlscript/godot/godot_pool_arrays.cpp b/modules/dlscript/godot/godot_pool_arrays.cpp new file mode 100644 index 0000000000..3fb030f835 --- /dev/null +++ b/modules/dlscript/godot/godot_pool_arrays.cpp @@ -0,0 +1,558 @@ +#include "godot_pool_arrays.h" + +#include "array.h" +#include "dvector.h" +#include "variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _pool_arrays_api_anchor() { +} + +#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) + +// byte + +void GDAPI godot_pool_byte_array_new(godot_pool_byte_array *p_pba) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + memnew_placement(pba, PoolVector<uint8_t>); +} + +void GDAPI godot_pool_byte_array_new_with_array(godot_pool_byte_array *p_pba, const godot_array *p_a) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<uint8_t>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_byte_array_append(godot_pool_byte_array *p_pba, const uint8_t p_data) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->append(p_data); +} + +void GDAPI godot_pool_byte_array_append_array(godot_pool_byte_array *p_pba, const godot_pool_byte_array *p_array) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + PoolVector<uint8_t> *array = (PoolVector<uint8_t> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_byte_array_insert(godot_pool_byte_array *p_pba, const godot_int p_idx, const uint8_t p_data) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + return pba->insert(p_idx, p_data); +} + +void GDAPI godot_pool_byte_array_invert(godot_pool_byte_array *p_pba) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_byte_array_push_back(godot_pool_byte_array *p_pba, const uint8_t p_data) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->push_back(p_data); +} + +void GDAPI godot_pool_byte_array_remove(godot_pool_byte_array *p_pba, const godot_int p_idx) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_byte_array_resize(godot_pool_byte_array *p_pba, const godot_int p_size) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_byte_array_set(godot_pool_byte_array *p_pba, const godot_int p_idx, const uint8_t p_data) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + pba->set(p_idx, p_data); +} + +uint8_t GDAPI godot_pool_byte_array_get(godot_pool_byte_array *p_pba, const godot_int p_idx) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + return pba->get(p_idx); +} + +godot_int GDAPI godot_pool_byte_array_size(godot_pool_byte_array *p_pba) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_byte_array_destroy(godot_pool_byte_array *p_pba) { + ((PoolVector<uint8_t> *)p_pba)->~PoolVector(); +} + +// int + +void GDAPI godot_pool_int_array_new(godot_pool_int_array *p_pba) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + memnew_placement(pba, PoolVector<uint8_t>); +} + +void GDAPI godot_pool_int_array_new_with_array(godot_pool_int_array *p_pba, const godot_array *p_a) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<uint8_t>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_int_array_append(godot_pool_int_array *p_pba, const godot_int p_data) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->append(p_data); +} + +void GDAPI godot_pool_int_array_append_array(godot_pool_int_array *p_pba, const godot_pool_int_array *p_array) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + PoolVector<godot_int> *array = (PoolVector<godot_int> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_int_array_insert(godot_pool_int_array *p_pba, const godot_int p_idx, const godot_int p_data) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + return pba->insert(p_idx, p_data); +} + +void GDAPI godot_pool_int_array_invert(godot_pool_int_array *p_pba) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_int_array_push_back(godot_pool_int_array *p_pba, const godot_int p_data) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->push_back(p_data); +} + +void GDAPI godot_pool_int_array_remove(godot_pool_int_array *p_pba, const godot_int p_idx) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_int_array_resize(godot_pool_int_array *p_pba, const godot_int p_size) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_int_array_set(godot_pool_int_array *p_pba, const godot_int p_idx, const godot_int p_data) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->set(p_idx, p_data); +} + +godot_int GDAPI godot_pool_int_array_get(godot_pool_int_array *p_pba, const godot_int p_idx) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + return pba->get(p_idx); +} + +godot_int GDAPI godot_pool_int_array_size(godot_pool_int_array *p_pba) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_int_array_destroy(godot_pool_int_array *p_pba) { + ((PoolVector<godot_int> *)p_pba)->~PoolVector(); +} + +// real + +void GDAPI godot_pool_real_array_new(godot_pool_real_array *p_pba) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + memnew_placement(pba, PoolVector<uint8_t>); +} + +void GDAPI godot_pool_real_array_new_with_array(godot_pool_real_array *p_pba, const godot_array *p_a) { + PoolVector<uint8_t> *pba = (PoolVector<uint8_t> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<uint8_t>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_real_array_append(godot_pool_real_array *p_pba, const godot_real p_data) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + pba->append(p_data); +} + +void GDAPI godot_pool_real_array_append_array(godot_pool_real_array *p_pba, const godot_pool_real_array *p_array) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + PoolVector<godot_real> *array = (PoolVector<godot_real> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_real_array_insert(godot_pool_real_array *p_pba, const godot_int p_idx, const godot_real p_data) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + return pba->insert(p_idx, p_data); +} + +void GDAPI godot_pool_real_array_invert(godot_pool_real_array *p_pba) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_real_array_push_back(godot_pool_real_array *p_pba, const godot_real p_data) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + pba->push_back(p_data); +} + +void GDAPI godot_pool_real_array_remove(godot_pool_real_array *p_pba, const godot_int p_idx) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_real_array_resize(godot_pool_real_array *p_pba, const godot_int p_size) { + PoolVector<godot_int> *pba = (PoolVector<godot_int> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_real_array_set(godot_pool_real_array *p_pba, const godot_int p_idx, const godot_real p_data) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + pba->set(p_idx, p_data); +} + +godot_real GDAPI godot_pool_real_array_get(godot_pool_real_array *p_pba, const godot_int p_idx) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + return pba->get(p_idx); +} + +godot_int GDAPI godot_pool_real_array_size(godot_pool_real_array *p_pba) { + PoolVector<godot_real> *pba = (PoolVector<godot_real> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_real_array_destroy(godot_pool_real_array *p_pba) { + ((PoolVector<godot_real> *)p_pba)->~PoolVector(); +} + +// string + +void GDAPI godot_pool_string_array_new(godot_pool_string_array *p_pba) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + memnew_placement(pba, PoolVector<String>); +} + +void GDAPI godot_pool_string_array_new_with_array(godot_pool_string_array *p_pba, const godot_array *p_a) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<String>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_string_array_append(godot_pool_string_array *p_pba, const godot_string *p_data) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + String &s = *(String *)p_data; + pba->append(s); +} + +void GDAPI godot_pool_string_array_append_array(godot_pool_string_array *p_pba, const godot_pool_string_array *p_array) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + PoolVector<String> *array = (PoolVector<String> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_string_array_insert(godot_pool_string_array *p_pba, const godot_int p_idx, const godot_string *p_data) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + String &s = *(String *)p_data; + return pba->insert(p_idx, s); +} + +void GDAPI godot_pool_string_array_invert(godot_pool_string_array *p_pba) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_string_array_push_back(godot_pool_string_array *p_pba, const godot_string *p_data) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + String &s = *(String *)p_data; + pba->push_back(s); +} + +void GDAPI godot_pool_string_array_remove(godot_pool_string_array *p_pba, const godot_int p_idx) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_string_array_resize(godot_pool_string_array *p_pba, const godot_int p_size) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_string_array_set(godot_pool_string_array *p_pba, const godot_int p_idx, const godot_string *p_data) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + String &s = *(String *)p_data; + pba->set(p_idx, s); +} + +godot_string GDAPI godot_pool_string_array_get(godot_pool_string_array *p_pba, const godot_int p_idx) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + godot_string str; + String *s = (String *)&str; + memnew_placement(s, String); + *s = pba->get(p_idx); + return str; +} + +godot_int GDAPI godot_pool_string_array_size(godot_pool_string_array *p_pba) { + PoolVector<String> *pba = (PoolVector<String> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_string_array_destroy(godot_pool_string_array *p_pba) { + ((PoolVector<String> *)p_pba)->~PoolVector(); +} + +// vector2 + +void GDAPI godot_pool_vector2_array_new(godot_pool_vector2_array *p_pba) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + memnew_placement(pba, PoolVector<Vector2>); +} + +void GDAPI godot_pool_vector2_array_new_with_array(godot_pool_vector2_array *p_pba, const godot_array *p_a) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<Vector2>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_vector2_array_append(godot_pool_vector2_array *p_pba, const godot_vector2 *p_data) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + Vector2 &s = *(Vector2 *)p_data; + pba->append(s); +} + +void GDAPI godot_pool_vector2_array_append_array(godot_pool_vector2_array *p_pba, const godot_pool_vector2_array *p_array) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + PoolVector<Vector2> *array = (PoolVector<Vector2> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_vector2_array_insert(godot_pool_vector2_array *p_pba, const godot_int p_idx, const godot_vector2 *p_data) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + Vector2 &s = *(Vector2 *)p_data; + return pba->insert(p_idx, s); +} + +void GDAPI godot_pool_vector2_array_invert(godot_pool_vector2_array *p_pba) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_vector2_array_push_back(godot_pool_vector2_array *p_pba, const godot_vector2 *p_data) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + Vector2 &s = *(Vector2 *)p_data; + pba->push_back(s); +} + +void GDAPI godot_pool_vector2_array_remove(godot_pool_vector2_array *p_pba, const godot_int p_idx) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_vector2_array_resize(godot_pool_vector2_array *p_pba, const godot_int p_size) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_vector2_array_set(godot_pool_vector2_array *p_pba, const godot_int p_idx, const godot_vector2 *p_data) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + Vector2 &s = *(Vector2 *)p_data; + pba->set(p_idx, s); +} + +godot_vector2 GDAPI godot_pool_vector2_array_get(godot_pool_vector2_array *p_pba, const godot_int p_idx) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + godot_vector2 v; + Vector2 *s = (Vector2 *)&v; + *s = pba->get(p_idx); + return v; +} + +godot_int GDAPI godot_pool_vector2_array_size(godot_pool_vector2_array *p_pba) { + PoolVector<Vector2> *pba = (PoolVector<Vector2> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_vector2_array_destroy(godot_pool_vector2_array *p_pba) { + ((PoolVector<Vector2> *)p_pba)->~PoolVector(); +} + +// vector3 + +void GDAPI godot_pool_vector3_array_new(godot_pool_vector3_array *p_pba) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + memnew_placement(pba, PoolVector<Vector3>); +} + +void GDAPI godot_pool_vector3_array_new_with_array(godot_pool_vector3_array *p_pba, const godot_array *p_a) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<Vector3>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_vector3_array_append(godot_pool_vector3_array *p_pba, const godot_vector3 *p_data) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + Vector3 &s = *(Vector3 *)p_data; + pba->append(s); +} + +void GDAPI godot_pool_vector3_array_append_array(godot_pool_vector3_array *p_pba, const godot_pool_vector3_array *p_array) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + PoolVector<Vector3> *array = (PoolVector<Vector3> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_vector3_array_insert(godot_pool_vector3_array *p_pba, const godot_int p_idx, const godot_vector3 *p_data) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + Vector3 &s = *(Vector3 *)p_data; + return pba->insert(p_idx, s); +} + +void GDAPI godot_pool_vector3_array_invert(godot_pool_vector3_array *p_pba) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_vector3_array_push_back(godot_pool_vector3_array *p_pba, const godot_vector3 *p_data) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + Vector3 &s = *(Vector3 *)p_data; + pba->push_back(s); +} + +void GDAPI godot_pool_vector3_array_remove(godot_pool_vector3_array *p_pba, const godot_int p_idx) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_vector3_array_resize(godot_pool_vector3_array *p_pba, const godot_int p_size) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_vector3_array_set(godot_pool_vector3_array *p_pba, const godot_int p_idx, const godot_vector3 *p_data) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + Vector3 &s = *(Vector3 *)p_data; + pba->set(p_idx, s); +} + +godot_vector3 GDAPI godot_pool_vector3_array_get(godot_pool_vector3_array *p_pba, const godot_int p_idx) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + godot_vector3 v; + Vector3 *s = (Vector3 *)&v; + *s = pba->get(p_idx); + return v; +} + +godot_int GDAPI godot_pool_vector3_array_size(godot_pool_vector3_array *p_pba) { + PoolVector<Vector3> *pba = (PoolVector<Vector3> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_vector3_array_destroy(godot_pool_vector3_array *p_pba) { + ((PoolVector<Vector3> *)p_pba)->~PoolVector(); +} + +// color + +void GDAPI godot_pool_color_array_new(godot_pool_color_array *p_pba) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + memnew_placement(pba, PoolVector<Color>); +} + +void GDAPI godot_pool_color_array_new_with_array(godot_pool_color_array *p_pba, const godot_array *p_a) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + Array *a = (Array *)p_a; + memnew_placement(pba, PoolVector<Color>); + + pba->resize(a->size()); + for (size_t i = 0; i < a->size(); i++) { + pba->set(i, (*a)[i]); + } +} + +void GDAPI godot_pool_color_array_append(godot_pool_color_array *p_pba, const godot_color *p_data) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + Color &s = *(Color *)p_data; + pba->append(s); +} + +void GDAPI godot_pool_color_array_append_array(godot_pool_color_array *p_pba, const godot_pool_color_array *p_array) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + PoolVector<Color> *array = (PoolVector<Color> *)p_array; + pba->append_array(*array); +} + +int GDAPI godot_pool_color_array_insert(godot_pool_color_array *p_pba, const godot_int p_idx, const godot_color *p_data) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + Color &s = *(Color *)p_data; + return pba->insert(p_idx, s); +} + +void GDAPI godot_pool_color_array_invert(godot_pool_color_array *p_pba) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + pba->invert(); +} + +void GDAPI godot_pool_color_array_push_back(godot_pool_color_array *p_pba, const godot_color *p_data) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + Color &s = *(Color *)p_data; + pba->push_back(s); +} + +void GDAPI godot_pool_color_array_remove(godot_pool_color_array *p_pba, const godot_int p_idx) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + pba->remove(p_idx); +} + +void GDAPI godot_pool_color_array_resize(godot_pool_color_array *p_pba, const godot_int p_size) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + pba->resize(p_size); +} + +void GDAPI godot_pool_color_array_set(godot_pool_color_array *p_pba, const godot_int p_idx, const godot_color *p_data) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + Color &s = *(Color *)p_data; + pba->set(p_idx, s); +} + +godot_color GDAPI godot_pool_color_array_get(godot_pool_color_array *p_pba, const godot_int p_idx) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + godot_color v; + Color *s = (Color *)&v; + *s = pba->get(p_idx); + return v; +} + +godot_int GDAPI godot_pool_color_array_size(godot_pool_color_array *p_pba) { + PoolVector<Color> *pba = (PoolVector<Color> *)p_pba; + return pba->size(); +} + +void GDAPI godot_pool_color_array_destroy(godot_pool_color_array *p_pba) { + ((PoolVector<Color> *)p_pba)->~PoolVector(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_pool_arrays.h b/modules/dlscript/godot/godot_pool_arrays.h new file mode 100644 index 0000000000..77b6c3dde0 --- /dev/null +++ b/modules/dlscript/godot/godot_pool_arrays.h @@ -0,0 +1,256 @@ +#ifndef GODOT_DLSCRIPT_POOL_ARRAYS_H +#define GODOT_DLSCRIPT_POOL_ARRAYS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +/////// PoolByteArray + +#ifndef GODOT_CORE_API_GODOT_POOL_BYTE_ARRAY_TYPE_DEFINED +typedef struct godot_pool_byte_array { + uint8_t _dont_touch_that[8]; +} godot_pool_byte_array; +#endif + +/////// PoolIntArray + +#ifndef GODOT_CORE_API_GODOT_POOL_INT_ARRAY_TYPE_DEFINED +typedef struct godot_pool_int_array { + uint8_t _dont_touch_that[8]; +} godot_pool_int_array; +#endif + +/////// PoolRealArray + +#ifndef GODOT_CORE_API_GODOT_POOL_REAL_ARRAY_TYPE_DEFINED +typedef struct godot_pool_real_array { + uint8_t _dont_touch_that[8]; +} godot_pool_real_array; +#endif + +/////// PoolStringArray + +#ifndef GODOT_CORE_API_GODOT_POOL_STRING_ARRAY_TYPE_DEFINED +typedef struct godot_pool_string_array { + uint8_t _dont_touch_that[8]; +} godot_pool_string_array; +#endif + +/////// PoolVector2Array + +#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR2_ARRAY_TYPE_DEFINED +typedef struct godot_pool_vector2_array { + uint8_t _dont_touch_that[8]; +} godot_pool_vector2_array; +#endif + +/////// PoolVector3Array + +#ifndef GODOT_CORE_API_GODOT_POOL_VECTOR3_ARRAY_TYPE_DEFINED +typedef struct godot_pool_vector3_array { + uint8_t _dont_touch_that[8]; +} godot_pool_vector3_array; +#endif + +/////// PoolColorArray + +#ifndef GODOT_CORE_API_GODOT_POOL_COLOR_ARRAY_TYPE_DEFINED +typedef struct godot_pool_color_array { + uint8_t _dont_touch_that[8]; +} godot_pool_color_array; +#endif + +#include "../godot.h" + +#include "godot_array.h" + +// byte + +void GDAPI godot_pool_byte_array_new(godot_pool_byte_array *p_pba); +void GDAPI godot_pool_byte_array_new_with_array(godot_pool_byte_array *p_pba, const godot_array *p_a); + +void GDAPI godot_pool_byte_array_append(godot_pool_byte_array *p_pba, const uint8_t p_data); + +void GDAPI godot_pool_byte_array_append_array(godot_pool_byte_array *p_pba, const godot_pool_byte_array *p_array); + +int GDAPI godot_pool_byte_array_insert(godot_pool_byte_array *p_pba, const godot_int p_idx, const uint8_t p_data); + +void GDAPI godot_pool_byte_array_invert(godot_pool_byte_array *p_pba); + +void GDAPI godot_pool_byte_array_push_back(godot_pool_byte_array *p_pba, const uint8_t p_data); + +void GDAPI godot_pool_byte_array_remove(godot_pool_byte_array *p_pba, const godot_int p_idx); + +void GDAPI godot_pool_byte_array_resize(godot_pool_byte_array *p_pba, const godot_int p_size); + +void GDAPI godot_pool_byte_array_set(godot_pool_byte_array *p_pba, const godot_int p_idx, const uint8_t p_data); +uint8_t GDAPI godot_pool_byte_array_get(godot_pool_byte_array *p_pba, const godot_int p_idx); + +godot_int GDAPI godot_pool_byte_array_size(godot_pool_byte_array *p_pba); + +void GDAPI godot_pool_byte_array_destroy(godot_pool_byte_array *p_pba); + +// int + +void GDAPI godot_pool_int_array_new(godot_pool_int_array *p_pia); +void GDAPI godot_pool_int_array_new_with_array(godot_pool_int_array *p_pia, const godot_array *p_a); + +void GDAPI godot_pool_int_array_append(godot_pool_int_array *p_pia, const godot_int p_data); + +void GDAPI godot_pool_int_array_append_array(godot_pool_int_array *p_pia, const godot_pool_int_array *p_array); + +int GDAPI godot_pool_int_array_insert(godot_pool_int_array *p_pia, const godot_int p_idx, const godot_int p_data); + +void GDAPI godot_pool_int_array_invert(godot_pool_int_array *p_pia); + +void GDAPI godot_pool_int_array_push_back(godot_pool_int_array *p_pia, const godot_int p_data); + +void GDAPI godot_pool_int_array_remove(godot_pool_int_array *p_pia, const godot_int p_idx); + +void GDAPI godot_pool_int_array_resize(godot_pool_int_array *p_pia, const godot_int p_size); + +void GDAPI godot_pool_int_array_set(godot_pool_int_array *p_pia, const godot_int p_idx, const godot_int p_data); +godot_int GDAPI godot_pool_int_array_get(godot_pool_int_array *p_pia, const godot_int p_idx); + +godot_int GDAPI godot_pool_int_array_size(godot_pool_int_array *p_pia); + +void GDAPI godot_pool_int_array_destroy(godot_pool_int_array *p_pia); + +// real + +void GDAPI godot_pool_real_array_new(godot_pool_real_array *p_pra); +void GDAPI godot_pool_real_array_new_with_array(godot_pool_real_array *p_pra, const godot_array *p_a); + +void GDAPI godot_pool_real_array_append(godot_pool_real_array *p_pra, const godot_real p_data); + +void GDAPI godot_pool_real_array_append_array(godot_pool_real_array *p_pra, const godot_pool_real_array *p_array); + +int GDAPI godot_pool_real_array_insert(godot_pool_real_array *p_pra, const godot_int p_idx, const godot_real p_data); + +void GDAPI godot_pool_real_array_invert(godot_pool_real_array *p_pra); + +void GDAPI godot_pool_real_array_push_back(godot_pool_real_array *p_pra, const godot_real p_data); + +void GDAPI godot_pool_real_array_remove(godot_pool_real_array *p_pra, const godot_int p_idx); + +void GDAPI godot_pool_real_array_resize(godot_pool_real_array *p_pra, const godot_int p_size); + +void GDAPI godot_pool_real_array_set(godot_pool_real_array *p_pra, const godot_int p_idx, const godot_real p_data); +godot_real GDAPI godot_pool_real_array_get(godot_pool_real_array *p_pra, const godot_int p_idx); + +godot_int GDAPI godot_pool_real_array_size(godot_pool_real_array *p_pra); + +void GDAPI godot_pool_real_array_destroy(godot_pool_real_array *p_pra); + +// string + +void GDAPI godot_pool_string_array_new(godot_pool_string_array *p_psa); +void GDAPI godot_pool_string_array_new_with_array(godot_pool_string_array *p_psa, const godot_array *p_a); + +void GDAPI godot_pool_string_array_append(godot_pool_string_array *p_psa, const godot_string *p_data); + +void GDAPI godot_pool_string_array_append_array(godot_pool_string_array *p_psa, const godot_pool_string_array *p_array); + +int GDAPI godot_pool_string_array_insert(godot_pool_string_array *p_psa, const godot_int p_idx, const godot_string *p_data); + +void GDAPI godot_pool_string_array_invert(godot_pool_string_array *p_psa); + +void GDAPI godot_pool_string_array_push_back(godot_pool_string_array *p_psa, const godot_string *p_data); + +void GDAPI godot_pool_string_array_remove(godot_pool_string_array *p_psa, const godot_int p_idx); + +void GDAPI godot_pool_string_array_resize(godot_pool_string_array *p_psa, const godot_int p_size); + +void GDAPI godot_pool_string_array_set(godot_pool_string_array *p_psa, const godot_int p_idx, const godot_string *p_data); +godot_string GDAPI godot_pool_string_array_get(godot_pool_string_array *p_psa, const godot_int p_idx); + +godot_int GDAPI godot_pool_string_array_size(godot_pool_string_array *p_psa); + +void GDAPI godot_pool_string_array_destroy(godot_pool_string_array *p_psa); + +// vector2 + +void GDAPI godot_pool_vector2_array_new(godot_pool_vector2_array *p_pv2a); +void GDAPI godot_pool_vector2_array_new_with_array(godot_pool_vector2_array *p_pv2a, const godot_array *p_a); + +void GDAPI godot_pool_vector2_array_append(godot_pool_vector2_array *p_pv2a, const godot_vector2 *p_data); + +void GDAPI godot_pool_vector2_array_append_array(godot_pool_vector2_array *p_pv2a, const godot_pool_vector2_array *p_array); + +int GDAPI godot_pool_vector2_array_insert(godot_pool_vector2_array *p_pv2a, const godot_int p_idx, const godot_vector2 *p_data); + +void GDAPI godot_pool_vector2_array_invert(godot_pool_vector2_array *p_pv2a); + +void GDAPI godot_pool_vector2_array_push_back(godot_pool_vector2_array *p_pv2a, const godot_vector2 *p_data); + +void GDAPI godot_pool_vector2_array_remove(godot_pool_vector2_array *p_pv2a, const godot_int p_idx); + +void GDAPI godot_pool_vector2_array_resize(godot_pool_vector2_array *p_pv2a, const godot_int p_size); + +void GDAPI godot_pool_vector2_array_set(godot_pool_vector2_array *p_pv2a, const godot_int p_idx, const godot_vector2 *p_data); +godot_vector2 GDAPI godot_pool_vector2_array_get(godot_pool_vector2_array *p_pv2a, const godot_int p_idx); + +godot_int GDAPI godot_pool_vector2_array_size(godot_pool_vector2_array *p_pv2a); + +void GDAPI godot_pool_vector2_array_destroy(godot_pool_vector2_array *p_pv2a); + +// vector3 + +void GDAPI godot_pool_vector3_array_new(godot_pool_vector3_array *p_pv3a); +void GDAPI godot_pool_vector3_array_new_with_array(godot_pool_vector3_array *p_pv3a, const godot_array *p_a); + +void GDAPI godot_pool_vector3_array_append(godot_pool_vector3_array *p_pv3a, const godot_vector3 *p_data); + +void GDAPI godot_pool_vector3_array_append_array(godot_pool_vector3_array *p_pv3a, const godot_pool_vector3_array *p_array); + +int GDAPI godot_pool_vector3_array_insert(godot_pool_vector3_array *p_pv3a, const godot_int p_idx, const godot_vector3 *p_data); + +void GDAPI godot_pool_vector3_array_invert(godot_pool_vector3_array *p_pv3a); + +void GDAPI godot_pool_vector3_array_push_back(godot_pool_vector3_array *p_pv3a, const godot_vector3 *p_data); + +void GDAPI godot_pool_vector3_array_remove(godot_pool_vector3_array *p_pv3a, const godot_int p_idx); + +void GDAPI godot_pool_vector3_array_resize(godot_pool_vector3_array *p_pv3a, const godot_int p_size); + +void GDAPI godot_pool_vector3_array_set(godot_pool_vector3_array *p_pv3a, const godot_int p_idx, const godot_vector3 *p_data); +godot_vector3 GDAPI godot_pool_vector3_array_get(godot_pool_vector3_array *p_pv3a, const godot_int p_idx); + +godot_int GDAPI godot_pool_vector3_array_size(godot_pool_vector3_array *p_pv3a); + +void GDAPI godot_pool_vector3_array_destroy(godot_pool_vector3_array *p_pv3a); + +// color + +void GDAPI godot_pool_color_array_new(godot_pool_color_array *p_pca); +void GDAPI godot_pool_color_array_new_with_array(godot_pool_color_array *p_pca, const godot_array *p_a); + +void GDAPI godot_pool_color_array_append(godot_pool_color_array *p_pca, const godot_color *p_data); + +void GDAPI godot_pool_color_array_append_array(godot_pool_color_array *p_pca, const godot_pool_color_array *p_array); + +int GDAPI godot_pool_color_array_insert(godot_pool_color_array *p_pca, const godot_int p_idx, const godot_color *p_data); + +void GDAPI godot_pool_color_array_invert(godot_pool_color_array *p_pca); + +void GDAPI godot_pool_color_array_push_back(godot_pool_color_array *p_pca, const godot_color *p_data); + +void GDAPI godot_pool_color_array_remove(godot_pool_color_array *p_pca, const godot_int p_idx); + +void GDAPI godot_pool_color_array_resize(godot_pool_color_array *p_pca, const godot_int p_size); + +void GDAPI godot_pool_color_array_set(godot_pool_color_array *p_pca, const godot_int p_idx, const godot_color *p_data); +godot_color GDAPI godot_pool_color_array_get(godot_pool_color_array *p_pca, const godot_int p_idx); + +godot_int GDAPI godot_pool_color_array_size(godot_pool_color_array *p_pca); + +void GDAPI godot_pool_color_array_destroy(godot_pool_color_array *p_pca); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_POOL_ARRAYS_H diff --git a/modules/dlscript/godot/godot_quat.cpp b/modules/dlscript/godot/godot_quat.cpp new file mode 100644 index 0000000000..9bd2eb0639 --- /dev/null +++ b/modules/dlscript/godot/godot_quat.cpp @@ -0,0 +1,77 @@ +#include "godot_quat.h" + +#include "math/quat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _quat_api_anchor() { +} + +void GDAPI godot_quat_new(godot_quat *p_quat) { + Quat *quat = (Quat *)p_quat; + *quat = Quat(); +} + +void GDAPI godot_quat_new_with_elements(godot_quat *p_quat, const godot_real x, const godot_real y, const godot_real z, const godot_real w) { + Quat *quat = (Quat *)p_quat; + *quat = Quat(x, y, z, w); +} + +void GDAPI godot_quat_new_with_rotation(godot_quat *p_quat, const godot_vector3 *p_axis, const godot_real p_angle) { + Quat *quat = (Quat *)p_quat; + const Vector3 *axis = (const Vector3 *)p_axis; + *quat = Quat(*axis, p_angle); +} + +void GDAPI godot_quat_new_with_shortest_arc(godot_quat *p_quat, const godot_vector3 *p_v0, const godot_vector3 *p_v1) { + Quat *quat = (Quat *)p_quat; + const Vector3 *v0 = (const Vector3 *)p_v0; + const Vector3 *v1 = (const Vector3 *)p_v1; + *quat = Quat(*v0, *v1); +} + +godot_vector3 GDAPI godot_quat_get_euler(const godot_quat *p_quat) { + Quat *quat = (Quat *)p_quat; + Vector3 euler = quat->get_euler(); + return *(godot_vector3 *)&euler; +} + +void GDAPI godot_quat_set_euler(godot_quat *p_quat, const godot_vector3 *p_euler) { + Quat *quat = (Quat *)p_quat; + const Vector3 *euler = (const Vector3 *)p_euler; + quat->set_euler(*euler); +} + +godot_real GDAPI *godot_quat_index(godot_quat *p_quat, const godot_int p_idx) { + Quat *quat = (Quat *)p_quat; + switch (p_idx) { + case 0: + return &quat->x; + case 1: + return &quat->y; + case 2: + return &quat->z; + default: + return &quat->y; + } +} + +godot_real GDAPI godot_quat_const_index(const godot_quat *p_quat, const godot_int p_idx) { + const Quat *quat = (const Quat *)p_quat; + switch (p_idx) { + case 0: + return quat->x; + case 1: + return quat->y; + case 2: + return quat->z; + default: + return quat->y; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_quat.h b/modules/dlscript/godot/godot_quat.h new file mode 100644 index 0000000000..4e3253c4e5 --- /dev/null +++ b/modules/dlscript/godot/godot_quat.h @@ -0,0 +1,33 @@ +#ifndef GODOT_DLSCRIPT_QUAT_H +#define GODOT_DLSCRIPT_QUAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_QUAT_TYPE_DEFINED +typedef struct godot_quat { + uint8_t _dont_touch_that[16]; +} godot_quat; +#endif + +#include "../godot.h" + +void GDAPI godot_quat_new(godot_quat *p_quat); +void GDAPI godot_quat_new_with_elements(godot_quat *p_quat, const godot_real x, const godot_real y, const godot_real z, const godot_real w); +void GDAPI godot_quat_new_with_rotation(godot_quat *p_quat, const godot_vector3 *p_axis, const godot_real p_angle); +void GDAPI godot_quat_new_with_shortest_arc(godot_quat *p_quat, const godot_vector3 *p_v0, const godot_vector3 *p_v1); + +godot_vector3 GDAPI godot_quat_get_euler(const godot_quat *p_quat); +void GDAPI godot_quat_set_euler(godot_quat *p_quat, const godot_vector3 *p_euler); + +godot_real GDAPI *godot_quat_index(godot_quat *p_quat, const godot_int p_idx); +godot_real GDAPI godot_quat_const_index(const godot_quat *p_quat, const godot_int p_idx); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_QUAT_H diff --git a/modules/dlscript/godot/godot_rect2.cpp b/modules/dlscript/godot/godot_rect2.cpp new file mode 100644 index 0000000000..8e60811114 --- /dev/null +++ b/modules/dlscript/godot/godot_rect2.cpp @@ -0,0 +1,48 @@ +#include "godot_rect2.h" + +#include "math/math_2d.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _rect2_api_anchor() { +} + +void GDAPI godot_rect2_new(godot_rect2 *p_rect) { + Rect2 *rect = (Rect2 *)p_rect; + *rect = Rect2(); +} + +void GDAPI godot_rect2_new_with_pos_and_size(godot_rect2 *p_rect, const godot_vector2 *p_pos, const godot_vector2 *p_size) { + Rect2 *rect = (Rect2 *)p_rect; + const Vector2 *pos = (const Vector2 *)p_pos; + const Vector2 *size = (const Vector2 *)p_size; + *rect = Rect2(*pos, *size); +} + +godot_vector2 GDAPI *godot_rect2_get_pos(godot_rect2 *p_rect) { + Rect2 *rect = (Rect2 *)p_rect; + return (godot_vector2 *)&rect->pos; +} + +void GDAPI godot_rect2_set_pos(godot_rect2 *p_rect, const godot_vector2 *p_pos) { + Rect2 *rect = (Rect2 *)p_rect; + const Vector2 *pos = (const Vector2 *)p_pos; + rect->pos = *pos; +} + +godot_vector2 GDAPI *godot_rect2_get_size(godot_rect2 *p_rect) { + Rect2 *rect = (Rect2 *)p_rect; + return (godot_vector2 *)&rect->size; +} + +void GDAPI godot_rect2_set_size(godot_rect2 *p_rect, const godot_vector2 *p_size) { + Rect2 *rect = (Rect2 *)p_rect; + const Vector2 *size = (const Vector2 *)p_size; + rect->size = *size; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_rect2.h b/modules/dlscript/godot/godot_rect2.h new file mode 100644 index 0000000000..a3b19bdb7e --- /dev/null +++ b/modules/dlscript/godot/godot_rect2.h @@ -0,0 +1,31 @@ +#ifndef GODOT_DLSCRIPT_RECT2_H +#define GODOT_DLSCRIPT_RECT2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_RECT2_TYPE_DEFINED +typedef struct godot_rect2 { + uint8_t _dont_touch_that[16]; +} godot_rect2; +#endif + +#include "../godot.h" + +void GDAPI godot_rect2_new(godot_rect2 *p_rect); +void GDAPI godot_rect2_new_with_pos_and_size(godot_rect2 *p_rect, const godot_vector2 *p_pos, const godot_vector2 *p_size); + +godot_vector2 GDAPI *godot_rect2_get_pos(godot_rect2 *p_rect); +void GDAPI godot_rect2_set_pos(godot_rect2 *p_rect, const godot_vector2 *p_pos); + +godot_vector2 GDAPI *godot_rect2_get_size(godot_rect2 *p_rect); +void GDAPI godot_rect2_set_size(godot_rect2 *p_rect, const godot_vector2 *p_size); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_RECT3_H diff --git a/modules/dlscript/godot/godot_rect3.cpp b/modules/dlscript/godot/godot_rect3.cpp new file mode 100644 index 0000000000..3c442a278b --- /dev/null +++ b/modules/dlscript/godot/godot_rect3.cpp @@ -0,0 +1,48 @@ +#include "godot_rect3.h" + +#include "math/rect3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _rect3_api_anchor() { +} + +void GDAPI godot_rect3_new(godot_rect3 *p_rect) { + Rect3 *rect = (Rect3 *)p_rect; + *rect = Rect3(); +} + +void GDAPI godot_rect3_new_with_pos_and_size(godot_rect3 *p_rect, const godot_vector3 *p_pos, const godot_vector3 *p_size) { + Rect3 *rect = (Rect3 *)p_rect; + const Vector3 *pos = (const Vector3 *)p_pos; + const Vector3 *size = (const Vector3 *)p_size; + *rect = Rect3(*pos, *size); +} + +godot_vector3 GDAPI *godot_rect3_get_pos(godot_rect3 *p_rect) { + Rect3 *rect = (Rect3 *)p_rect; + return (godot_vector3 *)&rect->pos; +} + +void GDAPI godot_rect3_set_pos(godot_rect3 *p_rect, const godot_vector3 *p_pos) { + Rect3 *rect = (Rect3 *)p_rect; + const Vector3 *pos = (const Vector3 *)p_pos; + rect->pos = *pos; +} + +godot_vector3 GDAPI *godot_rect3_get_size(godot_rect3 *p_rect) { + Rect3 *rect = (Rect3 *)p_rect; + return (godot_vector3 *)&rect->size; +} + +void GDAPI godot_rect3_set_size(godot_rect3 *p_rect, const godot_vector3 *p_size) { + Rect3 *rect = (Rect3 *)p_rect; + const Vector3 *size = (const Vector3 *)p_size; + rect->size = *size; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_rect3.h b/modules/dlscript/godot/godot_rect3.h new file mode 100644 index 0000000000..b9279616d1 --- /dev/null +++ b/modules/dlscript/godot/godot_rect3.h @@ -0,0 +1,31 @@ +#ifndef GODOT_DLSCRIPT_RECT3_H +#define GODOT_DLSCRIPT_RECT3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_RECT3_TYPE_DEFINED +typedef struct godot_rect3 { + uint8_t _dont_touch_that[24]; +} godot_rect3; +#endif + +#include "../godot.h" + +void GDAPI godot_rect3_new(godot_rect3 *p_rect); +void GDAPI godot_rect3_new_with_pos_and_size(godot_rect3 *p_rect, const godot_vector3 *p_pos, const godot_vector3 *p_size); + +godot_vector3 GDAPI *godot_rect3_get_pos(godot_rect3 *p_rect); +void GDAPI godot_rect3_set_pos(godot_rect3 *p_rect, const godot_vector3 *p_pos); + +godot_vector3 GDAPI *godot_rect3_get_size(godot_rect3 *p_rect); +void GDAPI godot_rect3_set_size(godot_rect3 *p_rect, const godot_vector3 *p_size); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_RECT3_H diff --git a/modules/dlscript/godot/godot_rid.cpp b/modules/dlscript/godot/godot_rid.cpp new file mode 100644 index 0000000000..a36a2e64a3 --- /dev/null +++ b/modules/dlscript/godot/godot_rid.cpp @@ -0,0 +1,36 @@ +#include "godot_rid.h" + +#include "object.h" +#include "resource.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _rid_api_anchor() { +} + +void GDAPI godot_rid_new(godot_rid *p_rid, godot_object *p_from) { + + Resource *res_from = ((Object *)p_from)->cast_to<Resource>(); + + RID *rid = (RID *)p_rid; + memnew_placement(rid, RID); + + if (res_from) { + *rid = RID(res_from->get_rid()); + } +} + +uint32_t GDAPI godot_rid_get_rid(const godot_rid *p_rid) { + RID *rid = (RID *)p_rid; + return rid->get_id(); +} + +void GDAPI godot_rid_destroy(godot_rid *p_rid) { + ((RID *)p_rid)->~RID(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_rid.h b/modules/dlscript/godot/godot_rid.h new file mode 100644 index 0000000000..f20c0d4dae --- /dev/null +++ b/modules/dlscript/godot/godot_rid.h @@ -0,0 +1,28 @@ +#ifndef GODOT_DLSCRIPT_RID_H +#define GODOT_DLSCRIPT_RID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_RID_TYPE_DEFINED +typedef struct godot_rid { + uint8_t _dont_touch_that[8]; +} godot_rid; +#endif + +#include "../godot.h" + +void GDAPI godot_rid_new(godot_rid *p_rid, godot_object *p_from); + +uint32_t GDAPI godot_rid_get_rid(const godot_rid *p_rid); + +void GDAPI godot_rid_destroy(godot_rid *p_rid); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_RID_H diff --git a/modules/dlscript/godot/godot_string.cpp b/modules/dlscript/godot/godot_string.cpp new file mode 100644 index 0000000000..97d0985a50 --- /dev/null +++ b/modules/dlscript/godot/godot_string.cpp @@ -0,0 +1,83 @@ +#include "godot_string.h" + +#include "string_db.h" +#include "ustring.h" + +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void _string_api_anchor() { +} + +void GDAPI godot_string_new(godot_string *p_str) { + String *p = (String *)p_str; + memnew_placement(p, String); + // *p = String(); // useless here +} + +void GDAPI godot_string_new_data(godot_string *p_str, const char *p_contents, const int p_size) { + String *p = (String *)p_str; + memnew_placement(p, String); + *p = String::utf8(p_contents, p_size); +} + +void GDAPI godot_string_get_data(const godot_string *p_str, wchar_t *p_dest, int *p_size) { + String *p = (String *)p_str; + if (p_size != NULL) { + *p_size = p->length(); + } + if (p_dest != NULL) { + memcpy(p_dest, p->ptr(), *p_size * sizeof(CharType)); + } +} + +void GDAPI godot_string_copy_string(const godot_string *p_dest, const godot_string *p_src) { + String *dest = (String *)p_dest; + String *src = (String *)p_src; + + *dest = *src; +} + +wchar_t GDAPI *godot_string_operator_index(godot_string *p_str, const godot_int p_idx) { + String *s = (String *)p_str; + return &(s->operator[](p_idx)); +} + +const wchar_t GDAPI *godot_string_c_str(const godot_string *p_str) { + const String *s = (const String *)p_str; + return s->c_str(); +} + +godot_bool GDAPI godot_string_operator_equal(const godot_string *p_a, const godot_string *p_b) { + String *a = (String *)p_a; + String *b = (String *)p_b; + return *a == *b; +} + +godot_bool GDAPI godot_string_operator_less(const godot_string *p_a, const godot_string *p_b) { + String *a = (String *)p_a; + String *b = (String *)p_b; + return *a < *b; +} + +void GDAPI godot_string_operator_plus(godot_string *p_dest, const godot_string *p_a, const godot_string *p_b) { + String *dest = (String *)p_dest; + const String *a = (String *)p_a; + const String *b = (String *)p_b; + + String tmp = *a + *b; + godot_string_new(p_dest); + *dest = tmp; +} + +void GDAPI godot_string_destroy(godot_string *p_str) { + String *p = (String *)p_str; + p->~String(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_string.h b/modules/dlscript/godot/godot_string.h new file mode 100644 index 0000000000..73b366d9cd --- /dev/null +++ b/modules/dlscript/godot/godot_string.h @@ -0,0 +1,42 @@ +#ifndef GODOT_DLSCRIPT_STRING_H +#define GODOT_DLSCRIPT_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED +typedef struct godot_string { + uint8_t _dont_touch_that[8]; +} godot_string; +#endif + +#include "../godot.h" + +void GDAPI godot_string_new(godot_string *p_str); +void GDAPI godot_string_new_data(godot_string *p_str, const char *p_contents, const int p_size); + +void GDAPI godot_string_get_data(const godot_string *p_str, wchar_t *p_dest, int *p_size); + +void GDAPI godot_string_copy_string(const godot_string *p_dest, const godot_string *p_src); + +wchar_t GDAPI *godot_string_operator_index(godot_string *p_str, const godot_int p_idx); +const wchar_t GDAPI *godot_string_c_str(const godot_string *p_str); + +godot_bool GDAPI godot_string_operator_equal(const godot_string *p_a, const godot_string *p_b); +godot_bool GDAPI godot_string_operator_less(const godot_string *p_a, const godot_string *p_b); +void GDAPI godot_string_operator_plus(godot_string *p_dest, const godot_string *p_a, const godot_string *p_b); + +// @Incomplete +// hmm, I guess exposing the whole API doesn't make much sense +// since the language used in the library has its own string funcs + +void GDAPI godot_string_destroy(godot_string *p_str); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_STRING_H diff --git a/modules/dlscript/godot/godot_transform.cpp b/modules/dlscript/godot/godot_transform.cpp new file mode 100644 index 0000000000..c8da519f6b --- /dev/null +++ b/modules/dlscript/godot/godot_transform.cpp @@ -0,0 +1,42 @@ +#include "godot_transform.h" + +#include "math/transform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _transform_api_anchor() { +} + +void GDAPI godot_transform_new(godot_transform *p_trans) { + Transform *trans = (Transform *)p_trans; + *trans = Transform(); +} + +void GDAPI godot_transform_new_with_basis(godot_transform *p_trans, const godot_basis *p_basis) { + Transform *trans = (Transform *)p_trans; + const Basis *basis = (const Basis *)p_basis; + *trans = Transform(*basis); +} + +void GDAPI godot_transform_new_with_basis_origin(godot_transform *p_trans, const godot_basis *p_basis, const godot_vector3 *p_origin) { + Transform *trans = (Transform *)p_trans; + const Basis *basis = (const Basis *)p_basis; + const Vector3 *origin = (const Vector3 *)p_origin; + *trans = Transform(*basis, *origin); +} + +godot_basis GDAPI *godot_transform_get_basis(godot_transform *p_trans) { + Transform *trans = (Transform *)p_trans; + return (godot_basis *)&trans->basis; +} + +godot_vector3 GDAPI *godot_transform_get_origin(godot_transform *p_trans) { + Transform *trans = (Transform *)p_trans; + return (godot_vector3 *)&trans->origin; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_transform.h b/modules/dlscript/godot/godot_transform.h new file mode 100644 index 0000000000..54af78d5b9 --- /dev/null +++ b/modules/dlscript/godot/godot_transform.h @@ -0,0 +1,29 @@ +#ifndef GODOT_DLSCRIPT_TRANSFORM_H +#define GODOT_DLSCRIPT_TRANSFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_TRANSFORM_TYPE_DEFINED +typedef struct godot_transform { + uint8_t _dont_touch_that[48]; +} godot_transform; +#endif + +#include "../godot.h" + +void GDAPI godot_transform_new(godot_transform *p_trans); +void GDAPI godot_transform_new_with_basis(godot_transform *p_trans, const godot_basis *p_basis); +void GDAPI godot_transform_new_with_basis_origin(godot_transform *p_trans, const godot_basis *p_basis, const godot_vector3 *p_origin); + +godot_basis GDAPI *godot_transform_get_basis(godot_transform *p_trans); +godot_vector3 GDAPI *godot_transform_get_origin(godot_transform *p_trans); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_DLSCRIPT_TRANSFORM_H diff --git a/modules/dlscript/godot/godot_transform2d.cpp b/modules/dlscript/godot/godot_transform2d.cpp new file mode 100644 index 0000000000..39fa0e7363 --- /dev/null +++ b/modules/dlscript/godot/godot_transform2d.cpp @@ -0,0 +1,59 @@ +#include "godot_transform2d.h" + +#include "../godot.h" + +#include "math/math_2d.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _transform2d_api_anchor() { +} + +void GDAPI godot_transform2d_new_identity(godot_transform2d *p_t) { + Transform2D *t = (Transform2D *)p_t; + *t = Transform2D(); +} + +void GDAPI godot_transform2d_new_elements(godot_transform2d *p_t, const godot_vector2 *p_a, const godot_vector2 *p_b, const godot_vector2 *p_c) { + Transform2D *t = (Transform2D *)p_t; + Vector2 *a = (Vector2 *)p_a; + Vector2 *b = (Vector2 *)p_b; + Vector2 *c = (Vector2 *)p_c; + *t = Transform2D(a->x, a->y, b->x, b->y, c->x, c->y); +} + +void GDAPI godot_transform2d_new(godot_transform2d *p_t, const godot_real p_rot, const godot_vector2 *p_pos) { + Transform2D *t = (Transform2D *)p_t; + Vector2 *pos = (Vector2 *)p_pos; + *t = Transform2D(p_rot, *pos); +} + +godot_vector2 const GDAPI *godot_transform2d_const_index(const godot_transform2d *p_t, const godot_int p_idx) { + const Transform2D *t = (const Transform2D *)p_t; + const Vector2 *e = &t->operator[](p_idx); + return (godot_vector2 const *)e; +} + +godot_vector2 GDAPI *godot_transform2d_index(godot_transform2d *p_t, const godot_int p_idx) { + Transform2D *t = (Transform2D *)p_t; + Vector2 *e = &t->operator[](p_idx); + return (godot_vector2 *)e; +} + +godot_vector2 GDAPI godot_transform2d_get_axis(const godot_transform2d *p_t, const godot_int p_axis) { + return *godot_transform2d_const_index(p_t, p_axis); +} + +void GDAPI godot_transform2d_set_axis(godot_transform2d *p_t, const godot_int p_axis, const godot_vector2 *p_vec) { + godot_vector2 *origin_v = godot_transform2d_index(p_t, p_axis); + *origin_v = *p_vec; +} + +// @Incomplete +// See header file + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_transform2d.h b/modules/dlscript/godot/godot_transform2d.h new file mode 100644 index 0000000000..7403954527 --- /dev/null +++ b/modules/dlscript/godot/godot_transform2d.h @@ -0,0 +1,48 @@ +#ifndef GODOT_TRANSFORM2D_H +#define GODOT_TRANSFORM2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_TRANSFORM2D_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_TRANSFORM2D_TYPE_DEFINED +typedef struct godot_transform2d { + uint8_t _dont_touch_that[24]; +} godot_transform2d; +#endif + +#include "../godot.h" + +#include "godot_vector2.h" + +void GDAPI godot_transform2d_new_identity(godot_transform2d *p_t); +void GDAPI godot_transform2d_new_elements(godot_transform2d *p_t, const godot_vector2 *p_a, const godot_vector2 *p_b, const godot_vector2 *p_c); +void GDAPI godot_transform2d_new(godot_transform2d *p_t, const godot_real p_rot, const godot_vector2 *p_pos); + +/* +godot_real GDAPI godot_transform2d_tdotx(const godot_transform2d *p_t, const godot_vector2 *p_v); +godot_real GDAPI godot_transform2d_tdoty(const godot_transform2d *p_t, const godot_vector2 *p_v); +*/ + +godot_vector2 const GDAPI *godot_transform2d_const_index(const godot_transform2d *p_t, const godot_int p_idx); +godot_vector2 GDAPI *godot_transform2d_index(godot_transform2d *p_t, const godot_int p_idx); + +godot_vector2 GDAPI godot_transform2d_get_axis(const godot_transform2d *p_t, const godot_int p_axis); +void GDAPI godot_transform2d_set_axis(godot_transform2d *p_t, const godot_int p_axis, const godot_vector2 *p_vec); + +/* +void GDAPI godot_transform2d_invert(godot_transform2d *p_t); +godot_transform2d GDAPI godot_transform2d_inverse(const godot_transform2d *p_t); +*/ + +// @Incomplete +// I feel like it should be enough to expose get and set, the whole logic can be done in the bindings. + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_TRANSFORM2D_H diff --git a/modules/dlscript/godot/godot_variant.cpp b/modules/dlscript/godot/godot_variant.cpp new file mode 100644 index 0000000000..3681f89753 --- /dev/null +++ b/modules/dlscript/godot/godot_variant.cpp @@ -0,0 +1,476 @@ +#include "godot_variant.h" + +#include "../godot.h" + +#include "variant.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _variant_api_anchor() { +} + +#define memnew_placement_custom(m_placement, m_class, m_constr) _post_initialize(new (m_placement, sizeof(m_class), "") m_constr) + +godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + return (godot_variant_type)v->get_type(); +} + +void GDAPI godot_variant_copy(godot_variant *p_dest, const godot_variant *p_src) { + Variant *dest = (Variant *)p_dest; + Variant *src = (Variant *)p_src; + *dest = *src; +} + +void GDAPI godot_variant_new_nil(godot_variant *p_v) { + Variant *v = (Variant *)p_v; + memnew_placement(v, Variant); +} + +void GDAPI godot_variant_new_bool(godot_variant *p_v, const godot_bool p_b) { + Variant *v = (Variant *)p_v; + memnew_placement_custom(v, Variant, Variant(p_b)); +} + +void GDAPI godot_variant_new_uint(godot_variant *p_v, const uint64_t p_i) { + Variant *v = (Variant *)p_v; + memnew_placement_custom(v, Variant, Variant(p_i)); +} + +void GDAPI godot_variant_new_int(godot_variant *p_v, const int64_t p_i) { + Variant *v = (Variant *)p_v; + memnew_placement_custom(v, Variant, Variant(p_i)); +} + +void GDAPI godot_variant_new_real(godot_variant *p_v, const double p_r) { + Variant *v = (Variant *)p_v; + memnew_placement_custom(v, Variant, Variant(p_r)); +} + +void GDAPI godot_variant_new_string(godot_variant *p_v, const godot_string *p_s) { + Variant *v = (Variant *)p_v; + String *s = (String *)p_s; + memnew_placement_custom(v, Variant, Variant(*s)); +} + +void GDAPI godot_variant_new_vector2(godot_variant *p_v, const godot_vector2 *p_v2) { + Variant *v = (Variant *)p_v; + Vector2 *v2 = (Vector2 *)p_v2; + memnew_placement_custom(v, Variant, Variant(*v2)); +} + +void GDAPI godot_variant_new_rect2(godot_variant *p_v, const godot_rect2 *p_rect2) { + Variant *v = (Variant *)p_v; + Rect2 *rect2 = (Rect2 *)p_rect2; + memnew_placement_custom(v, Variant, Variant(*rect2)); +} + +void GDAPI godot_variant_new_vector3(godot_variant *p_v, const godot_vector3 *p_v3) { + Variant *v = (Variant *)p_v; + Vector3 *v3 = (Vector3 *)p_v3; + memnew_placement_custom(v, Variant, Variant(*v3)); +} + +void GDAPI godot_variant_new_transform2d(godot_variant *p_v, const godot_transform2d *p_t2d) { + Variant *v = (Variant *)p_v; + Transform2D *t2d = (Transform2D *)p_t2d; + memnew_placement_custom(v, Variant, Variant(*t2d)); +} + +void GDAPI godot_variant_new_plane(godot_variant *p_v, const godot_plane *p_plane) { + Variant *v = (Variant *)p_v; + Plane *plane = (Plane *)p_plane; + memnew_placement_custom(v, Variant, Variant(*plane)); +} + +void GDAPI godot_variant_new_quat(godot_variant *p_v, const godot_quat *p_quat) { + Variant *v = (Variant *)p_v; + Quat *quat = (Quat *)p_quat; + memnew_placement_custom(v, Variant, Variant(*quat)); +} + +void GDAPI godot_variant_new_rect3(godot_variant *p_v, const godot_rect3 *p_rect3) { + Variant *v = (Variant *)p_v; + Rect3 *rect3 = (Rect3 *)p_rect3; + memnew_placement_custom(v, Variant, Variant(*rect3)); +} + +void GDAPI godot_variant_new_basis(godot_variant *p_v, const godot_basis *p_basis) { + Variant *v = (Variant *)p_v; + Basis *basis = (Basis *)p_basis; + memnew_placement_custom(v, Variant, Variant(*basis)); +} + +void GDAPI godot_variant_new_transform(godot_variant *p_v, const godot_transform *p_trans) { + Variant *v = (Variant *)p_v; + Transform *trans = (Transform *)p_trans; + memnew_placement_custom(v, Variant, Variant(*trans)); +} + +void GDAPI godot_variant_new_color(godot_variant *p_v, const godot_color *p_color) { + Variant *v = (Variant *)p_v; + Color *color = (Color *)p_color; + memnew_placement_custom(v, Variant, Variant(*color)); +} + +void GDAPI godot_variant_new_image(godot_variant *p_v, const godot_image *p_img) { + Variant *v = (Variant *)p_v; + Image *img = (Image *)p_img; + memnew_placement_custom(v, Variant, Variant(*img)); +} + +void GDAPI godot_variant_new_node_path(godot_variant *p_v, const godot_node_path *p_np) { + Variant *v = (Variant *)p_v; + NodePath *np = (NodePath *)p_np; + memnew_placement_custom(v, Variant, Variant(*np)); +} + +void GDAPI godot_variant_new_rid(godot_variant *p_v, const godot_rid *p_rid) { + Variant *v = (Variant *)p_v; + RID *rid = (RID *)p_rid; + memnew_placement_custom(v, Variant, Variant(*rid)); +} + +void GDAPI godot_variant_new_object(godot_variant *p_v, const godot_object *p_obj) { + Variant *v = (Variant *)p_v; + Object *obj = (Object *)p_obj; + memnew_placement_custom(v, Variant, Variant(obj)); +} + +void GDAPI godot_variant_new_input_event(godot_variant *p_v, const godot_input_event *p_event) { + Variant *v = (Variant *)p_v; + InputEvent *event = (InputEvent *)p_event; + memnew_placement_custom(v, Variant, Variant(*event)); +} + +void GDAPI godot_variant_new_dictionary(godot_variant *p_v, const godot_dictionary *p_dict) { + Variant *v = (Variant *)p_v; + Dictionary *dict = (Dictionary *)p_dict; + memnew_placement_custom(v, Variant, Variant(*dict)); +} + +void GDAPI godot_variant_new_array(godot_variant *p_v, const godot_array *p_arr) { + Variant *v = (Variant *)p_v; + Array *arr = (Array *)p_arr; + memnew_placement_custom(v, Variant, Variant(*arr)); +} + +void GDAPI godot_variant_new_pool_byte_array(godot_variant *p_v, const godot_pool_byte_array *p_pba) { + Variant *v = (Variant *)p_v; + PoolByteArray *pba = (PoolByteArray *)p_pba; + memnew_placement_custom(v, Variant, Variant(*pba)); +} + +void GDAPI godot_variant_new_pool_int_array(godot_variant *p_v, const godot_pool_int_array *p_pia) { + Variant *v = (Variant *)p_v; + PoolIntArray *pia = (PoolIntArray *)p_pia; + memnew_placement_custom(v, Variant, Variant(*pia)); +} + +void GDAPI godot_variant_new_pool_real_array(godot_variant *p_v, const godot_pool_real_array *p_pra) { + Variant *v = (Variant *)p_v; + PoolRealArray *pra = (PoolRealArray *)p_pra; + memnew_placement_custom(v, Variant, Variant(*pra)); +} + +void GDAPI godot_variant_new_pool_string_array(godot_variant *p_v, const godot_pool_string_array *p_psa) { + Variant *v = (Variant *)p_v; + PoolStringArray *psa = (PoolStringArray *)p_psa; + memnew_placement_custom(v, Variant, Variant(*psa)); +} + +void GDAPI godot_variant_new_pool_vector2_array(godot_variant *p_v, const godot_pool_vector2_array *p_pv2a) { + Variant *v = (Variant *)p_v; + PoolVector2Array *pv2a = (PoolVector2Array *)p_pv2a; + memnew_placement_custom(v, Variant, Variant(*pv2a)); +} + +void GDAPI godot_variant_new_pool_vector3_array(godot_variant *p_v, const godot_pool_vector3_array *p_pv3a) { + Variant *v = (Variant *)p_v; + PoolVector3Array *pv3a = (PoolVector3Array *)p_pv3a; + memnew_placement_custom(v, Variant, Variant(*pv3a)); +} + +void GDAPI godot_variant_new_pool_color_array(godot_variant *p_v, const godot_pool_color_array *p_pca) { + Variant *v = (Variant *)p_v; + PoolColorArray *pca = (PoolColorArray *)p_pca; + memnew_placement_custom(v, Variant, Variant(*pca)); +} + +godot_bool GDAPI godot_variant_as_bool(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + return v->operator bool(); +} + +uint64_t GDAPI godot_variant_as_uint(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + return v->operator uint64_t(); +} + +int64_t GDAPI godot_variant_as_int(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + return v->operator int64_t(); +} + +double GDAPI godot_variant_as_real(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + return v->operator double(); +} + +godot_string GDAPI godot_variant_as_string(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_string s; + godot_string_new(&s); + String *str = (String *)&s; + *str = v->operator String(); + return s; +} + +godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_vector2 v2; + Vector2 *vec2 = (Vector2 *)&v2; + *vec2 = *v; + return v2; +} + +godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_rect2 r2; + Rect2 *rect2 = (Rect2 *)&r2; + *rect2 = *v; + return r2; +} + +godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_vector3 v3; + Vector3 *vec3 = (Vector3 *)&v3; + *vec3 = *v; + return v3; +} + +godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_transform2d t2; + Transform2D *t = (Transform2D *)&t2; + *t = *v; + return t2; +} + +godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_plane p; + Plane *pl = (Plane *)&p; + *pl = *v; + return p; +} + +godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_quat q; + Quat *qt = (Quat *)&q; + *qt = *v; + return q; +} + +godot_rect3 GDAPI godot_variant_as_rect3(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_rect3 r; + Rect3 *r3 = (Rect3 *)&r; + *r3 = *v; + return r; +} + +godot_basis GDAPI godot_variant_as_basis(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_basis b; + Basis *bs = (Basis *)&b; + *bs = *v; + return b; +} + +godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_transform t; + Transform *tr = (Transform *)&t; + *tr = *v; + return t; +} + +godot_color GDAPI godot_variant_as_color(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_color c; + Color *col = (Color *)&c; + *col = *v; + return c; +} + +godot_image GDAPI godot_variant_as_image(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_image img; + godot_image_new(&img); + Image *i = (Image *)&img; + *i = *v; + return img; +} + +godot_node_path GDAPI godot_variant_as_node_path(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_node_path np; + memnew_placement_custom((NodePath *)&np, NodePath, NodePath((String)*v)); + return np; +} + +godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_rid rid; + memnew_placement_custom((RID *)&rid, RID, RID(*v)); + return rid; +} + +godot_object GDAPI *godot_variant_as_object(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_object *p = NULL; + Object **op = (Object **)&p; + *op = *v; + return p; +} + +godot_input_event GDAPI godot_variant_as_input_event(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_input_event ev; + InputEvent *event = (InputEvent *)&ev; + *event = *v; + return ev; +} + +godot_dictionary GDAPI godot_variant_as_dictionary(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_dictionary dict; + godot_dictionary_new(&dict); + Dictionary *d = (Dictionary *)&dict; + *d = *v; + return dict; +} + +godot_array GDAPI godot_variant_as_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_array array; + godot_array_new(&array); + Array *a = (Array *)&array; + *a = *v; + return array; +} + +godot_pool_byte_array GDAPI godot_variant_as_pool_byte_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_byte_array pba; + godot_pool_byte_array_new(&pba); + PoolByteArray *p = (PoolByteArray *)&pba; + *p = *v; + return pba; +} + +godot_pool_int_array GDAPI godot_variant_as_pool_int_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_int_array pba; + godot_pool_int_array_new(&pba); + PoolIntArray *p = (PoolIntArray *)&pba; + *p = *v; + return pba; +} + +godot_pool_real_array GDAPI godot_variant_as_pool_real_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_real_array pba; + godot_pool_real_array_new(&pba); + PoolRealArray *p = (PoolRealArray *)&pba; + *p = *v; + return pba; +} + +godot_pool_string_array GDAPI godot_variant_as_pool_string_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_string_array pba; + godot_pool_string_array_new(&pba); + PoolStringArray *p = (PoolStringArray *)&pba; + *p = *v; + return pba; +} + +godot_pool_vector2_array GDAPI godot_variant_as_pool_vector2_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_vector2_array pba; + godot_pool_vector2_array_new(&pba); + PoolVector2Array *p = (PoolVector2Array *)&pba; + *p = *v; + return pba; +} + +godot_pool_vector3_array GDAPI godot_variant_as_pool_vector3_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_vector3_array pba; + godot_pool_vector3_array_new(&pba); + PoolVector3Array *p = (PoolVector3Array *)&pba; + *p = *v; + return pba; +} + +godot_pool_color_array GDAPI godot_variant_as_pool_color_array(const godot_variant *p_v) { + const Variant *v = (const Variant *)p_v; + godot_pool_color_array pba; + godot_pool_color_array_new(&pba); + PoolColorArray *p = (PoolColorArray *)&pba; + *p = *v; + return pba; +} + +godot_variant GDAPI godot_variant_call(godot_variant *p_v, const godot_string *p_method, const godot_variant **p_args, const godot_int p_argcount /*, godot_variant_call_error *r_error */) { + Variant *v = (Variant *)p_v; + String *method = (String *)p_method; + Variant **args = (Variant **)p_args; + godot_variant res; + memnew_placement_custom((Variant *)&res, Variant, Variant(v->call(*method, args, p_argcount))); + return res; +} + +godot_bool GDAPI godot_variant_has_method(godot_variant *p_v, const godot_string *p_method) { + Variant *v = (Variant *)p_v; + String *method = (String *)p_method; + return v->has_method(*method); +} + +godot_bool GDAPI godot_variant_operator_equal(const godot_variant *p_a, const godot_variant *p_b) { + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + return a->operator==(*b); +} + +godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_a, const godot_variant *p_b) { + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + return a->operator<(*b); +} + +godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_a, const godot_variant *p_b) { + const Variant *a = (const Variant *)p_a; + const Variant *b = (const Variant *)p_b; + return a->hash_compare(*b); +} + +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_v, godot_bool *p_valid) { + const Variant *v = (const Variant *)p_v; + bool &valid = *p_valid; + return v->booleanize(valid); +} + +void GDAPI godot_variant_destroy(godot_variant *p_v) { + ((Variant *)p_v)->~Variant(); +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_variant.h b/modules/dlscript/godot/godot_variant.h new file mode 100644 index 0000000000..1ff5ba4a57 --- /dev/null +++ b/modules/dlscript/godot/godot_variant.h @@ -0,0 +1,150 @@ +#ifndef GODOT_VARIANT_H +#define GODOT_VARIANT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_VARIANT_TYPE_DEFINED +typedef struct godot_variant { + uint8_t _dont_touch_that[24]; +} godot_variant; +#endif + +struct godot_transform2d; +typedef struct godot_transform2d godot_transform2d; + +#include "godot_array.h" +#include "godot_dictionary.h" +#include "godot_input_event.h" +#include "godot_node_path.h" +#include "godot_rid.h" +#include "godot_transform2d.h" + +typedef enum godot_variant_type { + GODOT_VARIANT_TYPE_NIL, + + // atomic types + GODOT_VARIANT_TYPE_BOOL, + GODOT_VARIANT_TYPE_INT, + GODOT_VARIANT_TYPE_REAL, + GODOT_VARIANT_TYPE_STRING, + + // math types + + GODOT_VARIANT_TYPE_VECTOR2, // 5 + GODOT_VARIANT_TYPE_RECT2, + GODOT_VARIANT_TYPE_VECTOR3, + GODOT_VARIANT_TYPE_TRANSFORM2D, + GODOT_VARIANT_TYPE_PLANE, + GODOT_VARIANT_TYPE_QUAT, // 10 + GODOT_VARIANT_TYPE_RECT3, //sorry naming convention fail :( not like it's used often + GODOT_VARIANT_TYPE_BASIS, + GODOT_VARIANT_TYPE_TRANSFORM, + + // misc types + GODOT_VARIANT_TYPE_COLOR, + GODOT_VARIANT_TYPE_IMAGE, // 15 + GODOT_VARIANT_TYPE_NODE_PATH, + GODOT_VARIANT_TYPE_RID, + GODOT_VARIANT_TYPE_OBJECT, + GODOT_VARIANT_TYPE_INPUT_EVENT, + GODOT_VARIANT_TYPE_DICTIONARY, // 20 + GODOT_VARIANT_TYPE_ARRAY, + + // arrays + GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY, + GODOT_VARIANT_TYPE_POOL_INT_ARRAY, + GODOT_VARIANT_TYPE_POOL_REAL_ARRAY, + GODOT_VARIANT_TYPE_POOL_STRING_ARRAY, // 25 + GODOT_VARIANT_TYPE_POOL_VECTOR2_ARRAY, + GODOT_VARIANT_TYPE_POOL_VECTOR3_ARRAY, + GODOT_VARIANT_TYPE_POOL_COLOR_ARRAY, +} godot_variant_type; + +godot_variant_type GDAPI godot_variant_get_type(const godot_variant *p_v); + +void GDAPI godot_variant_copy(godot_variant *p_dest, const godot_variant *p_src); + +void GDAPI godot_variant_new_nil(godot_variant *p_v); + +void GDAPI godot_variant_new_bool(godot_variant *p_v, const godot_bool p_b); +void GDAPI godot_variant_new_uint(godot_variant *p_v, const uint64_t p_i); +void GDAPI godot_variant_new_int(godot_variant *p_v, const int64_t p_i); +void GDAPI godot_variant_new_real(godot_variant *p_v, const double p_r); +void GDAPI godot_variant_new_string(godot_variant *p_v, const godot_string *p_s); +void GDAPI godot_variant_new_vector2(godot_variant *p_v, const godot_vector2 *p_v2); +void GDAPI godot_variant_new_rect2(godot_variant *p_v, const godot_rect2 *p_rect2); +void GDAPI godot_variant_new_vector3(godot_variant *p_v, const godot_vector3 *p_v3); +void GDAPI godot_variant_new_transform2d(godot_variant *p_v, const godot_transform2d *p_t2d); +void GDAPI godot_variant_new_plane(godot_variant *p_v, const godot_plane *p_plane); +void GDAPI godot_variant_new_quat(godot_variant *p_v, const godot_quat *p_quat); +void GDAPI godot_variant_new_rect3(godot_variant *p_v, const godot_rect3 *p_rect3); +void GDAPI godot_variant_new_basis(godot_variant *p_v, const godot_basis *p_basis); +void GDAPI godot_variant_new_transform(godot_variant *p_v, const godot_transform *p_trans); +void GDAPI godot_variant_new_color(godot_variant *p_v, const godot_color *p_color); +void GDAPI godot_variant_new_image(godot_variant *p_v, const godot_image *p_img); +void GDAPI godot_variant_new_node_path(godot_variant *p_v, const godot_node_path *p_np); +void GDAPI godot_variant_new_rid(godot_variant *p_v, const godot_rid *p_rid); +void GDAPI godot_variant_new_object(godot_variant *p_v, const godot_object *p_obj); +void GDAPI godot_variant_new_input_event(godot_variant *p_v, const godot_input_event *p_event); +void GDAPI godot_variant_new_dictionary(godot_variant *p_v, const godot_dictionary *p_dict); +void GDAPI godot_variant_new_array(godot_variant *p_v, const godot_array *p_arr); +void GDAPI godot_variant_new_pool_byte_array(godot_variant *p_v, const godot_pool_byte_array *p_pba); +void GDAPI godot_variant_new_pool_int_array(godot_variant *p_v, const godot_pool_int_array *p_pia); +void GDAPI godot_variant_new_pool_real_array(godot_variant *p_v, const godot_pool_real_array *p_pra); +void GDAPI godot_variant_new_pool_string_array(godot_variant *p_v, const godot_pool_string_array *p_psa); +void GDAPI godot_variant_new_pool_vector2_array(godot_variant *p_v, const godot_pool_vector2_array *p_pv2a); +void GDAPI godot_variant_new_pool_vector3_array(godot_variant *p_v, const godot_pool_vector3_array *p_pv3a); +void GDAPI godot_variant_new_pool_color_array(godot_variant *p_v, const godot_pool_color_array *p_pca); + +godot_bool GDAPI godot_variant_as_bool(const godot_variant *p_v); +uint64_t GDAPI godot_variant_as_uint(const godot_variant *p_v); +int64_t GDAPI godot_variant_as_int(const godot_variant *p_v); +double GDAPI godot_variant_as_real(const godot_variant *p_v); +godot_string GDAPI godot_variant_as_string(const godot_variant *p_v); +godot_vector2 GDAPI godot_variant_as_vector2(const godot_variant *p_v); +godot_rect2 GDAPI godot_variant_as_rect2(const godot_variant *p_v); +godot_vector3 GDAPI godot_variant_as_vector3(const godot_variant *p_v); +godot_transform2d GDAPI godot_variant_as_transform2d(const godot_variant *p_v); +godot_plane GDAPI godot_variant_as_plane(const godot_variant *p_v); +godot_quat GDAPI godot_variant_as_quat(const godot_variant *p_v); +godot_rect3 GDAPI godot_variant_as_rect3(const godot_variant *p_v); +godot_basis GDAPI godot_variant_as_basis(const godot_variant *p_v); +godot_transform GDAPI godot_variant_as_transform(const godot_variant *p_v); +godot_color GDAPI godot_variant_as_color(const godot_variant *p_v); +godot_image GDAPI godot_variant_as_image(const godot_variant *p_v); +godot_node_path GDAPI godot_variant_as_node_path(const godot_variant *p_v); +godot_rid GDAPI godot_variant_as_rid(const godot_variant *p_v); +godot_object GDAPI *godot_variant_as_object(const godot_variant *p_v); +godot_input_event GDAPI godot_variant_as_input_event(const godot_variant *p_v); +godot_dictionary GDAPI godot_variant_as_dictionary(const godot_variant *p_v); +godot_array GDAPI godot_variant_as_array(const godot_variant *p_v); +godot_pool_byte_array GDAPI godot_variant_as_pool_byte_array(const godot_variant *p_v); +godot_pool_int_array GDAPI godot_variant_as_pool_int_array(const godot_variant *p_v); +godot_pool_real_array GDAPI godot_variant_as_pool_real_array(const godot_variant *p_v); +godot_pool_string_array GDAPI godot_variant_as_pool_string_array(const godot_variant *p_v); +godot_pool_vector2_array GDAPI godot_variant_as_pool_vector2_array(const godot_variant *p_v); +godot_pool_vector3_array GDAPI godot_variant_as_pool_vector3_array(const godot_variant *p_v); +godot_pool_color_array GDAPI godot_variant_as_pool_color_array(const godot_variant *p_v); + +godot_variant GDAPI godot_variant_call(godot_variant *p_v, const godot_string *p_method, const godot_variant **p_args, const godot_int p_argcount /*, godot_variant_call_error *r_error */); + +godot_bool GDAPI godot_variant_has_method(godot_variant *p_v, const godot_string *p_method); + +godot_bool GDAPI godot_variant_operator_equal(const godot_variant *p_a, const godot_variant *p_b); +godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_a, const godot_variant *p_b); + +godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_a, const godot_variant *p_b); + +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_v, godot_bool *p_valid); + +void GDAPI godot_variant_destroy(godot_variant *p_v); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/modules/dlscript/godot/godot_vector2.cpp b/modules/dlscript/godot/godot_vector2.cpp new file mode 100644 index 0000000000..0664da186e --- /dev/null +++ b/modules/dlscript/godot/godot_vector2.cpp @@ -0,0 +1,124 @@ +#include "godot_vector2.h" + +#include "math/math_2d.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _vector2_api_anchor() { +} + +void GDAPI godot_vector2_new(godot_vector2 *p_v, godot_real p_x, godot_real p_y) { + Vector2 *v = (Vector2 *)p_v; + v->x = p_x; + v->y = p_y; +} + +void GDAPI godot_vector2_set_x(godot_vector2 *p_v, const godot_real p_x) { + Vector2 *v = (Vector2 *)p_v; + v->x = p_x; +} + +void GDAPI godot_vector2_set_y(godot_vector2 *p_v, const godot_real p_y) { + Vector2 *v = (Vector2 *)p_v; + v->y = p_y; +} + +godot_real GDAPI godot_vector2_get_x(const godot_vector2 *p_v) { + Vector2 *v = (Vector2 *)p_v; + return v->x; +} +godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_v) { + Vector2 *v = (Vector2 *)p_v; + return v->y; +} + +void GDAPI godot_vector2_normalize(godot_vector2 *p_v) { + Vector2 *v = (Vector2 *)p_v; + v->normalize(); +} +void GDAPI godot_vector2_normalized(godot_vector2 *p_dest, const godot_vector2 *p_src) { + Vector2 *v = (Vector2 *)p_src; + Vector2 *d = (Vector2 *)p_dest; + + *d = v->normalized(); +} + +godot_real GDAPI godot_vector2_length(const godot_vector2 *p_v) { + Vector2 *v = (Vector2 *)p_v; + return v->length(); +} + +godot_real GDAPI godot_vector2_length_squared(const godot_vector2 *p_v) { + Vector2 *v = (Vector2 *)p_v; + return v->length_squared(); +} + +godot_real GDAPI godot_vector2_distance_to(const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *a = (Vector2 *)p_a; + Vector2 *b = (Vector2 *)p_b; + return a->distance_to(*b); +} + +godot_real GDAPI godot_vector2_distance_squared_to(const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *a = (Vector2 *)p_a; + Vector2 *b = (Vector2 *)p_b; + return a->distance_squared_to(*b); +} + +void GDAPI godot_vector2_operator_add(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + *dest = *a + *b; +} + +void GDAPI godot_vector2_operator_subtract(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + *dest = *a - *b; +} + +void GDAPI godot_vector2_operator_multiply_vector(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + *dest = *a * *b; +} + +void GDAPI godot_vector2_operator_multiply_scalar(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_real p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + *dest = *a * p_b; +} + +void GDAPI godot_vector2_operator_divide_vector(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + *dest = *a / *b; +} + +void GDAPI godot_vector2_operator_divide_scalar(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_real p_b) { + Vector2 *dest = (Vector2 *)p_dest; + const Vector2 *a = (Vector2 *)p_a; + *dest = *a / p_b; +} + +godot_bool GDAPI godot_vector2_operator_equal(const godot_vector2 *p_a, const godot_vector2 *p_b) { + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + return *a == *b; +} + +godot_bool GDAPI godot_vector2_operator_less(const godot_vector2 *p_a, const godot_vector2 *p_b) { + const Vector2 *a = (Vector2 *)p_a; + const Vector2 *b = (Vector2 *)p_b; + return *a < *b; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_vector2.h b/modules/dlscript/godot/godot_vector2.h new file mode 100644 index 0000000000..63da367e4f --- /dev/null +++ b/modules/dlscript/godot/godot_vector2.h @@ -0,0 +1,78 @@ +#ifndef GODOT_VECTOR2_H +#define GODOT_VECTOR2_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_VECTOR2_TYPE_DEFINED +typedef struct godot_vector2 { + uint8_t _dont_touch_that[8]; +} godot_vector2; +#endif + +#include "../godot.h" + +void GDAPI godot_vector2_new(godot_vector2 *p_v, const godot_real p_x, const godot_real p_y); + +void GDAPI godot_vector2_set_x(godot_vector2 *p_v, const godot_real p_x); +void GDAPI godot_vector2_set_y(godot_vector2 *p_v, const godot_real p_y); +godot_real GDAPI godot_vector2_get_x(const godot_vector2 *p_v); +godot_real GDAPI godot_vector2_get_y(const godot_vector2 *p_v); + +void GDAPI godot_vector2_normalize(godot_vector2 *p_v); +void GDAPI godot_vector2_normalized(godot_vector2 *p_dest, const godot_vector2 *p_src); + +godot_real GDAPI godot_vector2_length(const godot_vector2 *p_v); +godot_real GDAPI godot_vector2_length_squared(const godot_vector2 *p_v); + +godot_real GDAPI godot_vector2_distance_to(const godot_vector2 *p_a, const godot_vector2 *p_b); +godot_real GDAPI godot_vector2_distance_squared_to(const godot_vector2 *p_a, const godot_vector2 *p_b); + +// @Incomplete +/* + * missing: + * + * angle_to + * angle_to_point + * dot + * cross_vector + * cross_scalar + * project + * plane_project + * clamped + * linear_interpolate + * cubic_interpolate + * cubic_interpolate_soft + * slide + * reflect + * angle + * abs + * rotated + * tangent + * floor + * snapped + * aspect + * + * + * to_string + */ + +void GDAPI godot_vector2_operator_add(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b); +void GDAPI godot_vector2_operator_subtract(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b); +void GDAPI godot_vector2_operator_multiply_vector(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b); +void GDAPI godot_vector2_operator_multiply_scalar(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_real p_b); +void GDAPI godot_vector2_operator_divide_vector(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_vector2 *p_b); +void GDAPI godot_vector2_operator_divide_scalar(godot_vector2 *p_dest, const godot_vector2 *p_a, const godot_real p_b); + +godot_bool GDAPI godot_vector2_operator_equal(const godot_vector2 *p_a, const godot_vector2 *p_b); +godot_bool GDAPI godot_vector2_operator_less(const godot_vector2 *p_a, const godot_vector2 *p_b); + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_VECTOR2_H diff --git a/modules/dlscript/godot/godot_vector3.cpp b/modules/dlscript/godot/godot_vector3.cpp new file mode 100644 index 0000000000..34005cbcb8 --- /dev/null +++ b/modules/dlscript/godot/godot_vector3.cpp @@ -0,0 +1,150 @@ +#include "godot_vector3.h" + +#include "math/vector3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void _vector3_api_anchor() { +} + +void GDAPI godot_vector3_new(godot_vector3 *p_v, const godot_real p_x, const godot_real p_y, const godot_real p_z) { + Vector3 *v = (Vector3 *)p_v; + *v = Vector3(p_x, p_y, p_z); +} + +void GDAPI godot_vector3_set_axis(godot_vector3 *p_v, const godot_int p_axis, const godot_real p_val) { + Vector3 *v = (Vector3 *)p_v; + v->set_axis(p_axis, p_val); +} + +godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_v, const godot_int p_axis) { + Vector3 *v = (Vector3 *)p_v; + return v->get_axis(p_axis); +} + +godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_v) { + Vector3 *v = (Vector3 *)p_v; + return v->min_axis(); +} + +godot_int GDAPI godot_vector3_max_axis(const godot_vector3 *p_v) { + Vector3 *v = (Vector3 *)p_v; + return v->max_axis(); +} + +godot_real GDAPI godot_vector3_length(const godot_vector3 *p_v) { + Vector3 *v = (Vector3 *)p_v; + return v->length(); +} + +godot_real GDAPI godot_vector3_length_squared(const godot_vector3 *p_v) { + Vector3 *v = (Vector3 *)p_v; + return v->length_squared(); +} + +void GDAPI godot_vector3_normalize(godot_vector3 *p_v) { + Vector3 *v = (Vector3 *)p_v; + v->normalize(); +} + +void GDAPI godot_vector3_normalized(godot_vector3 *p_dest, const godot_vector3 *p_src) { + Vector3 *src = (Vector3 *)p_src; + Vector3 *dest = (Vector3 *)p_dest; + *dest = src->normalized(); +} + +/* + * inverse + * zero + * snap + * snapped + * rotate + * rotated + * + * + * linear_interpolate + * cubic_interpolate + * cubic_interpolaten + * cross + * dot + * outer + * to_diagonal_matrix + * abs + * floor + * ceil + */ + +godot_real GDAPI godot_vector3_distance_to(const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + return a->distance_to(*b); +} + +godot_real GDAPI godot_vector3_distance_squared_to(const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + return a->distance_squared_to(*b); +} + +/* + * slide + * reflect + */ + +void GDAPI godot_vector3_operator_add(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + *dest = *a + *b; +} + +void GDAPI godot_vector3_operator_subtract(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + *dest = *a - *b; +} + +void GDAPI godot_vector3_operator_multiply_vector(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + *dest = *a * *b; +} + +void GDAPI godot_vector3_operator_multiply_scalar(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_real p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + *dest = *a * p_b; +} + +void GDAPI godot_vector3_operator_divide_vector(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + *dest = *a / *b; +} + +void GDAPI godot_vector3_operator_divide_scalar(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_real p_b) { + Vector3 *dest = (Vector3 *)p_dest; + Vector3 *a = (Vector3 *)p_a; + *dest = *a / p_b; +} + +godot_bool GDAPI godot_vector3_operator_equal(const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + return *a == *b; +} + +godot_bool GDAPI godot_vector3_operator_less(const godot_vector3 *p_a, const godot_vector3 *p_b) { + Vector3 *a = (Vector3 *)p_a; + Vector3 *b = (Vector3 *)p_b; + return *a < *b; +} + +#ifdef __cplusplus +} +#endif diff --git a/modules/dlscript/godot/godot_vector3.h b/modules/dlscript/godot/godot_vector3.h new file mode 100644 index 0000000000..7fe93e3fd5 --- /dev/null +++ b/modules/dlscript/godot/godot_vector3.h @@ -0,0 +1,82 @@ +#ifndef GODOT_VECTOR3_H +#define GODOT_VECTOR3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#ifndef GODOT_CORE_API_GODOT_VECTOR3_TYPE_DEFINED +typedef struct godot_vector3 { + uint8_t _dont_touch_that[12]; +} godot_vector3; +#endif + +#include "../godot.h" + +void GDAPI godot_vector3_new(godot_vector3 *p_v, const godot_real p_x, const godot_real p_y, const godot_real p_z); + +void GDAPI godot_vector3_set_axis(godot_vector3 *p_v, const godot_int p_axis, const godot_real p_val); +godot_real GDAPI godot_vector3_get_axis(const godot_vector3 *p_v, const godot_int p_axis); + +godot_int GDAPI godot_vector3_min_axis(const godot_vector3 *p_v); +godot_int GDAPI godot_vector3_max_axis(const godot_vector3 *p_v); + +godot_real GDAPI godot_vector3_length(const godot_vector3 *p_v); +godot_real GDAPI godot_vector3_length_squared(const godot_vector3 *p_v); + +void GDAPI godot_vector3_normalize(godot_vector3 *p_v); +void GDAPI godot_vector3_normalized(godot_vector3 *p_dest, const godot_vector3 *p_src); + +// @Incomplete + +/* + * inverse + * zero + * snap + * snapped + * rotate + * rotated + * + * + * linear_interpolate + * cubic_interpolate + * cubic_interpolaten + * cross + * dot + * outer + * to_diagonal_matrix + * abs + * floor + * ceil + */ + +godot_real GDAPI godot_vector3_distance_to(const godot_vector3 *p_a, const godot_vector3 *p_b); +godot_real GDAPI godot_vector3_distance_squared_to(const godot_vector3 *p_a, const godot_vector3 *p_b); + +// @Incomplete +/* + * slide + * reflect + */ + +void GDAPI godot_vector3_operator_add(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b); +void GDAPI godot_vector3_operator_subtract(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b); +void GDAPI godot_vector3_operator_multiply_vector(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b); +void GDAPI godot_vector3_operator_multiply_scalar(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_real p_b); +void GDAPI godot_vector3_operator_divide_vector(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_vector3 *p_b); +void GDAPI godot_vector3_operator_divide_scalar(godot_vector3 *p_dest, const godot_vector3 *p_a, const godot_real p_b); + +godot_bool GDAPI godot_vector3_operator_equal(const godot_vector3 *p_a, const godot_vector3 *p_b); +godot_bool GDAPI godot_vector3_operator_less(const godot_vector3 *p_a, const godot_vector3 *p_b); + +/* + * to_string + */ + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_VECTOR3_H diff --git a/modules/cscript/register_types.cpp b/modules/dlscript/register_types.cpp index 2477bc51e2..1da00701a0 100644 --- a/modules/cscript/register_types.cpp +++ b/modules/dlscript/register_types.cpp @@ -27,8 +27,43 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" +#include "dl_script.h" -void register_cscript_types() { +#include "io/resource_loader.h" +#include "io/resource_saver.h" + +DLScriptLanguage *script_language_dl = NULL; +ResourceFormatLoaderDLScript *resource_loader_dl = NULL; +ResourceFormatSaverDLScript *resource_saver_dl = NULL; +//ResourceFormatLoaderDLLibrary *resource_loader_dllib=NULL; + +void register_dlscript_types() { + + ClassDB::register_class<DLLibrary>(); + ClassDB::register_class<DLScript>(); + + script_language_dl = memnew(DLScriptLanguage); + //script_language_gd->init(); + ScriptServer::register_language(script_language_dl); + resource_loader_dl = memnew(ResourceFormatLoaderDLScript); + ResourceLoader::add_resource_format_loader(resource_loader_dl); + resource_saver_dl = memnew(ResourceFormatSaverDLScript); + ResourceSaver::add_resource_format_saver(resource_saver_dl); + + // resource_loader_dllib=memnew( ResourceFormatLoaderDLLibrary ); + // ResourceLoader::add_resource_format_loader(resource_loader_gd); } -void unregister_cscript_types() { + +void unregister_dlscript_types() { + + ScriptServer::unregister_language(script_language_dl); + + if (script_language_dl) + memdelete(script_language_dl); + + if (resource_loader_dl) + memdelete(resource_loader_dl); + + if (resource_saver_dl) + memdelete(resource_saver_dl); } diff --git a/modules/cscript/register_types.h b/modules/dlscript/register_types.h index 6614ee3a19..90aa1d87fc 100644 --- a/modules/cscript/register_types.h +++ b/modules/dlscript/register_types.h @@ -26,5 +26,5 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -void register_cscript_types(); -void unregister_cscript_types(); +void register_dlscript_types(); +void unregister_dlscript_types(); diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 1540bb51f8..4c2965c8ec 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2420,7 +2420,7 @@ void GDParser::_parse_block(BlockNode *p_block, bool p_static) { p_block->sub_blocks.push_back(cf_if->body); if (!_enter_indent_block(cf_if->body)) { - _set_error("Expected intended block after 'if'"); + _set_error("Expected indented block after 'if'"); p_block->end_line = tokenizer->get_token_line(); return; } diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 981924191f..dca34f923e 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -117,6 +117,7 @@ const char *GDTokenizer::token_names[TK_MAX] = { "'.'", "'?'", "':'", + "'$'", "'\\n'", "PI", "_", diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index a6a3a03503..64426298ef 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -834,9 +834,9 @@ void GridMapEditor::edit(GridMap *p_gridmap) { //update grids indicator_mat.instance(); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); - indicator_mat->set_flag(FixedSpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true); + indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true); indicator_mat->set_albedo(Color(0.8, 0.5, 0.1)); Vector<Vector3> grid_points[3]; @@ -1309,9 +1309,9 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { inner_mat.instance(); inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.3)); - inner_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true); - inner_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); - inner_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + inner_mat->set_flag(SpatialMaterial::FLAG_ONTOP, true); + inner_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); + inner_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); d[VS::ARRAY_VERTEX] = triangles; VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_TRIANGLES, d); @@ -1319,10 +1319,10 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { outer_mat.instance(); outer_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.3)); - outer_mat->set_flag(FixedSpatialMaterial::FLAG_ONTOP, true); - outer_mat->set_flag(FixedSpatialMaterial::FLAG_UNSHADED, true); + outer_mat->set_flag(SpatialMaterial::FLAG_ONTOP, true); + outer_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); outer_mat->set_line_width(3.0); - outer_mat->set_feature(FixedSpatialMaterial::FEATURE_TRANSPARENT, true); + outer_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true); d[VS::ARRAY_VERTEX] = lines; VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 27a063ee41..947af0815f 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -112,9 +112,9 @@ class GridMapEditor : public VBoxContainer { RID duplicate_mesh; RID duplicate_instance; - Ref<FixedSpatialMaterial> indicator_mat; - Ref<FixedSpatialMaterial> inner_mat; - Ref<FixedSpatialMaterial> outer_mat; + Ref<SpatialMaterial> indicator_mat; + Ref<SpatialMaterial> inner_mat; + Ref<SpatialMaterial> outer_mat; bool updating; diff --git a/platform/android/detect.py b/platform/android/detect.py index 0e78a4618d..8d2ed59f17 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -175,6 +175,8 @@ def configure(env): if env['android_arch'] == 'x86': can_vectorize = True target_opts = ['-target', 'i686-none-linux-android'] + # The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least + env.Append(CPPFLAGS=['-mstackrealign']) elif env["android_arch"] == "armv6": can_vectorize = False target_opts = ['-target', 'armv6-none-linux-androideabi'] diff --git a/platform/iphone/rasterizer_iphone.cpp b/platform/iphone/rasterizer_iphone.cpp index 14288e4ba0..9563df5a2f 100644 --- a/platform/iphone/rasterizer_iphone.cpp +++ b/platform/iphone/rasterizer_iphone.cpp @@ -447,7 +447,7 @@ RID RasterizerIPhone::material_create() { return material_owner.make_rid(memnew(Material)); } -void RasterizerIPhone::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant &p_value) { +void RasterizerIPhone::fixed_material_set_parameter(RID p_material, VS::SpatialMaterialParam p_parameter, const Variant &p_value) { Material *m = material_owner.get(p_material); ERR_FAIL_COND(!m); @@ -455,7 +455,7 @@ void RasterizerIPhone::fixed_material_set_parameter(RID p_material, VS::FixedSpa m->parameters[p_parameter] = p_value; } -Variant RasterizerIPhone::fixed_material_get_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const { +Variant RasterizerIPhone::fixed_material_get_parameter(RID p_material, VS::SpatialMaterialParam p_parameter) const { Material *m = material_owner.get(p_material); ERR_FAIL_COND_V(!m, Variant()); @@ -464,7 +464,7 @@ Variant RasterizerIPhone::fixed_material_get_parameter(RID p_material, VS::Fixed return m->parameters[p_parameter]; } -void RasterizerIPhone::fixed_material_set_texture(RID p_material, VS::FixedSpatialMaterialParam p_parameter, RID p_texture) { +void RasterizerIPhone::fixed_material_set_texture(RID p_material, VS::SpatialMaterialParam p_parameter, RID p_texture) { Material *m = material_owner.get(p_material); ERR_FAIL_COND(!m); @@ -472,7 +472,7 @@ void RasterizerIPhone::fixed_material_set_texture(RID p_material, VS::FixedSpati m->textures[p_parameter] = p_texture; } -RID RasterizerIPhone::fixed_material_get_texture(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const { +RID RasterizerIPhone::fixed_material_get_texture(RID p_material, VS::SpatialMaterialParam p_parameter) const { Material *m = material_owner.get(p_material); ERR_FAIL_COND_V(!m, RID()); @@ -496,7 +496,7 @@ VS::MaterialBlendMode RasterizerIPhone::fixed_material_get_detail_blend_mode(RID return m->detail_blend_mode; } -void RasterizerIPhone::fixed_material_set_texcoord_mode(RID p_material, VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode) { +void RasterizerIPhone::fixed_material_set_texcoord_mode(RID p_material, VS::SpatialMaterialParam p_parameter, VS::SpatialMaterialTexCoordMode p_mode) { Material *m = material_owner.get(p_material); ERR_FAIL_COND(!m); @@ -504,7 +504,7 @@ void RasterizerIPhone::fixed_material_set_texcoord_mode(RID p_material, VS::Fixe m->texcoord_mode[p_parameter] = p_mode; } -VS::FixedSpatialMaterialTexCoordMode RasterizerIPhone::fixed_material_get_texcoord_mode(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const { +VS::SpatialMaterialTexCoordMode RasterizerIPhone::fixed_material_get_texcoord_mode(RID p_material, VS::SpatialMaterialParam p_parameter) const { Material *m = material_owner.get(p_material); ERR_FAIL_COND_V(!m, VS::FIXED_MATERIAL_TEXCOORD_TEXGEN); @@ -513,7 +513,7 @@ VS::FixedSpatialMaterialTexCoordMode RasterizerIPhone::fixed_material_get_texcoo return m->texcoord_mode[p_parameter]; // for now } -void RasterizerIPhone::fixed_material_set_texgen_mode(RID p_material, VS::FixedSpatialMaterialTexGenMode p_mode) { +void RasterizerIPhone::fixed_material_set_texgen_mode(RID p_material, VS::SpatialMaterialTexGenMode p_mode) { Material *m = material_owner.get(p_material); ERR_FAIL_COND(!m); @@ -521,7 +521,7 @@ void RasterizerIPhone::fixed_material_set_texgen_mode(RID p_material, VS::FixedS m->texgen_mode = p_mode; }; -VS::FixedSpatialMaterialTexGenMode RasterizerIPhone::fixed_material_get_texgen_mode(RID p_material) const { +VS::SpatialMaterialTexGenMode RasterizerIPhone::fixed_material_get_texgen_mode(RID p_material) const { Material *m = material_owner.get(p_material); ERR_FAIL_COND_V(!m, VS::FIXED_MATERIAL_TEXGEN_SPHERE); diff --git a/platform/iphone/rasterizer_iphone.h b/platform/iphone/rasterizer_iphone.h index 02cb985dc8..5fee149e79 100644 --- a/platform/iphone/rasterizer_iphone.h +++ b/platform/iphone/rasterizer_iphone.h @@ -100,11 +100,11 @@ class RasterizerIPhone : public Rasterizer { RID textures[VisualServer::FIXED_MATERIAL_PARAM_MAX]; Transform uv_transform; - VS::FixedSpatialMaterialTexCoordMode texcoord_mode[VisualServer::FIXED_MATERIAL_PARAM_MAX]; + VS::SpatialMaterialTexCoordMode texcoord_mode[VisualServer::FIXED_MATERIAL_PARAM_MAX]; VS::MaterialBlendMode detail_blend_mode; - VS::FixedSpatialMaterialTexGenMode texgen_mode; + VS::SpatialMaterialTexGenMode texgen_mode; Material() { @@ -614,20 +614,20 @@ public: virtual RID material_create(); - virtual void fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant &p_value); - virtual Variant fixed_material_get_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_parameter(RID p_material, VS::SpatialMaterialParam p_parameter, const Variant &p_value); + virtual Variant fixed_material_get_parameter(RID p_material, VS::SpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texture(RID p_material, VS::FixedSpatialMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_texture(RID p_material, VS::SpatialMaterialParam p_parameter, RID p_texture); + virtual RID fixed_material_get_texture(RID p_material, VS::SpatialMaterialParam p_parameter) const; virtual void fixed_material_set_detail_blend_mode(RID p_material, VS::MaterialBlendMode p_mode); virtual VS::MaterialBlendMode fixed_material_get_detail_blend_mode(RID p_material) const; - virtual void fixed_material_set_texgen_mode(RID p_material, VS::FixedSpatialMaterialTexGenMode p_mode); - virtual VS::FixedSpatialMaterialTexGenMode fixed_material_get_texgen_mode(RID p_material) const; + virtual void fixed_material_set_texgen_mode(RID p_material, VS::SpatialMaterialTexGenMode p_mode); + virtual VS::SpatialMaterialTexGenMode fixed_material_get_texgen_mode(RID p_material) const; - virtual void fixed_material_set_texcoord_mode(RID p_material, VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode); - virtual VS::FixedSpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material, VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_texcoord_mode(RID p_material, VS::SpatialMaterialParam p_parameter, VS::SpatialMaterialTexCoordMode p_mode); + virtual VS::SpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material, VS::SpatialMaterialParam p_parameter) const; virtual void fixed_material_set_uv_transform(RID p_material, const Transform &p_transform); virtual Transform fixed_material_get_uv_transform(RID p_material) const; diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index bb51474a8c..df1605ae9e 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -26,28 +26,25 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "export.h" #include "editor/editor_export.h" #include "platform/windows/logo.h" void register_windows_exporter() { -#if 0 + Ref<EditorExportPlatformPC> platform; + platform.instance(); + Image img(_windows_logo); - Ref<ImageTexture> logo = memnew( ImageTexture ); + Ref<ImageTexture> logo; + logo.instance(); logo->create_from_image(img); + platform->set_logo(logo); + platform->set_name("Windows Desktop"); + platform->set_extension("exe"); + platform->set_release_32("windows_32_release.exe"); + platform->set_debug_32("windows_32_debug.exe"); + platform->set_release_64("windows_64_release.exe"); + platform->set_debug_64("windows_64_debug.exe"); - { - Ref<EditorExportPlatformPC> exporter = Ref<EditorExportPlatformPC>( memnew(EditorExportPlatformPC) ); - exporter->set_binary_extension("exe"); - exporter->set_release_binary32("windows_32_release.exe"); - exporter->set_debug_binary32("windows_32_debug.exe"); - exporter->set_release_binary64("windows_64_release.exe"); - exporter->set_debug_binary64("windows_64_debug.exe"); - exporter->set_name("Windows Desktop"); - exporter->set_logo(logo); - EditorImportExport::get_singleton()->add_export_platform(exporter); - } - -#endif + EditorExport::get_singleton()->add_export_platform(platform); } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 83a6aa6079..cfc97d57da 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1582,6 +1582,32 @@ bool OS_Windows::get_borderless_window() { return video_mode.borderless_window; } +Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle) { + p_library_handle = (void *)LoadLibrary(p_path.utf8().get_data()); + if (!p_library_handle) { + ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + String::num(GetLastError())); + ERR_FAIL_V(ERR_CANT_OPEN); + } + return OK; +} + +Error OS_Windows::close_dynamic_library(void *p_library_handle) { + if (!FreeLibrary((HMODULE)p_library_handle)) { + return FAILED; + } + return OK; +} + +Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { + char *error; + p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data()); + if (!p_symbol_handle) { + ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError())); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } + return OK; +} + void OS_Windows::request_attention() { FLASHWINFO info; @@ -2167,9 +2193,6 @@ void OS_Windows::run() { if (!main_loop) return; - // Process all events before the main initialization so the cursor will get initialized properly - process_events(); // get rid of pending events - main_loop->init(); uint64_t last_ticks = get_ticks_usec(); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 25c3102ee6..050067ad7d 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -222,6 +222,10 @@ public: virtual void set_borderless_window(int p_borderless); virtual bool get_borderless_window(); + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle); + virtual Error close_dynamic_library(void *p_library_handle); + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle); + virtual MainLoop *get_main_loop() const; virtual String get_name(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 4606a90835..6aeab21c7f 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1277,12 +1277,8 @@ void OS_X11::process_xevents() { case EnterNotify: { if (main_loop && !mouse_mode_grab) main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - if (input) { - // Update mouse position. It is triggered before mouse motion. - Point2i pos(event.xmotion.x, event.xmotion.y); - input->set_mouse_pos(pos); + if (input) input->set_mouse_in_window(true); - } } break; case FocusIn: minimized = false; @@ -1904,9 +1900,6 @@ void OS_X11::run() { if (!main_loop) return; - // Process all events before the main initialization so the cursor will get initialized properly - process_xevents(); // get rid of pending events - main_loop->init(); //uint64_t last_ticks=get_ticks_usec(); 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; diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index 1be65be927..22bec0a31f 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -54,10 +54,10 @@ RID Rasterizer::create_default_material() { /* Fixed MAterial SHADER API */ -RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) { +RID Rasterizer::_create_shader(const SpatialMaterialShaderKey& p_key) { ERR_FAIL_COND_V(!p_key.valid,RID()); - Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<SpatialMaterialShaderKey,SpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); if (E) { E->get().refcount++; @@ -66,7 +66,7 @@ RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) { uint64_t t = OS::get_singleton()->get_ticks_usec(); - FixedSpatialMaterialShader fms; + SpatialMaterialShader fms; fms.refcount=1; fms.shader=shader_create(); @@ -312,12 +312,12 @@ RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) { return fms.shader; } -void Rasterizer::_free_shader(const FixedSpatialMaterialShaderKey& p_key) { +void Rasterizer::_free_shader(const SpatialMaterialShaderKey& p_key) { if (p_key.valid==0) return; //not a valid key - Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<SpatialMaterialShaderKey,SpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); ERR_FAIL_COND(!E); E->get().refcount--; @@ -329,12 +329,12 @@ void Rasterizer::_free_shader(const FixedSpatialMaterialShaderKey& p_key) { } -void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled) { +void Rasterizer::fixed_material_set_flag(RID p_material, VS::SpatialMaterialFlags p_flag, bool p_enabled) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); switch(p_flag) { @@ -350,11 +350,11 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedSpatialMateria } -bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const{ +bool Rasterizer::fixed_material_get_flag(RID p_material, VS::SpatialMaterialFlags p_flag) const{ - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,false); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); switch(p_flag) { case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break; @@ -373,8 +373,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedSpatialMateria RID Rasterizer::fixed_material_create() { RID mat = material_create(); - fixed_materials[mat]=memnew( FixedSpatialMaterial() ); - FixedSpatialMaterial &fm=*fixed_materials[mat]; + fixed_materials[mat]=memnew( SpatialMaterial() ); + SpatialMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); @@ -390,11 +390,11 @@ RID Rasterizer::fixed_material_create() { -void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value){ +void Rasterizer::fixed_material_set_parameter(RID p_material, VS::SpatialMaterialParam p_parameter, const Variant& p_value){ - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); RID material=E->key(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -417,24 +417,24 @@ void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMa } -Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ +Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::SpatialMaterialParam p_parameter) const{ - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Variant()); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,Variant()); return fm.param[p_parameter]; } -void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture){ +void Rasterizer::fixed_material_set_texture(RID p_material,VS::SpatialMaterialParam p_parameter, RID p_texture){ - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (!E) { print_line("Not found: "+itos(p_material.get_id())); } ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -449,22 +449,22 @@ void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedSpatialMater } -RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ +RID Rasterizer::fixed_material_get_texture(RID p_material,VS::SpatialMaterialParam p_parameter) const{ - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,RID()); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,RID()); return fm.texture[p_parameter]; } -void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode) { +void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::SpatialMaterialParam p_parameter, VS::SpatialMaterialTexCoordMode p_mode) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); fm.get_key(); @@ -476,11 +476,11 @@ void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatia } -VS::FixedSpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const { +VS::SpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::SpatialMaterialParam p_parameter) const { - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_TEXCOORD_UV); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,VS::FIXED_MATERIAL_TEXCOORD_UV); return fm.texture_tc[p_parameter]; @@ -488,9 +488,9 @@ VS::FixedSpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mod void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_uv_xform_name,p_transform); @@ -503,18 +503,18 @@ void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& Transform Rasterizer::fixed_material_get_uv_transform(RID p_material) const { - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Transform()); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); return fm.uv_xform; } -void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader) { +void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::SpatialMaterialLightShader p_shader) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); fm.light_shader=p_shader; @@ -523,20 +523,20 @@ void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedSpatial } -VS::FixedSpatialMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { +VS::SpatialMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); return fm.light_shader; } void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedSpatialMaterial &fm=*E->get(); + SpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_point_size_name,p_size); @@ -548,9 +548,9 @@ void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { float Rasterizer::fixed_material_get_point_size(RID p_material) const{ - const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,1.0); - const FixedSpatialMaterial &fm=*E->get(); + const SpatialMaterial &fm=*E->get(); return fm.point_size; @@ -561,9 +561,9 @@ void Rasterizer::_update_fixed_materials() { while(fixed_material_dirty_list.first()) { - FixedSpatialMaterial &fm=*fixed_material_dirty_list.first()->self(); + SpatialMaterial &fm=*fixed_material_dirty_list.first()->self(); - FixedSpatialMaterialShaderKey new_key = fm.get_key(); + SpatialMaterialShaderKey new_key = fm.get_key(); if (new_key.key!=fm.current_key.key) { _free_shader(fm.current_key); @@ -593,7 +593,7 @@ void Rasterizer::_update_fixed_materials() { void Rasterizer::_free_fixed_material(const RID& p_material) { - Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,SpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (E) { @@ -636,7 +636,7 @@ Rasterizer::Rasterizer() { draw_viewport_func=NULL; - ERR_FAIL_COND( sizeof(FixedSpatialMaterialShaderKey)!=4); + ERR_FAIL_COND( sizeof(SpatialMaterialShaderKey)!=4); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 838ddead75..56c6dfe30a 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -98,9 +98,6 @@ public: //int baked_lightmap_id; bool mirror : 8; - bool depth_scale : 8; - bool billboard : 8; - bool billboard_y : 8; bool receive_shadows : 8; bool visible : 8; @@ -120,9 +117,6 @@ public: base_type = VS::INSTANCE_NONE; cast_shadows = VS::SHADOW_CASTING_SETTING_ON; receive_shadows = true; - depth_scale = false; - billboard = false; - billboard_y = false; visible = true; depth_layer = 0; layer_mask = 1; @@ -198,10 +192,7 @@ public: /* SHADER API */ - virtual RID shader_create(VS::ShaderMode p_mode = VS::SHADER_SPATIAL) = 0; - - virtual void shader_set_mode(RID p_shader, VS::ShaderMode p_mode) = 0; - virtual VS::ShaderMode shader_get_mode(RID p_shader) const = 0; + virtual RID shader_create() = 0; virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual String shader_get_code(RID p_shader) const = 0; @@ -452,19 +443,19 @@ public: virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity) = 0; virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; - - virtual void particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape) = 0; - virtual void particles_set_emission_sphere_radius(RID p_particles, float p_radius) = 0; - virtual void particles_set_emission_box_extents(RID p_particles, const Vector3 &p_extents) = 0; - virtual void particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points) = 0; + virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0; virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; - virtual void particles_set_draw_pass_material(RID p_particles, int p_pass, RID p_material) = 0; virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; + virtual void particles_request_process(RID p_particles) = 0; virtual Rect3 particles_get_current_aabb(RID p_particles) = 0; + virtual Rect3 particles_get_aabb(RID p_particles) const = 0; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; /* RENDER TARGET */ @@ -971,7 +962,7 @@ protected: /* Fixed Material Shader API */ - union FixedSpatialMaterialShaderKey { + union SpatialMaterialShaderKey { struct { uint16_t texcoord_mask; @@ -987,21 +978,21 @@ protected: uint32_t key; - _FORCE_INLINE_ bool operator<(const FixedSpatialMaterialShaderKey& p_key) const { return key<p_key.key; } + _FORCE_INLINE_ bool operator<(const SpatialMaterialShaderKey& p_key) const { return key<p_key.key; } }; - struct FixedSpatialMaterialShader { + struct SpatialMaterialShader { int refcount; RID shader; }; - Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader> fixed_material_shaders; + Map<SpatialMaterialShaderKey,SpatialMaterialShader> fixed_material_shaders; - RID _create_shader(const FixedSpatialMaterialShaderKey& p_key); - void _free_shader(const FixedSpatialMaterialShaderKey& p_key); + RID _create_shader(const SpatialMaterialShaderKey& p_key); + void _free_shader(const SpatialMaterialShaderKey& p_key); - struct FixedSpatialMaterial { + struct SpatialMaterial { RID self; @@ -1012,19 +1003,19 @@ protected: bool use_xy_normalmap; float point_size; Transform uv_xform; - VS::FixedSpatialMaterialLightShader light_shader; + VS::SpatialMaterialLightShader light_shader; RID texture[VS::FIXED_MATERIAL_PARAM_MAX]; Variant param[VS::FIXED_MATERIAL_PARAM_MAX]; - VS::FixedSpatialMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; + VS::SpatialMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; - SelfList<FixedSpatialMaterial> dirty_list; + SelfList<SpatialMaterial> dirty_list; - FixedSpatialMaterialShaderKey current_key; + SpatialMaterialShaderKey current_key; - _FORCE_INLINE_ FixedSpatialMaterialShaderKey get_key() const { + _FORCE_INLINE_ SpatialMaterialShaderKey get_key() const { - FixedSpatialMaterialShaderKey k; + SpatialMaterialShaderKey k; k.key=0; k.use_alpha=use_alpha; k.use_color_array=use_color_array; @@ -1045,7 +1036,7 @@ protected: } - FixedSpatialMaterial() : dirty_list(this) { + SpatialMaterial() : dirty_list(this) { use_alpha=false; use_color_array=false; @@ -1077,9 +1068,9 @@ protected: StringName _fixed_material_uv_xform_name; StringName _fixed_material_point_size_name; - Map<RID,FixedSpatialMaterial*> fixed_materials; + Map<RID,SpatialMaterial*> fixed_materials; - SelfList<FixedSpatialMaterial>::List fixed_material_dirty_list; + SelfList<SpatialMaterial>::List fixed_material_dirty_list; protected: void _update_fixed_materials(); @@ -1166,23 +1157,23 @@ public: virtual RID fixed_material_create(); - virtual void fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const; + virtual void fixed_material_set_flag(RID p_material, VS::SpatialMaterialFlags p_flag, bool p_enabled); + virtual bool fixed_material_get_flag(RID p_material, VS::SpatialMaterialFlags p_flag) const; - virtual void fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_parameter(RID p_material, VS::SpatialMaterialParam p_parameter, const Variant& p_value); + virtual Variant fixed_material_get_parameter(RID p_material,VS::SpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_texture(RID p_material,VS::SpatialMaterialParam p_parameter, RID p_texture); + virtual RID fixed_material_get_texture(RID p_material,VS::SpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode); - virtual VS::FixedSpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; + virtual void fixed_material_set_texcoord_mode(RID p_material,VS::SpatialMaterialParam p_parameter, VS::SpatialMaterialTexCoordMode p_mode); + virtual VS::SpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::SpatialMaterialParam p_parameter) const; virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); virtual Transform fixed_material_get_uv_transform(RID p_material) const; - virtual void fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader); - virtual VS::FixedSpatialMaterialLightShader fixed_material_get_light_shader(RID p_material) const; + virtual void fixed_material_set_light_shader(RID p_material,VS::SpatialMaterialLightShader p_shader); + virtual VS::SpatialMaterialLightShader fixed_material_get_light_shader(RID p_material) const; virtual void fixed_material_set_point_size(RID p_material,float p_size); virtual float fixed_material_get_point_size(RID p_material) const; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index bc4452d5a8..ecb0bdef37 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -81,7 +81,8 @@ String ShaderLanguage::get_operator_text(Operator p_op) { "++" "--", "()", - "construct" }; + "construct", + "index" }; return op_names[p_op]; } @@ -176,6 +177,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "PERIOD", "UNIFORM", "VARYING", + "IN", + "OUT", + "INOUT", "RENDER_MODE", "HINT_WHITE_TEXTURE", "HINT_BLACK_TEXTURE", @@ -185,6 +189,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = { "HINT_BLACK_ALBEDO_TEXTURE", "HINT_COLOR", "HINT_RANGE", + "SHADER_TYPE", "CURSOR", "ERROR", "EOF", @@ -258,6 +263,9 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_CF_RETURN, "return" }, { TK_UNIFORM, "uniform" }, { TK_VARYING, "varying" }, + { TK_ARG_IN, "in" }, + { TK_ARG_OUT, "out" }, + { TK_ARG_INOUT, "inout" }, { TK_RENDER_MODE, "render_mode" }, { TK_HINT_WHITE_TEXTURE, "hint_white" }, { TK_HINT_BLACK_TEXTURE, "hint_black" }, @@ -267,6 +275,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" }, { TK_HINT_COLOR, "hint_color" }, { TK_HINT_RANGE, "hint_range" }, + { TK_SHADER_TYPE, "shader_type" }, { TK_ERROR, NULL } }; @@ -368,7 +377,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { if (GETCHAR(0) == '=') { char_idx++; return _make_token(TK_OP_GREATER_EQUAL); - } else if (GETCHAR(0) == '<') { + } else if (GETCHAR(0) == '>') { char_idx++; if (GETCHAR(0) == '=') { char_idx++; @@ -871,7 +880,7 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } if (na == nb) { - valid = (na > TYPE_BOOL && na < TYPE_MAT2) || (p_op->op == OP_MUL && na >= TYPE_MAT2 && na <= TYPE_MAT4); + valid = (na > TYPE_BOOL && na <= TYPE_MAT4); ret_type = na; } else if (na == TYPE_INT && nb == TYPE_IVEC2) { valid = true; @@ -900,15 +909,24 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } else if (na == TYPE_FLOAT && nb == TYPE_VEC4) { valid = true; ret_type = TYPE_VEC4; - } else if (p_op->op == OP_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT2) { valid = true; ret_type = TYPE_MAT2; - } else if (p_op->op == OP_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT3) { valid = true; ret_type = TYPE_MAT3; - } else if (p_op->op == OP_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT4) { valid = true; ret_type = TYPE_MAT4; + } else if (p_op->op == OP_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { + valid = true; + ret_type = TYPE_VEC2; + } else if (p_op->op == OP_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { + valid = true; + ret_type = TYPE_VEC3; + } else if (p_op->op == OP_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { + valid = true; + ret_type = TYPE_VEC4; } } break; case OP_ASSIGN_MOD: @@ -977,14 +995,6 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type DataType na = p_op->arguments[0]->get_datatype(); DataType nb = p_op->arguments[1]->get_datatype(); - if (na >= TYPE_UINT && na <= TYPE_UVEC4) { - na = DataType(na - 4); - } - - if (nb >= TYPE_UINT && nb <= TYPE_UVEC4) { - nb = DataType(nb - 4); - } - if (na == TYPE_INT && nb == TYPE_INT) { valid = true; ret_type = TYPE_INT; @@ -1006,6 +1016,27 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { valid = true; ret_type = TYPE_IVEC4; + } else if (na == TYPE_UINT && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UINT; + } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { + valid = true; + ret_type = TYPE_UVEC4; } } break; case OP_ASSIGN: { @@ -1651,25 +1682,19 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "not", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID } }, //builtins - texture - { "textureSize", TYPE_VEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } }, - { "textureSize", TYPE_VEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } }, - { "textureSize", TYPE_VEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } }, - { "textureSize", TYPE_VEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } }, + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID } }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } }, { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, @@ -1689,9 +1714,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, - { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, - { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } }, { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } }, { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } }, @@ -2308,9 +2333,17 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); + //test if function was parsed first for (int i = 0; i < shader->functions.size(); i++) { if (shader->functions[i].name == name) { - shader->functions[i].uses_function.insert(name); + //add to current function as dependency + for (int j = 0; j < shader->functions.size(); j++) { + if (shader->functions[j].name == current_function) { + shader->functions[j].uses_function.insert(name); + break; + } + } + break; } } @@ -2514,18 +2547,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } } break; - case TYPE_MAT2: - ok = (ident == "x" || ident == "y"); - member_type = TYPE_VEC2; - break; - case TYPE_MAT3: - ok = (ident == "x" || ident == "y" || ident == "z"); - member_type = TYPE_VEC3; - break; - case TYPE_MAT4: - ok = (ident == "x" || ident == "y" || ident == "z" || ident == "w"); - member_type = TYPE_VEC4; - break; + default: {} } @@ -2552,6 +2574,116 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons //creates a subindexing expression in place */ + } else if (tk.type == TK_BRACKET_OPEN) { + + Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); + + if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) { + _set_error("Only integer datatypes are allowed for indexing"); + return NULL; + } + + bool index_valid = false; + DataType member_type; + + switch (expr->get_datatype()) { + case TYPE_BVEC2: + case TYPE_VEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_MAT2: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; + if (index_constant >= 2) { + _set_error("Index out of range (0-1)"); + return NULL; + } + } else { + _set_error("Only integer constants are allowed as index at the moment"); + return NULL; + } + index_valid = true; + switch (expr->get_datatype()) { + case TYPE_BVEC2: member_type = TYPE_BOOL; break; + case TYPE_VEC2: member_type = TYPE_FLOAT; break; + case TYPE_IVEC2: member_type = TYPE_INT; break; + case TYPE_UVEC2: member_type = TYPE_UINT; break; + case TYPE_MAT2: member_type = TYPE_VEC2; break; + } + + break; + case TYPE_BVEC3: + case TYPE_VEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_MAT3: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; + if (index_constant >= 3) { + _set_error("Index out of range (0-2)"); + return NULL; + } + } else { + _set_error("Only integer constants are allowed as index at the moment"); + return NULL; + } + index_valid = true; + switch (expr->get_datatype()) { + case TYPE_BVEC3: member_type = TYPE_BOOL; break; + case TYPE_VEC3: member_type = TYPE_FLOAT; break; + case TYPE_IVEC3: member_type = TYPE_INT; break; + case TYPE_UVEC3: member_type = TYPE_UINT; break; + case TYPE_MAT3: member_type = TYPE_VEC3; break; + } + break; + case TYPE_BVEC4: + case TYPE_VEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_MAT4: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint; + if (index_constant >= 4) { + _set_error("Index out of range (0-3)"); + return NULL; + } + } else { + _set_error("Only integer constants are allowed as index at the moment"); + return NULL; + } + index_valid = true; + switch (expr->get_datatype()) { + case TYPE_BVEC4: member_type = TYPE_BOOL; break; + case TYPE_VEC4: member_type = TYPE_FLOAT; break; + case TYPE_IVEC4: member_type = TYPE_INT; break; + case TYPE_UVEC4: member_type = TYPE_UINT; break; + case TYPE_MAT4: member_type = TYPE_VEC4; break; + } + break; + default: { + _set_error("Object of type '" + get_datatype_name(expr->get_datatype()) + "' can't be indexed"); + return NULL; + } + } + + if (!index_valid) { + _set_error("Invalid index"); + return NULL; + } + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OP_INDEX; + op->return_cache = member_type; + op->arguments.push_back(expr); + op->arguments.push_back(index); + expr = op; + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']' after indexing expression"); + return NULL; + } + } else if (tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { OperatorNode *op = alloc_node<OperatorNode>(); @@ -3077,6 +3209,52 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat _set_tkpos(pos); //rollback } + } else if (tk.type == TK_CF_RETURN) { + + //check return type + BlockNode *b = p_block; + while (b && !b->parent_function) { + b = b->parent_block; + } + + if (!b) { + _set_error("Bug"); + return ERR_BUG; + } + + ControlFlowNode *flow = alloc_node<ControlFlowNode>(); + flow->flow_op = FLOW_OP_RETURN; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_SEMICOLON) { + //all is good + if (b->parent_function->return_type != TYPE_VOID) { + _set_error("Expected return with expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); + return ERR_PARSE_ERROR; + } + } else { + _set_tkpos(pos); //rollback, wants expression + Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!expr) + return ERR_PARSE_ERROR; + + if (b->parent_function->return_type != expr->get_datatype()) { + _set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after return expression"); + return ERR_PARSE_ERROR; + } + + flow->expressions.push_back(expr); + } + + p_block->statements.push_back(flow); + } else { //nothng else, so expression @@ -3100,10 +3278,47 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat return OK; } -Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes) { +Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { Token tk = _get_token(); + if (tk.type != TK_SHADER_TYPE) { + _set_error("Expected 'shader_type' at the begining of shader."); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier after 'shader_type', indicating type of shader."); + return ERR_PARSE_ERROR; + } + + String shader_type_identifier; + + shader_type_identifier = tk.text; + + if (!p_shader_types.has(shader_type_identifier)) { + + String valid; + for (Set<String>::Element *E = p_shader_types.front(); E; E = E->next()) { + if (valid != String()) { + valid += ", "; + } + valid += "'" + E->get() + "'"; + } + _set_error("Invalid shader type, valid types are: " + valid); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after 'shader_type <type>'."); + } + + tk = _get_token(); + int texture_uniforms = 0; int uniforms = 0; @@ -3428,6 +3643,19 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataTy break; } + ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; + + if (tk.type == TK_ARG_IN) { + qualifier = ARGUMENT_QUALIFIER_IN; + tk = _get_token(); + } else if (tk.type == TK_ARG_OUT) { + qualifier = ARGUMENT_QUALIFIER_OUT; + tk = _get_token(); + } else if (tk.type == TK_ARG_INOUT) { + qualifier = ARGUMENT_QUALIFIER_INOUT; + tk = _get_token(); + } + DataType ptype; StringName pname; DataPrecision pprecision = PRECISION_DEFAULT; @@ -3466,6 +3694,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataTy arg.type = ptype; arg.name = pname; arg.precision = pprecision; + arg.qualifier = qualifier; func_node->arguments.push_back(arg); @@ -3515,7 +3744,42 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, Map<StringName, DataTy return OK; } -Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes) { +String ShaderLanguage::get_shader_type(const String &p_code) { + + bool reading_type = false; + + String cur_identifier; + + for (int i = 0; i < p_code.length() + 1; i++) { + + if (p_code[i] == ';') { + break; + + } else if (p_code[i] <= 32) { + if (cur_identifier != String()) { + if (!reading_type) { + if (cur_identifier != "shader_type") { + return String(); + } + + reading_type = true; + cur_identifier = String(); + } else { + return cur_identifier; + } + } + } else { + cur_identifier += String::chr(p_code[i]); + } + } + + if (reading_type) + return cur_identifier; + + return String(); +} + +Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types) { clear(); @@ -3524,7 +3788,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<St nodes = NULL; shader = alloc_node<ShaderNode>(); - Error err = _parse_shader(p_functions, p_render_modes); + Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); if (err != OK) { return err; @@ -3532,7 +3796,7 @@ Error ShaderLanguage::compile(const String &p_code, const Map<StringName, Map<St return OK; } -Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, List<String> *r_options, String &r_call_hint) { +Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint) { clear(); @@ -3541,7 +3805,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Map<S nodes = NULL; shader = alloc_node<ShaderNode>(); - Error err = _parse_shader(p_functions, p_render_modes); + Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); switch (completion_type) { diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index a4757e3419..5e7ae3b70f 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -130,6 +130,9 @@ public: TK_PERIOD, TK_UNIFORM, TK_VARYING, + TK_ARG_IN, + TK_ARG_OUT, + TK_ARG_INOUT, TK_RENDER_MODE, TK_HINT_WHITE_TEXTURE, TK_HINT_BLACK_TEXTURE, @@ -139,6 +142,7 @@ public: TK_HINT_BLACK_ALBEDO_TEXTURE, TK_HINT_COLOR, TK_HINT_RANGE, + TK_SHADER_TYPE, TK_CURSOR, TK_ERROR, TK_EOF, @@ -227,6 +231,7 @@ public: OP_POST_DECREMENT, OP_CALL, OP_CONSTRUCT, + OP_INDEX, OP_MAX }; @@ -242,6 +247,13 @@ public: }; + enum ArgumentQualifier { + ARGUMENT_QUALIFIER_IN, + ARGUMENT_QUALIFIER_OUT, + ARGUMENT_QUALIFIER_INOUT, + + }; + struct Node { Node *next; @@ -363,6 +375,7 @@ public: struct Argument { + ArgumentQualifier qualifier; StringName name; DataType type; DataPrecision precision; @@ -577,14 +590,16 @@ private: Error _parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - Error _parse_shader(const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes); + Error _parse_shader(const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types); public: //static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); void clear(); - Error compile(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes); - Error complete(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, List<String> *r_options, String &r_call_hint); + + static String get_shader_type(const String &p_code); + Error compile(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types); + Error complete(const String &p_code, const Map<StringName, Map<StringName, DataType> > &p_functions, const Set<String> &p_render_modes, const Set<String> &p_shader_types, List<String> *r_options, String &r_call_hint); String get_error_text(); int get_error_line(); diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index c5e31b235a..02e970c786 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -38,6 +38,10 @@ const Set<String> &ShaderTypes::get_modes(VS::ShaderMode p_mode) { return shader_modes[p_mode].modes; } +const Set<String> &ShaderTypes::get_types() { + return shader_types; +} + ShaderTypes *ShaderTypes::singleton = NULL; ShaderTypes::ShaderTypes() { @@ -61,11 +65,14 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INSTANCE_ID"] = ShaderLanguage::TYPE_INT; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; //builtins shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2; @@ -122,7 +129,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop"); - shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_default_transform"); /************ CANVAS ITEM **************************/ @@ -136,6 +143,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PARTICLE_CUSTOM"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"] = ShaderLanguage::TYPE_VEC2; @@ -189,14 +197,21 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RESTART"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["CUSTOM"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["LIFETIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"] = ShaderLanguage::TYPE_BOOL; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ORIGIN"] = ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["NUMBER"] = ShaderLanguage::TYPE_UINT; shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"] = ShaderLanguage::TYPE_INT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"] = ShaderLanguage::TYPE_UINT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["GRAVITY"] = ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["EMISSION_TRANSFORM"] = ShaderLanguage::TYPE_MAT4; shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard"); shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force"); shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("keep_data"); + + shader_types.insert("spatial"); + shader_types.insert("canvas_item"); + shader_types.insert("particles"); } diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h index 1bddde8c82..1f5131e019 100644 --- a/servers/visual/shader_types.h +++ b/servers/visual/shader_types.h @@ -43,11 +43,14 @@ class ShaderTypes { static ShaderTypes *singleton; + Set<String> shader_types; + public: static ShaderTypes *get_singleton() { return singleton; } const Map<StringName, Map<StringName, ShaderLanguage::DataType> > &get_functions(VS::ShaderMode p_mode); const Set<String> &get_modes(VS::ShaderMode p_mode); + const Set<String> &get_types(); ShaderTypes(); }; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 2666a95595..624dc6dfe0 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -38,6 +38,8 @@ // careful, these may run in different threads than the visual server +int VisualServerRaster::changes = 0; + /* CURSOR */ void VisualServerRaster::cursor_set_rotation(float p_rotation, int p_cursor) { } @@ -391,33 +393,33 @@ RID VisualServerRaster::fixed_material_create() { return rasterizer->fixed_material_create(); } -void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedSpatialMaterialFlags p_flag, bool p_enabled) { +void VisualServerRaster::fixed_material_set_flag(RID p_material, SpatialMaterialFlags p_flag, bool p_enabled) { rasterizer->fixed_material_set_flag(p_material,p_flag,p_enabled); } -bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedSpatialMaterialFlags p_flag) const { +bool VisualServerRaster::fixed_material_get_flag(RID p_material, SpatialMaterialFlags p_flag) const { return rasterizer->fixed_material_get_flag(p_material,p_flag); } -void VisualServerRaster::fixed_material_set_param(RID p_material, FixedSpatialMaterialParam p_parameter, const Variant& p_value) { +void VisualServerRaster::fixed_material_set_param(RID p_material, SpatialMaterialParam p_parameter, const Variant& p_value) { VS_CHANGED; rasterizer->fixed_material_set_parameter(p_material,p_parameter,p_value); } -Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedSpatialMaterialParam p_parameter) const { +Variant VisualServerRaster::fixed_material_get_param(RID p_material,SpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_parameter(p_material,p_parameter); } -void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedSpatialMaterialParam p_parameter, RID p_texture) { +void VisualServerRaster::fixed_material_set_texture(RID p_material,SpatialMaterialParam p_parameter, RID p_texture) { VS_CHANGED; rasterizer->fixed_material_set_texture(p_material,p_parameter,p_texture); } -RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedSpatialMaterialParam p_parameter) const { +RID VisualServerRaster::fixed_material_get_texture(RID p_material,SpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texture(p_material,p_parameter); } @@ -425,12 +427,12 @@ RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedSpatialMa -void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter, FixedSpatialMaterialTexCoordMode p_mode) { +void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,SpatialMaterialParam p_parameter, SpatialMaterialTexCoordMode p_mode) { VS_CHANGED; rasterizer->fixed_material_set_texcoord_mode(p_material,p_parameter,p_mode); } -VS::FixedSpatialMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter) const { +VS::SpatialMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,SpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texcoord_mode(p_material,p_parameter); } @@ -457,14 +459,14 @@ Transform VisualServerRaster::fixed_material_get_uv_transform(RID p_material) co return rasterizer->fixed_material_get_uv_transform(p_material); } -void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedSpatialMaterialLightShader p_shader) { +void VisualServerRaster::fixed_material_set_light_shader(RID p_material,SpatialMaterialLightShader p_shader) { VS_CHANGED; rasterizer->fixed_material_set_light_shader(p_material,p_shader); } -VisualServerRaster::FixedSpatialMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ +VisualServerRaster::SpatialMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ return rasterizer->fixed_material_get_light_shader(p_material); } @@ -4521,7 +4523,7 @@ void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_po RID VisualServerRaster::canvas_item_material_create() { - Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial ); + Rasterizer::ShaderMaterial *material = memnew( Rasterizer::ShaderMaterial ); return canvas_item_material_owner.make_rid(material); } @@ -4529,7 +4531,7 @@ RID VisualServerRaster::canvas_item_material_create() { void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){ VS_CHANGED; - Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + Rasterizer::ShaderMaterial *material = canvas_item_material_owner.get( p_material ); ERR_FAIL_COND(!material); material->shader=p_shader; @@ -4537,7 +4539,7 @@ void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_s void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){ VS_CHANGED; - Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + Rasterizer::ShaderMaterial *material = canvas_item_material_owner.get( p_material ); ERR_FAIL_COND(!material); if (p_value.get_type()==Variant::NIL) material->shader_param.erase(p_param); @@ -4547,7 +4549,7 @@ void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, c } Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{ - Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + Rasterizer::ShaderMaterial *material = canvas_item_material_owner.get( p_material ); ERR_FAIL_COND_V(!material,Variant()); if (!material->shader_param.has(p_param)) { ERR_FAIL_COND_V(!material->shader.is_valid(),Variant()); @@ -4560,7 +4562,7 @@ Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material void VisualServerRaster::canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode) { VS_CHANGED; - Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + Rasterizer::ShaderMaterial *material = canvas_item_material_owner.get( p_material ); ERR_FAIL_COND(!material); material->shading_mode=p_mode; @@ -4869,7 +4871,7 @@ void VisualServerRaster::free( RID p_rid ) { } else if (canvas_item_material_owner.owns(p_rid)) { - Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid); + Rasterizer::ShaderMaterial *material = canvas_item_material_owner.get(p_rid); ERR_FAIL_COND(!material); for(Set<Rasterizer::CanvasItem*>::Element *E=material->owners.front();E;E=E->next()) { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 58e07057f2..a0d567e872 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -56,7 +56,7 @@ class VisualServerRaster : public VisualServer { }; - int changes; + static int changes; bool draw_extra_frame; RID test_cube; @@ -376,7 +376,7 @@ class VisualServerRaster : public VisualServer { - mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner; + mutable RID_Owner<Rasterizer::ShaderMaterial> canvas_item_material_owner; @@ -575,6 +575,8 @@ class VisualServerRaster : public VisualServer { #endif public: + _FORCE_INLINE_ static void redraw_request() { changes++; } + #define DISPLAY_CHANGED changes++; #define BIND0R(m_r, m_name) \ @@ -647,10 +649,7 @@ public: /* SHADER API */ - BIND1R(RID, shader_create, ShaderMode) - - BIND2(shader_set_mode, RID, ShaderMode) - BIND1RC(ShaderMode, shader_get_mode, RID) + BIND0R(RID, shader_create) BIND2(shader_set_code, RID, const String &) BIND1RC(String, shader_get_code, RID) @@ -855,16 +854,12 @@ public: BIND2(particles_set_gravity, RID, const Vector3 &) BIND2(particles_set_use_local_coordinates, RID, bool) BIND2(particles_set_process_material, RID, RID) - - BIND2(particles_set_emission_shape, RID, VS::ParticlesEmissionShape) - BIND2(particles_set_emission_sphere_radius, RID, float) - BIND2(particles_set_emission_box_extents, RID, const Vector3 &) - BIND2(particles_set_emission_points, RID, const PoolVector<Vector3> &) + BIND2(particles_set_fixed_fps, RID, int) + BIND2(particles_set_fractional_delta, RID, bool) BIND2(particles_set_draw_order, RID, VS::ParticlesDrawOrder) BIND2(particles_set_draw_passes, RID, int) - BIND3(particles_set_draw_pass_material, RID, int, RID) BIND3(particles_set_draw_pass_mesh, RID, int, RID) BIND1R(Rect3, particles_get_current_aabb, RID); diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 9b77ca9e1c..acaf5dc792 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -29,6 +29,7 @@ #include "visual_server_scene.h" #include "os/os.h" #include "visual_server_global.h" +#include "visual_server_raster.h" /* CAMERA API */ RID VisualServerScene::camera_create() { @@ -609,7 +610,8 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { } break; case VS::INSTANCE_MESH: case VS::INSTANCE_MULTIMESH: - case VS::INSTANCE_IMMEDIATE: { + case VS::INSTANCE_IMMEDIATE: + case VS::INSTANCE_PARTICLES: { InstanceGeometryData *geom = memnew(InstanceGeometryData); instance->base_data = geom; @@ -975,16 +977,6 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF switch (p_flags) { - case VS::INSTANCE_FLAG_BILLBOARD: { - - instance->billboard = p_enabled; - - } break; - case VS::INSTANCE_FLAG_BILLBOARD_FIX_Y: { - - instance->billboard_y = p_enabled; - - } break; case VS::INSTANCE_FLAG_CAST_SHADOW: { if (p_enabled == true) { instance->cast_shadows = VS::SHADOW_CASTING_SETTING_ON; @@ -995,11 +987,6 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceF instance->base_material_changed(); // to actually compute if shadows are visible or not } break; - case VS::INSTANCE_FLAG_DEPH_SCALE: { - - instance->depth_scale = p_enabled; - - } break; case VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS: { instance->visible_in_all_rooms = p_enabled; @@ -1050,6 +1037,11 @@ void VisualServerScene::_update_instance(Instance *p_instance) { reflection_probe->reflection_dirty = true; } + if (p_instance->base_type == VS::INSTANCE_PARTICLES) { + + VSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); + } + if (p_instance->aabb.has_no_surface()) return; @@ -1235,6 +1227,11 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) { new_aabb = VSG::storage->immediate_get_aabb(p_instance->base); } break; + case VisualServer::INSTANCE_PARTICLES: { + + new_aabb = VSG::storage->particles_get_aabb(p_instance->base); + + } break; #if 0 case VisualServer::INSTANCE_PARTICLES: { @@ -1914,6 +1911,13 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform, const Cam InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(ins->base_data); + if (ins->base_type == VS::INSTANCE_PARTICLES) { + //particles visible? process them + VSG::storage->particles_request_process(ins->base); + //particles visible? request redraw + VisualServerRaster::redraw_request(); + } + if (geom->lighting_dirty) { int l = 0; //only called when lights AABB enter/exit this geometry diff --git a/servers/visual_server.h b/servers/visual_server.h index dfa253ff25..d9a84697a4 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -153,10 +153,7 @@ public: SHADER_MAX }; - virtual RID shader_create(ShaderMode p_mode = SHADER_SPATIAL) = 0; - - virtual void shader_set_mode(RID p_shader, ShaderMode p_mode) = 0; - virtual ShaderMode shader_get_mode(RID p_shader) const = 0; + virtual RID shader_create() = 0; virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual String shader_get_code(RID p_shader) const = 0; @@ -485,19 +482,8 @@ public: virtual void particles_set_gravity(RID p_particles, const Vector3 &p_gravity) = 0; virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; - - enum ParticlesEmissionShape { - PARTICLES_EMSSION_POINT, - PARTICLES_EMSSION_SPHERE, - PARTICLES_EMSSION_BOX, - PARTICLES_EMSSION_POINTS, - PARTICLES_EMSSION_SEGMENTS, - }; - - virtual void particles_set_emission_shape(RID p_particles, ParticlesEmissionShape) = 0; - virtual void particles_set_emission_sphere_radius(RID p_particles, float p_radius) = 0; - virtual void particles_set_emission_box_extents(RID p_particles, const Vector3 &p_extents) = 0; - virtual void particles_set_emission_points(RID p_particles, const PoolVector<Vector3> &p_points) = 0; + virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; enum ParticlesDrawOrder { PARTICLES_DRAW_ORDER_INDEX, @@ -507,13 +493,7 @@ public: virtual void particles_set_draw_order(RID p_particles, ParticlesDrawOrder p_order) = 0; - enum ParticlesDrawPassMode { - PARTICLES_DRAW_PASS_MODE_QUAD, - PARTICLES_DRAW_PASS_MODE_MESH - }; - virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; - virtual void particles_set_draw_pass_material(RID p_particles, int p_pass, RID p_material) = 0; virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; virtual Rect3 particles_get_current_aabb(RID p_particles) = 0; @@ -689,7 +669,7 @@ public: INSTANCE_MAX, /*INSTANCE_BAKED_LIGHT_SAMPLER,*/ - INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) + INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES) }; virtual RID instance_create2(RID p_base, RID p_scenario); @@ -718,10 +698,7 @@ public: virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0; enum InstanceFlags { - INSTANCE_FLAG_BILLBOARD, - INSTANCE_FLAG_BILLBOARD_FIX_Y, INSTANCE_FLAG_CAST_SHADOW, - INSTANCE_FLAG_DEPH_SCALE, INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, INSTANCE_FLAG_USE_BAKED_LIGHT, INSTANCE_FLAG_MAX |