diff options
42 files changed, 1487 insertions, 340 deletions
diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 130fca1b2a..3cf4ff8f83 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -476,7 +476,6 @@ static _GlobalConstant _global_constants[]={ BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ), - BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_STORAGE ), BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_EDITOR ), BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_NETWORK ), BIND_GLOBAL_CONSTANT( PROPERTY_USAGE_DEFAULT ), diff --git a/core/vector.h b/core/vector.h index 16a09c1ddd..87248ccf68 100644 --- a/core/vector.h +++ b/core/vector.h @@ -70,7 +70,8 @@ class Vector { } _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const { - return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); + //return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); + return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int)); } _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { @@ -79,7 +80,7 @@ class Vector { size_t p; if (_mul_overflow(p_elements, sizeof(T), &o)) return false; if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false; - *out = nearest_power_of_2_templated(p); + *out = nearest_power_of_2(p); return true; #else // Speed is more important than correctness here, do the operations unchecked diff --git a/demos/3d/inverse_kinematics/engine.cfg b/demos/3d/inverse_kinematics/engine.cfg new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/demos/3d/inverse_kinematics/engine.cfg diff --git a/demos/3d/inverse_kinematics/main.scn b/demos/3d/inverse_kinematics/main.scn Binary files differnew file mode 100644 index 0000000000..918fd09a3a --- /dev/null +++ b/demos/3d/inverse_kinematics/main.scn diff --git a/doc/base/classes.xml b/doc/base/classes.xml index b6457f0d89..23b699ecb0 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<doc version="2.0.stable.custom_build" name="Engine Types"> +<doc version="2.1.alpha.custom_build" name="Engine Types"> <class name="@GDScript" category="Core"> <brief_description> Built-in GDScript functions. @@ -591,7 +591,7 @@ <method name="hash"> <return type="int"> </return> - <argument index="0" name="Variant" type="Variant"> + <argument index="0" name="var:Variant" type="Variant"> </argument> <description> Hash the variable passed and return an integer. @@ -638,7 +638,7 @@ </description> </method> <method name="yield"> - <return type="Object"> + <return type="Nil"> </return> <argument index="0" name="object" type="Object"> </argument> @@ -5149,6 +5149,42 @@ <description> </description> </method> + <method name="set_realtime_color_enabled"> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_realtime_color_enabled" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_realtime_color"> + <argument index="0" name="tint" type="Color"> + </argument> + <description> + </description> + </method> + <method name="get_realtime_color" qualifiers="const"> + <return type="Color"> + </return> + <description> + </description> + </method> + <method name="set_realtime_energy"> + <argument index="0" name="energy" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_realtime_energy" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> <method name="set_format"> <argument index="0" name="format" type="int"> </argument> @@ -5506,6 +5542,12 @@ Base class for Box containers. It arranges children controls vertically or horizontally, and rearranges them automatically when their minimum size changes. </description> <methods> + <method name="add_spacer"> + <argument index="0" name="begin" type="bool"> + </argument> + <description> + </description> + </method> <method name="get_alignment" qualifiers="const"> <return type="int"> </return> @@ -10074,7 +10116,9 @@ Returns an empty String "" at the end of the list. </constant> <constant name="MODE_OPEN_DIR" value="2"> </constant> - <constant name="MODE_SAVE_FILE" value="3"> + <constant name="MODE_OPEN_ANY" value="3"> + </constant> + <constant name="MODE_SAVE_FILE" value="4"> </constant> <constant name="ACCESS_RESOURCES" value="0"> </constant> @@ -11756,7 +11800,9 @@ Returns an empty String "" at the end of the list. <constant name="MODE_OPEN_DIR" value="2"> The dialog functions as a folder selector, disallowing the selection of any file. </constant> - <constant name="MODE_SAVE_FILE" value="3"> + <constant name="MODE_OPEN_ANY" value="3"> + </constant> + <constant name="MODE_SAVE_FILE" value="4"> The dialog will warn when a file exists. </constant> <constant name="ACCESS_RESOURCES" value="0"> @@ -12646,6 +12692,18 @@ Returns an empty String "" at the end of the list. <description> </description> </method> + <method name="set_cast_shadows_setting"> + <argument index="0" name="shadow_casting_setting" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_cast_shadows_setting" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> <method name="set_draw_range_begin"> <argument index="0" name="mode" type="float"> </argument> @@ -12712,6 +12770,14 @@ Returns an empty String "" at the end of the list. </constant> <constant name="FLAG_MAX" value="8"> </constant> + <constant name="SHADOW_CASTING_SETTING_OFF" value="0"> + </constant> + <constant name="SHADOW_CASTING_SETTING_ON" value="1"> + </constant> + <constant name="SHADOW_CASTING_SETTING_DOUBLE_SIDED" value="2"> + </constant> + <constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3"> + </constant> </constants> </class> <class name="Globals" inherits="Object" category="Core"> @@ -14035,6 +14101,134 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) </constant> </constants> </class> +<class name="HTTPRequest" inherits="Node" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="request"> + <return type="int"> + </return> + <argument index="0" name="url" type="String"> + </argument> + <argument index="1" name="custom_headers" type="StringArray" default="StringArray()"> + </argument> + <argument index="2" name="ssl_validate_domain" type="bool" default="true"> + </argument> + <description> + </description> + </method> + <method name="cancel_request"> + <description> + </description> + </method> + <method name="get_http_client_status" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_use_threads"> + <argument index="0" name="enable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_using_threads" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="set_body_size_limit"> + <argument index="0" name="bytes" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_body_size_limit" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_max_redirects"> + <argument index="0" name="amount" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_max_redirects" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_download_file"> + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_download_file" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_downloaded_bytes" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_body_size" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <signals> + <signal name="request_completed"> + <argument index="0" name="result" type="int"> + </argument> + <argument index="1" name="response_code" type="int"> + </argument> + <argument index="2" name="headers" type="StringArray"> + </argument> + <argument index="3" name="body" type="RawArray"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + <constant name="RESULT_SUCCESS" value="0"> + </constant> + <constant name="RESULT_CHUNKED_BODY_SIZE_MISMATCH" value="1"> + </constant> + <constant name="RESULT_CANT_CONNECT" value="2"> + </constant> + <constant name="RESULT_CANT_RESOLVE" value="3"> + </constant> + <constant name="RESULT_CONNECTION_ERROR" value="4"> + </constant> + <constant name="RESULT_SSL_HANDSHAKE_ERROR" value="5"> + </constant> + <constant name="RESULT_NO_RESPONSE" value="6"> + </constant> + <constant name="RESULT_BODY_SIZE_LIMIT_EXCEEDED" value="7"> + </constant> + <constant name="RESULT_REQUEST_FAILED" value="8"> + </constant> + <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="11"> + </constant> + <constant name="RESULT_DOWNLOAD_FILE_WRITE_ERROR" value="10"> + </constant> + </constants> +</class> <class name="HingeJoint" inherits="Joint" category="Core"> <brief_description> </brief_description> @@ -15846,6 +16040,76 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <constants> </constants> </class> +<class name="InverseKinematics" inherits="Spatial" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_bone_name"> + <argument index="0" name="ik_bone" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_bone_name" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="set_iterations"> + <argument index="0" name="iterations" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_iterations" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_chain_size"> + <argument index="0" name="chain_size" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_chain_size" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="set_precision"> + <argument index="0" name="precision" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_precision" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> + <method name="set_speed"> + <argument index="0" name="speed" type="float"> + </argument> + <description> + </description> + </method> + <method name="get_speed" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> <class name="ItemList" inherits="Control" category="Core"> <brief_description> </brief_description> @@ -15902,6 +16166,22 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <description> </description> </method> + <method name="set_item_icon_region"> + <argument index="0" name="idx" type="int"> + </argument> + <argument index="1" name="rect" type="Rect2"> + </argument> + <description> + </description> + </method> + <method name="get_item_icon_region" qualifiers="const"> + <return type="Rect2"> + </return> + <argument index="0" name="idx" type="int"> + </argument> + <description> + </description> + </method> <method name="set_item_selectable"> <argument index="0" name="idx" type="int"> </argument> @@ -17423,6 +17703,56 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <constants> </constants> </class> +<class name="LinkButton" inherits="BaseButton" category="Core"> + <brief_description> + </brief_description> + <description> + </description> + <methods> + <method name="set_text"> + <argument index="0" name="text" type="String"> + </argument> + <description> + </description> + </method> + <method name="get_text" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="set_underline_mode"> + <argument index="0" name="underline_mode" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_underline_mode" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + </methods> + <constants> + <constant name="UNDERLINE_MODE_ALWAYS" value="0"> + </constant> + <constant name="UNDERLINE_MODE_ON_HOVER" value="1"> + </constant> + </constants> + <theme_items> + <theme_item name="underline_spacing" type="int"> + </theme_item> + <theme_item name="font_color" type="Color"> + </theme_item> + <theme_item name="font_color_hover" type="Color"> + </theme_item> + <theme_item name="font_color_pressed" type="Color"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + </theme_items> +</class> <class name="MainLoop" inherits="Object" category="Core"> <brief_description> Main loop is the abstract main loop base class. @@ -19650,7 +19980,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <argument index="2" name="owned" type="bool" default="true"> </argument> <description> - Find a descendant of this node whose name matches [code]mask[/code] as in [method String.match] (i.e. case sensitive, but '*' matches zero or more characters and '?' matches any single character except '.'). Note that it does not match against the full path, just against individual node names. + Find a descendant of this node whose name matches [code]mask[/code] as in [method String.match] (i.e. case sensitive, but '*' matches zero or more characters and '?' matches any single character except '.'). Note that it does not match against the full path, just against individual node names. </description> </method> <method name="has_node_and_resource" qualifiers="const"> @@ -20444,6 +20774,18 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <description> </description> </method> + <method name="set_borderless_window"> + <argument index="0" name="borderless" type="bool"> + </argument> + <description> + </description> + </method> + <method name="get_borderless_window" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="set_screen_orientation"> <argument index="0" name="orientation" type="int"> </argument> @@ -20624,24 +20966,22 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) Return the main loop object (see [MainLoop]). </description> </method> - <method name="get_date" qualifiers="const"> + <method name="get_datetime" qualifiers="const"> <return type="Dictionary"> </return> <argument index="0" name="utc" type="bool" default="false"> </argument> <description> - Returns current date in a dictionary of keys: year, month, - day, weekday, dst (daylight savings time). + Returns current datetime as a dictionary of keys: year, month, day, weekday, dst (daylight savings time), hour, minute, second. </description> </method> - <method name="get_datetime" qualifiers="const"> + <method name="get_date" qualifiers="const"> <return type="Dictionary"> </return> <argument index="0" name="utc" type="bool" default="false"> </argument> <description> - Returns current datetime in a dictionary of keys: year, - month, day, weekday, dst (daylight savings time), hour, minute, second + Returns current date as a dictionary of keys: year, month, day, weekday, dst (daylight savings time). </description> </method> <method name="get_time" qualifiers="const"> @@ -20650,48 +20990,40 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8) <argument index="0" name="utc" type="bool" default="false"> </argument> <description> - Returns current time in a dictionary of keys: - hour, minute, second + Returns current time as a dictionary of keys: hour, minute, second </description> </method> - <method name="get_datetime_from_unix_time" qualifiers="const"> + <method name="get_time_zone_info" qualifiers="const"> <return type="Dictionary"> </return> - <argument index="0" name="unix_time_val" type="int"> - </argument> <description> - Get a dictionary of time values when given epoch time. - Dictionary Time values will be a union of values from [method get_time] - and [method get_date] dictionaries (with the exception of dst = - day light standard time, as it cannot be determined from epoc) </description> </method> - <method name="get_unix_time_from_datetime" qualifiers="const"> + <method name="get_unix_time" qualifiers="const"> <return type="int"> </return> - <argument index="0" name="datetime" type="Dictionary"> - </argument> <description> - Get an epoch time value from a dictionary of time values - datetime must be populated with the following keys: - day, hour, minute, month, second, year. You can pass the output from - [method get_datetime_from_unix_time] directly into this function. Day - light savings time (dst), if present, is ignored. - - To be accurate, datetime dictionary must have keys for: year, month, day, - hour, minute, second </description> </method> - <method name="get_time_zone_info" qualifiers="const"> + <method name="get_datetime_from_unix_time" qualifiers="const"> <return type="Dictionary"> </return> + <argument index="0" name="unix_time_val" type="int"> + </argument> <description> + Get a dictionary of time values when given epoch time. + Dictionary Time values will be a union of values from [method get_time] and [method get_date] dictionaries (with the exception of dst = day light standard time, as it cannot be determined from epoch). </description> </method> - <method name="get_unix_time" qualifiers="const"> + <method name="get_unix_time_from_datetime" qualifiers="const"> <return type="int"> </return> + <argument index="0" name="datetime" type="Dictionary"> + </argument> <description> + Get an epoch time value from a dictionary of time values. + [code]datetime[/code] must be populated with the following keys: year, month, day, hour, minute, second. + You can pass the output from [method get_datetime_from_unix_time] directly into this function. Daylight savings time (dst), if present, is ignored. </description> </method> <method name="get_system_time_secs" qualifiers="const"> @@ -29430,6 +29762,10 @@ This method controls whether the position between two cached points is interpola <description> </description> </signal> + <signal name="sleeping_state_changed"> + <description> + </description> + </signal> </signals> <constants> <constant name="MODE_STATIC" value="1"> @@ -29779,6 +30115,10 @@ This method controls whether the position between two cached points is interpola This signal not only receives the body that stopped colliding with this one, but also its [RID] (body_id), the shape index from the colliding body (body_shape), and the shape index from this body (local_shape) the other body stopped colliding with. </description> </signal> + <signal name="sleeping_state_changed"> + <description> + </description> + </signal> </signals> <constants> <constant name="MODE_STATIC" value="1"> @@ -34503,14 +34843,14 @@ This method controls whether the position between two cached points is interpola </description> <methods> <method name="set_stream"> - <argument index="0" name="stream" type="Stream"> + <argument index="0" name="stream" type="AudioStream"> </argument> <description> Set the [EventStream] this player will play. </description> </method> <method name="get_stream" qualifiers="const"> - <return type="Stream"> + <return type="AudioStream"> </return> <description> Return the currently assigned stream. @@ -37721,6 +38061,18 @@ This method controls whether the position between two cached points is interpola Stop (cancel) the timer. </description> </method> + <method name="set_active"> + <argument index="0" name="active" type="bool"> + </argument> + <description> + </description> + </method> + <method name="is_active" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> <method name="get_time_left" qualifiers="const"> <return type="float"> </return> diff --git a/drivers/nrex/README.md b/drivers/nrex/README.md index 9ff67992dc..7a942b2452 100644 --- a/drivers/nrex/README.md +++ b/drivers/nrex/README.md @@ -1,6 +1,8 @@ # NREX: Node RegEx -Version 0.1 +[](https://travis-ci.org/leezh/nrex) + +** Version 0.2 ** Small node-based regular expression library. It only does text pattern matchhing, not replacement. To use add the files `nrex.hpp`, `nrex.cpp` @@ -38,7 +40,7 @@ Currently supported features: ## License -Copyright (c) 2015, Zher Huei Lee +Copyright (c) 2015-2016, Zher Huei Lee All rights reserved. This software is provided 'as-is', without any express or implied @@ -59,3 +61,15 @@ freely, subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. + + +# Changes + +## Version 0.2 (2016-08-04) + * Fixed capturing groups matching to invalid results + * Fixed parents of recursive quantifiers not expanding properly + * Fixed LookAhead sometimes adding to result + * More verbose unit testing + +## Version 0.1 (2015-12-04) + * Initial release diff --git a/drivers/nrex/nrex.cpp b/drivers/nrex/nrex.cpp index 1eb9ec38c8..ac19c71408 100644 --- a/drivers/nrex/nrex.cpp +++ b/drivers/nrex/nrex.cpp @@ -1,7 +1,7 @@ // NREX: Node RegEx -// Version 0.1 +// Version 0.2 // -// Copyright (c) 2015, Zher Huei Lee +// Copyright (c) 2015-2016, Zher Huei Lee // All rights reserved. // // This software is provided 'as-is', without any express or implied @@ -68,6 +68,13 @@ class nrex_array { } + nrex_array(unsigned int size) + : _data(NREX_NEW_ARRAY(T, size)) + , _reserved(size) + , _size(0) + { + } + ~nrex_array() { NREX_DELETE_ARRAY(_data); @@ -100,7 +107,7 @@ class nrex_array _size++; } - T& top() + const T& top() const { return _data[_size - 1]; } @@ -189,17 +196,19 @@ struct nrex_search nrex_result* captures; int end; bool complete; + nrex_array<int> lookahead_pos; nrex_char at(int pos) { return str[pos]; } - nrex_search(const nrex_char* str, nrex_result* captures) + nrex_search(const nrex_char* str, nrex_result* captures, int lookahead) : str(str) , captures(captures) , end(0) { + lookahead_pos.reserve(lookahead); } }; @@ -239,13 +248,17 @@ struct nrex_node { pos = next->test(s, pos); } + if (pos >= 0) + { + s->complete = true; + } if (parent && pos >= 0) { pos = parent->test_parent(s, pos); } - if (pos >= 0) + if (pos < 0) { - s->complete = true; + s->complete = false; } return pos; } @@ -274,25 +287,31 @@ struct nrex_node } }; -struct nrex_node_group : public nrex_node +enum nrex_group_type { - static const int NonCapture = -1; - static const int Bracket = -2; - static const int LookAhead = -3; - static const int LookBehind = -4; + nrex_group_capture, + nrex_group_non_capture, + nrex_group_bracket, + nrex_group_look_ahead, + nrex_group_look_behind, +}; - int mode; +struct nrex_node_group : public nrex_node +{ + nrex_group_type type; + int id; bool negate; nrex_array<nrex_node*> childset; nrex_node* back; - nrex_node_group(int mode) + nrex_node_group(nrex_group_type type, int id = 0) : nrex_node(true) - , mode(mode) + , type(type) + , id(id) , negate(false) , back(NULL) { - if (mode != Bracket) + if (type != nrex_group_bracket) { length = 0; } @@ -300,7 +319,7 @@ struct nrex_node_group : public nrex_node { length = 1; } - if (mode == LookAhead || mode == LookBehind) + if (type == nrex_group_look_ahead || type == nrex_group_look_behind) { quantifiable = false; } @@ -317,15 +336,17 @@ struct nrex_node_group : public nrex_node int test(nrex_search* s, int pos) const { - if (mode >= 0) + int old_start; + if (type == nrex_group_capture) { - s->captures[mode].start = pos; + old_start = s->captures[id].start; + s->captures[id].start = pos; } for (unsigned int i = 0; i < childset.size(); ++i) { s->complete = false; int offset = 0; - if (mode == LookBehind) + if (type == nrex_group_look_behind) { if (pos < length) { @@ -333,7 +354,15 @@ struct nrex_node_group : public nrex_node } offset = length; } + if (type == nrex_group_look_ahead) + { + s->lookahead_pos.push(pos); + } int res = childset[i]->test(s, pos - offset); + if (type == nrex_group_look_ahead) + { + s->lookahead_pos.pop(); + } if (s->complete) { return res; @@ -355,32 +384,40 @@ struct nrex_node_group : public nrex_node } if (res >= 0) { - if (mode >= 0) + if (type == nrex_group_capture) { - s->captures[mode].length = res - pos; + s->captures[id].length = res - pos; } - else if (mode == LookAhead || mode == LookBehind) + else if (type == nrex_group_look_ahead || type == nrex_group_look_behind) { res = pos; } return next ? next->test(s, res) : res; } } + if (type == nrex_group_capture) + { + s->captures[id].start = old_start; + } return -1; } virtual int test_parent(nrex_search* s, int pos) const { - if (mode >= 0) + if (type == nrex_group_capture) + { + s->captures[id].length = pos - s->captures[id].start; + } + if (type == nrex_group_look_ahead) { - s->captures[mode].length = pos - s->captures[mode].start; + pos = s->lookahead_pos[id]; } return nrex_node::test_parent(s, pos); } void add_childset() { - if (childset.size() > 0 && mode != Bracket) + if (childset.size() > 0 && type != nrex_group_bracket) { length = -1; } @@ -391,7 +428,7 @@ struct nrex_node_group : public nrex_node { node->parent = this; node->previous = back; - if (back && mode != Bracket) + if (back && type != nrex_group_bracket) { back->next = node; } @@ -399,7 +436,7 @@ struct nrex_node_group : public nrex_node { childset.push(node); } - if (mode != Bracket) + if (type != nrex_group_bracket) { increment_length(node->length); } @@ -418,7 +455,7 @@ struct nrex_node_group : public nrex_node { childset.pop(); } - if (mode != Bracket) + if (type != nrex_group_bracket) { increment_length(old->length, true); } @@ -436,7 +473,7 @@ struct nrex_node_group : public nrex_node { childset.pop(); } - if (mode != Bracket) + if (type != nrex_group_bracket) { increment_length(old->length, true); } @@ -887,6 +924,12 @@ struct nrex_node_quantifier : public nrex_node } return -1; } + + virtual int test_parent(nrex_search* s, int pos) const + { + s->complete = false; + return pos; + } }; struct nrex_node_anchor : public nrex_node @@ -986,7 +1029,7 @@ bool nrex_has_lookbehind(nrex_array<nrex_node_group*>& stack) { for (unsigned int i = 0; i < stack.size(); i++) { - if (stack[i]->mode == nrex_node_group::LookBehind) + if (stack[i]->type == nrex_group_look_behind) { return true; } @@ -996,12 +1039,14 @@ bool nrex_has_lookbehind(nrex_array<nrex_node_group*>& stack) nrex::nrex() : _capturing(0) + , _lookahead_depth(0) , _root(NULL) { } nrex::nrex(const nrex_char* pattern, int captures) : _capturing(0) + , _lookahead_depth(0) , _root(NULL) { compile(pattern, captures); @@ -1023,6 +1068,7 @@ bool nrex::valid() const void nrex::reset() { _capturing = 0; + _lookahead_depth = 0; if (_root) { NREX_DELETE(_root); @@ -1042,9 +1088,10 @@ int nrex::capture_size() const bool nrex::compile(const nrex_char* pattern, int captures) { reset(); - nrex_node_group* root = NREX_NEW(nrex_node_group(_capturing)); + nrex_node_group* root = NREX_NEW(nrex_node_group(nrex_group_capture, _capturing)); nrex_array<nrex_node_group*> stack; stack.push(root); + unsigned int lookahead_level = 0; _root = root; for (const nrex_char* c = pattern; c[0] != '\0'; ++c) @@ -1056,22 +1103,26 @@ bool nrex::compile(const nrex_char* pattern, int captures) if (c[2] == ':') { c = &c[2]; - nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::NonCapture)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_non_capture)); stack.top()->add_child(group); stack.push(group); } else if (c[2] == '!' || c[2] == '=') { c = &c[2]; - nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::LookAhead)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_look_ahead, lookahead_level++)); group->negate = (c[0] == '!'); stack.top()->add_child(group); stack.push(group); + if (lookahead_level > _lookahead_depth) + { + _lookahead_depth = lookahead_level; + } } else if (c[2] == '<' && (c[3] == '!' || c[3] == '=')) { c = &c[3]; - nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::LookBehind)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_look_behind)); group->negate = (c[0] == '!'); stack.top()->add_child(group); stack.push(group); @@ -1083,13 +1134,13 @@ bool nrex::compile(const nrex_char* pattern, int captures) } else if (captures >= 0 && _capturing < captures) { - nrex_node_group* group = NREX_NEW(nrex_node_group(++_capturing)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_capture, ++_capturing)); stack.top()->add_child(group); stack.push(group); } else { - nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::NonCapture)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_non_capture)); stack.top()->add_child(group); stack.push(group); } @@ -1098,6 +1149,10 @@ bool nrex::compile(const nrex_char* pattern, int captures) { if (stack.size() > 1) { + if (stack.top()->type == nrex_group_look_ahead) + { + --lookahead_level; + } stack.pop(); } else @@ -1107,7 +1162,7 @@ bool nrex::compile(const nrex_char* pattern, int captures) } else if (c[0] == '[') { - nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::Bracket)); + nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_group_bracket)); stack.top()->add_child(group); if (c[1] == '^') { @@ -1410,7 +1465,7 @@ bool nrex::match(const nrex_char* str, nrex_result* captures, int offset, int en { return false; } - nrex_search s(str, captures); + nrex_search s(str, captures, _lookahead_depth); if (end >= offset) { s.end = end; diff --git a/drivers/nrex/nrex.hpp b/drivers/nrex/nrex.hpp index 44e950c517..d30b7d0102 100644 --- a/drivers/nrex/nrex.hpp +++ b/drivers/nrex/nrex.hpp @@ -1,7 +1,7 @@ // NREX: Node RegEx -// Version 0.1 +// Version 0.2 // -// Copyright (c) 2015, Zher Huei Lee +// Copyright (c) 2015-2016, Zher Huei Lee // All rights reserved. // // This software is provided 'as-is', without any express or implied @@ -57,7 +57,8 @@ class nrex_node; class nrex { private: - int _capturing; + unsigned int _capturing; + unsigned int _lookahead_depth; nrex_node* _root; public: diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index e8e8ce4e96..d38f5f3e35 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -1421,7 +1421,22 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars if (path.is_rel_path()) { - String base = p_script->get_path(); + String base; + + if (p_owner) { + GDScript *current_class = p_owner; + while (current_class != NULL) { + base=current_class->get_path(); + if (base=="") + current_class = current_class->_owner; + else + break; + } + } + else { + base = p_script->get_path(); + } + if (base=="" || base.is_rel_path()) { _set_error("Could not resolve relative path for parent class: "+path,p_class); return ERR_FILE_NOT_FOUND; diff --git a/modules/ik/SCsub b/modules/ik/SCsub new file mode 100644 index 0000000000..211a043468 --- /dev/null +++ b/modules/ik/SCsub @@ -0,0 +1,3 @@ +Import('env') + +env.add_source_files(env.modules_sources,"*.cpp") diff --git a/modules/ik/config.py b/modules/ik/config.py new file mode 100644 index 0000000000..f9bd7da08d --- /dev/null +++ b/modules/ik/config.py @@ -0,0 +1,11 @@ + + +def can_build(platform): + return True + + +def configure(env): + pass + + + diff --git a/modules/ik/ik.cpp b/modules/ik/ik.cpp new file mode 100644 index 0000000000..6c383fdb55 --- /dev/null +++ b/modules/ik/ik.cpp @@ -0,0 +1,326 @@ +/*************************************************************************/ +/* ik.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* This file is Copyright (c) 2016 Sergey Lapin <slapinid@gmail.com> */ +/* */ +/* 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 "ik.h" + +bool InverseKinematics::_get(const StringName& p_name,Variant &r_ret) const +{ + + if (String(p_name)=="ik_bone") { + + r_ret=get_bone_name(); + return true; + } + + return false; +} + +bool InverseKinematics::_set(const StringName& p_name, const Variant& p_value) +{ + + if (String(p_name)=="ik_bone") { + + set_bone_name(p_value); + changed = true; + return true; + } + + return false; +} + +void InverseKinematics::_get_property_list( List<PropertyInfo>* p_list ) const +{ + + Skeleton *parent=NULL; + if(get_parent()) + parent=get_parent()->cast_to<Skeleton>(); + + if (parent) { + + String names; + for(int i=0;i<parent->get_bone_count();i++) { + if(i>0) + names+=","; + names+=parent->get_bone_name(i); + } + + p_list->push_back(PropertyInfo(Variant::STRING,"ik_bone",PROPERTY_HINT_ENUM,names)); + } else { + + p_list->push_back(PropertyInfo(Variant::STRING,"ik_bone")); + + } + +} + +void InverseKinematics::_check_bind() +{ + + if (get_parent() && get_parent()->cast_to<Skeleton>()) { + Skeleton *sk = get_parent()->cast_to<Skeleton>(); + int idx = sk->find_bone(ik_bone); + if (idx!=-1) { + ik_bone_no = idx; + bound=true; + } + skel = sk; + } +} + +void InverseKinematics::_check_unbind() +{ + + if (bound) { + + if (get_parent() && get_parent()->cast_to<Skeleton>()) { + Skeleton *sk = get_parent()->cast_to<Skeleton>(); + int idx = sk->find_bone(ik_bone); + if (idx!=-1) + ik_bone_no = idx; + else + ik_bone_no = 0; + skel = sk; + + } + bound=false; + } +} + + +void InverseKinematics::set_bone_name(const String& p_name) +{ + + if (is_inside_tree()) + _check_unbind(); + + ik_bone=p_name; + + if (is_inside_tree()) + _check_bind(); + changed = true; +} + +String InverseKinematics::get_bone_name() const +{ + + return ik_bone; +} + +void InverseKinematics::set_iterations(int itn) +{ + + if (is_inside_tree()) + _check_unbind(); + + iterations=itn; + + if (is_inside_tree()) + _check_bind(); + changed = true; +} + +int InverseKinematics::get_iterations() const +{ + + return iterations; +} + +void InverseKinematics::set_chain_size(int cs) +{ + if (is_inside_tree()) + _check_unbind(); + + chain_size=cs; + chain.clear(); + if (bound) + update_parameters(); + + if (is_inside_tree()) + _check_bind(); + changed = true; +} + +int InverseKinematics::get_chain_size() const +{ + + return chain_size; +} + +void InverseKinematics::set_precision(float p) +{ + + if (is_inside_tree()) + _check_unbind(); + + precision=p; + + if (is_inside_tree()) + _check_bind(); + changed = true; +} + +float InverseKinematics::get_precision() const +{ + + return precision; +} + +void InverseKinematics::set_speed(float p) +{ + + if (is_inside_tree()) + _check_unbind(); + + speed=p; + + if (is_inside_tree()) + _check_bind(); + changed = true; +} + +float InverseKinematics::get_speed() const +{ + + return speed; +} + +void InverseKinematics::update_parameters() +{ + tail_bone = -1; + for (int i = 0; i < skel->get_bone_count(); i++) + if (skel->get_bone_parent(i) == ik_bone_no) + tail_bone = i; + int cur_bone = ik_bone_no; + int its = chain_size; + while (its > 0 && cur_bone >= 0) { + chain.push_back(cur_bone); + cur_bone = skel->get_bone_parent(cur_bone); + its--; + } +} + +void InverseKinematics::_notification(int p_what) +{ + + switch(p_what) { + + case NOTIFICATION_ENTER_TREE: { + + _check_bind(); + if (bound) { + update_parameters(); + changed = false; + set_process(true); + } + } break; + case NOTIFICATION_PROCESS: { + float delta = get_process_delta_time(); + Spatial *sksp = skel->cast_to<Spatial>(); + if (!bound) + break; + if (!sksp) + break; + if (changed) { + update_parameters(); + changed = false; + } + Vector3 to = get_translation(); + for (int hump = 0; hump < iterations; hump++) { + int depth = 0; + float olderr = 1000.0; + float psign = 1.0; + bool reached = false; + + for (List<int>::Element *b = chain.front(); b; b = b->next()) { + int cur_bone = b->get(); + Vector3 d = skel->get_bone_global_pose(tail_bone).origin; + Vector3 rg = to; + float err = d.distance_squared_to(rg); + if (err < precision) { + if (!reached && err < precision) + reached = true; + break; + } else + if (reached) + reached = false; + if (err > olderr) + psign = -psign; + Transform mod = skel->get_bone_global_pose(cur_bone); + Quat q1 = Quat(mod.basis).normalized(); + Transform mod2 = mod.looking_at(to, Vector3(0.0, 1.0, 0.0)); + Quat q2 = Quat(mod2.basis).normalized(); + if (psign < 0.0) + q2 = q2.inverse(); + Quat q = q1.slerp(q2, speed / (1.0 + 500.0 * depth)).normalized(); + Transform fin = Transform(q); + fin.origin = mod.origin; + skel->set_bone_global_pose(cur_bone, fin); + depth++; + } + if (reached) + break; + + } + + } break; + case NOTIFICATION_EXIT_TREE: { + set_process(false); + + _check_unbind(); + } break; + } +} +void InverseKinematics::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_bone_name","ik_bone"),&InverseKinematics::set_bone_name); + ObjectTypeDB::bind_method(_MD("get_bone_name"),&InverseKinematics::get_bone_name); + ObjectTypeDB::bind_method(_MD("set_iterations","iterations"),&InverseKinematics::set_iterations); + ObjectTypeDB::bind_method(_MD("get_iterations"),&InverseKinematics::get_iterations); + ObjectTypeDB::bind_method(_MD("set_chain_size","chain_size"),&InverseKinematics::set_chain_size); + ObjectTypeDB::bind_method(_MD("get_chain_size"),&InverseKinematics::get_chain_size); + ObjectTypeDB::bind_method(_MD("set_precision","precision"),&InverseKinematics::set_precision); + ObjectTypeDB::bind_method(_MD("get_precision"),&InverseKinematics::get_precision); + ObjectTypeDB::bind_method(_MD("set_speed","speed"),&InverseKinematics::set_speed); + ObjectTypeDB::bind_method(_MD("get_speed"),&InverseKinematics::get_speed); + ADD_PROPERTY(PropertyInfo(Variant::INT, "iterations"), _SCS("set_iterations"), _SCS("get_iterations")); + ADD_PROPERTY(PropertyInfo(Variant::INT, "chain_size"), _SCS("set_chain_size"), _SCS("get_chain_size")); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "precision"), _SCS("set_precision"), _SCS("get_precision")); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed"), _SCS("set_speed"), _SCS("get_speed")); +} + +InverseKinematics::InverseKinematics() +{ + bound=false; + chain_size = 2; + iterations = 100; + precision = 0.001; + speed = 0.2; + +} + diff --git a/modules/ik/ik.h b/modules/ik/ik.h new file mode 100644 index 0000000000..9daddb229d --- /dev/null +++ b/modules/ik/ik.h @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* ik.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* This file is (c) 2016 Sergey Lapin <slapinid@gmail.com> */ +/* */ +/* 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 IK_H +#define IK_H + +#include "scene/3d/skeleton.h" +class InverseKinematics : public Spatial { + OBJ_TYPE(InverseKinematics, Spatial); + bool bound; + String ik_bone; + int ik_bone_no; + int tail_bone; + int chain_size; + Skeleton *skel; + List<int> chain; + void _check_bind(); + void _check_unbind(); + int iterations; + float precision; + float speed; + bool changed; + +protected: + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + + void _notification(int p_what); + static void _bind_methods(); + void update_parameters(); +public: + Skeleton *get_skeleton(); + void set_bone_name(const String& p_name); + String get_bone_name() const; + void set_iterations(int itn); + int get_iterations() const; + void set_chain_size(int cs); + int get_chain_size() const; + void set_precision(float p); + float get_precision() const; + void set_speed(float p); + float get_speed() const; + InverseKinematics(); +}; + +#endif + diff --git a/modules/ik/register_types.cpp b/modules/ik/register_types.cpp new file mode 100644 index 0000000000..e7df7f55b2 --- /dev/null +++ b/modules/ik/register_types.cpp @@ -0,0 +1,47 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* 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. */ +/*************************************************************************/ +#include "register_types.h" +#ifndef _3D_DISABLED +#include "object_type_db.h" +#include "ik.h" +#endif + +void register_ik_types() { + +#ifndef _3D_DISABLED + ObjectTypeDB::register_type<InverseKinematics>(); +#endif +} + + + +void unregister_ik_types() { + + +} diff --git a/modules/ik/register_types.h b/modules/ik/register_types.h new file mode 100644 index 0000000000..828917ade7 --- /dev/null +++ b/modules/ik/register_types.h @@ -0,0 +1,30 @@ +/*************************************************************************/ +/* register_types.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. */ +/*************************************************************************/ +void register_ik_types(); +void unregister_ik_types(); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index cc2e5c0d72..dc038f010c 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -544,7 +544,10 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { set_global_transform(state->get_transform()); linear_velocity=state->get_linear_velocity(); angular_velocity=state->get_angular_velocity(); - sleeping=state->is_sleeping(); + if(sleeping!=state->is_sleeping()) { + sleeping=state->is_sleeping(); + emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed); + } if (get_script_instance()) get_script_instance()->call("_integrate_forces",state); set_block_transform_notify(false); // want it back @@ -934,6 +937,7 @@ void RigidBody2D::_bind_methods() { ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body"))); ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body"))); + ADD_SIGNAL( MethodInfo("sleeping_state_changed")); BIND_CONSTANT( MODE_STATIC ); BIND_CONSTANT( MODE_KINEMATIC ); diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 4a774b0198..6cda52fa4e 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -33,7 +33,7 @@ void RayCast2D::set_cast_to(const Vector2& p_point) { cast_to=p_point; - if (is_inside_tree() && get_tree()->is_editor_hint()) + if (is_inside_tree() && (get_tree()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) update(); } diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 1a2665b6ad..bc637eed44 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -419,7 +419,10 @@ void RigidBody::_direct_state_changed(Object *p_state) { set_global_transform(state->get_transform()); linear_velocity=state->get_linear_velocity(); angular_velocity=state->get_angular_velocity(); - sleeping=state->is_sleeping(); + if(sleeping!=state->is_sleeping()) { + sleeping=state->is_sleeping(); + emit_signal(SceneStringNames::get_singleton()->sleeping_state_changed); + } if (get_script_instance()) get_script_instance()->call("_integrate_forces",state); set_ignore_transform_notification(false); @@ -811,6 +814,7 @@ void RigidBody::_bind_methods() { ADD_SIGNAL( MethodInfo("body_exit_shape",PropertyInfo(Variant::INT,"body_id"),PropertyInfo(Variant::OBJECT,"body"),PropertyInfo(Variant::INT,"body_shape"),PropertyInfo(Variant::INT,"local_shape"))); ADD_SIGNAL( MethodInfo("body_enter",PropertyInfo(Variant::OBJECT,"body"))); ADD_SIGNAL( MethodInfo("body_exit",PropertyInfo(Variant::OBJECT,"body"))); + ADD_SIGNAL( MethodInfo("sleeping_state_changed")); BIND_CONSTANT( MODE_STATIC ); BIND_CONSTANT( MODE_KINEMATIC ); diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index ab2c4fc8dc..29813597fa 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -33,7 +33,7 @@ void RayCast::set_cast_to(const Vector3& p_point) { cast_to=p_point; - if (is_inside_tree() && get_tree()->is_editor_hint()) + if (is_inside_tree() && (get_tree()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) update_gizmo(); } diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 9dcad8a533..ce341e2b09 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -432,7 +432,7 @@ void AnimationTreePlayer::_notification(int p_what) { } -float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool switched, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) { +float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) { ERR_FAIL_COND_V(!node_map.has(p_node), 0); NodeBase *nb=node_map[p_node]; @@ -445,7 +445,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode case NODE_OUTPUT: { NodeOut *on = static_cast<NodeOut*>(nb); - return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek); + return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek); } break; case NODE_ANIMATION: { @@ -479,9 +479,6 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode an->time=anim_size; } - if (switched && an->time >= anim_size) { - an->time = 0.0; - } an->skip=true; for (List<AnimationNode::TrackRef>::Element *E=an->tref.front();E;E=E->next()) { @@ -523,13 +520,17 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode if (!osn->active) { //make it as if this node doesn't exist, pass input 0 by. - return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight); + return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); } + float os_seek = p_seek; + if (p_seek) osn->time=p_time; - if (osn->start) + if (osn->start) { osn->time=0; + os_seek = true; + } float blend; @@ -554,13 +555,13 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode if (!osn->filter.empty()) { - main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek,&osn->filter,p_weight); - os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek,&osn->filter,-1); + main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,&osn->filter,p_weight); + os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek,&osn->filter,-1); } else { - main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek); - os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek); + main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek); + os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek); } if (osn->start) { @@ -570,8 +571,8 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode if (!p_seek) { osn->time+=p_time; - osn->remaining-=p_time; - if (osn->remaining<0) + osn->remaining=os_rem; + if (osn->remaining<=0) osn->active=false; } @@ -581,8 +582,8 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode MixNode *mn = static_cast<MixNode*>(nb); - float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight); - _process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,switched,p_seek,p_filter,p_reverse_weight); + float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); + _process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,p_seek,p_filter,p_reverse_weight); return rem; } break; @@ -593,12 +594,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode float rem; if (!bn->filter.empty()) { - rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,&bn->filter,p_weight); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,&bn->filter,-1); + rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,&bn->filter,p_weight); + _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,&bn->filter,-1); } else { - rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value)); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value); + rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value)); + _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,p_filter,p_reverse_weight*bn->value); } return rem; @@ -618,19 +619,19 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode upper_blend = bn->value; } - rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,switched,p_seek,p_filter,p_reverse_weight*blend); - _process_node(bn->inputs[2].node,r_prev_anim,p_weight*upper_blend,p_time,switched,p_seek,p_filter,p_reverse_weight*upper_blend); - _process_node(bn->inputs[0].node,r_prev_anim,p_weight*lower_blend,p_time,switched,p_seek,p_filter,p_reverse_weight*lower_blend); + rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,p_seek,p_filter,p_reverse_weight*blend); + _process_node(bn->inputs[2].node,r_prev_anim,p_weight*upper_blend,p_time,p_seek,p_filter,p_reverse_weight*upper_blend); + _process_node(bn->inputs[0].node,r_prev_anim,p_weight*lower_blend,p_time,p_seek,p_filter,p_reverse_weight*lower_blend); return rem; } break; case NODE_BLEND4: { Blend4Node *bn = static_cast<Blend4Node*>(nb); - float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x)); - _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.x); - float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y)); - _process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.y); + float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x)); + _process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,p_seek,p_filter,p_reverse_weight*bn->value.x); + float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y)); + _process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,p_seek,p_filter,p_reverse_weight*bn->value.y); return MAX(rem,rem2); @@ -639,9 +640,9 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode TimeScaleNode *tsn = static_cast<TimeScaleNode*>(nb); float rem; if (p_seek) - rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,true,p_filter,p_reverse_weight); + rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,true,p_filter,p_reverse_weight); else - rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,switched,false,p_filter,p_reverse_weight); + rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,false,p_filter,p_reverse_weight); if (tsn->scale == 0) return INFINITY; else @@ -651,68 +652,58 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode case NODE_TIMESEEK: { TimeSeekNode *tsn = static_cast<TimeSeekNode*>(nb); - if (tsn->seek_pos>=0) { + if (tsn->seek_pos>=0 && !p_seek) { - float res = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,tsn->seek_pos,switched,true,p_filter,p_reverse_weight); - tsn->seek_pos=-1; - return res; + p_time = tsn->seek_pos; + p_seek = true; + } + tsn->seek_pos=-1; - } else - return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek); + return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek); } break; case NODE_TRANSITION: { TransitionNode *tn = static_cast<TransitionNode*>(nb); - if (tn->prev<0) { + if (tn->prev<0) { // process current animation, check for transition - float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight); + float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight); if (p_seek) tn->time=p_time; else tn->time+=p_time; - if (tn->input_data[tn->current].auto_advance && rem < tn->xfade) { + if (tn->input_data[tn->current].auto_advance && rem <= tn->xfade) { - tn->prev=tn->current; - tn->current++; - if (tn->current>=tn->inputs.size()) - tn->current=0; - tn->prev_xfading=tn->xfade; - tn->prev_time=tn->time; - tn->time=0; - tn->switched=true; + tn->set_current((tn->current+1) % tn->inputs.size()); } return rem; - } else { + } else { // cross-fading from tn->prev to tn->current float blend = tn->xfade? (tn->prev_xfading/tn->xfade) : 1; float rem; - if (!p_seek && tn->switched) { //just switched + if (!p_seek && tn->switched) { //just switched, seek to start of current - rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,true,p_filter,p_reverse_weight*(1.0-blend)); + rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,p_filter,p_reverse_weight*(1.0-blend)); } else { - rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-blend)); + rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,p_seek,p_filter,p_reverse_weight*(1.0-blend)); } tn->switched=false; - //if (!p_seek) - - - if (p_seek) { - _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,true,false,p_filter,p_reverse_weight*blend); + if (p_seek) { // don't seek prev animation + _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,false,p_filter,p_reverse_weight*blend); tn->time=p_time; } else { - _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,switched,false,p_filter,p_reverse_weight*blend); + _process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,false,p_filter,p_reverse_weight*blend); tn->time+=p_time; tn->prev_xfading-=p_time; if (tn->prev_xfading<0) { @@ -749,10 +740,10 @@ void AnimationTreePlayer::_process_animation(float p_delta) { AnimationNode *prev=NULL; if (reset_request) { - _process_node(out_name,&prev, 1.0, 0, true, true ); + _process_node(out_name,&prev, 1.0, 0, true); reset_request=false; } else - _process_node(out_name,&prev, 1.0, p_delta, false, false ); + _process_node(out_name,&prev, 1.0, p_delta); if (dirty_caches) { //some animation changed.. ignore this pass @@ -1158,21 +1149,24 @@ void AnimationTreePlayer::transition_node_set_xfade_time(const StringName& p_nod n->xfade=p_time; } +void AnimationTreePlayer::TransitionNode::set_current(int p_current) { + ERR_FAIL_INDEX(p_current,inputs.size()); -void AnimationTreePlayer::transition_node_set_current(const StringName& p_node, int p_current) { - - GET_NODE( NODE_TRANSITION, TransitionNode ); - ERR_FAIL_INDEX(p_current,n->inputs.size()); - - if (n->current==p_current) + if (current==p_current) return; - n->prev=n->current; - n->prev_xfading=n->xfade; - n->prev_time=n->time; - n->time=0; - n->current=p_current; + prev=current; + prev_xfading=xfade; + prev_time=time; + time=0; + current=p_current; + switched=true; +} + +void AnimationTreePlayer::transition_node_set_current(const StringName& p_node, int p_current) { + GET_NODE( NODE_TRANSITION, TransitionNode ); + n->set_current(p_current); } @@ -1606,6 +1600,7 @@ void AnimationTreePlayer::set_active(bool p_active) { active = p_active; processing = active; + reset_request = p_active; _set_process(processing, true); } @@ -1623,7 +1618,7 @@ AnimationTreePlayer::ConnectError AnimationTreePlayer::get_last_error() const { void AnimationTreePlayer::reset() { - reset_request=false; + reset_request=true; } @@ -1865,7 +1860,7 @@ AnimationTreePlayer::AnimationTreePlayer() { processing = false; active=false; dirty_caches=true; - reset_request=false; + reset_request=true; last_error=CONNECT_INCOMPLETE; base_path=String(".."); } diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 0fec9a9551..7cc96fc1e3 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -246,6 +246,7 @@ private: float xfade; TransitionNode() { type=NODE_TRANSITION; xfade=0; inputs.resize(1); input_data.resize(1); current=0; prev=-1; prev_time=0; prev_xfading=0; switched=false; } + void set_current(int p_current); }; @@ -267,7 +268,7 @@ private: Map<StringName,NodeBase*> node_map; // return time left to finish animation - float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool switched, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0); + float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0); void _process_animation(float p_delta); bool reset_request; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 7edd57603b..6f6f5d3aff 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -1045,6 +1045,7 @@ bool Tween::interpolate_property(Object *p_object if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1104,6 +1105,7 @@ bool Tween::interpolate_method(Object *p_object if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_initial_val.get_type() != p_final_val.get_type(), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); @@ -1154,7 +1156,9 @@ bool Tween::interpolate_callback(Object *p_object ); return true; } + ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); ERR_EXPLAIN("Object has no callback named: %s" + p_callback); @@ -1219,6 +1223,7 @@ bool Tween::interpolate_deferred_callback(Object *p_object return true; } ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_times_in_sec < 0, false); ERR_EXPLAIN("Object has no callback named: %s" + p_callback); @@ -1291,7 +1296,9 @@ bool Tween::follow_property(Object *p_object if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_target == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_target), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); @@ -1357,7 +1364,9 @@ bool Tween::follow_method(Object *p_object if(p_initial_val.get_type() == Variant::INT) p_initial_val = p_initial_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_target == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_target), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); @@ -1424,7 +1433,9 @@ bool Tween::targeting_property(Object *p_object if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_initial == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_initial), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); @@ -1495,7 +1506,9 @@ bool Tween::targeting_method(Object *p_object if(p_final_val.get_type() == Variant::INT) p_final_val = p_final_val.operator real_t(); ERR_FAIL_COND_V(p_object == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false); ERR_FAIL_COND_V(p_initial == NULL, false); + ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_initial), false); ERR_FAIL_COND_V(p_times_in_sec <= 0, false); ERR_FAIL_COND_V(p_trans_type < 0 || p_trans_type >= TRANS_COUNT, false); ERR_FAIL_COND_V(p_ease_type < 0 || p_ease_type >= EASE_COUNT, false); diff --git a/scene/audio/stream_player.cpp b/scene/audio/stream_player.cpp index c1799ec12c..b6b1ee85f3 100644 --- a/scene/audio/stream_player.cpp +++ b/scene/audio/stream_player.cpp @@ -342,8 +342,8 @@ int StreamPlayer::get_buffering_msec() const{ void StreamPlayer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&StreamPlayer::set_stream); - ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&StreamPlayer::get_stream); + ObjectTypeDB::bind_method(_MD("set_stream","stream:AudioStream"),&StreamPlayer::set_stream); + ObjectTypeDB::bind_method(_MD("get_stream:AudioStream"),&StreamPlayer::get_stream); ObjectTypeDB::bind_method(_MD("play","offset"),&StreamPlayer::play,DEFVAL(0)); ObjectTypeDB::bind_method(_MD("stop"),&StreamPlayer::stop); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index b393f926e7..a30c05527c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -604,8 +604,11 @@ void Control::_notification(int p_notification) { if(get_viewport() != NULL) get_viewport()->_gui_hid_control(this); - _modal_stack_remove(); - minimum_size_changed(); + + if(is_inside_tree()) { + _modal_stack_remove(); + minimum_size_changed(); + } //remove key focus //remove modalness diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index cb8806e2ef..0f415f013d 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -53,23 +53,7 @@ void MenuButton::_unhandled_key_input(InputEvent p_event) { code|=KEY_MASK_SHIFT; - int item = popup->find_item_by_accelerator(code); - - - if (item>=0 && ! popup->is_item_disabled(item)) - popup->activate_item(item); - /* - for(int i=0;i<items.size();i++) { - - - if (items[i].accel==0) - continue; - - if (items[i].accel==code) { - - emit_signal("item_pressed",items[i].ID); - } - }*/ + int item = popup->activate_item_by_accelerator(code); } } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 3329d24890..819885809b 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -740,15 +740,33 @@ int PopupMenu::get_item_count() const { return items.size(); } -int PopupMenu::find_item_by_accelerator(uint32_t p_accel) const { +bool PopupMenu::activate_item_by_accelerator(uint32_t p_accel) { int il=items.size(); for(int i=0;i<il;i++) { + if (is_item_disabled(i)) + continue; - if (items[i].accel==p_accel) - return i; + if (items[i].accel==p_accel) { + activate_item(i); + return true; + } + + if (items[i].submenu!="") { + Node* n = get_node(items[i].submenu); + if(!n) + continue; + + PopupMenu* pm = n->cast_to<PopupMenu>(); + if(!pm) + continue; + + if(pm->activate_item_by_accelerator(p_accel)) { + return true; + } + } } - return -1; + return false; } void PopupMenu::activate_item(int p_item) { diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 72f8795067..0e98765dc4 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -117,7 +117,7 @@ public: int get_item_count() const; - int find_item_by_accelerator(uint32_t p_accel) const; + bool activate_item_by_accelerator(uint32_t p_accel); void activate_item(int p_item); void remove_item(int p_idx); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 4be8dd850c..f7461a736c 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -672,6 +672,7 @@ void TextEdit::_notification(int p_what) { bool in_keyword=false; bool in_word = false; bool in_function_name = false; + bool in_member_variable = false; Color keyword_color; // check if line contains highlighted word @@ -681,14 +682,12 @@ void TextEdit::_notification(int p_what) { } if (cache.line_number_w) { - Color fcol = cache.font_color; - fcol.a*=0.4; String fc = String::num(line+1); while (fc.length() < line_number_char_count) { fc="0"+fc; } - cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,fcol); + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); } const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); @@ -803,14 +802,28 @@ void TextEdit::_notification(int p_what) { } } + if (!in_function_name && !in_member_variable && !in_keyword && !is_number && in_word) { + int k = j; + while(k > 0 && !_is_symbol(str[k]) && str[k] != '\t' && str[k] != ' ') { + k--; + } + + if (str[k] == '.') { + in_member_variable = true; + } + } + if (is_symbol) { in_function_name = false; + in_member_variable = false; } if (in_region>=0) color=color_regions[in_region].color; else if (in_keyword) color=keyword_color; + else if (in_member_variable) + color=cache.member_variable_color; else if (in_function_name) color=cache.function_color; else if (is_symbol) @@ -910,9 +923,9 @@ void TextEdit::_notification(int p_what) { cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { cursor_pos.y += get_row_height(); - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.font_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); } @@ -927,9 +940,9 @@ void TextEdit::_notification(int p_what) { if (insert_mode) { cursor_pos.y += get_row_height(); int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.font_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); } } } @@ -1132,7 +1145,7 @@ void TextEdit::_consume_pair_symbol(CharType ch) { int new_column,new_line; - _begin_compex_operation(); + begin_complex_operation(); _insert_text(get_selection_from_line(), get_selection_from_column(), ch_single, &new_line, &new_column); @@ -1145,7 +1158,7 @@ void TextEdit::_consume_pair_symbol(CharType ch) { get_selection_to_column() + to_col_offset, ch_single_pair, &new_line,&new_column); - _end_compex_operation(); + end_complex_operation(); cursor_set_line(get_selection_to_line()); cursor_set_column(get_selection_to_column() + to_col_offset); @@ -1229,6 +1242,66 @@ void TextEdit::backspace_at_cursor() { } +void TextEdit::indent_selection_right() { + + if (!is_selection_active()) { + return; + } + begin_complex_operation(); + int start_line = get_selection_from_line(); + int end_line = get_selection_to_line(); + + // ignore if the cursor is not past the first column + if (get_selection_to_column() == 0) { + end_line--; + } + + for (int i = start_line; i <= end_line; i++) { + String line_text = get_line(i); + line_text = '\t' + line_text; + set_line(i, line_text); + } + + // fix selection being off by one on the last line + selection.to_column++; + end_complex_operation(); + update(); +} + +void TextEdit::indent_selection_left() { + + if (!is_selection_active()) { + return; + } + begin_complex_operation(); + int start_line = get_selection_from_line(); + int end_line = get_selection_to_line(); + + // ignore if the cursor is not past the first column + if (get_selection_to_column() == 0) { + end_line--; + } + String last_line_text = get_line(end_line); + + for (int i = start_line; i <= end_line; i++) { + String line_text = get_line(i); + + if (line_text.begins_with("\t")) { + line_text = line_text.substr(1, line_text.length()); + set_line(i, line_text); + } else if (line_text.begins_with(" ")) { + line_text = line_text.substr(4, line_text.length()); + set_line(i, line_text); + } + } + + // fix selection being off by one on the last line + if (last_line_text != get_line(end_line) && selection.to_column > 0) { + selection.to_column--; + } + end_complex_operation(); + update(); +} void TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const { @@ -1599,7 +1672,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { // remove the old character if in insert mode if (insert_mode) { - _begin_compex_operation(); + begin_complex_operation(); // make sure we don't try and remove empty space if (cursor.column < get_line(cursor.line).length()) { @@ -1610,7 +1683,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { _insert_text_at_cursor(chr); if (insert_mode) { - _end_compex_operation(); + end_complex_operation(); } } } @@ -1656,51 +1729,13 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { switch(k.scancode) { case KEY_TAB: { - - String txt = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - String prev_txt=txt; - if (k.mod.shift) { - - for(int i=0;i<txt.length();i++) { - if (((i>0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/)) && (txt[i]=='\t' || txt[i]==' ')) { - txt.remove(i); - //i--; - } - } + indent_selection_left(); } else { - - for(int i=0;i<txt.length();i++) { - - if (((i>0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/))) { - txt=txt.insert(i,"\t"); - //i--; - } - } + indent_selection_right(); } - - if (txt!=prev_txt) { - - int sel_line=selection.from_line; - int sel_column=selection.from_column; - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - _begin_compex_operation(); - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - _insert_text_at_cursor(txt); - _end_compex_operation(); - selection.active=true; - selection.from_column=sel_column; - selection.from_line=sel_line; - selection.to_column=cursor.column; - selection.to_line=cursor.line; - update(); - } - dobreak=true; accept_event(); - } break; case KEY_X: case KEY_C: @@ -1747,6 +1782,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (clear) { + begin_complex_operation(); selection.active=false; update(); _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); @@ -2395,7 +2431,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { // remove the old character if in insert mode and no selection if (insert_mode && !had_selection) { - _begin_compex_operation(); + begin_complex_operation(); // make sure we don't try and remove empty space if (cursor.column < get_line(cursor.line).length()) { @@ -2415,7 +2451,11 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (insert_mode && !had_selection) { - _end_compex_operation(); + end_complex_operation(); + } + + if (selection.active != had_selection) { + end_complex_operation(); } accept_event(); } else { @@ -3040,10 +3080,13 @@ void TextEdit::_update_caches() { cache.style_normal=get_stylebox("normal"); cache.style_focus=get_stylebox("focus"); cache.font=get_font("font"); + cache.caret_color=get_color("caret_color"); + cache.line_number_color=get_color("line_number_color"); cache.font_color=get_color("font_color"); cache.font_selected_color=get_color("font_selected_color"); cache.keyword_color=get_color("keyword_color"); cache.function_color=get_color("function_color"); + cache.member_variable_color=get_color("member_variable_color"); cache.number_color=get_color("number_color"); cache.selection_color=get_color("selection_color"); cache.mark_color=get_color("mark_color"); @@ -3608,12 +3651,12 @@ void TextEdit::clear_undo_history() { } -void TextEdit::_begin_compex_operation() { +void TextEdit::begin_complex_operation() { _push_current_op(); next_operation_is_complex=true; } -void TextEdit::_end_compex_operation() { +void TextEdit::end_complex_operation() { _push_current_op(); ERR_FAIL_COND(undo_stack.size() == 0); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 22071640a2..09c2a4d729 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -73,11 +73,14 @@ class TextEdit : public Control { Ref<StyleBox> style_normal; Ref<StyleBox> style_focus; Ref<Font> font; + Color caret_color; + Color line_number_color; Color font_color; Color font_selected_color; Color keyword_color; Color number_color; Color function_color; + Color member_variable_color; Color selection_color; Color mark_color; Color breakpoint_color; @@ -265,8 +268,6 @@ class TextEdit : public Control { void _cursor_changed_emit(); void _text_changed_emit(); - void _begin_compex_operation(); - void _end_compex_operation(); void _push_current_op(); /* super internal api, undo/redo builds on it */ @@ -318,6 +319,9 @@ public: //void delete_char(); //void delete_line(); + void begin_complex_operation(); + void end_complex_operation(); + void set_text(String p_text); void insert_text_at_cursor(const String& p_text); void insert_at(const String& p_text, int at); @@ -331,6 +335,9 @@ public: void set_line(int line, String new_text); void backspace_at_cursor(); + void indent_selection_left(); + void indent_selection_right(); + inline void set_scroll_pass_end_of_file(bool p_enabled) { scroll_past_end_of_file_enabled = p_enabled; update(); diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index 57bde00de4..f47b61001c 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -48,6 +48,7 @@ SceneStringNames::SceneStringNames() { item_rect_changed=StaticCString::create("item_rect_changed"); size_flags_changed=StaticCString::create("size_flags_changed"); minimum_size_changed=StaticCString::create("minimum_size_changed"); + sleeping_state_changed=StaticCString::create("sleeping_state_changed"); finished=StaticCString::create("finished"); animation_changed=StaticCString::create("animation_changed"); diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index b2c0e9abf0..fc45351c33 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -62,6 +62,7 @@ public: StringName exit_tree; StringName size_flags_changed; StringName minimum_size_changed; + StringName sleeping_state_changed; StringName idle; StringName iteration; StringName update; diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 968d02dfa5..cf8f40430b 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -148,6 +148,7 @@ void FindReplaceDialog::_replace_skip_callback() { void FindReplaceDialog::_replace() { + text_edit->begin_complex_operation(); if (is_replace_all_mode()) { //line as x so it gets priority in comparison, column as y @@ -228,7 +229,7 @@ void FindReplaceDialog::_replace() { _search(); } - + text_edit->end_complex_operation(); } diff --git a/tools/editor/editor_data.cpp b/tools/editor/editor_data.cpp index f78ab93c30..8bb2d60cab 100644 --- a/tools/editor/editor_data.cpp +++ b/tools/editor/editor_data.cpp @@ -260,6 +260,16 @@ EditorPlugin* EditorData::get_subeditor(Object *p_object) { return NULL; } +Vector<EditorPlugin*> EditorData::get_subeditors(Object* p_object) { + Vector<EditorPlugin*> sub_plugins; + for (int i = 0; i < editor_plugins.size(); i++) { + if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) { + sub_plugins.push_back(editor_plugins[i]); + } + } + return sub_plugins; +} + EditorPlugin* EditorData::get_editor(String p_name) { for(int i=0;i<editor_plugins.size();i++) { diff --git a/tools/editor/editor_data.h b/tools/editor/editor_data.h index 5814ae8f5c..79843c4df5 100644 --- a/tools/editor/editor_data.h +++ b/tools/editor/editor_data.h @@ -150,6 +150,7 @@ public: EditorPlugin* get_editor(Object *p_object); EditorPlugin* get_subeditor(Object *p_object); + Vector<EditorPlugin*> get_subeditors(Object *p_object); EditorPlugin* get_editor(String p_name); void copy_object_params(Object *p_object); diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 6d033a5c25..aa47e97622 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1571,15 +1571,27 @@ void EditorNode::_imported(Node *p_node) { } +void EditorNode::_hide_top_editors() { + _display_top_editors(false); -void EditorNode::_hide_top_editors() { + editor_plugins_over->clear(); +} + +void EditorNode::_display_top_editors(bool p_display) { + editor_plugins_over->make_visible(p_display); +} + +void EditorNode::_set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over) { + editor_plugins_over->set_plugins_list(p_editor_plugins_over); +} - if (editor_plugin_over) - editor_plugin_over->make_visible(false); - editor_plugin_over=NULL; +void EditorNode::_set_editing_top_editors(Object* p_current_object) { + editor_plugins_over->edit(p_current_object); } + + void EditorNode::_edit_current() { uint32_t current = editor_history.get_current(); @@ -1598,8 +1610,7 @@ void EditorNode::_edit_current() { property_editor->edit( NULL ); object_menu->set_disabled(true); - if (editor_plugin_over) - editor_plugin_over->make_visible(false); + _display_top_editors(false); return; } @@ -1679,20 +1690,18 @@ void EditorNode::_edit_current() { } - EditorPlugin *sub_plugin = editor_data.get_subeditor(current_obj); - - if (sub_plugin) { + Vector<EditorPlugin*> sub_plugins = editor_data.get_subeditors(current_obj); + if (!sub_plugins.empty()) { + _display_top_editors(false); - if (editor_plugin_over) - editor_plugin_over->make_visible(false); - editor_plugin_over=sub_plugin; - editor_plugin_over->edit(current_obj); - editor_plugin_over->make_visible(true); - } else if (editor_plugin_over) { + _set_top_editors(sub_plugins); + _set_editing_top_editors(current_obj); + _display_top_editors(true); + + } else if (!editor_plugins_over->get_plugins_list().empty()) { - editor_plugin_over->make_visible(false); - editor_plugin_over=NULL; + _hide_top_editors(); } /* @@ -2583,10 +2592,9 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { } editor_data.get_undo_redo().clear_history(); - if (editor_plugin_over) { //reload editor plugin - editor_plugin_over->edit(NULL); - editor_plugin_over->edit(current); - } + + _set_editing_top_editors(NULL); + _set_editing_top_editors(current); } break; case OBJECT_CALL_METHOD: { @@ -6138,7 +6146,7 @@ EditorNode::EditorNode() { _rebuild_import_menu(); editor_plugin_screen=NULL; - editor_plugin_over=NULL; + editor_plugins_over = memnew(EditorPluginList); // force_top_viewport(true); _edit_current(); @@ -6270,12 +6278,72 @@ EditorNode::EditorNode() { EditorNode::~EditorNode() { - - + memdelete( EditorHelp::get_doc_data() ); memdelete(editor_selection); + memdelete(editor_plugins_over); memdelete(file_server); EditorSettings::destroy(); } +/* + * EDITOR PLUGIN LIST + */ + + +void EditorPluginList::make_visible(bool p_visible) { + if (!plugins_list.empty()) { + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->make_visible(p_visible); + } + } +} + +void EditorPluginList::edit(Object* p_object) { + if (!plugins_list.empty()) { + for (int i = 0; i < plugins_list.size(); i++) { + plugins_list[i]->edit(p_object); + } + } +} + +bool EditorPluginList::forward_input_event(const InputEvent& p_event) { + bool discard = false; + if (!plugins_list.empty()) { + for (int i = 0; i < plugins_list.size(); i++) { + if (plugins_list[i]->forward_input_event(p_event)) { + discard = true; + } + } + } + return discard; +} + +bool EditorPluginList::forward_spatial_input_event(Camera* p_camera, const InputEvent& p_event) { + bool discard = false; + if (!plugins_list.empty()) { + for (int i = 0; i < plugins_list.size(); i++) { + if (plugins_list[i]->forward_spatial_input_event(p_camera, p_event)) { + discard = true; + } + } + } + return discard; +} + +bool EditorPluginList::empty() { + return plugins_list.empty(); +} + +void EditorPluginList::clear() { + plugins_list.clear(); +} + +EditorPluginList::EditorPluginList() { +} + +EditorPluginList::~EditorPluginList() { +} + + diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index b8fabb4c55..e4939afd34 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -95,7 +95,7 @@ typedef void (*EditorNodeInitCallback)(); - +class EditorPluginList; class EditorNode : public Node { @@ -372,7 +372,7 @@ private: Vector<EditorPlugin*> editor_plugins; EditorPlugin *editor_plugin_screen; - EditorPlugin *editor_plugin_over; + EditorPluginList *editor_plugins_over; EditorHistory editor_history; EditorData editor_data; @@ -449,6 +449,10 @@ private: void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key); void _hide_top_editors(); + void _display_top_editors(bool p_display); + void _set_top_editors(Vector<EditorPlugin*> p_editor_plugins_over); + void _set_editing_top_editors(Object * p_current_object); + void _quick_opened(); void _quick_run(); @@ -575,7 +579,7 @@ public: EditorPlugin *get_editor_plugin_screen() { return editor_plugin_screen; } - EditorPlugin *get_editor_plugin_over() { return editor_plugin_over; } + EditorPluginList *get_editor_plugins_over() { return editor_plugins_over; } PropertyEditor *get_property_editor() { return property_editor; } static void add_editor_plugin(EditorPlugin *p_editor); @@ -710,6 +714,32 @@ struct EditorProgress { ~EditorProgress() { EditorNode::progress_end_task(task); } }; +class EditorPluginList : public Object { +private: + Vector<EditorPlugin*> plugins_list; + +public: + + void set_plugins_list(Vector<EditorPlugin*> p_plugins_list) { + plugins_list = p_plugins_list; + } + + Vector<EditorPlugin*> get_plugins_list() { + return plugins_list; + } + + void make_visible(bool p_visible); + void edit(Object *p_object); + bool forward_input_event(const InputEvent& p_event); + bool forward_spatial_input_event(Camera* p_camera, const InputEvent& p_event); + void clear(); + bool empty(); + + EditorPluginList(); + ~EditorPluginList(); + +} ; + struct EditorProgressBG { String task; diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index a7c01e0f6f..31da68cb8c 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -392,12 +392,15 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["global/default_project_export_path"]=PropertyInfo(Variant::STRING,"global/default_project_export_path",PROPERTY_HINT_GLOBAL_DIR); set("global/show_script_in_scene_tabs",false); set("text_editor/background_color",Color::html("3b000000")); + set("text_editor/caret_color",Color::html("aaaaaa")); + set("text_editor/line_number_color",Color::html("66aaaaaa")); set("text_editor/text_color",Color::html("aaaaaa")); set("text_editor/text_selected_color",Color::html("000000")); set("text_editor/keyword_color",Color::html("ffffb3")); set("text_editor/base_type_color",Color::html("a4ffd4")); set("text_editor/engine_type_color",Color::html("83d3ff")); set("text_editor/function_color",Color::html("66a2ce")); + set("text_editor/member_variable_color",Color::html("e64e59")); set("text_editor/comment_color",Color::html("983d1b")); set("text_editor/string_color",Color::html("ef6ebe")); set("text_editor/number_color",Color::html("EB9532")); @@ -407,6 +410,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set("text_editor/current_line_color",Color(0.3,0.5,0.8,0.15)); set("text_editor/word_highlighted_color",Color(0.8,0.9,0.9,0.15)); + set("text_editor/syntax_highlighting", true); + set("text_editor/highlight_all_occurrences", true); set("text_editor/scroll_past_end_of_file", false); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 6eb26542be..91c26d9d59 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -39,6 +39,7 @@ #include "scene/gui/grid_container.h" #include "tools/editor/animation_editor.h" #include "tools/editor/plugins/animation_player_editor_plugin.h" +#include "scene/resources/packed_scene.h" class SnapDialog : public ConfirmationDialog { @@ -415,6 +416,14 @@ void CanvasItemEditor::_keying_changed() { animation_hb->hide(); } +bool CanvasItemEditor::_is_part_of_subscene(CanvasItem *p_item) { + + Node* scene_node = get_tree()->get_edited_scene_root(); + Node* item_owner = p_item->get_owner(); + + return item_owner && item_owner!=scene_node && p_item!=scene_node && item_owner->get_filename()!=""; +} + // slow but modern computers should have no problem CanvasItem* CanvasItemEditor::_select_canvas_item_at_pos(const Point2& p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform) { @@ -441,8 +450,7 @@ CanvasItem* CanvasItemEditor::_select_canvas_item_at_pos(const Point2& p_pos,Nod return r; } - - if (c && c->is_visible() && !c->has_meta("_edit_lock_") && !c->cast_to<CanvasLayer>()) { + if (c && c->is_visible() && !c->has_meta("_edit_lock_") && !_is_part_of_subscene(c) && !c->cast_to<CanvasLayer>()) { Rect2 rect = c->get_item_rect(); Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos); @@ -1037,10 +1045,10 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { { EditorNode *en = editor; - EditorPlugin *over_plugin = en->get_editor_plugin_over(); + EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - if (over_plugin) { - bool discard = over_plugin->forward_input_event(p_event); + if (!over_plugin_list->empty()) { + bool discard = over_plugin_list->forward_input_event(p_event); if (discard) { accept_event(); return; @@ -3345,7 +3353,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { PopupMenu *p2 = memnew(PopupMenu); p->add_child(p2); p2->set_name("skeleton"); - p2->add_item("Make Bones",SKELETON_MAKE_BONES,KEY_MASK_CMD|KEY_SHIFT|KEY_B); + p2->add_item("Make Bones",SKELETON_MAKE_BONES,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_B); p2->add_item("Clear Bones",SKELETON_CLEAR_BONES); p2->add_separator(); p2->add_item("Make IK Chain",SKELETON_SET_IK_CHAIN); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 301c67756c..22acfceed0 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -295,6 +295,7 @@ class CanvasItemEditor : public VBoxContainer { int handle_len; + bool _is_part_of_subscene(CanvasItem *p_item); CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform); void _find_canvas_items_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform, Vector<_SelectResult> &r_items); void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index bef1a8e028..6ed44901f1 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -288,6 +288,8 @@ void ScriptTextEditor::_load_theme_settings() { get_text_edit()->set_custom_bg_color(EDITOR_DEF("text_editor/background_color",Color(0,0,0,0))); get_text_edit()->add_color_override("font_color",EDITOR_DEF("text_editor/text_color",Color(0,0,0))); + get_text_edit()->add_color_override("line_number_color",EDITOR_DEF("text_editor/line_number_color",Color(0,0,0))); + get_text_edit()->add_color_override("caret_color",EDITOR_DEF("text_editor/caret_color",Color(0,0,0))); get_text_edit()->add_color_override("font_selected_color",EDITOR_DEF("text_editor/text_selected_color",Color(1,1,1))); get_text_edit()->add_color_override("selection_color",EDITOR_DEF("text_editor/selection_color",Color(0.2,0.2,1))); get_text_edit()->add_color_override("brace_mismatch_color",EDITOR_DEF("text_editor/brace_mismatch_color",Color(1,0.2,0.2))); @@ -295,10 +297,10 @@ void ScriptTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("word_highlighted_color",EDITOR_DEF("text_editor/word_highlighted_color",Color(0.8,0.9,0.9,0.15))); get_text_edit()->add_color_override("number_color",EDITOR_DEF("text_editor/number_color",Color(0.9,0.6,0.0,2))); get_text_edit()->add_color_override("function_color",EDITOR_DEF("text_editor/function_color",Color(0.4,0.6,0.8))); + get_text_edit()->add_color_override("member_variable_color",EDITOR_DEF("text_editor/member_variable_color",Color(0.9,0.3,0.3))); Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2)); - get_text_edit()->set_syntax_coloring(true); List<String> keywords; script->get_language()->get_reserved_words(&keywords); for(List<String>::Element *E=keywords.front();E;E=E->next()) { @@ -1071,6 +1073,7 @@ void ScriptEditor::_menu_option(int p_option) { if (scr.is_null()) return; + tx->begin_complex_operation(); if (tx->is_selection_active()) { int from_line = tx->get_selection_from_line(); @@ -1102,6 +1105,7 @@ void ScriptEditor::_menu_option(int p_option) { swap_lines(tx, line_id, next_id); } + tx->end_complex_operation(); tx->update(); } break; @@ -1112,6 +1116,7 @@ void ScriptEditor::_menu_option(int p_option) { if (scr.is_null()) return; + tx->begin_complex_operation(); if (tx->is_selection_active()) { int from_line = tx->get_selection_from_line(); @@ -1143,6 +1148,7 @@ void ScriptEditor::_menu_option(int p_option) { swap_lines(tx, line_id, next_id); } + tx->end_complex_operation(); tx->update(); } break; @@ -1153,27 +1159,10 @@ void ScriptEditor::_menu_option(int p_option) { if (scr.is_null()) return; - + tx->begin_complex_operation(); if (tx->is_selection_active()) { - int begin = tx->get_selection_from_line(); - int end = tx->get_selection_to_line(); - for (int i = begin; i <= end; i++) - { - String line_text = tx->get_line(i); - // begins with tab - if (line_text.begins_with("\t")) - { - line_text = line_text.substr(1, line_text.length()); - tx->set_line(i, line_text); - } - // begins with 4 spaces - else if (line_text.begins_with(" ")) - { - line_text = line_text.substr(4, line_text.length()); - tx->set_line(i, line_text); - } - } + tx->indent_selection_left(); } else { @@ -1192,6 +1181,7 @@ void ScriptEditor::_menu_option(int p_option) { tx->set_line(begin, line_text); } } + tx->end_complex_operation(); tx->update(); //tx->deselect(); @@ -1203,16 +1193,10 @@ void ScriptEditor::_menu_option(int p_option) { if (scr.is_null()) return; + tx->begin_complex_operation(); if (tx->is_selection_active()) { - int begin = tx->get_selection_from_line(); - int end = tx->get_selection_to_line(); - for (int i = begin; i <= end; i++) - { - String line_text = tx->get_line(i); - line_text = '\t' + line_text; - tx->set_line(i, line_text); - } + tx->indent_selection_right(); } else { @@ -1221,6 +1205,7 @@ void ScriptEditor::_menu_option(int p_option) { line_text = '\t' + line_text; tx->set_line(begin, line_text); } + tx->end_complex_operation(); tx->update(); //tx->deselect(); @@ -1252,7 +1237,7 @@ void ScriptEditor::_menu_option(int p_option) { return; - + tx->begin_complex_operation(); if (tx->is_selection_active()) { int begin = tx->get_selection_from_line(); @@ -1284,6 +1269,7 @@ void ScriptEditor::_menu_option(int p_option) { line_text = "#" + line_text; tx->set_line(begin, line_text); } + tx->end_complex_operation(); tx->update(); //tx->deselect(); @@ -1940,6 +1926,7 @@ void ScriptEditor::edit(const Ref<Script>& p_script) { ste->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); ste->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); ste->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); + ste->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); ste->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); ste->get_text_edit()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/put_callhint_tooltip_below_current_line"), @@ -2081,6 +2068,7 @@ void ScriptEditor::_editor_settings_changed() { ste->get_text_edit()->set_tab_size(EditorSettings::get_singleton()->get("text_editor/tab_size")); ste->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/draw_tabs")); ste->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers")); + ste->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting")); ste->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences")); } diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 79ff78ca0d..9ab7aafeb2 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -51,7 +51,31 @@ #define GIZMO_SCALE_DEFAULT 0.15 -//void SpatialEditorViewport::_update_camera(); +void SpatialEditorViewport::_update_camera() { + if (orthogonal) { + Size2 size = get_size(); + Size2 vpsize = Point2(cursor.distance*size.get_aspect(), cursor.distance / size.get_aspect()); + //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar()); + camera->set_orthogonal(2 * cursor.distance, 0.1, 8192); + } + else + camera->set_perspective(get_fov(), get_znear(), get_zfar()); + + Transform camera_transform; + camera_transform.translate(cursor.pos); + camera_transform.basis.rotate(Vector3(0, 1, 0), cursor.y_rot); + camera_transform.basis.rotate(Vector3(1, 0, 0), cursor.x_rot); + + if (orthogonal) + camera_transform.translate(0, 0, 4096); + else + camera_transform.translate(0, 0, cursor.distance); + + if (camera->get_global_transform() != camera_transform) { + camera->set_global_transform(camera_transform); + update_transform_gizmo_view(); + } +} String SpatialEditorGizmo::get_handle_name(int p_idx) const { @@ -810,16 +834,15 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { { EditorNode *en = editor; - EditorPlugin *over_plugin = en->get_editor_plugin_over(); + EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - if (over_plugin) { - bool discard = over_plugin->forward_spatial_input_event(camera,p_event); + if (!over_plugin_list->empty()) { + bool discard = over_plugin_list->forward_spatial_input_event(camera,p_event); if (discard) return; } } - switch(p_event.type) { case InputEvent::MOUSE_BUTTON: { @@ -1204,11 +1227,9 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { } } break; case InputEvent::MOUSE_MOTION: { - const InputEventMouseMotion &m=p_event.mouse_motion; _edit.mouse_pos=Point2(p_event.mouse_motion.x,p_event.mouse_motion.y); - - + if (spatial_editor->get_selected()) { @@ -1244,7 +1265,7 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { NavigationScheme nav_scheme = _get_navigation_schema("3d_editor/navigation_scheme"); NavigationMode nav_mode = NAVIGATION_NONE; - + if (_edit.gizmo.is_valid()) { Plane plane=Plane(_edit.gizmo_initial_pos,_get_camera_normal()); @@ -1558,6 +1579,26 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (m.mod.alt) nav_mode = NAVIGATION_PAN; } + }else{ + // Handle trackpad (no external mouse) use case + int mod = 0; + if (m.mod.shift) + mod=KEY_SHIFT; + if (m.mod.alt) + mod=KEY_ALT; + if (m.mod.control) + mod=KEY_CONTROL; + if (m.mod.meta) + mod=KEY_META; + + if(mod){ + if (mod == _get_key_modifier("3d_editor/pan_modifier")) + nav_mode = NAVIGATION_PAN; + else if (mod == _get_key_modifier("3d_editor/zoom_modifier")) + nav_mode = NAVIGATION_ZOOM; + else if (mod == _get_key_modifier("3d_editor/orbit_modifier")) + nav_mode = NAVIGATION_ORBIT; + } } switch(nav_mode) { @@ -1770,6 +1811,10 @@ void SpatialEditorViewport::_notification(int p_what) { bool visible=is_visible(); set_process(visible); + + if (visible) + _update_camera(); + call_deferred("update_transform_gizmo_view"); } @@ -1791,28 +1836,7 @@ void SpatialEditorViewport::_notification(int p_what) { } */ - if (orthogonal) { - Size2 size=get_size(); - Size2 vpsize = Point2(cursor.distance*size.get_aspect(),cursor.distance/size.get_aspect()); - //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar()); - camera->set_orthogonal(2*cursor.distance,0.1,8192); - } else - camera->set_perspective(get_fov(),get_znear(),get_zfar()); - - Transform camera_transform; - camera_transform.translate( cursor.pos ); - camera_transform.basis.rotate(Vector3(0,1,0),cursor.y_rot); - camera_transform.basis.rotate(Vector3(1,0,0),cursor.x_rot); - - if (orthogonal) - camera_transform.translate(0,0,4096); - else - camera_transform.translate(0,0,cursor.distance); - - if (camera->get_global_transform()!=camera_transform) { - camera->set_global_transform( camera_transform ); - update_transform_gizmo_view(); - } + _update_camera(); Map<Node*,Object*> &selection = editor_selection->get_selection(); @@ -1915,7 +1939,6 @@ void SpatialEditorViewport::_notification(int p_what) { surface->connect("mouse_enter",this,"_smouseenter"); preview_camera->set_icon(get_icon("Camera","EditorIcons")); _init_gizmo_instance(index); - } if (p_what==NOTIFICATION_EXIT_TREE) { @@ -3553,9 +3576,9 @@ void SpatialEditor::_unhandled_key_input(InputEvent p_event) { { EditorNode *en = editor; - EditorPlugin *over_plugin = en->get_editor_plugin_over(); + EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - if (over_plugin && over_plugin->forward_input_event(p_event)) { + if (!over_plugin_list->empty() && over_plugin_list->forward_input_event(p_event)) { return; //ate the over input event } @@ -3579,6 +3602,17 @@ void SpatialEditor::_unhandled_key_input(InputEvent p_event) { case KEY_E: _menu_item_pressed(MENU_TOOL_ROTATE); break; case KEY_R: _menu_item_pressed(MENU_TOOL_SCALE); break; + case KEY_Z: { + if (k.mod.shift || k.mod.control || k.mod.command) + break; + + if (view_menu->get_popup()->is_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_DISPLAY_WIREFRAME))) { + _menu_item_pressed(MENU_VIEW_DISPLAY_NORMAL); + } else { + _menu_item_pressed(MENU_VIEW_DISPLAY_WIREFRAME); + } + } break; + #if 0 #endif } diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index 5877ce1a43..6b2961ea72 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -1098,8 +1098,7 @@ void SceneTreeDock::_delete_confirm() { return; - if (editor->get_editor_plugin_over()) - editor->get_editor_plugin_over()->make_visible(false); + editor->get_editor_plugins_over()->make_visible(false); editor_data->get_undo_redo().create_action("Remove Node(s)"); |