diff options
132 files changed, 1755 insertions, 454 deletions
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index b2145eca85..a3b48320b1 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -30,6 +30,17 @@ #include "geometry.h" #include "print_string.h" +bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { + + Vector<int> indices = Geometry::triangulate_polygon(p_polygon); + for (int j = 0; j + 3 <= indices.size(); j += 3) { + int i1 = indices[j], i2 = indices[j + 1], i3 = indices[j + 2]; + if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3])) + return true; + } + return false; +} + void Geometry::MeshData::optimize_vertices() { Map<int, int> vtx_remap; diff --git a/core/math/geometry.h b/core/math/geometry.h index ac1a22289c..fefdd88794 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -512,6 +512,9 @@ public: return true; } + + static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon); + static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 *p_segment) { Vector2 p = p_point - p_segment[0]; diff --git a/core/os/input.cpp b/core/os/input.cpp index 2795b11243..a44adde425 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -84,7 +84,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position); ClassDB::bind_method(D_METHOD("action_press", "action"), &Input::action_press); ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release); - ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); @@ -92,6 +92,24 @@ void Input::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); + BIND_ENUM_CONSTANT(CURSOR_ARROW); + BIND_ENUM_CONSTANT(CURSOR_IBEAM); + BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND); + BIND_ENUM_CONSTANT(CURSOR_CROSS); + BIND_ENUM_CONSTANT(CURSOR_WAIT); + BIND_ENUM_CONSTANT(CURSOR_BUSY); + BIND_ENUM_CONSTANT(CURSOR_DRAG); + BIND_ENUM_CONSTANT(CURSOR_CAN_DROP); + BIND_ENUM_CONSTANT(CURSOR_FORBIDDEN); + BIND_ENUM_CONSTANT(CURSOR_VSIZE); + BIND_ENUM_CONSTANT(CURSOR_HSIZE); + BIND_ENUM_CONSTANT(CURSOR_BDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_FDIAGSIZE); + BIND_ENUM_CONSTANT(CURSOR_MOVE); + BIND_ENUM_CONSTANT(CURSOR_VSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HSPLIT); + BIND_ENUM_CONSTANT(CURSOR_HELP); + ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected"))); } diff --git a/core/os/input.h b/core/os/input.h index 608484ccd0..140d11de4d 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -51,6 +51,28 @@ public: MOUSE_MODE_CONFINED }; +#undef CursorShape + enum CursorShape { + CURSOR_ARROW, + CURSOR_IBEAM, + CURSOR_POINTING_HAND, + CURSOR_CROSS, + CURSOR_WAIT, + CURSOR_BUSY, + CURSOR_DRAG, + CURSOR_CAN_DROP, + CURSOR_FORBIDDEN, + CURSOR_VSIZE, + CURSOR_HSIZE, + CURSOR_BDIAGSIZE, + CURSOR_FDIAGSIZE, + CURSOR_MOVE, + CURSOR_VSPLIT, + CURSOR_HSPLIT, + CURSOR_HELP, + CURSOR_MAX + }; + void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; @@ -96,7 +118,7 @@ public: virtual bool is_emulating_touchscreen() const = 0; - virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2()) = 0; + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) = 0; virtual void set_mouse_in_window(bool p_in_window) = 0; virtual String get_joy_button_string(int p_button) = 0; @@ -110,5 +132,6 @@ public: }; VARIANT_ENUM_CAST(Input::MouseMode); +VARIANT_ENUM_CAST(Input::CursorShape); #endif // INPUT_H diff --git a/core/os/os.h b/core/os/os.h index 5dc39b52d6..c9c228cfaf 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -325,6 +325,7 @@ public: virtual int get_virtual_keyboard_height() const; virtual void set_cursor_shape(CursorShape p_shape) = 0; + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) = 0; virtual bool get_swap_ok_cancel() { return false; } virtual void dump_memory_to_file(const char *p_file); diff --git a/core/ring_buffer.h b/core/ring_buffer.h index 4b4a7fe9cf..c8562a0570 100644 --- a/core/ring_buffer.h +++ b/core/ring_buffer.h @@ -40,7 +40,7 @@ class RingBuffer { int write_pos; int size_mask; - inline int inc(int &p_var, int p_size) { + inline int inc(int &p_var, int p_size) const { int ret = p_var; p_var += p_size; p_var = p_var & size_mask; @@ -50,7 +50,7 @@ class RingBuffer { public: T read() { ERR_FAIL_COND_V(space_left() < 1, T()); - return data[inc(read_pos, 1)]; + return data.ptr()[inc(read_pos, 1)]; }; int read(T *p_buf, int p_size, bool p_advance = true) { @@ -63,8 +63,9 @@ public: int end = pos + to_read; end = MIN(end, size()); int total = end - pos; + const T *read = data.ptr(); for (int i = 0; i < total; i++) { - p_buf[dst++] = data[pos + i]; + p_buf[dst++] = read[pos + i]; }; to_read -= total; pos = 0; @@ -75,7 +76,7 @@ public: return p_size; }; - int copy(T *p_buf, int p_offset, int p_size) { + int copy(T *p_buf, int p_offset, int p_size) const { int left = data_left(); if ((p_offset + p_size) > left) { @@ -101,7 +102,7 @@ public: return p_size; }; - int find(const T &t, int p_offset, int p_max_size) { + int find(const T &t, int p_offset, int p_max_size) const { int left = data_left(); if ((p_offset + p_max_size) > left) { @@ -164,7 +165,7 @@ public: return p_size; }; - inline int space_left() { + inline int space_left() const { int left = read_pos - write_pos; if (left < 0) { return size() + left - 1; @@ -174,11 +175,11 @@ public: }; return left - 1; }; - inline int data_left() { + inline int data_left() const { return size() - space_left() - 1; }; - inline int size() { + inline int size() const { return data.size(); }; diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index a2505cbc53..a0a55ce86e 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -129,15 +129,21 @@ static ObjectID safe_get_instance_id(const Variant &p_v) { void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_variable) { packet_peer_stream->put_var(p_name); + + Variant var = p_variable; + if (p_variable.get_type() == Variant::OBJECT && !ObjectDB::instance_validate(p_variable)) { + var = Variant(); + } + int len = 0; - Error err = encode_variant(p_variable, NULL, len); + Error err = encode_variant(var, NULL, len); if (err != OK) ERR_PRINT("Failed to encode variant"); if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size packet_peer_stream->put_var(Variant()); } else { - packet_peer_stream->put_var(p_variable); + packet_peer_stream->put_var(var); } } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index a2794e7052..81e823b5db 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -101,9 +101,10 @@ struct _VariantCall { const Variant *newargs[VARIANT_ARG_MAX]; for (int i = 0; i < p_argcount; i++) newargs[i] = p_args[i]; - int defargcount = def_argcount; + // fill in any remaining parameters with defaults + int first_default_arg = arg_count - def_argcount; for (int i = p_argcount; i < arg_count; i++) - newargs[i] = &default_args[defargcount - (i - p_argcount) - 1]; //default arguments + newargs[i] = &default_args[i - first_default_arg]; #ifdef DEBUG_ENABLED if (!verify_arguments(newargs, r_error)) return; diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index bee2cdf387..cd05c83347 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -535,7 +535,7 @@ <argument index="0" name="path" type="String"> </argument> <description> - Loads a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". + Loads a resource from the filesystem located at [code]path[/code]. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". [codeblock] # load a scene called main located in the root of the project directory var main = load("res://main.tscn") @@ -866,9 +866,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns sign of [code]s[/code] -1 or 1. + Returns the sign of [code]s[/code]: -1 or 1. Returns 0 if [code]s[/code] is 0. [codeblock] sign(-6) # returns -1 + sign(0) # returns 0 sign(6) # returns 1 [/codeblock] </description> diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index de5dc18702..6e8b760966 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -93,6 +93,14 @@ <constant name="MARGIN_BOTTOM" value="3" enum="Margin"> Bottom margin, used usually for [Control] or [StyleBox] derived classes. </constant> + <constant name="CORNER_TOP_LEFT" value="0" enum="Corner"> + </constant> + <constant name="CORNER_TOP_RIGHT" value="1" enum="Corner"> + </constant> + <constant name="CORNER_BOTTOM_RIGHT" value="2" enum="Corner"> + </constant> + <constant name="CORNER_BOTTOM_LEFT" value="3" enum="Corner"> + </constant> <constant name="VERTICAL" value="1" enum="Orientation"> General vertical alignment, used usually for [Separator], [ScrollBar], [Slider], etc. </constant> @@ -1385,5 +1393,57 @@ <constant name="TYPE_MAX" value="27" enum="Variant.Type"> Marker for end of type constants. </constant> + <constant name="OP_EQUAL" value="0" enum="Variant.Operator"> + </constant> + <constant name="OP_NOT_EQUAL" value="1" enum="Variant.Operator"> + </constant> + <constant name="OP_LESS" value="2" enum="Variant.Operator"> + </constant> + <constant name="OP_LESS_EQUAL" value="3" enum="Variant.Operator"> + </constant> + <constant name="OP_GREATER" value="4" enum="Variant.Operator"> + </constant> + <constant name="OP_GREATER_EQUAL" value="5" enum="Variant.Operator"> + </constant> + <constant name="OP_ADD" value="6" enum="Variant.Operator"> + </constant> + <constant name="OP_SUBTRACT" value="7" enum="Variant.Operator"> + </constant> + <constant name="OP_MULTIPLY" value="8" enum="Variant.Operator"> + </constant> + <constant name="OP_DIVIDE" value="9" enum="Variant.Operator"> + </constant> + <constant name="OP_NEGATE" value="10" enum="Variant.Operator"> + </constant> + <constant name="OP_POSITIVE" value="11" enum="Variant.Operator"> + </constant> + <constant name="OP_MODULE" value="12" enum="Variant.Operator"> + </constant> + <constant name="OP_STRING_CONCAT" value="13" enum="Variant.Operator"> + </constant> + <constant name="OP_SHIFT_LEFT" value="14" enum="Variant.Operator"> + </constant> + <constant name="OP_SHIFT_RIGHT" value="15" enum="Variant.Operator"> + </constant> + <constant name="OP_BIT_AND" value="16" enum="Variant.Operator"> + </constant> + <constant name="OP_BIT_OR" value="17" enum="Variant.Operator"> + </constant> + <constant name="OP_BIT_XOR" value="18" enum="Variant.Operator"> + </constant> + <constant name="OP_BIT_NEGATE" value="19" enum="Variant.Operator"> + </constant> + <constant name="OP_AND" value="20" enum="Variant.Operator"> + </constant> + <constant name="OP_OR" value="21" enum="Variant.Operator"> + </constant> + <constant name="OP_XOR" value="22" enum="Variant.Operator"> + </constant> + <constant name="OP_NOT" value="23" enum="Variant.Operator"> + </constant> + <constant name="OP_IN" value="24" enum="Variant.Operator"> + </constant> + <constant name="OP_MAX" value="25" enum="Variant.Operator"> + </constant> </constants> </class> diff --git a/doc/classes/ARVRServer.xml b/doc/classes/ARVRServer.xml index ffe6c35240..7f9eedce50 100644 --- a/doc/classes/ARVRServer.xml +++ b/doc/classes/ARVRServer.xml @@ -14,7 +14,7 @@ <method name="center_on_hmd"> <return type="void"> </return> - <argument index="0" name="rotation_mode" type="bool"> + <argument index="0" name="rotation_mode" type="int" enum="ARVRServer.RotationMode"> </argument> <argument index="1" name="keep_height" type="bool"> </argument> diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml index e0e3261edf..08ac12736a 100644 --- a/doc/classes/AStar.xml +++ b/doc/classes/AStar.xml @@ -171,7 +171,7 @@ <method name="get_point_connections"> <return type="PoolIntArray"> </return> - <argument index="0" name="arg0" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> Returns an array with the ids of the points that form the connect with the given point. diff --git a/doc/classes/BakedLightmap.xml b/doc/classes/BakedLightmap.xml index b351aeac05..b23b608589 100644 --- a/doc/classes/BakedLightmap.xml +++ b/doc/classes/BakedLightmap.xml @@ -27,38 +27,28 @@ </method> </methods> <members> - <member name="bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="BakedLightmap.BakeMode"> + <member name="bake_cell_size" type="float" setter="set_bake_cell_size" getter="get_bake_cell_size"> </member> - <member name="bake_quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="BakedLightmap.BakeQuality"> + <member name="bake_energy" type="float" setter="set_energy" getter="get_energy"> + </member> + <member name="bake_extents" type="Vector3" setter="set_extents" getter="get_extents"> </member> - <member name="bake_subdiv" type="int" setter="set_bake_subdiv" getter="get_bake_subdiv" enum="BakedLightmap.Subdiv"> + <member name="bake_hdr" type="bool" setter="set_hdr" getter="is_hdr"> </member> - <member name="capture_subdiv" type="int" setter="set_capture_subdiv" getter="get_capture_subdiv" enum="BakedLightmap.Subdiv"> + <member name="bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="BakedLightmap.BakeMode"> </member> - <member name="energy" type="float" setter="set_energy" getter="get_energy"> + <member name="bake_propagation" type="float" setter="set_propagation" getter="get_propagation"> </member> - <member name="extents" type="Vector3" setter="set_extents" getter="get_extents"> + <member name="bake_quality" type="int" setter="set_bake_quality" getter="get_bake_quality" enum="BakedLightmap.BakeQuality"> </member> - <member name="hdr" type="bool" setter="set_hdr" getter="is_hdr"> + <member name="capture_cell_size" type="float" setter="set_capture_cell_size" getter="get_capture_cell_size"> </member> <member name="image_path" type="String" setter="set_image_path" getter="get_image_path"> </member> <member name="light_data" type="BakedLightmapData" setter="set_light_data" getter="get_light_data"> </member> - <member name="propagation" type="float" setter="set_propagation" getter="get_propagation"> - </member> </members> <constants> - <constant name="SUBDIV_128" value="0" enum="Subdiv"> - </constant> - <constant name="SUBDIV_256" value="1" enum="Subdiv"> - </constant> - <constant name="SUBDIV_512" value="2" enum="Subdiv"> - </constant> - <constant name="SUBDIV_1024" value="3" enum="Subdiv"> - </constant> - <constant name="SUBDIV_MAX" value="4" enum="Subdiv"> - </constant> <constant name="BAKE_QUALITY_LOW" value="0" enum="BakeQuality"> </constant> <constant name="BAKE_QUALITY_MEDIUM" value="1" enum="BakeQuality"> diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml index 91c9ecc774..c2ae9101e1 100644 --- a/doc/classes/Camera.xml +++ b/doc/classes/Camera.xml @@ -150,9 +150,6 @@ <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset"> The horizontal (Y) offset of the Camear viewport. </member> - <member name="vaspect" type="bool" setter="set_vaspect" getter="get_vaspect"> - A boolean representation of [member keep_aspect] in which [code]true[/code] is equivalent to [code]KEEP_WIDTH[/code]. - </member> </members> <constants> <constant name="PROJECTION_PERSPECTIVE" value="0" enum="Projection"> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 54eaf6cc7a..230978950b 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -314,6 +314,22 @@ Loads an image from file [code]path[/code]. </description> </method> + <method name="load_jpg_from_buffer"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="buffer" type="PoolByteArray"> + </argument> + <description> + </description> + </method> + <method name="load_png_from_buffer"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="buffer" type="PoolByteArray"> + </argument> + <description> + </description> + </method> <method name="lock"> <return type="void"> </return> @@ -430,65 +446,67 @@ </constant> <constant name="FORMAT_RGBA5551" value="7" enum="Format"> </constant> - <constant name="FORMAT_RF" value="8" enum="Format"> + <constant name="FORMAT_RGB10A2" value="8" enum="Format"> + </constant> + <constant name="FORMAT_RF" value="9" enum="Format"> </constant> - <constant name="FORMAT_RGF" value="9" enum="Format"> + <constant name="FORMAT_RGF" value="10" enum="Format"> </constant> - <constant name="FORMAT_RGBF" value="10" enum="Format"> + <constant name="FORMAT_RGBF" value="11" enum="Format"> </constant> - <constant name="FORMAT_RGBAF" value="11" enum="Format"> + <constant name="FORMAT_RGBAF" value="12" enum="Format"> </constant> - <constant name="FORMAT_RH" value="12" enum="Format"> + <constant name="FORMAT_RH" value="13" enum="Format"> </constant> - <constant name="FORMAT_RGH" value="13" enum="Format"> + <constant name="FORMAT_RGH" value="14" enum="Format"> </constant> - <constant name="FORMAT_RGBH" value="14" enum="Format"> + <constant name="FORMAT_RGBH" value="15" enum="Format"> </constant> - <constant name="FORMAT_RGBAH" value="15" enum="Format"> + <constant name="FORMAT_RGBAH" value="16" enum="Format"> </constant> - <constant name="FORMAT_RGBE9995" value="16" enum="Format"> + <constant name="FORMAT_RGBE9995" value="17" enum="Format"> </constant> - <constant name="FORMAT_DXT1" value="17" enum="Format"> + <constant name="FORMAT_DXT1" value="18" enum="Format"> </constant> - <constant name="FORMAT_DXT3" value="18" enum="Format"> + <constant name="FORMAT_DXT3" value="19" enum="Format"> </constant> - <constant name="FORMAT_DXT5" value="19" enum="Format"> + <constant name="FORMAT_DXT5" value="20" enum="Format"> </constant> - <constant name="FORMAT_RGTC_R" value="20" enum="Format"> + <constant name="FORMAT_RGTC_R" value="21" enum="Format"> </constant> - <constant name="FORMAT_RGTC_RG" value="21" enum="Format"> + <constant name="FORMAT_RGTC_RG" value="22" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBA" value="22" enum="Format"> + <constant name="FORMAT_BPTC_RGBA" value="23" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBF" value="23" enum="Format"> + <constant name="FORMAT_BPTC_RGBF" value="24" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBFU" value="24" enum="Format"> + <constant name="FORMAT_BPTC_RGBFU" value="25" enum="Format"> </constant> - <constant name="FORMAT_PVRTC2" value="25" enum="Format"> + <constant name="FORMAT_PVRTC2" value="26" enum="Format"> </constant> - <constant name="FORMAT_PVRTC2A" value="26" enum="Format"> + <constant name="FORMAT_PVRTC2A" value="27" enum="Format"> </constant> - <constant name="FORMAT_PVRTC4" value="27" enum="Format"> + <constant name="FORMAT_PVRTC4" value="28" enum="Format"> </constant> - <constant name="FORMAT_PVRTC4A" value="28" enum="Format"> + <constant name="FORMAT_PVRTC4A" value="29" enum="Format"> </constant> - <constant name="FORMAT_ETC" value="29" enum="Format"> + <constant name="FORMAT_ETC" value="30" enum="Format"> </constant> - <constant name="FORMAT_ETC2_R11" value="30" enum="Format"> + <constant name="FORMAT_ETC2_R11" value="31" enum="Format"> </constant> - <constant name="FORMAT_ETC2_R11S" value="31" enum="Format"> + <constant name="FORMAT_ETC2_R11S" value="32" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RG11" value="32" enum="Format"> + <constant name="FORMAT_ETC2_RG11" value="33" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RG11S" value="33" enum="Format"> + <constant name="FORMAT_ETC2_RG11S" value="34" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGB8" value="34" enum="Format"> + <constant name="FORMAT_ETC2_RGB8" value="35" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGBA8" value="35" enum="Format"> + <constant name="FORMAT_ETC2_RGBA8" value="36" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGB8A1" value="36" enum="Format"> + <constant name="FORMAT_ETC2_RGB8A1" value="37" enum="Format"> </constant> - <constant name="FORMAT_MAX" value="37" enum="Format"> + <constant name="FORMAT_MAX" value="38" enum="Format"> </constant> <constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation"> </constant> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 1200ac5170..79dc45fa1f 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -275,9 +275,12 @@ </return> <argument index="0" name="image" type="Resource"> </argument> - <argument index="1" name="hotspot" type="Vector2" default="Vector2( 0, 0 )"> + <argument index="1" name="shape" type="int" enum="Input.CursorShape" default="0"> + </argument> + <argument index="2" name="hotspot" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> + Set a custom mouse cursor image, which is only visible inside the game window. The hotspot can also be specified. See enum [code]CURSOR_*[/code] for the list of shapes. </description> </method> <method name="set_mouse_mode"> @@ -347,5 +350,39 @@ </constant> <constant name="MOUSE_MODE_CONFINED" value="3" enum="MouseMode"> </constant> + <constant name="CURSOR_ARROW" value="0" enum="CursorShape"> + </constant> + <constant name="CURSOR_IBEAM" value="1" enum="CursorShape"> + </constant> + <constant name="CURSOR_POINTING_HAND" value="2" enum="CursorShape"> + </constant> + <constant name="CURSOR_CROSS" value="3" enum="CursorShape"> + </constant> + <constant name="CURSOR_WAIT" value="4" enum="CursorShape"> + </constant> + <constant name="CURSOR_BUSY" value="5" enum="CursorShape"> + </constant> + <constant name="CURSOR_DRAG" value="6" enum="CursorShape"> + </constant> + <constant name="CURSOR_CAN_DROP" value="7" enum="CursorShape"> + </constant> + <constant name="CURSOR_FORBIDDEN" value="8" enum="CursorShape"> + </constant> + <constant name="CURSOR_VSIZE" value="9" enum="CursorShape"> + </constant> + <constant name="CURSOR_HSIZE" value="10" enum="CursorShape"> + </constant> + <constant name="CURSOR_BDIAGSIZE" value="11" enum="CursorShape"> + </constant> + <constant name="CURSOR_FDIAGSIZE" value="12" enum="CursorShape"> + </constant> + <constant name="CURSOR_MOVE" value="13" enum="CursorShape"> + </constant> + <constant name="CURSOR_VSPLIT" value="14" enum="CursorShape"> + </constant> + <constant name="CURSOR_HSPLIT" value="15" enum="CursorShape"> + </constant> + <constant name="CURSOR_HELP" value="16" enum="CursorShape"> + </constant> </constants> </class> diff --git a/doc/classes/InputEvent.xml b/doc/classes/InputEvent.xml index cc31da0627..a8abe60f78 100644 --- a/doc/classes/InputEvent.xml +++ b/doc/classes/InputEvent.xml @@ -28,13 +28,6 @@ Returns a [String] representation of the event. </description> </method> - <method name="get_id" qualifiers="const"> - <return type="int"> - </return> - <description> - Returns the event's ID. - </description> - </method> <method name="is_action" qualifiers="const"> <return type="bool"> </return> @@ -83,14 +76,6 @@ Returns [code]true[/code] if this input event is pressed. Not relevant for the event types [code]MOUSE_MOTION[/code], [code]SCREEN_DRAG[/code] or [code]NONE[/code]. </description> </method> - <method name="set_id"> - <return type="void"> - </return> - <argument index="0" name="id" type="int"> - </argument> - <description> - </description> - </method> <method name="shortcut_match" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml index 22231cfdf3..af681c9456 100644 --- a/doc/classes/MenuButton.xml +++ b/doc/classes/MenuButton.xml @@ -18,6 +18,14 @@ Return the [PopupMenu] contained in this button. </description> </method> + <method name="set_disable_shortcuts"> + <return type="void"> + </return> + <argument index="0" name="disabled" type="bool"> + </argument> + <description> + </description> + </method> </methods> <signals> <signal name="about_to_show"> diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml index 81978809d7..ae2a67312e 100644 --- a/doc/classes/Node2D.xml +++ b/doc/classes/Node2D.xml @@ -157,7 +157,7 @@ <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform"> Local [Transform2D]. </member> - <member name="z" type="int" setter="set_z" getter="get_z"> + <member name="z_index" type="int" setter="set_z_index" getter="get_z_index"> Z-index. Controls the order in which the nodes render. A node with a higher Z-index will display in front of others. </member> <member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative"> diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml index 67f5f84a49..8bad396b84 100644 --- a/doc/classes/Physics2DServer.xml +++ b/doc/classes/Physics2DServer.xml @@ -216,7 +216,7 @@ <argument index="2" name="disable" type="bool"> </argument> <description> - Disables a given shape in this area if [code]disable is true[/code] + Disables a given shape in an area. </description> </method> <method name="area_set_shape_transform"> @@ -638,7 +638,7 @@ <argument index="2" name="enable" type="bool"> </argument> <description> - Enables one way collision on body if [code]enable is true[/code]. + Enables one way collision on body if [code]enable[/code] is [code]true[/code]. </description> </method> <method name="body_set_shape_disabled"> @@ -651,7 +651,7 @@ <argument index="2" name="disable" type="bool"> </argument> <description> - Disables shape in body if [code]disable is true[/code]. + Disables shape in body if [code]disable[/code] is [code]true[/code]. </description> </method> <method name="body_set_shape_metadata"> @@ -1135,6 +1135,12 @@ <constant name="JOINT_DAMPED_SPRING" value="2" enum="JointType"> Constant to create damped spring joints. </constant> + <constant name="JOINT_PARAM_BIAS" value="0" enum="JointParam"> + </constant> + <constant name="JOINT_PARAM_MAX_BIAS" value="1" enum="JointParam"> + </constant> + <constant name="JOINT_PARAM_MAX_FORCE" value="2" enum="JointParam"> + </constant> <constant name="DAMPED_STRING_REST_LENGTH" value="0" enum="DampedStringParam"> Set the resting length of the spring joint. The joint will always try to go to back this length when pulled apart. </constant> diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml index a78fe03cab..3a4b843b06 100644 --- a/doc/classes/SceneTree.xml +++ b/doc/classes/SceneTree.xml @@ -302,6 +302,14 @@ <description> </description> </method> + <method name="set_quit_on_go_back"> + <return type="void"> + </return> + <argument index="0" name="enabled" type="bool"> + </argument> + <description> + </description> + </method> <method name="set_refuse_new_network_connections"> <return type="void"> </return> @@ -402,13 +410,13 @@ </signal> </signals> <constants> - <constant name="GROUP_CALL_DEFAULT" value="0" enum="CallGroupFlags"> + <constant name="GROUP_CALL_DEFAULT" value="0" enum="GroupCallFlags"> </constant> - <constant name="GROUP_CALL_REVERSE" value="1" enum="CallGroupFlags"> + <constant name="GROUP_CALL_REVERSE" value="1" enum="GroupCallFlags"> </constant> - <constant name="GROUP_CALL_REALTIME" value="2" enum="CallGroupFlags"> + <constant name="GROUP_CALL_REALTIME" value="2" enum="GroupCallFlags"> </constant> - <constant name="GROUP_CALL_UNIQUE" value="4" enum="CallGroupFlags"> + <constant name="GROUP_CALL_UNIQUE" value="4" enum="GroupCallFlags"> </constant> <constant name="STRETCH_MODE_DISABLED" value="0" enum="StretchMode"> </constant> diff --git a/doc/classes/ScriptEditor.xml b/doc/classes/ScriptEditor.xml index 81b0b3d0c3..1e1a8d516e 100644 --- a/doc/classes/ScriptEditor.xml +++ b/doc/classes/ScriptEditor.xml @@ -12,11 +12,11 @@ <method name="can_drop_data_fw" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="point" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Variant"> + <argument index="1" name="data" type="Variant"> </argument> - <argument index="2" name="arg2" type="Control"> + <argument index="2" name="from" type="Control"> </argument> <description> </description> @@ -24,11 +24,11 @@ <method name="drop_data_fw"> <return type="void"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="point" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Variant"> + <argument index="1" name="data" type="Variant"> </argument> - <argument index="2" name="arg2" type="Control"> + <argument index="2" name="from" type="Control"> </argument> <description> </description> @@ -43,9 +43,9 @@ <method name="get_drag_data_fw"> <return type="Variant"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="point" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Control"> + <argument index="1" name="from" type="Control"> </argument> <description> </description> diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml index 7940e4065e..d0addcf9f9 100644 --- a/doc/classes/Spatial.xml +++ b/doc/classes/Spatial.xml @@ -34,7 +34,7 @@ Returns the current [World] resource this Spatial node is registered to. </description> </method> - <method name="rotate_object_local"> + <method name="global_rotate"> <return type="void"> </return> <argument index="0" name="axis" type="Vector3"> @@ -42,27 +42,15 @@ <argument index="1" name="angle" type="float"> </argument> <description> - Rotates the local transformation around axis, a unit [Vector3], by specified angle in radians. The rotation axis is in object-local coordinate system. + Rotates the global (world) transformation around axis, a unit [Vector3], by specified angle in radians. The rotation axis is in global coordinate system. </description> </method> - <method name="scale_object_local"> + <method name="global_scale"> <return type="void"> </return> <argument index="0" name="scale" type="Vector3"> </argument> <description> - Scales the local transformation by given 3D scale factors in object-local coordinate system. - </description> - </method> - <method name="global_rotate"> - <return type="void"> - </return> - <argument index="0" name="axis" type="Vector3"> - </argument> - <argument index="1" name="angle" type="float"> - </argument> - <description> - Rotates the global (world) transformation around axis, a unit [Vector3], by specified angle in radians. The rotation axis is in global coordinate system. </description> </method> <method name="global_translate"> @@ -151,6 +139,17 @@ Rotates the local transformation around axis, a unit [Vector3], by specified angle in radians. </description> </method> + <method name="rotate_object_local"> + <return type="void"> + </return> + <argument index="0" name="axis" type="Vector3"> + </argument> + <argument index="1" name="angle" type="float"> + </argument> + <description> + Rotates the local transformation around axis, a unit [Vector3], by specified angle in radians. The rotation axis is in object-local coordinate system. + </description> + </method> <method name="rotate_x"> <return type="void"> </return> @@ -178,6 +177,15 @@ Rotates the local transformation around the Z axis by angle in radians. </description> </method> + <method name="scale_object_local"> + <return type="void"> + </return> + <argument index="0" name="scale" type="Vector3"> + </argument> + <description> + Scales the local transformation by given 3D scale factors in object-local coordinate system. + </description> + </method> <method name="set_as_toplevel"> <return type="void"> </return> @@ -264,6 +272,14 @@ Changes the node's position by given offset [Vector3]. </description> </method> + <method name="translate_object_local"> + <return type="void"> + </return> + <argument index="0" name="offset" type="Vector3"> + </argument> + <description> + </description> + </method> <method name="update_gizmo"> <return type="void"> </return> diff --git a/doc/classes/StreamPeer.xml b/doc/classes/StreamPeer.xml index d757b6f2d8..8ecd9e5816 100644 --- a/doc/classes/StreamPeer.xml +++ b/doc/classes/StreamPeer.xml @@ -105,7 +105,7 @@ <return type="int"> </return> <description> - Get an unsigned 16 bit value from the stream. + Get an unsigned 64 bit value from the stream. </description> </method> <method name="get_u8"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index ab722a24c3..f4d80c46b4 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -213,7 +213,7 @@ <method name="is_line_hidden" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="arg0" type="int"> + <argument index="0" name="line" type="int"> </argument> <description> </description> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index a09f6b6dc3..daba0a0fc1 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -185,7 +185,7 @@ <method name="update_bitmask_area"> <return type="void"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="position" type="Vector2"> </argument> <description> Applies autotiling rules to the cell (and its adjacent cells) referenced by its grid-based X and Y coordinates. diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 3dbf172c5a..716f89eab6 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -39,7 +39,7 @@ <method name="autotile_get_bitmask_mode" qualifiers="const"> <return type="int" enum="TileSet.BitmaskMode"> </return> - <argument index="0" name="arg0" type="int"> + <argument index="0" name="id" type="int"> </argument> <description> </description> @@ -47,9 +47,9 @@ <method name="autotile_set_bitmask_mode"> <return type="void"> </return> - <argument index="0" name="mode" type="int"> + <argument index="0" name="id" type="int"> </argument> - <argument index="1" name="arg1" type="int" enum="TileSet.BitmaskMode"> + <argument index="1" name="mode" type="int" enum="TileSet.BitmaskMode"> </argument> <description> </description> diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml index 11bd3b3b86..e26082c47e 100644 --- a/doc/classes/Tree.xml +++ b/doc/classes/Tree.xml @@ -41,6 +41,8 @@ </return> <argument index="0" name="parent" type="Object" default="null"> </argument> + <argument index="1" name="idx" type="int" default="-1"> + </argument> <description> Create an item in the tree and add it as the last child of [code]parent[/code]. If parent is not given, it will be added as the root's last child, or it'll the be the root itself if the tree is empty. </description> diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 5ce544ecfb..d35d624589 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -6943,6 +6943,10 @@ bool RasterizerStorageGLES3::free(RID p_rid) { glDeleteTextures(1, &cls->distance); canvas_light_shadow_owner.free(p_rid); memdelete(cls); + } else if (particles_owner.owns(p_rid)) { + Particles *particles = particles_owner.get(p_rid); + particles_owner.free(p_rid); + memdelete(particles); } else { return false; } diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index cc4d060c02..fa8094f31a 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -298,7 +298,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo args.push_back(0); #ifdef __FreeBSD__ - if (p_path.find("/")) { + if (p_path.find("/") != -1) { // exec name contains path so use it execv(p_path.utf8().get_data(), &args[0]); } else { diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 256fe302d7..4b59656903 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1251,7 +1251,7 @@ CodeTextEditor::CodeTextEditor() { error = memnew(Label); status_bar->add_child(error); - error->set_clip_text(true); //do not change, or else very long errors can push the whole container to the right + error->set_autowrap(true); error->set_valign(Label::VALIGN_CENTER); error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor")); error->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts")); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index a601c8cd2b..96c3a27ea7 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -37,7 +37,7 @@ #include "print_string.h" #include "scene/gui/box_container.h" -void CreateDialog::popup_create(bool p_dontclear) { +void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { recent->clear(); @@ -89,11 +89,12 @@ void CreateDialog::popup_create(bool p_dontclear) { popup_centered_ratio(); } - if (p_dontclear) + if (p_dont_clear) { search_box->select_all(); - else { + } else { search_box->clear(); } + search_box->grab_focus(); _update_search(); @@ -104,8 +105,19 @@ void CreateDialog::popup_create(bool p_dontclear) { if (enable_rl) { search_options->add_constant_override("draw_relationship_lines", 1); search_options->add_color_override("relationship_line_color", rl_color); - } else + } else { search_options->add_constant_override("draw_relationship_lines", 0); + } + + is_replace_mode = p_replace_mode; + + if (p_replace_mode) { + set_title(vformat(TTR("Change %s Type"), base_type)); + get_ok()->set_text(TTR("Change")); + } else { + set_title(vformat(TTR("Create New %s"), base_type)); + get_ok()->set_text(TTR("Create")); + } } void CreateDialog::_text_changed(const String &p_newtext) { @@ -369,7 +381,11 @@ void CreateDialog::_notification(int p_what) { void CreateDialog::set_base_type(const String &p_base) { base_type = p_base; - set_title(vformat(TTR("Create New %s"), p_base)); + if (is_replace_mode) + set_title(vformat(TTR("Change %s Type"), p_base)); + else + set_title(vformat(TTR("Create New %s"), p_base)); + _update_search(); } @@ -624,6 +640,8 @@ void CreateDialog::_bind_methods() { CreateDialog::CreateDialog() { + is_replace_mode = false; + ClassDB::get_class_list(&type_list); type_list.sort_custom<StringName::AlphCompare>(); @@ -678,7 +696,6 @@ CreateDialog::CreateDialog() { search_box->connect("gui_input", this, "_sbox_input"); search_options = memnew(Tree); vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_text(TTR("Create")); get_ok()->set_disabled(true); register_text_enter(search_box); set_hide_on_ok(false); diff --git a/editor/create_dialog.h b/editor/create_dialog.h index 56ba7f8a3e..ed23fb4ae8 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -52,6 +52,7 @@ class CreateDialog : public ConfirmationDialog { Button *favorite; LineEdit *search_box; Tree *search_options; + bool is_replace_mode; String base_type; String preferred_search_result_type; EditorHelpBit *help_bit; @@ -97,7 +98,7 @@ public: void set_preferred_search_result_type(const String &p_preferred_type); String get_preferred_search_result_type(); - void popup_create(bool p_dontclear); + void popup_create(bool p_dont_clear, bool p_replace_mode = false); CreateDialog(); }; diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 1d6d933924..7fa4776141 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -131,7 +131,8 @@ EditorAbout::EditorAbout() { Label *about_text = memnew(Label); about_text->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - about_text->set_text(VERSION_FULL_NAME + hash + String::utf8("\n\xc2\xa9 2007-2018 Juan Linietsky, Ariel Manzur.\n\xc2\xa9 2014-2017 ") + + about_text->set_text(VERSION_FULL_NAME + hash + + String::utf8("\n\xc2\xa9 2007-2018 Juan Linietsky, Ariel Manzur.\n\xc2\xa9 2014-2018 ") + TTR("Godot Engine contributors") + "\n"); hbc->add_child(about_text); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index f2882561aa..c50995fc2b 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -77,12 +77,27 @@ static Ref<BitmapFont> make_font(int p_height, int p_ascent, int p_valign, int p Ref<DynamicFont> m_name; \ m_name.instance(); \ m_name->set_size(m_size); \ - m_name->set_font_data(DefaultFont); \ + if (CustomFont.is_valid()) { \ + m_name->set_font_data(CustomFont); \ + m_name->add_fallback(DefaultFont); \ + } else { \ + m_name->set_font_data(DefaultFont); \ + } \ m_name->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE); \ m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \ MAKE_FALLBACKS(m_name); void editor_register_fonts(Ref<Theme> p_theme) { + /* Custom font */ + + String custom_font = EditorSettings::get_singleton()->get("interface/editor/custom_font"); + Ref<DynamicFontData> CustomFont; + if (custom_font.length() > 0) { + CustomFont.instance(); + CustomFont->set_font_path(custom_font); + CustomFont->set_force_autohinter(true); //just looks better..i think? + } + /* Droid Sans */ Ref<DynamicFontData> DefaultFont; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index cf19af7ef6..1b885adf37 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "editor_log.h" +#include "core/os/keyboard.h" #include "editor_node.h" #include "scene/gui/center_container.h" #include "scene/resources/dynamic_font.h" @@ -154,6 +155,7 @@ EditorLog::EditorLog() { clearbutton = memnew(Button); hb->add_child(clearbutton); clearbutton->set_text(TTR("Clear")); + clearbutton->set_shortcut(ED_SHORTCUT("editor/clear_output", TTR("Clear Output"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_K)); clearbutton->connect("pressed", this, "_clear_request"); log = memnew(RichTextLabel); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bd37e7d0be..b52161813d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4419,10 +4419,11 @@ void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_current_path()); DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + Vector<String> just_copy = String("ttf,otf").split(","); for (int i = 0; i < p_files.size(); i++) { String from = p_files[i]; - if (!ResourceFormatImporter::get_singleton()->can_be_imported(from)) { + if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) != -1)) { continue; } String to = to_path.plus_file(from.get_file()); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 5a16ec7eab..dc82a02f46 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -277,7 +277,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("interface/editor/source_font_size", 14); hints["interface/editor/source_font_size"] = PropertyInfo(Variant::INT, "interface/editor/source_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); _initial_set("interface/editor/custom_font", ""); - hints["interface/editor/custom_font"] = PropertyInfo(Variant::STRING, "interface/editor/custom_font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + hints["interface/editor/custom_font"] = PropertyInfo(Variant::STRING, "interface/editor/custom_font", PROPERTY_HINT_GLOBAL_FILE, "*.ttf,*.otf", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); _initial_set("interface/editor/dim_editor_on_dialog_popup", true); _initial_set("interface/editor/dim_amount", 0.6f); hints["interface/editor/dim_amount"] = PropertyInfo(Variant::REAL, "interface/editor/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 3644893663..b19d015455 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1135,16 +1135,5 @@ Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) { theme = create_editor_theme(p_theme); } - String global_font = EditorSettings::get_singleton()->get("interface/editor/custom_font"); - if (global_font != "") { - Ref<Font> fnt = ResourceLoader::load(global_font); - if (fnt.is_valid()) { - if (!theme.is_valid()) { - theme.instance(); - } - theme->set_default_theme_font(fnt); - } - } - return theme; } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 949455ff98..b18cd6b747 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -819,7 +819,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); print_line("Duplicating " + old_path + " -> " + new_path); - Error err = da->copy(old_path, new_path); + Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path); if (err == OK) { //Move/Rename any corresponding import settings too if (p_item.is_file && FileAccess::exists(old_path + ".import")) { @@ -980,10 +980,12 @@ void FileSystemDock::_duplicate_operation_confirm() { return; } - String old_path = to_duplicate.path.ends_with("/") ? to_duplicate.path.substr(0, to_duplicate.path.length() - 1) : to_rename.path; - String new_path = old_path.get_base_dir().plus_file(new_name); - if (old_path == new_path) { - return; + String new_path; + String base_dir = to_duplicate.path.get_base_dir(); + if (to_duplicate.is_file) { + new_path = base_dir.plus_file(new_name); + } else { + new_path = base_dir.substr(0, base_dir.find_last("/")) + "/" + new_name; } //Present a more user friendly warning for name conflict @@ -995,7 +997,7 @@ void FileSystemDock::_duplicate_operation_confirm() { } memdelete(da); - _try_duplicate_item(to_duplicate, new_name); + _try_duplicate_item(to_duplicate, new_path); //Rescan everything print_line("call rescan!"); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 53b52c5f1b..a52c914096 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -612,6 +612,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no if (Object::cast_to<Viewport>(p_node)) return; + const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); CanvasItem *c = Object::cast_to<CanvasItem>(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { @@ -630,14 +631,17 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no if (c && c->is_visible_in_tree() && !c->has_meta("_edit_lock_") && !Object::cast_to<CanvasLayer>(c)) { Rect2 rect = c->_edit_get_rect(); - Point2 local_pos = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse().xform(p_pos); + Transform2D to_local = (p_parent_xform * p_canvas_xform * c->get_transform()).affine_inverse(); + Point2 local_pos = to_local.xform(p_pos); + const real_t local_grab_distance = (to_local.xform(p_pos + Vector2(grab_distance, 0)) - local_pos).length(); + Rect2 local_pos_rect = Rect2(local_pos, Vector2(0, 0)).grow(local_grab_distance); - if (rect.has_point(local_pos)) { + if (rect.intersects(local_pos_rect) && c->_edit_is_selected_on_click(local_pos, local_grab_distance)) { Node2D *node = Object::cast_to<Node2D>(c); _SelectResult res; res.item = c; - res.z = node ? node->get_z() : 0; + res.z_index = node ? node->get_z_index() : 0; res.has_z = node; r_items.push_back(res); } @@ -3464,7 +3468,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) + if (!canvas_item || !canvas_item->is_inside_tree()) continue; if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) @@ -3482,7 +3486,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) + if (!canvas_item || !canvas_item->is_inside_tree()) continue; if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) @@ -3502,7 +3506,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) + if (!canvas_item || !canvas_item->is_inside_tree()) continue; if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) @@ -3520,7 +3524,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); - if (!canvas_item || !canvas_item->is_visible_in_tree()) + if (!canvas_item || !canvas_item->is_inside_tree()) continue; if (canvas_item->get_viewport() != EditorNode::get_singleton()->get_scene_root()) diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index f14f1a92a6..0866fe77aa 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -252,10 +252,10 @@ class CanvasItemEditor : public VBoxContainer { struct _SelectResult { CanvasItem *item; - float z; + float z_index; bool has_z; _FORCE_INLINE_ bool operator<(const _SelectResult &p_rr) const { - return has_z && p_rr.has_z ? p_rr.z < z : p_rr.has_z; + return has_z && p_rr.has_z ? p_rr.z_index < z_index : p_rr.has_z; } }; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index c865ddd4b0..3be68f21af 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -347,7 +347,8 @@ void CurveEditor::open_context_menu(Vector2 pos) { _context_menu->set_item_checked(_context_menu->get_item_index(CONTEXT_LINEAR), is_linear); } else { - _context_menu->add_separator(); + if (_selected_point > 0 || _selected_point + 1 < _curve_ref->get_point_count()) + _context_menu->add_separator(); if (_selected_point > 0) { _context_menu->add_check_item(TTR("Left linear"), CONTEXT_LEFT_LINEAR); @@ -367,6 +368,7 @@ void CurveEditor::open_context_menu(Vector2 pos) { _context_menu->add_submenu_item(TTR("Load preset"), _presets_menu->get_name()); + _context_menu->set_size(Size2(0, 0)); _context_menu->popup(); } @@ -566,7 +568,6 @@ static void plot_curve_accurate(const Curve &curve, float step, T plot_func) { Vector2 prev_pos = a; float len = b.x - a.x; - //float step = 4.f / view_size.x; for (float x = step; x < len; x += step) { pos.x = a.x + x; @@ -694,24 +695,6 @@ void CurveEditor::_draw() { CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color); plot_curve_accurate(curve, 4.f / view_size.x, plot_func); - /*// TEST draw baked curve - { - Vector2 pos = Vector2(0, curve.interpolate_baked(0)); - Vector2 prev_pos = pos; - - float len = 1.0; - float step = 4.f / view_size.x; - - for(float x = step; x < len; x += step) { - pos.x = x; - pos.y = curve.interpolate_baked(x); - draw_line(get_point_view_pos(prev_pos), get_point_view_pos(pos), Color(0,1,0)); - prev_pos = pos; - } - - draw_line(get_point_view_pos(prev_pos), get_point_view_pos(Vector2(1, curve.interpolate_baked(1))), Color(0,1,0)); - }//*/ - // Draw points draw_set_transform_matrix(Transform2D()); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 73fd64f8db..bc29c92d7f 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1027,6 +1027,15 @@ void ScriptEditor::_menu_option(int p_option) { case FILE_COPY_PATH: { _copy_script_path(); } break; + case SHOW_IN_FILE_SYSTEM: { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(tab_container->get_current_tab())); + Ref<Script> script = se->get_edited_script(); + FileSystemDock *file_system_dock = EditorNode::get_singleton()->get_filesystem_dock(); + file_system_dock->navigate_to_path(script->get_path()); + // Ensure that the FileSystem dock is visible. + TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control(); + tab_container->set_current_tab(file_system_dock->get_position_in_parent()); + } break; case CLOSE_DOCS: { _close_docs_tab(); } break; @@ -2164,7 +2173,7 @@ void ScriptEditor::_make_script_list_context_menu() { context_menu->add_separator(); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/copy_path"), FILE_COPY_PATH); context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/reload_script_soft"), FILE_TOOL_RELOAD_SOFT); - + context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/show_in_file_system"), SHOW_IN_FILE_SYSTEM); Ref<Script> scr = se->get_edited_script(); if (!scr.is_null() && scr->is_tool()) { context_menu->add_separator(); @@ -2613,6 +2622,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/show_in_file_system", TTR("Show In File System")), SHOW_IN_FILE_SYSTEM); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/history_previous", TTR("History Prev"), KEY_MASK_ALT | KEY_LEFT), WINDOW_PREV); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 3305147442..d90cf7b912 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -137,6 +137,7 @@ class ScriptEditor : public PanelContainer { CLOSE_ALL, CLOSE_OTHER_TABS, TOGGLE_SCRIPTS_PANEL, + SHOW_IN_FILE_SYSTEM, FILE_COPY_PATH, FILE_TOOL_RELOAD, FILE_TOOL_RELOAD_SOFT, diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index da507db5da..eccb11ba12 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -333,7 +333,7 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { autotile_list = memnew(ItemList); autotile_list->set_v_size_flags(SIZE_EXPAND_FILL); autotile_list->set_h_size_flags(SIZE_EXPAND_FILL); - autotile_list->set_custom_minimum_size(Size2(02, 200)); + autotile_list->set_custom_minimum_size(Size2(10, 200)); autotile_list->connect("item_selected", this, "_on_autotile_selected"); split->add_child(autotile_list); @@ -531,7 +531,7 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { main_vb->add_child(toolbar); - ScrollContainer *scroll = memnew(ScrollContainer); + scroll = memnew(ScrollContainer); main_vb->add_child(scroll); scroll->set_v_size_flags(SIZE_EXPAND_FILL); @@ -619,6 +619,7 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) { tool_containers[TOOLBAR_BITMASK]->hide(); tool_containers[TOOLBAR_SHAPE]->show(); tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.")); + current_shape = PoolVector2Array(); spin_priority->hide(); } break; default: { @@ -1061,20 +1062,43 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } else { int t_id = get_current_tile(); if (t_id >= 0) { - Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(t_id); - for (int i = 0; i < sd.size(); i++) { - if (sd[i].autotile_coord == edited_shape_coord) { - Ref<ConvexPolygonShape2D> shape = sd[i].shape; + if (edit_mode == EDITMODE_COLLISION) { + Vector<TileSet::ShapeData> sd = tile_set->tile_get_shapes(t_id); + for (int i = 0; i < sd.size(); i++) { + if (sd[i].autotile_coord == edited_shape_coord) { + Ref<ConvexPolygonShape2D> shape = sd[i].shape; + + if (!shape.is_null()) { + sd.remove(i); + tile_set->tile_set_shapes(get_current_tile(), sd); + edited_collision_shape = Ref<Shape2D>(); + workspace->update(); + } + break; + } + } + } else if (edit_mode == EDITMODE_OCCLUSION) { + Map<Vector2, Ref<OccluderPolygon2D> > map = tile_set->autotile_get_light_oclusion_map(t_id); + for (Map<Vector2, Ref<OccluderPolygon2D> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tile_set->autotile_set_light_occluder(get_current_tile(), Ref<OccluderPolygon2D>(), edited_shape_coord); + break; + } + } - if (!shape.is_null()) { - sd.remove(i); - tile_set->tile_set_shapes(get_current_tile(), sd); - edited_collision_shape = Ref<Shape2D>(); - current_shape.resize(0); - workspace->update(); + edited_occlusion_shape = Ref<OccluderPolygon2D>(); + workspace->update(); + } else if (edit_mode == EDITMODE_NAVIGATION) { + Map<Vector2, Ref<NavigationPolygon> > map = tile_set->autotile_get_navigation_map(t_id); + for (Map<Vector2, Ref<NavigationPolygon> >::Element *E = map.front(); E; E = E->next()) { + if (E->key() == edited_shape_coord) { + tile_set->autotile_set_navigation_polygon(t_id, Ref<NavigationPolygon>(), edited_shape_coord); + break; } - break; } + + edited_navigation_shape = Ref<NavigationPolygon>(); + workspace->update(); } } @@ -1095,6 +1119,16 @@ void AutotileEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } } break; } + + //Drag Middle Mouse + if (mm.is_valid()) { + if (mm->get_button_mask() & BUTTON_MASK_MIDDLE) { + + Vector2 dragged(mm->get_relative().x, mm->get_relative().y); + scroll->set_h_scroll(scroll->get_h_scroll() - dragged.x * workspace->get_scale().x); + scroll->set_v_scroll(scroll->get_v_scroll() - dragged.y * workspace->get_scale().x); + } + } } } @@ -1453,11 +1487,20 @@ void AutotileEditor::close_shape(const Vector2 &shape_anchor) { Ref<ConvexPolygonShape2D> shape = memnew(ConvexPolygonShape2D); Vector<Vector2> segments; + float p_total = 0; for (int i = 0; i < current_shape.size(); i++) { segments.push_back(current_shape[i] - shape_anchor); + + if (i != current_shape.size() - 1) + p_total += ((current_shape[i + 1].x - current_shape[i].x) * (-current_shape[i + 1].y + (-current_shape[i].y))); + else + p_total += ((current_shape[0].x - current_shape[i].x) * (-current_shape[0].y + (-current_shape[i].y))); } + if (p_total < 0) + segments.invert(); + shape->set_points(segments); tile_set->tile_add_shape(get_current_tile(), shape, Transform2D(), false, edited_shape_coord); diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 7d9558d4e7..0f66f04cb1 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -86,6 +86,7 @@ class AutotileEditor : public Control { int current_item_index; Sprite *preview; + ScrollContainer *scroll; Control *workspace_container; Control *workspace; Button *tool_editmode[EDITMODE_MAX]; diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 0411656857..eb5cec2a2e 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -89,33 +89,50 @@ private: String created_folder_path; void set_message(const String &p_msg, MessageType p_type = MESSAGE_SUCCESS) { + msg->set_text(p_msg); - if (p_msg == "") { - status_btn->set_icon(get_icon("StatusSuccess", "EditorIcons")); - return; - } - msg->hide(); + Ref<Texture> current_icon = status_btn->get_icon(); + switch (p_type) { - case MESSAGE_ERROR: + + case MESSAGE_ERROR: { + msg->add_color_override("font_color", get_color("error_color", "Editor")); - status_btn->set_icon(get_icon("StatusError", "EditorIcons")); - msg->show(); - break; - case MESSAGE_WARNING: + Ref<Texture> new_icon = get_icon("StatusError", "EditorIcons"); + if (current_icon != new_icon) { + + status_btn->set_icon(new_icon); + msg->show(); + } + } break; + case MESSAGE_WARNING: { + msg->add_color_override("font_color", get_color("warning_color", "Editor")); - status_btn->set_icon(get_icon("StatusWarning", "EditorIcons")); - break; - case MESSAGE_SUCCESS: + Ref<Texture> new_icon = get_icon("StatusWarning", "EditorIcons"); + if (current_icon != new_icon) { + + status_btn->set_icon(new_icon); + if (current_icon != get_icon("StatusSuccess", "EditorIcons")) + msg->hide(); + } + } break; + case MESSAGE_SUCCESS: { + msg->add_color_override("font_color", get_color("success_color", "Editor")); - status_btn->set_icon(get_icon("StatusSuccess", "EditorIcons")); - break; + Ref<Texture> new_icon = get_icon("StatusSuccess", "EditorIcons"); + if (current_icon != new_icon) { + + status_btn->set_icon(new_icon); + msg->hide(); + } + } break; } + + set_size(Size2(500, 0) * EDSCALE); } String _test_path() { - set_message(" "); - get_ok()->set_disabled(true); DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String valid_path; if (d->change_dir(project_path->get_text()) == OK) { @@ -127,6 +144,7 @@ private: if (valid_path == "") { set_message(TTR("The path does not exist."), MESSAGE_ERROR); memdelete(d); + get_ok()->set_disabled(true); return ""; } @@ -136,6 +154,7 @@ private: set_message(TTR("Please choose a 'project.godot' file."), MESSAGE_ERROR); memdelete(d); + get_ok()->set_disabled(true); return ""; } @@ -155,19 +174,22 @@ private: d->list_dir_end(); if (!is_empty) { + set_message(TTR("Your project will be created in a non empty folder (you might want to create a new folder)."), MESSAGE_WARNING); + memdelete(d); + get_ok()->set_disabled(false); + return valid_path; } - } else { - - if (d->file_exists("project.godot")) { + } else if (d->file_exists("project.godot")) { - set_message(TTR("Please choose a folder that does not contain a 'project.godot' file."), MESSAGE_ERROR); - memdelete(d); - return ""; - } + set_message(TTR("Please choose a folder that does not contain a 'project.godot' file."), MESSAGE_ERROR); + memdelete(d); + get_ok()->set_disabled(true); + return ""; } + set_message(TTR("That's a BINGO!")); memdelete(d); get_ok()->set_disabled(false); return valid_path; @@ -213,7 +235,6 @@ private: } String sp = p.simplify_path(); project_path->set_text(sp); - set_message(" "); // just so it does not disappear get_ok()->call_deferred("grab_focus"); } @@ -242,21 +263,32 @@ private: void _create_folder() { - if (project_name->get_text() == "" || created_folder_path != "") { + if (project_name->get_text() == "" || created_folder_path != "") return; - } DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); if (d->change_dir(project_path->get_text()) == OK) { + if (!d->dir_exists(project_name->get_text())) { + if (d->make_dir(project_name->get_text()) == OK) { + d->change_dir(project_name->get_text()); project_path->set_text(d->get_current_dir()); created_folder_path = d->get_current_dir(); create_dir->set_disabled(true); + } else { + + dialog_error->set_text(TTR("Couldn't create folder.")); + dialog_error->popup_centered_minsize(); } + } else { + + dialog_error->set_text(TTR("There is already a folder in this path with the specified name.")); + dialog_error->popup_centered_minsize(); } } + memdelete(d); } @@ -337,6 +369,7 @@ private: if (!pkg) { dialog_error->set_text(TTR("Error opening package file, not in zip format.")); + dialog_error->popup_centered_minsize(); return; } @@ -448,7 +481,10 @@ private: } void _toggle_message() { + msg->set_visible(!msg->is_visible()); + if (!msg->is_visible()) + set_size(Size2(500, 0) * EDSCALE); } void cancel_pressed() { @@ -457,6 +493,15 @@ private: project_path->clear(); project_name->clear(); + + if (status_btn->get_icon() == get_icon("StatusError", "EditorIcons")) + msg->show(); + } + + void _notification(int p_what) { + + if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) + _remove_created_folder(); } protected: @@ -558,7 +603,7 @@ public: _test_path(); } - popup_centered(Size2(500, 125) * EDSCALE); + popup_centered(Size2(500, 0) * EDSCALE); } ProjectDialog() { @@ -610,7 +655,6 @@ public: pphb->add_child(browse); msg = memnew(Label); - msg->set_text(TTR("That's a BINGO!")); msg->set_align(Label::ALIGN_CENTER); msg->hide(); vb->add_child(msg); @@ -652,19 +696,20 @@ struct ProjectItem { void ProjectManager::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - - Engine::get_singleton()->set_editor_hint(false); - - } else if (p_what == NOTIFICATION_READY) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { - if (scroll_childs->get_child_count() == 0) { - open_templates->popup_centered_minsize(); - } + Engine::get_singleton()->set_editor_hint(false); + } break; + case NOTIFICATION_READY: { - } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (scroll_childs->get_child_count() == 0) + open_templates->popup_centered_minsize(); + } break; + case NOTIFICATION_VISIBILITY_CHANGED: { - set_process_unhandled_input(is_visible_in_tree()); + set_process_unhandled_input(is_visible_in_tree()); + } break; } } @@ -1214,7 +1259,6 @@ void ProjectManager::_run_project_confirm() { Error err = OS::get_singleton()->execute(exec, args, false, &pid); ERR_FAIL_COND(err); } - //get_scene()->quit(); do not quit } void ProjectManager::_run_project() { @@ -1556,9 +1600,6 @@ ProjectManager::ProjectManager() { scroll_childs->set_h_size_flags(SIZE_EXPAND_FILL); scroll->add_child(scroll_childs); - //HBoxContainer *hb = memnew( HBoxContainer ); - //vb->add_child(hb); - Button *open = memnew(Button); open->set_text(TTR("Edit")); tree_vb->add_child(open); @@ -1663,7 +1704,7 @@ ProjectManager::ProjectManager() { cancel->connect("pressed", this, "_exit_dialog"); vb->add_child(cc); - // + ////////////////////////////////////////////////////////////// language_restart_ask = memnew(ConfirmationDialog); language_restart_ask->get_ok()->set_text(TTR("Restart Now")); @@ -1772,12 +1813,9 @@ void ProjectListFilter::_filter_option_selected(int p_idx) { } void ProjectListFilter::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - clear_search_button->set_icon(get_icon("Close", "EditorIcons")); - } break; - } + if (p_what == NOTIFICATION_ENTER_TREE) + clear_search_button->set_icon(get_icon("Close", "EditorIcons")); } void ProjectListFilter::_bind_methods() { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7e8a6fcb6d..e7da78a35c 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -307,7 +307,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_REPLACE: { - create_dialog->popup_create(false); + create_dialog->popup_create(false, true); } break; case TOOL_ATTACH_SCRIPT: { @@ -417,7 +417,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (editor_selection->is_selected(edited_scene)) { current_option = -1; - //accept->get_cancel()->hide(); accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("This operation can't be done on the tree root.")); accept->popup_centered_minsize(); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index ad6ea2180f..96863a59d2 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -232,7 +232,7 @@ void ScriptCreateDialog::_lang_changed(int l) { String path = file_path->get_text(); String extension = ""; if (path != "") { - if (path.find(".") >= 0) { + if (path.find(".") != -1) { extension = path.get_extension(); } @@ -359,16 +359,14 @@ void ScriptCreateDialog::_path_changed(const String &p_path) { return; } - if (p.find("/") || p.find("\\")) { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (d->change_dir(p.get_base_dir()) != OK) { - _msg_path_valid(false, TTR("Invalid base path")); - memdelete(d); - _update_dialog(); - return; - } + DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (d->change_dir(p.get_base_dir()) != OK) { + _msg_path_valid(false, TTR("Invalid base path")); memdelete(d); + _update_dialog(); + return; } + memdelete(d); /* Does file already exist */ diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 4fe7bef9f7..f1a5aa4654 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1686,6 +1686,45 @@ void ScriptEditorDebugger::_clear_remote_objects() { remote_objects.clear(); } +void ScriptEditorDebugger::_clear_errors_list() { + + error_list->clear(); + error_count = 0; + _notification(NOTIFICATION_PROCESS); +} + +// Right click on specific file(s) or folder(s). +void ScriptEditorDebugger::_error_list_item_rmb_selected(int p_item, const Vector2 &p_pos) { + + item_menu->clear(); + item_menu->set_size(Size2(1, 1)); + + // Allow specific actions only on one item. + bool single_item_selected = error_list->get_selected_items().size() == 1; + + if (single_item_selected) { + item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Error"), ITEM_MENU_COPY_ERROR); + } + + if (item_menu->get_item_count() > 0) { + item_menu->set_position(error_list->get_global_position() + p_pos); + item_menu->popup(); + } +} + +void ScriptEditorDebugger::_item_menu_id_pressed(int p_option) { + + switch (p_option) { + + case ITEM_MENU_COPY_ERROR: { + String title = error_list->get_item_text(error_list->get_current()); + String desc = error_list->get_item_tooltip(error_list->get_current()); + + OS::get_singleton()->set_clipboard(title + "\n----------\n" + desc); + } break; + } +} + void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_stack_dump_frame_selected"), &ScriptEditorDebugger::_stack_dump_frame_selected); @@ -1705,6 +1744,10 @@ void ScriptEditorDebugger::_bind_methods() { ClassDB::bind_method(D_METHOD("_error_stack_selected"), &ScriptEditorDebugger::_error_stack_selected); ClassDB::bind_method(D_METHOD("_profiler_activate"), &ScriptEditorDebugger::_profiler_activate); ClassDB::bind_method(D_METHOD("_profiler_seeked"), &ScriptEditorDebugger::_profiler_seeked); + ClassDB::bind_method(D_METHOD("_clear_errors_list"), &ScriptEditorDebugger::_clear_errors_list); + + ClassDB::bind_method(D_METHOD("_error_list_item_rmb_selected"), &ScriptEditorDebugger::_error_list_item_rmb_selected); + ClassDB::bind_method(D_METHOD("_item_menu_id_pressed"), &ScriptEditorDebugger::_item_menu_id_pressed); ClassDB::bind_method(D_METHOD("_paused"), &ScriptEditorDebugger::_paused); @@ -1829,9 +1872,31 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { error_split = memnew(HSplitContainer); VBoxContainer *errvb = memnew(VBoxContainer); + HBoxContainer *errhb = memnew(HBoxContainer); errvb->set_h_size_flags(SIZE_EXPAND_FILL); + Label *velb = memnew(Label(TTR("Errors:"))); + velb->set_h_size_flags(SIZE_EXPAND_FILL); + errhb->add_child(velb); + + clearbutton = memnew(Button); + clearbutton->set_text(TTR("Clear")); + clearbutton->connect("pressed", this, "_clear_errors_list"); + errhb->add_child(clearbutton); + errvb->add_child(errhb); + error_list = memnew(ItemList); - errvb->add_margin_child(TTR("Errors:"), error_list, true); + error_list->set_v_size_flags(SIZE_EXPAND_FILL); + error_list->set_h_size_flags(SIZE_EXPAND_FILL); + error_list->connect("item_rmb_selected", this, "_error_list_item_rmb_selected"); + error_list->set_allow_rmb_select(true); + error_list->set_autoscroll_to_bottom(true); + + item_menu = memnew(PopupMenu); + item_menu->connect("id_pressed", this, "_item_menu_id_pressed"); + error_list->add_child(item_menu); + + errvb->add_child(error_list); + error_split->add_child(errvb); errvb = memnew(VBoxContainer); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index e380a56b18..7f8348d82f 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -62,6 +62,10 @@ class ScriptEditorDebugger : public Control { MESSAGE_SUCCESS, }; + enum ItemMenu { + ITEM_MENU_COPY_ERROR, + }; + AcceptDialog *msgdialog; Button *debugger_button; @@ -85,6 +89,8 @@ class ScriptEditorDebugger : public Control { ItemList *error_list; ItemList *error_stack; Tree *inspect_scene_tree; + Button *clearbutton; + PopupMenu *item_menu; int error_count; int last_error_count; @@ -175,6 +181,10 @@ class ScriptEditorDebugger : public Control { void _set_remote_object(ObjectID p_id, ScriptEditorDebuggerInspectedObject *p_obj); void _clear_remote_objects(); + void _clear_errors_list(); + + void _error_list_item_rmb_selected(int p_item, const Vector2 &p_pos); + void _item_menu_id_pressed(int p_option); protected: void _notification(int p_what); diff --git a/main/input_default.cpp b/main/input_default.cpp index 5026b8bb39..c3454d86f3 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -497,26 +497,16 @@ bool InputDefault::is_emulating_touchscreen() const { return emulate_touch; } -void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot) { - /* no longer supported, leaving this for reference to anyone who might want to implement hardware cursors +void InputDefault::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (Engine::get_singleton()->is_editor_hint()) + return; + if (custom_cursor == p_cursor) return; custom_cursor = p_cursor; - if (p_cursor.is_null()) { - set_mouse_mode(MOUSE_MODE_VISIBLE); - //removed, please insist us to implement hardare cursors - //VisualServer::get_singleton()->cursor_set_visible(false); - } else { - Ref<AtlasTexture> atex = custom_cursor; - Rect2 region = atex.is_valid() ? atex->get_region() : Rect2(); - set_mouse_mode(MOUSE_MODE_HIDDEN); - VisualServer::get_singleton()->cursor_set_visible(true); - VisualServer::get_singleton()->cursor_set_texture(custom_cursor->get_rid(), p_hotspot, 0, region); - VisualServer::get_singleton()->cursor_set_pos(get_mouse_position()); - } - */ + OS::get_singleton()->set_custom_mouse_cursor(p_cursor, (OS::CursorShape)p_shape, p_hotspot); } void InputDefault::set_mouse_in_window(bool p_in_window) { diff --git a/main/input_default.h b/main/input_default.h index 62ba0b0c32..3d9a809325 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -225,7 +225,7 @@ public: void set_emulate_touch(bool p_emulate); virtual bool is_emulating_touchscreen() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, const Vector2 &p_hotspot = Vector2()); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); virtual void set_mouse_in_window(bool p_in_window); void parse_mapping(String p_mapping); diff --git a/main/main.cpp b/main/main.cpp index 5936a323d4..ac68fe1296 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1107,7 +1107,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { if (cursor.is_valid()) { //print_line("loaded ok"); Vector2 hotspot = ProjectSettings::get_singleton()->get("display/mouse_cursor/custom_image_hotspot"); - Input::get_singleton()->set_custom_mouse_cursor(cursor, hotspot); + Input::get_singleton()->set_custom_mouse_cursor(cursor, Input::CURSOR_ARROW, hotspot); } } #ifdef TOOLS_ENABLED diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist index 2a4914ec75..895eda14db 100755 --- a/misc/dist/osx_tools.app/Contents/Info.plist +++ b/misc/dist/osx_tools.app/Contents/Info.plist @@ -9,7 +9,7 @@ <key>CFBundleName</key> <string>Godot</string> <key>CFBundleGetInfoString</key> - <string>(c) 2007-2018 Juan Linietsky, Ariel Manzur./string> + <string>(c) 2007-2018 Juan Linietsky, Ariel Manzur.</string> <key>CFBundleIconFile</key> <string>Godot.icns</string> <key>CFBundleIdentifier</key> @@ -25,7 +25,7 @@ <key>CFBundleVersion</key> <string>3.0-dev</string> <key>NSHumanReadableCopyright</key> - <string>© 2007-2018 Juan Linietsky, Ariel Manzur./string> + <string>© 2007-2018 Juan Linietsky, Ariel Manzur.</string> <key>LSMinimumSystemVersion</key> <string>10.9.0</string> <key>LSMinimumSystemVersionByArchitecture</key> diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index d97f355400..3023b489e5 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -605,7 +605,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #ifdef DEBUG_ENABLED if (!valid) { if (src->has_method(*index)) { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' ?"; + err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?"; } else { err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; } diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index e9bb90631d..c30c6d77b9 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -95,6 +95,22 @@ Returns whether or not grid items are centered on the Z axis. </description> </method> + <method name="get_collision_layer_bit" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="bit" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_collision_mask_bit" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="bit" type="int"> + </argument> + <description> + </description> + </method> <method name="get_meshes"> <return type="Array"> </return> @@ -222,6 +238,26 @@ <description> </description> </method> + <method name="set_collision_layer_bit"> + <return type="void"> + </return> + <argument index="0" name="bit" type="int"> + </argument> + <argument index="1" name="value" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_collision_mask_bit"> + <return type="void"> + </return> + <argument index="0" name="bit" type="int"> + </argument> + <argument index="1" name="value" type="bool"> + </argument> + <description> + </description> + </method> <method name="set_octant_size"> <return type="void"> </return> @@ -249,6 +285,12 @@ </description> </method> </methods> + <members> + <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + </member> + <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + </member> + </members> <constants> <constant name="INVALID_CELL_ITEM" value="-1"> Invalid cell item that can be used in [method set_cell_item] to clear cells (or represent an empty cell in [method get_cell_item]). diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index bd37118847..9a03bc410a 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -198,6 +198,58 @@ void GridMap::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE)); } +void GridMap::set_collision_layer(uint32_t p_layer) { + + collision_layer = p_layer; + _reset_physic_bodies_collision_filters(); +} + +uint32_t GridMap::get_collision_layer() const { + + return collision_layer; +} + +void GridMap::set_collision_mask(uint32_t p_mask) { + + collision_mask = p_mask; + _reset_physic_bodies_collision_filters(); +} + +uint32_t GridMap::get_collision_mask() const { + + return collision_mask; +} + +void GridMap::set_collision_mask_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_mask(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_mask(mask); +} + +bool GridMap::get_collision_mask_bit(int p_bit) const { + + return get_collision_mask() & (1 << p_bit); +} + +void GridMap::set_collision_layer_bit(int p_bit, bool p_value) { + + uint32_t mask = get_collision_layer(); + if (p_value) + mask |= 1 << p_bit; + else + mask &= ~(1 << p_bit); + set_collision_layer(mask); +} + +bool GridMap::get_collision_layer_bit(int p_bit) const { + + return get_collision_layer() & (1 << p_bit); +} + void GridMap::set_theme(const Ref<MeshLibrary> &p_theme) { if (!theme.is_null()) @@ -311,6 +363,8 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { g->dirty = true; g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); PhysicsServer::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id()); + PhysicsServer::get_singleton()->body_set_collision_layer(g->static_body, collision_layer); + PhysicsServer::get_singleton()->body_set_collision_mask(g->static_body, collision_mask); SceneTree *st = SceneTree::get_singleton(); if (st && st->is_debugging_collisions_hint()) { @@ -575,6 +629,13 @@ bool GridMap::_octant_update(const OctantKey &p_key) { return false; } +void GridMap::_reset_physic_bodies_collision_filters() { + for (Map<OctantKey, Octant *>::Element *E = octant_map.front(); E; E = E->next()) { + PhysicsServer::get_singleton()->body_set_collision_layer(E->get()->static_body, collision_layer); + PhysicsServer::get_singleton()->body_set_collision_mask(E->get()->static_body, collision_mask); + } +} + void GridMap::_octant_enter_world(const OctantKey &p_key) { ERR_FAIL_COND(!octant_map.has(p_key)); @@ -815,6 +876,18 @@ void GridMap::_update_octants_callback() { void GridMap::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &GridMap::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &GridMap::get_collision_layer); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "mask"), &GridMap::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &GridMap::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &GridMap::set_collision_mask_bit); + ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &GridMap::get_collision_mask_bit); + + ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &GridMap::set_collision_layer_bit); + ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &GridMap::get_collision_layer_bit); + ClassDB::bind_method(D_METHOD("set_theme", "theme"), &GridMap::set_theme); ClassDB::bind_method(D_METHOD("get_theme"), &GridMap::get_theme); @@ -855,6 +928,10 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_baked_meshes"), &GridMap::clear_baked_meshes); ClassDB::bind_method(D_METHOD("make_baked_meshes", "gen_lightmap_uv", "lightmap_uv_texel_size"), &GridMap::make_baked_meshes, DEFVAL(false), DEFVAL(0.1)); + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + BIND_CONSTANT(INVALID_CELL_ITEM); } @@ -1067,6 +1144,9 @@ RID GridMap::get_bake_mesh_instance(int p_idx) { GridMap::GridMap() { + collision_layer = 1; + collision_mask = 1; + cell_size = Vector3(2, 2, 2); octant_size = 8; awaiting_update = false; diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 18a9551edf..7b97fe3183 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -136,6 +136,9 @@ class GridMap : public Spatial { OctantKey() { key = 0; } }; + uint32_t collision_layer; + uint32_t collision_mask; + Transform last_transform; bool _in_tree; @@ -173,6 +176,7 @@ class GridMap : public Spatial { return Vector3(p_key.x, p_key.y, p_key.z) * cell_size * octant_size; } + void _reset_physic_bodies_collision_filters(); void _octant_enter_world(const OctantKey &p_key); void _octant_exit_world(const OctantKey &p_key); bool _octant_update(const OctantKey &p_key); @@ -210,6 +214,18 @@ public: INVALID_CELL_ITEM = -1 }; + void set_collision_layer(uint32_t p_layer); + uint32_t get_collision_layer() const; + + void set_collision_mask(uint32_t p_mask); + uint32_t get_collision_mask() const; + + void set_collision_layer_bit(int p_bit, bool p_value); + bool get_collision_layer_bit(int p_bit) const; + + void set_collision_mask_bit(int p_bit, bool p_value); + bool get_collision_mask_bit(int p_bit) const; + void set_theme(const Ref<MeshLibrary> &p_theme); Ref<MeshLibrary> get_theme() const; diff --git a/modules/thekla_unwrap/register_types.cpp b/modules/thekla_unwrap/register_types.cpp index 2dc9217e48..eb11325dde 100644 --- a/modules/thekla_unwrap/register_types.cpp +++ b/modules/thekla_unwrap/register_types.cpp @@ -28,7 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" +#include "error_macros.h" #include "thirdparty/thekla_atlas/thekla/thekla_atlas.h" + #include <stdio.h> #include <stdlib.h> extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y); @@ -74,6 +76,11 @@ bool thekla_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver delete[] input_mesh.face_array; delete[] input_mesh.vertex_array; + if (output == NULL) { + ERR_PRINT("could not generate atlas output mesh"); + return false; + } + if (err != Thekla::Atlas_Error_Success) { printf("error with atlas\n"); } else { diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 5702134791..2ff3fb6d7a 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -309,9 +309,6 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { /* and now we have it all. initialize decoders */ if (theora_p) { td = th_decode_alloc(&ti, ts); - printf("Ogg logical stream %lx is Theora %dx%d %.02f fps", - to.serialno, ti.pic_width, ti.pic_height, - (double)ti.fps_numerator / ti.fps_denominator); px_fmt = ti.pixel_fmt; switch (ti.pixel_fmt) { case TH_PF_420: printf(" 4:2:0 video\n"); break; @@ -322,9 +319,6 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { printf(" video\n (UNKNOWN Chroma sampling!)\n"); break; } - if (ti.pic_width != ti.frame_width || ti.pic_height != ti.frame_height) - printf(" Frame content is %dx%d with offset (%d,%d).\n", - ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y); th_decode_ctl(td, TH_DECCTL_GET_PPLEVEL_MAX, &pp_level_max, sizeof(pp_level_max)); pp_level = 0; @@ -351,10 +345,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { if (vorbis_p) { vorbis_synthesis_init(&vd, &vi); vorbis_block_init(&vd, &vb); - fprintf(stderr, "Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n", - vo.serialno, vi.channels, vi.rate); //_setup(vi.channels, vi.rate); - } else { /* tear down the partial vorbis setup */ vorbis_info_clear(&vi); diff --git a/platform/android/SCsub b/platform/android/SCsub index 0cd91276ef..d2285a82dd 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -104,7 +104,7 @@ gradle_asset_dirs_text = "" gradle_default_config_text = "" minSdk = 18 -targetSdk = 23 +targetSdk = 27 for x in env.android_default_config: if x.startswith("minSdkVersion") and int(x.split(" ")[-1]) < minSdk: diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template index 4a44d1c5f9..13b4d3b6c7 100644 --- a/platform/android/build.gradle.template +++ b/platform/android/build.gradle.template @@ -31,8 +31,8 @@ android { disable 'MissingTranslation' } - compileSdkVersion 26 - buildToolsVersion "26.0.1" + compileSdkVersion 27 + buildToolsVersion "27.0.3" useLibrary 'org.apache.http.legacy' packagingOptions { diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties index ee6901c9d7..fe37fa74a9 100644 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index dd23a81977..97e81874c9 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -248,6 +248,9 @@ void OS_Android::set_cursor_shape(CursorShape p_shape) { //android really really really has no mouse.. how amazing.. } +void OS_Android::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +} + void OS_Android::main_loop_begin() { if (main_loop) diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 744dce7ff1..adfd88b59b 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -182,6 +182,7 @@ public: virtual bool can_draw() const; virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); void main_loop_begin(); bool main_loop_iterate(); diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index 3324b33e95..65a220f8ca 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -200,6 +200,10 @@ void OS_Haiku::set_cursor_shape(CursorShape p_shape) { //ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED"); } +void OS_Haiku::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + // TODO +} + int OS_Haiku::get_screen_count() const { // TODO: implement get_screen_count() return 1; diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index b4d0add04b..6d69c1997f 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -87,6 +87,7 @@ public: virtual Point2 get_mouse_position() const; virtual int get_mouse_button_state() const; virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); virtual int get_screen_count() const; virtual int get_current_screen() const; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index dcb7b8b1f4..507d4f22db 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -490,6 +490,8 @@ String OSIPhone::get_user_data_dir() const { return data_dir; }; +void OSIPhone::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot){}; + String OSIPhone::get_name() { return "iOS"; diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 7e310e3a03..8e701a7fab 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -173,6 +173,7 @@ public: virtual int get_virtual_keyboard_height() const; virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); virtual Size2 get_window_size() const; diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index a24bf6c0bc..0411b4e72b 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -41,6 +41,7 @@ #include "servers/visual/rasterizer.h" #include "servers/visual/visual_server_wrap_mt.h" #include "servers/visual_server.h" +#include <AppKit/NSCursor.h> #include <ApplicationServices/ApplicationServices.h> #undef CursorShape @@ -86,6 +87,7 @@ public: id context; CursorShape cursor_shape; + NSCursor *cursors[CURSOR_MAX] = { NULL }; MouseMode mouse_mode; String title; @@ -137,6 +139,7 @@ public: virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); virtual void set_mouse_show(bool p_show); virtual void set_mouse_grab(bool p_grab); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 0cd02663da..99c5995d7a 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -577,8 +577,11 @@ static void _mouseDownEvent(NSEvent *event, int index, int mask, bool pressed) { return; if (OS_OSX::singleton->main_loop && OS_OSX::singleton->mouse_mode != OS::MOUSE_MODE_CAPTURED) OS_OSX::singleton->main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER); - if (OS_OSX::singleton->input) + if (OS_OSX::singleton->input) { OS_OSX::singleton->input->set_mouse_in_window(true); + OS_OSX::singleton->cursor_shape = OS::CURSOR_MAX; + OS_OSX::singleton->set_cursor_shape(OS::CURSOR_ARROW); + } } - (void)magnifyWithEvent:(NSEvent *)event { @@ -1240,30 +1243,84 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) { if (cursor_shape == p_shape) return; - switch (p_shape) { - case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break; - case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break; - case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break; - case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break; - case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break; - case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break; - case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break; - case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break; - case CURSOR_FORBIDDEN: [[NSCursor arrowCursor] set]; break; - case CURSOR_VSIZE: [[NSCursor resizeUpDownCursor] set]; break; - case CURSOR_HSIZE: [[NSCursor resizeLeftRightCursor] set]; break; - case CURSOR_BDIAGSIZE: [[NSCursor arrowCursor] set]; break; - case CURSOR_FDIAGSIZE: [[NSCursor arrowCursor] set]; break; - case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break; - case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break; - case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break; - case CURSOR_HELP: [[NSCursor arrowCursor] set]; break; - default: {}; + if (cursors[p_shape] != NULL) { + [cursors[p_shape] set]; + } else { + switch (p_shape) { + case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break; + case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break; + case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break; + case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break; + case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break; + case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break; + case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break; + case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break; + case CURSOR_FORBIDDEN: [[NSCursor arrowCursor] set]; break; + case CURSOR_VSIZE: [[NSCursor resizeUpDownCursor] set]; break; + case CURSOR_HSIZE: [[NSCursor resizeLeftRightCursor] set]; break; + case CURSOR_BDIAGSIZE: [[NSCursor arrowCursor] set]; break; + case CURSOR_FDIAGSIZE: [[NSCursor arrowCursor] set]; break; + case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break; + case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break; + case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break; + case CURSOR_HELP: [[NSCursor arrowCursor] set]; break; + default: {}; + } } cursor_shape = p_shape; } +void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (p_cursor.is_valid()) { + Ref<Texture> texture = p_cursor; + Ref<Image> image = texture->get_data(); + + int image_size = 32 * 32; + + ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + + NSBitmapImageRep *imgrep = [[[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:image->get_width() + pixelsHigh:image->get_height() + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:image->get_width() * 4 + bitsPerPixel:32] autorelease]; + + ERR_FAIL_COND(imgrep == nil); + uint8_t *pixels = [imgrep bitmapData]; + + int len = image->get_width() * image->get_height(); + PoolVector<uint8_t> data = image->get_data(); + PoolVector<uint8_t>::Read r = data.read(); + + /* Premultiply the alpha channel */ + for (int i = 0; i < len; i++) { + uint8_t alpha = r[i * 4 + 3]; + pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); + pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); + pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); + pixels[i * 4 + 3] = alpha; + } + + NSImage *nsimage = [[[NSImage alloc] initWithSize:NSMakeSize(image->get_width(), image->get_height())] autorelease]; + [nsimage addRepresentation:imgrep]; + + NSCursor *cursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSMakePoint(p_hotspot.x, p_hotspot.y)]; + + cursors[p_shape] = cursor; + + if (p_shape == CURSOR_ARROW) { + [cursor set]; + } + } +} + void OS_OSX::set_mouse_show(bool p_show) { } diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index c34567aaab..13264ed46e 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -179,6 +179,9 @@ void OS_Server::move_window_to_foreground() { void OS_Server::set_cursor_shape(CursorShape p_shape) { } +void OS_Server::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { +} + OS::PowerState OS_Server::get_power_state() { return power_manager->get_power_state(); } diff --git a/platform/server/os_server.h b/platform/server/os_server.h index c58c48500e..7b7d4a38a8 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -75,6 +75,7 @@ public: virtual String get_name(); virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); virtual void set_mouse_show(bool p_show); virtual void set_mouse_grab(bool p_grab); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index ceccfb281c..603a918cca 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -651,6 +651,10 @@ void OSUWP::set_cursor_shape(CursorShape p_shape) { cursor_shape = p_shape; } +void OSUWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + // TODO +} + Error OSUWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { return FAILED; diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 7c2371b097..976eda1fe1 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -218,6 +218,7 @@ public: virtual String get_clipboard() const; void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); void set_icon(const Ref<Image> &p_icon); virtual String get_executable_path() const; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 8edc2c5cff..e3af82b629 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1844,10 +1844,125 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) { IDC_HELP }; - SetCursor(LoadCursor(hInstance, win_cursors[p_shape])); + if (cursors[p_shape] != NULL) { + SetCursor(cursors[p_shape]); + } else { + SetCursor(LoadCursor(hInstance, win_cursors[p_shape])); + } cursor_shape = p_shape; } +void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (p_cursor.is_valid()) { + Ref<Texture> texture = p_cursor; + Ref<Image> image = texture->get_data(); + + UINT image_size = 32 * 32; + UINT size = sizeof(UINT) * image_size; + + ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + + // Create the BITMAP with alpha channel + COLORREF *buffer = (COLORREF *)malloc(sizeof(COLORREF) * image_size); + + image->lock(); + for (UINT index = 0; index < image_size; index++) { + int column_index = floor(index / 32); + int row_index = index % 32; + + Color pcColor = image->get_pixel(row_index, column_index); + *(buffer + index) = image->get_pixel(row_index, column_index).to_argb32(); + } + image->unlock(); + + // Using 4 channels, so 4 * 8 bits + HBITMAP bitmap = CreateBitmap(32, 32, 1, 4 * 8, buffer); + COLORREF clrTransparent = -1; + + // Create the AND and XOR masks for the bitmap + HBITMAP hAndMask = NULL; + HBITMAP hXorMask = NULL; + + GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask); + + if (NULL == hAndMask || NULL == hXorMask) { + return; + } + + // Finally, create the icon + ICONINFO iconinfo = { 0 }; + iconinfo.fIcon = FALSE; + iconinfo.xHotspot = p_hotspot.x; + iconinfo.yHotspot = p_hotspot.y; + iconinfo.hbmMask = hAndMask; + iconinfo.hbmColor = hXorMask; + + cursors[p_shape] = CreateIconIndirect(&iconinfo); + + if (p_shape == CURSOR_ARROW) { + SetCursor(cursors[p_shape]); + } + + if (hAndMask != NULL) { + DeleteObject(hAndMask); + } + + if (hXorMask != NULL) { + DeleteObject(hXorMask); + } + } +} + +void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) { + + // Get the system display DC + HDC hDC = GetDC(NULL); + + // Create helper DC + HDC hMainDC = CreateCompatibleDC(hDC); + HDC hAndMaskDC = CreateCompatibleDC(hDC); + HDC hXorMaskDC = CreateCompatibleDC(hDC); + + // Get the dimensions of the source bitmap + BITMAP bm; + GetObject(hSourceBitmap, sizeof(BITMAP), &bm); + + // Create the mask bitmaps + hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color + hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color + + // Release the system display DC + ReleaseDC(NULL, hDC); + + // Select the bitmaps to helper DC + HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap); + HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap); + HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap); + + // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap + // with 'clrTransparent' will be white pixels of the monochrome bitmap + SetBkColor(hMainDC, clrTransparent); + BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY); + + // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap + // with 'clrTransparent' will be black and rest the pixels same as corresponding + // pixels of the source bitmap + SetBkColor(hXorMaskDC, RGB(0, 0, 0)); + SetTextColor(hXorMaskDC, RGB(255, 255, 255)); + BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY); + BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND); + + // Deselect bitmaps from the helper DC + SelectObject(hMainDC, hOldMainBitmap); + SelectObject(hAndMaskDC, hOldAndMaskBitmap); + SelectObject(hXorMaskDC, hOldXorMaskBitmap); + + // Delete the helper DC + DeleteDC(hXorMaskDC); + DeleteDC(hAndMaskDC); + DeleteDC(hMainDC); +} + Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) { if (p_blocking && r_pipe) { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index d709fb3fe5..9d254ccf27 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -113,6 +113,7 @@ class OS_Windows : public OS { bool window_has_focus; uint32_t last_button_state; + HCURSOR cursors[CURSOR_MAX] = { NULL }; CursorShape cursor_shape; InputDefault *input; @@ -244,6 +245,8 @@ public: virtual String get_clipboard() const; void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); + void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap); void set_icon(const Ref<Image> &p_icon); virtual String get_executable_path() const; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 240d6638a9..e9920b18a4 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1050,13 +1050,59 @@ void OS_X11::set_window_maximized(bool p_enabled) { XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); - while (p_enabled && !is_window_maximized()) { - // Wait for effective resizing (so the GLX context is too). + if (is_window_maximize_allowed()) { + while (p_enabled && !is_window_maximized()) { + // Wait for effective resizing (so the GLX context is too). + } } maximized = p_enabled; } +bool OS_X11::is_window_maximize_allowed() { + Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + + int result = XGetWindowProperty( + x11_display, + x11_window, + property, + 0, + 1024, + False, + XA_ATOM, + &type, + &format, + &len, + &remaining, + &data); + + if (result == Success) { + Atom *atoms = (Atom *)data; + Atom wm_act_max_horz = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); + Atom wm_act_max_vert = XInternAtom(x11_display, "_NET_WM_ACTION_MAXIMIZE_VERT", False); + bool found_wm_act_max_horz = false; + bool found_wm_act_max_vert = false; + + for (unsigned int i = 0; i < len; i++) { + if (atoms[i] == wm_act_max_horz) + found_wm_act_max_horz = true; + if (atoms[i] == wm_act_max_vert) + found_wm_act_max_vert = true; + + if (found_wm_act_max_horz || found_wm_act_max_vert) + return true; + } + XFree(atoms); + } + + return false; +} + bool OS_X11::is_window_maximized() const { // Using EWMH -- Extended Window Manager Hints Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False); @@ -2205,6 +2251,48 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) { current_cursor = p_shape; } +void OS_X11::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (p_cursor.is_valid()) { + Ref<Texture> texture = p_cursor; + Ref<Image> image = texture->get_data(); + + ERR_FAIL_COND(texture->get_width() != 32 || texture->get_height() != 32); + + // Create the cursor structure + XcursorImage *cursor_image = XcursorImageCreate(texture->get_width(), texture->get_height()); + XcursorUInt image_size = 32 * 32; + XcursorDim size = sizeof(XcursorPixel) * image_size; + + cursor_image->version = 1; + cursor_image->size = size; + cursor_image->xhot = p_hotspot.x; + cursor_image->yhot = p_hotspot.y; + + // allocate memory to contain the whole file + cursor_image->pixels = (XcursorPixel *)malloc(size); + + image->lock(); + + for (XcursorPixel index = 0; index < image_size; index++) { + int column_index = floor(index / 32); + int row_index = index % 32; + + *(cursor_image->pixels + index) = image->get_pixel(row_index, column_index).to_argb32(); + } + + image->unlock(); + + ERR_FAIL_COND(cursor_image->pixels == NULL); + + // Save it for a further usage + cursors[p_shape] = XcursorImageLoadCursor(x11_display, cursor_image); + + if (p_shape == CURSOR_ARROW) { + XDefineCursor(x11_display, x11_window, cursors[p_shape]); + } + } +} + void OS_X11::release_rendering_thread() { context_gl->release_current(); diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 59b9c8caa8..04243a9b36 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -200,10 +200,13 @@ protected: void _window_changed(XEvent *xevent); + bool is_window_maximize_allowed(); + public: virtual String get_name(); virtual void set_cursor_shape(CursorShape p_shape); + virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index e994ebb5aa..1db9e4902a 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -229,6 +229,7 @@ public: // Used to resize/move/select the node virtual void _edit_set_rect(const Rect2 &p_rect){}; virtual Rect2 _edit_get_rect() const { return Rect2(-32, -32, 64, 64); }; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; } Rect2 _edit_get_item_and_children_rect() const; virtual bool _edit_use_rect() const { return false; }; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index eaa650b140..8c6b25f296 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -131,7 +131,7 @@ void CollisionPolygon2D::_notification(int p_what) { /*if (Engine::get_singleton()->is_editor_hint()) { //display above all else set_z_as_relative(false); - set_z(VS::CANVAS_ITEM_Z_MAX - 1); + set_z_index(VS::CANVAS_ITEM_Z_MAX - 1); }*/ } break; @@ -248,6 +248,11 @@ Rect2 CollisionPolygon2D::_edit_get_rect() const { return aabb; } +bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return Geometry::is_point_in_polygon(p_point, Variant(polygon)); +} + String CollisionPolygon2D::get_configuration_warning() const { if (!Object::cast_to<CollisionObject2D>(get_parent())) { diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 4c8b55a9ee..fa7e5e1046 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -70,6 +70,7 @@ public: Vector<Point2> get_polygon() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; virtual String get_configuration_warning() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 1cadbe83d0..1956e23421 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -64,7 +64,7 @@ void CollisionShape2D::_notification(int p_what) { /*if (Engine::get_singleton()->is_editor_hint()) { //display above all else set_z_as_relative(false); - set_z(VS::CANVAS_ITEM_Z_MAX - 1); + set_z_index(VS::CANVAS_ITEM_Z_MAX - 1); }*/ } break; @@ -163,6 +163,14 @@ Rect2 CollisionShape2D::_edit_get_rect() const { return rect; } +bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + if (!shape.is_valid()) + return false; + + return shape->_edit_is_selected_on_click(p_point, p_tolerance); +} + String CollisionShape2D::get_configuration_warning() const { if (!Object::cast_to<CollisionObject2D>(get_parent())) { diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 833d9ae5cb..921066c5c8 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -52,6 +52,7 @@ protected: public: virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; void set_shape(const Ref<Shape2D> &p_shape); Ref<Shape2D> get_shape() const; diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index f108df140f..abc80216d4 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -48,6 +48,32 @@ Line2D::Line2D() : _round_precision = 8; } +Rect2 Line2D::_edit_get_rect() const { + + if (_points.size() == 0) + return Rect2(0, 0, 0, 0); + Vector2 d = Vector2(_width, _width); + Rect2 aabb = Rect2(_points[0] - d, 2 * d); + for (int i = 1; i < _points.size(); i++) { + aabb.expand_to(_points[i] - d); + aabb.expand_to(_points[i] + d); + } + return aabb; +} + +bool Line2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + const real_t d = _width / 2 + p_tolerance; + PoolVector<Vector2>::Read points = _points.read(); + for (int i = 0; i < _points.size() - 1; i++) { + Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, &points[i]); + if (p.distance_to(p_point) <= d) + return true; + } + + return false; +} + void Line2D::set_points(const PoolVector<Vector2> &p_points) { _points = p_points; update(); diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 123728ab39..54a4683dc7 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -57,6 +57,9 @@ public: Line2D(); + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_points(const PoolVector<Vector2> &p_points); PoolVector<Vector2> get_points() const; diff --git a/scene/2d/navigation_polygon.cpp b/scene/2d/navigation_polygon.cpp index 9c297db52b..dde41dbf3f 100644 --- a/scene/2d/navigation_polygon.cpp +++ b/scene/2d/navigation_polygon.cpp @@ -35,9 +35,50 @@ #include "thirdparty/misc/triangulator.h" +Rect2 NavigationPolygon::_edit_get_rect() const { + + if (rect_cache_dirty) { + item_rect = Rect2(); + bool first = true; + + for (int i = 0; i < outlines.size(); i++) { + const PoolVector<Vector2> &outline = outlines[i]; + const int outline_size = outline.size(); + if (outline_size < 3) + continue; + PoolVector<Vector2>::Read p = outline.read(); + for (int j = 0; j < outline_size; j++) { + if (first) { + item_rect = Rect2(p[j], Vector2(0, 0)); + first = false; + } else { + item_rect.expand_to(p[j]); + } + } + } + + rect_cache_dirty = false; + } + return item_rect; +} + +bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + for (int i = 0; i < outlines.size(); i++) { + const PoolVector<Vector2> &outline = outlines[i]; + const int outline_size = outline.size(); + if (outline_size < 3) + continue; + if (Geometry::is_point_in_polygon(p_point, Variant(outline))) + return true; + } + return false; +} + void NavigationPolygon::set_vertices(const PoolVector<Vector2> &p_vertices) { vertices = p_vertices; + rect_cache_dirty = true; } PoolVector<Vector2> NavigationPolygon::get_vertices() const { @@ -70,6 +111,7 @@ void NavigationPolygon::_set_outlines(const Array &p_array) { for (int i = 0; i < p_array.size(); i++) { outlines[i] = p_array[i]; } + rect_cache_dirty = true; } Array NavigationPolygon::_get_outlines() const { @@ -93,6 +135,7 @@ void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) { void NavigationPolygon::add_outline_at_index(const PoolVector<Vector2> &p_outline, int p_index) { outlines.insert(p_index, p_outline); + rect_cache_dirty = true; } int NavigationPolygon::get_polygon_count() const { @@ -112,6 +155,7 @@ void NavigationPolygon::clear_polygons() { void NavigationPolygon::add_outline(const PoolVector<Vector2> &p_outline) { outlines.push_back(p_outline); + rect_cache_dirty = true; } int NavigationPolygon::get_outline_count() const { @@ -122,12 +166,14 @@ int NavigationPolygon::get_outline_count() const { void NavigationPolygon::set_outline(int p_idx, const PoolVector<Vector2> &p_outline) { ERR_FAIL_INDEX(p_idx, outlines.size()); outlines[p_idx] = p_outline; + rect_cache_dirty = true; } void NavigationPolygon::remove_outline(int p_idx) { ERR_FAIL_INDEX(p_idx, outlines.size()); outlines.remove(p_idx); + rect_cache_dirty = true; } PoolVector<Vector2> NavigationPolygon::get_outline(int p_idx) const { @@ -138,6 +184,7 @@ PoolVector<Vector2> NavigationPolygon::get_outline(int p_idx) const { void NavigationPolygon::clear_outlines() { outlines.clear(); + rect_cache_dirty = true; } void NavigationPolygon::make_polygons_from_outlines() { @@ -269,7 +316,8 @@ void NavigationPolygon::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_outlines", "_get_outlines"); } -NavigationPolygon::NavigationPolygon() { +NavigationPolygon::NavigationPolygon() : + rect_cache_dirty(true) { } void NavigationPolygonInstance::set_enabled(bool p_enabled) { @@ -311,6 +359,16 @@ bool NavigationPolygonInstance::is_enabled() const { ///////////////////////////// +Rect2 NavigationPolygonInstance::_edit_get_rect() const { + + return navpoly.is_valid() ? navpoly->_edit_get_rect() : Rect2(); +} + +bool NavigationPolygonInstance::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return navpoly.is_valid() ? navpoly->_edit_is_selected_on_click(p_point, p_tolerance) : false; +} + void NavigationPolygonInstance::_notification(int p_what) { switch (p_what) { diff --git a/scene/2d/navigation_polygon.h b/scene/2d/navigation_polygon.h index febdcf2ca6..7b5220f92d 100644 --- a/scene/2d/navigation_polygon.h +++ b/scene/2d/navigation_polygon.h @@ -43,6 +43,9 @@ class NavigationPolygon : public Resource { Vector<Polygon> polygons; Vector<PoolVector<Vector2> > outlines; + mutable Rect2 item_rect; + mutable bool rect_cache_dirty; + protected: static void _bind_methods(); @@ -53,6 +56,9 @@ protected: Array _get_outlines() const; public: + Rect2 _edit_get_rect() const; + bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_vertices(const PoolVector<Vector2> &p_vertices); PoolVector<Vector2> get_vertices() const; @@ -93,6 +99,9 @@ protected: static void _bind_methods(); public: + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_enabled(bool p_enabled); bool is_enabled() const; diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 2a305512af..e133f86ef7 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -329,13 +329,13 @@ void Node2D::set_global_transform(const Transform2D &p_transform) { set_transform(p_transform); } -void Node2D::set_z(int p_z) { +void Node2D::set_z_index(int p_z) { ERR_FAIL_COND(p_z < VS::CANVAS_ITEM_Z_MIN); ERR_FAIL_COND(p_z > VS::CANVAS_ITEM_Z_MAX); - z = p_z; - VS::get_singleton()->canvas_item_set_z(get_canvas_item(), z); - _change_notify("z"); + z_index = p_z; + VS::get_singleton()->canvas_item_set_z_index(get_canvas_item(), z_index); + _change_notify("z_index"); } void Node2D::set_z_as_relative(bool p_enabled) { @@ -351,9 +351,9 @@ bool Node2D::is_z_relative() const { return z_relative; } -int Node2D::get_z() const { +int Node2D::get_z_index() const { - return z; + return z_index; } Transform2D Node2D::get_relative_transform_to_parent(const Node *p_parent) const { @@ -427,8 +427,8 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Node2D::to_local); ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Node2D::to_global); - ClassDB::bind_method(D_METHOD("set_z", "z"), &Node2D::set_z); - ClassDB::bind_method(D_METHOD("get_z"), &Node2D::get_z); + ClassDB::bind_method(D_METHOD("set_z_index", "z_index"), &Node2D::set_z_index); + ClassDB::bind_method(D_METHOD("get_z_index"), &Node2D::get_z_index); ClassDB::bind_method(D_METHOD("set_z_as_relative", "enable"), &Node2D::set_z_as_relative); ClassDB::bind_method(D_METHOD("is_z_relative"), &Node2D::is_z_relative); @@ -448,8 +448,8 @@ void Node2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "global_scale", PROPERTY_HINT_NONE, "", 0), "set_global_scale", "get_global_scale"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); - ADD_GROUP("Z", ""); - ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "z", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z", "get_z"); + ADD_GROUP("Z Index", ""); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative"); } @@ -458,6 +458,6 @@ Node2D::Node2D() { angle = 0; _scale = Vector2(1, 1); _xform_dirty = false; - z = 0; + z_index = 0; z_relative = true; } diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 7d2e5aa00c..321021a748 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -39,7 +39,7 @@ class Node2D : public CanvasItem { Point2 pos; float angle; Size2 _scale; - int z; + int z_index; bool z_relative; Transform2D _mat; @@ -96,8 +96,8 @@ public: void set_global_rotation_degrees(float p_degrees); void set_global_scale(const Size2 &p_scale); - void set_z(int p_z); - int get_z() const; + void set_z_index(int p_z); + int get_z_index() const; void look_at(const Vector2 &p_pos); float get_angle_to(const Vector2 &p_pos) const; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index 06bd55858c..d2a307a9ed 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -32,6 +32,51 @@ #include "engine.h" #include "scene/scene_string_names.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_scale.h" +#endif + +Rect2 Path2D::_edit_get_rect() const { + + if (curve->get_point_count() == 0) + return Rect2(0, 0, 0, 0); + + Rect2 aabb = Rect2(curve->get_point_position(0), Vector2(0, 0)); + + for (int i = 0; i < curve->get_point_count(); i++) { + + for (int j = 0; j <= 8; j++) { + + real_t frac = j / 8.0; + Vector2 p = curve->interpolate(i, frac); + aabb.expand_to(p); + } + } + + return aabb; +} + +bool Path2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + for (int i = 0; i < curve->get_point_count(); i++) { + Vector2 s[2]; + s[0] = curve->get_point_position(i); + + for (int j = 1; j <= 8; j++) { + real_t frac = j / 8.0; + s[1] = curve->interpolate(i, frac); + + Vector2 p = Geometry::get_closest_point_to_segment_2d(p_point, s); + if (p.distance_to(p_point) <= p_tolerance) + return true; + + s[0] = s[1]; + } + } + + return false; +} + void Path2D::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW && curve.is_valid()) { @@ -41,6 +86,13 @@ void Path2D::_notification(int p_what) { return; } +#if TOOLS_ENABLED + const float line_width = 2 * EDSCALE; +#else + const float line_width = 2; +#endif + const Color color = Color(0.5, 0.6, 1.0, 0.7); + for (int i = 0; i < curve->get_point_count(); i++) { Vector2 prev_p = curve->get_point_position(i); @@ -49,7 +101,7 @@ void Path2D::_notification(int p_what) { real_t frac = j / 8.0; Vector2 p = curve->interpolate(i, frac); - draw_line(prev_p, p, Color(0.5, 0.6, 1.0, 0.7), 2); + draw_line(prev_p, p, color, line_width); prev_p = p; } } diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index ebfa77d605..7f53821c7e 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -46,6 +46,9 @@ protected: static void _bind_methods(); public: + virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_curve(const Ref<Curve2D> &p_curve); Ref<Curve2D> get_curve() const; diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index a2f49d938b..f9951cdd08 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -28,6 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "polygon_2d.h" +#include "core/math/geometry.h" Rect2 Polygon2D::_edit_get_rect() const { @@ -42,13 +43,17 @@ Rect2 Polygon2D::_edit_get_rect() const { else item_rect.expand_to(pos); } - item_rect = item_rect.grow(20); rect_cache_dirty = false; } return item_rect; } +bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return Geometry::is_point_in_polygon(p_point, Variant(polygon)); +} + void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) { set_offset(p_pivot); diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h index a23e223e6e..5014cbc6e9 100644 --- a/scene/2d/polygon_2d.h +++ b/scene/2d/polygon_2d.h @@ -104,6 +104,7 @@ public: virtual bool _edit_use_pivot() const; virtual Rect2 _edit_get_rect() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; Polygon2D(); }; diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp index c4a7e5aebd..68df95c042 100644 --- a/scene/2d/sprite.cpp +++ b/scene/2d/sprite.cpp @@ -47,6 +47,40 @@ bool Sprite::_edit_use_pivot() const { return true; } +void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const { + + Size2 s; + r_filter_clip = false; + + if (region) { + + s = region_rect.size; + r_src_rect = region_rect; + r_filter_clip = region_filter_clip; + } else { + s = Size2(texture->get_size()); + s = s / Size2(hframes, vframes); + + r_src_rect.size = s; + r_src_rect.position.x += float(frame % hframes) * s.x; + r_src_rect.position.y += float(frame / hframes) * s.y; + } + + Point2 ofs = offset; + if (centered) + ofs -= s / 2; + if (Engine::get_singleton()->get_use_pixel_snap()) { + ofs = ofs.floor(); + } + + r_dst_rect = Rect2(ofs, s); + + if (hflip) + r_dst_rect.size.x = -r_dst_rect.size.x; + if (vflip) + r_dst_rect.size.y = -r_dst_rect.size.y; +} + void Sprite::_notification(int p_what) { switch (p_what) { @@ -63,38 +97,9 @@ void Sprite::_notification(int p_what) { break; */ - Size2 s; - Rect2 src_rect; - bool filter_clip = false; - - if (region) { - - s = region_rect.size; - src_rect = region_rect; - filter_clip = region_filter_clip; - } else { - s = Size2(texture->get_size()); - s = s / Size2(hframes, vframes); - - src_rect.size = s; - src_rect.position.x += float(frame % hframes) * s.x; - src_rect.position.y += float(frame / hframes) * s.y; - } - - Point2 ofs = offset; - if (centered) - ofs -= s / 2; - if (Engine::get_singleton()->get_use_pixel_snap()) { - ofs = ofs.floor(); - } - - Rect2 dst_rect(ofs, s); - - if (hflip) - dst_rect.size.x = -dst_rect.size.x; - if (vflip) - dst_rect.size.y = -dst_rect.size.y; - + Rect2 src_rect, dst_rect; + bool filter_clip; + _get_rects(src_rect, dst_rect, filter_clip); texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, filter_clip); } break; @@ -257,6 +262,30 @@ int Sprite::get_hframes() const { return hframes; } +bool Sprite::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + if (texture.is_null()) + return false; + + Rect2 src_rect, dst_rect; + bool filter_clip; + _get_rects(src_rect, dst_rect, filter_clip); + + if (!dst_rect.has_point(p_point)) + return false; + + Vector2 q = ((p_point - dst_rect.position) / dst_rect.size) * src_rect.size + src_rect.position; + + Ref<Image> image = texture->get_data(); + ERR_FAIL_COND_V(image.is_null(), false); + + image->lock(); + const Color c = image->get_pixel((int)q.x, (int)q.y); + image->unlock(); + + return c.a > 0.01; +} + Rect2 Sprite::_edit_get_rect() const { if (texture.is_null()) diff --git a/scene/2d/sprite.h b/scene/2d/sprite.h index c437f6d404..7d9b2cf457 100644 --- a/scene/2d/sprite.h +++ b/scene/2d/sprite.h @@ -54,6 +54,8 @@ class Sprite : public Node2D { int vframes; int hframes; + void _get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const; + protected: void _notification(int p_what); @@ -65,6 +67,7 @@ public: virtual void _edit_set_pivot(const Point2 &p_pivot); virtual Point2 _edit_get_pivot() const; virtual bool _edit_use_pivot() const; + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; virtual Rect2 _edit_get_rect() const; void set_texture(const Ref<Texture> &p_texture); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 73fce4be75..8bd5676bc7 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -336,7 +336,7 @@ void TileMap::_update_dirty_quadrants() { debug_canvas_item = vs->canvas_item_create(); vs->canvas_item_set_parent(debug_canvas_item, canvas_item); vs->canvas_item_set_z_as_relative_to_parent(debug_canvas_item, false); - vs->canvas_item_set_z(debug_canvas_item, VS::CANVAS_ITEM_Z_MAX - 1); + vs->canvas_item_set_z_index(debug_canvas_item, VS::CANVAS_ITEM_Z_MAX - 1); q.canvas_items.push_back(debug_canvas_item); prev_debug_canvas_item = debug_canvas_item; } diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index ef60a2151d..aaa378bb68 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -160,14 +160,14 @@ void Skeleton::_notification(int p_what) { //if moved, just update transforms VisualServer *vs = VisualServer::get_singleton(); - Bone *bonesptr = &bones[0]; + const Bone *bonesptr = bones.ptr(); int len = bones.size(); Transform global_transform = get_global_transform(); Transform global_transform_inverse = global_transform.affine_inverse(); for (int i = 0; i < len; i++) { - Bone &b = bonesptr[i]; + const Bone &b = bonesptr[i]; vs->skeleton_bone_set_transform(skeleton, i, global_transform * (b.transform_final * global_transform_inverse)); } } break; diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 6463180d9e..bac95c6cca 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -547,12 +547,14 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f if (!backwards && cd.pos <= len && next_pos == len /*&& playback.blend.empty()*/) { //playback finished - end_notify = true; + end_reached = true; + end_notify = cd.pos < len; // Notify only if not already at the end } if (backwards && cd.pos >= 0 && next_pos == 0 /*&& playback.blend.empty()*/) { //playback finished - end_notify = true; + end_reached = true; + end_notify = cd.pos > 0; // Notify only if not already at the beginning } } @@ -679,24 +681,26 @@ void AnimationPlayer::_animation_process(float p_delta) { if (playback.current.from) { + end_reached = false; end_notify = false; _animation_process2(p_delta); _animation_update_transforms(); - if (end_notify) { + if (end_reached) { if (queued.size()) { String old = playback.assigned; play(queued.front()->get()); String new_name = playback.assigned; queued.pop_front(); - end_notify = false; - emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name); + if (end_notify) + emit_signal(SceneStringNames::get_singleton()->animation_changed, old, new_name); } else { //stop(); playing = false; _set_process(false); - end_notify = false; - emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned); + if (end_notify) + emit_signal(SceneStringNames::get_singleton()->animation_finished, playback.assigned); } + end_reached = false; } } else { @@ -954,7 +958,7 @@ void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float c.current.speed_scale = p_custom_scale; c.assigned = p_name; - if (!end_notify) + if (!end_reached) queued.clear(); _set_process(true); // always process when starting an animation playing = true; @@ -1348,6 +1352,7 @@ AnimationPlayer::AnimationPlayer() { cache_update_size = 0; cache_update_prop_size = 0; speed_scale = 1; + end_reached = false; end_notify = false; animation_process_mode = ANIMATION_PROCESS_IDLE; processing = false; diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 57c658e054..40a7252528 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -205,6 +205,7 @@ private: List<StringName> queued; + bool end_reached; bool end_notify; String autoplay; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 2f30337cb8..1711fbffee 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -561,57 +561,50 @@ void Tween::_tween_process(float p_delta) { data.finish = true; } - switch (data.type) { - case INTER_PROPERTY: - case INTER_METHOD: { - Variant result = _run_equation(data); - emit_signal("tween_step", object, NodePath(Vector<StringName>(), data.key, false), data.elapsed, result); - _apply_tween_value(data, result); - if (data.finish) - _apply_tween_value(data, data.final_val); - } break; - - case INTER_CALLBACK: - if (data.finish) { - if (data.call_deferred) { - - switch (data.args) { - case 0: - object->call_deferred(data.key[0]); - break; - case 1: - object->call_deferred(data.key[0], data.arg[0]); - break; - case 2: - object->call_deferred(data.key[0], data.arg[0], data.arg[1]); - break; - case 3: - object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2]); - break; - case 4: - object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3]); - break; - case 5: - object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]); - break; - } - } else { - Variant::CallError error; - Variant *arg[5] = { - &data.arg[0], - &data.arg[1], - &data.arg[2], - &data.arg[3], - &data.arg[4], - }; - object->call(data.key[0], (const Variant **)arg, data.args, error); + if (data.type == INTER_CALLBACK) { + if (data.finish) { + if (data.call_deferred) { + + switch (data.args) { + case 0: + object->call_deferred(data.key[0]); + break; + case 1: + object->call_deferred(data.key[0], data.arg[0]); + break; + case 2: + object->call_deferred(data.key[0], data.arg[0], data.arg[1]); + break; + case 3: + object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2]); + break; + case 4: + object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3]); + break; + case 5: + object->call_deferred(data.key[0], data.arg[0], data.arg[1], data.arg[2], data.arg[3], data.arg[4]); + break; } + } else { + Variant::CallError error; + Variant *arg[5] = { + &data.arg[0], + &data.arg[1], + &data.arg[2], + &data.arg[3], + &data.arg[4], + }; + object->call(data.key[0], (const Variant **)arg, data.args, error); } - break; - default: {} + } + } else { + Variant result = _run_equation(data); + emit_signal("tween_step", object, NodePath(Vector<StringName>(), data.key, false), data.elapsed, result); + _apply_tween_value(data, result); } if (data.finish) { + _apply_tween_value(data, data.final_val); emit_signal("tween_completed", object, NodePath(Vector<StringName>(), data.key, false)); // not repeat mode, remove completed action if (!repeat) diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 95298f5a18..63478886c6 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -209,6 +209,7 @@ Color ColorPicker::get_pick_color() const { } void ColorPicker::add_preset(const Color &p_color) { + if (presets.find(p_color)) { presets.move_to_back(presets.find(p_color)); } else { diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index b1c862d1d1..5a4a0b2106 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -930,6 +930,9 @@ void ItemList::_notification(int p_what) { scroll_bar->hide(); } else { scroll_bar->show(); + + if (do_autoscroll_to_bottom) + scroll_bar->set_value(max); } break; } @@ -1313,6 +1316,11 @@ Size2 ItemList::get_minimum_size() const { return Size2(); } +void ItemList::set_autoscroll_to_bottom(const bool p_enable) { + + do_autoscroll_to_bottom = p_enable; +} + void ItemList::set_auto_height(bool p_enable) { auto_height = p_enable; @@ -1466,6 +1474,7 @@ ItemList::ItemList() { ensure_selected_visible = false; defer_select_single = -1; allow_rmb_select = false; + do_autoscroll_to_bottom = false; icon_scale = 1.0f; set_clip_contents(true); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index df751d8b9d..e56d5e5224 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -107,6 +107,8 @@ private: real_t icon_scale; + bool do_autoscroll_to_bottom; + Array _get_items() const; void _set_items(const Array &p_items); @@ -212,6 +214,8 @@ public: Size2 get_minimum_size() const; + void set_autoscroll_to_bottom(const bool p_enable); + VScrollBar *get_v_scroll() { return scroll_bar; } ItemList(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 34abb1fbcc..dff7722a9e 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -368,6 +368,18 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { shift_selection_check_post(k->get_shift()); } break; + case KEY_UP: { + + shift_selection_check_pre(k->get_shift()); + set_cursor_position(0); + shift_selection_check_post(k->get_shift()); + } break; + case KEY_DOWN: { + + shift_selection_check_pre(k->get_shift()); + set_cursor_position(text.length()); + shift_selection_check_post(k->get_shift()); + } break; case KEY_DELETE: { if (!editable) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index dde274e55e..87043c65eb 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1498,7 +1498,7 @@ void TextEdit::_notification(int p_what) { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect()); if (raised_from_completion) { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); } } break; @@ -1512,7 +1512,7 @@ void TextEdit::_notification(int p_what) { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); if (raised_from_completion) { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); } } break; } @@ -2733,6 +2733,8 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { _scroll_lines_down(); break; } + + { #else if (k->get_command() && k->get_alt()) { _scroll_lines_down(); @@ -2741,9 +2743,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_command()) cursor_set_line(text.size() - 1, true, false); - else + else { #endif - cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false); + if (!is_last_visible_line(cursor.line)) { + cursor_set_line(cursor_get_line() + num_lines_from(CLAMP(cursor.line + 1, 0, text.size() - 1), 1), true, false); + } else { + cursor_set_line(text.size() - 1); + cursor_set_column(get_line(cursor.line).length(), true); + } + } if (k->get_shift()) _post_shift_selection(); @@ -3139,6 +3147,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { void TextEdit::_scroll_up(real_t p_delta) { + if (scrolling && smooth_scroll_enabled && SGN(target_v_scroll - v_scroll->get_value()) != SGN(-p_delta)) + scrolling = false; + if (scrolling) { target_v_scroll = (target_v_scroll - p_delta); } else { @@ -3149,8 +3160,12 @@ void TextEdit::_scroll_up(real_t p_delta) { if (target_v_scroll <= 0) { target_v_scroll = 0; } - scrolling = true; - set_physics_process(true); + if (Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { + v_scroll->set_value(target_v_scroll); + } else { + scrolling = true; + set_physics_process(true); + } } else { v_scroll->set_value(target_v_scroll); } @@ -3158,6 +3173,9 @@ void TextEdit::_scroll_up(real_t p_delta) { void TextEdit::_scroll_down(real_t p_delta) { + if (scrolling && smooth_scroll_enabled && SGN(target_v_scroll - v_scroll->get_value()) != SGN(p_delta)) + scrolling = false; + if (scrolling) { target_v_scroll = (target_v_scroll + p_delta); } else { @@ -3174,8 +3192,13 @@ void TextEdit::_scroll_down(real_t p_delta) { if (target_v_scroll > max_v_scroll) { target_v_scroll = max_v_scroll; } - scrolling = true; - set_physics_process(true); + + if (Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { + v_scroll->set_value(target_v_scroll); + } else { + scrolling = true; + set_physics_process(true); + } } else { v_scroll->set_value(target_v_scroll); } @@ -4592,6 +4615,24 @@ int TextEdit::num_lines_from(int p_line_from, int unhidden_amount) const { return num_total; } +bool TextEdit::is_last_visible_line(int p_line) const { + + ERR_FAIL_INDEX_V(p_line, text.size(), false); + + if (p_line == text.size() - 1) + return true; + + if (!is_hiding_enabled()) + return false; + + for (int i = p_line + 1; i < text.size(); i++) { + if (!is_line_hidden(i)) + return false; + } + + return true; +} + int TextEdit::get_indent_level(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), 0); @@ -5021,7 +5062,7 @@ void TextEdit::_confirm_completion() { void TextEdit::_cancel_code_hint() { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); raised_from_completion = false; completion_hint = ""; update(); @@ -5029,7 +5070,7 @@ void TextEdit::_cancel_code_hint() { void TextEdit::_cancel_completion() { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 0); raised_from_completion = false; if (!completion_active) return; @@ -5204,7 +5245,7 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String &p_hint) { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); raised_from_completion = true; completion_hint = p_hint; completion_hint_offset = -0xFFFF; @@ -5213,7 +5254,7 @@ void TextEdit::set_code_hint(const String &p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) { - VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + VisualServer::get_singleton()->canvas_item_set_z_index(get_canvas_item(), 1); raised_from_completion = true; completion_strings = p_strings; completion_active = true; diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 320bb6d9fd..ccd7ba8278 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -433,6 +433,7 @@ public: void fold_all_lines(); void unhide_all_lines(); int num_lines_from(int p_line_from, int unhidden_amount) const; + bool is_last_visible_line(int p_line) const; bool can_fold(int p_line) const; bool is_folded(int p_line) const; void fold_line(int p_line); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 07f93fa52b..632d912e43 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -2126,6 +2126,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("has_group", "name"), &SceneTree::has_group); ClassDB::bind_method(D_METHOD("set_auto_accept_quit", "enabled"), &SceneTree::set_auto_accept_quit); + ClassDB::bind_method(D_METHOD("set_quit_on_go_back", "enabled"), &SceneTree::set_quit_on_go_back); ClassDB::bind_method(D_METHOD("set_debug_collisions_hint", "enable"), &SceneTree::set_debug_collisions_hint); ClassDB::bind_method(D_METHOD("is_debugging_collisions_hint"), &SceneTree::is_debugging_collisions_hint); diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 7b2dbf8e8c..2722ff7207 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -32,6 +32,25 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" +Vector<Vector2> CapsuleShape2D::_get_points() const { + + Vector<Vector2> points; + for (int i = 0; i < 24; i++) { + Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5); + + points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() + ofs); + if (i == 6 || i == 18) + points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() - ofs); + } + + return points; +} + +bool CapsuleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return Geometry::is_point_in_polygon(p_point, _get_points()); +} + void CapsuleShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height)); @@ -62,15 +81,7 @@ real_t CapsuleShape2D::get_height() const { void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { - Vector<Vector2> points; - for (int i = 0; i < 24; i++) { - Vector2 ofs = Vector2(0, (i > 6 && i <= 18) ? -get_height() * 0.5 : get_height() * 0.5); - - points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() + ofs); - if (i == 6 || i == 18) - points.push_back(Vector2(Math::sin(i * Math_PI * 2 / 24.0), Math::cos(i * Math_PI * 2 / 24.0)) * get_radius() - ofs); - } - + Vector<Vector2> points = _get_points(); Vector<Color> col; col.push_back(p_color); VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); diff --git a/scene/resources/capsule_shape_2d.h b/scene/resources/capsule_shape_2d.h index 7ce6a4ed63..784f2c02c8 100644 --- a/scene/resources/capsule_shape_2d.h +++ b/scene/resources/capsule_shape_2d.h @@ -39,11 +39,14 @@ class CapsuleShape2D : public Shape2D { real_t radius; void _update_shape(); + Vector<Vector2> _get_points() const; protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_height(real_t p_height); real_t get_height() const; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index d9d0ddbe8f..669b1d8e7d 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -31,6 +31,12 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" + +bool CircleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return p_point.length() < get_radius() + p_tolerance; +} + void CircleShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(), radius); diff --git a/scene/resources/circle_shape_2d.h b/scene/resources/circle_shape_2d.h index f14f8f6776..3668521a55 100644 --- a/scene/resources/circle_shape_2d.h +++ b/scene/resources/circle_shape_2d.h @@ -42,6 +42,8 @@ protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_radius(real_t p_radius); real_t get_radius() const; diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index 19985d4acf..69765796f6 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -32,6 +32,23 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" +bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + PoolVector<Vector2> s = get_segments(); + int len = s.size(); + if (len == 0 || (len % 2) == 1) + return false; + + PoolVector<Vector2>::Read r = s.read(); + for (int i = 0; i < len; i += 2) { + Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, &r[i]); + if (p_point.distance_to(closest) < p_tolerance) + return true; + } + + return false; +} + void ConcavePolygonShape2D::set_segments(const PoolVector<Vector2> &p_segments) { Physics2DServer::get_singleton()->shape_set_data(get_rid(), p_segments); diff --git a/scene/resources/concave_polygon_shape_2d.h b/scene/resources/concave_polygon_shape_2d.h index 4a5defe72c..7ca14d4d66 100644 --- a/scene/resources/concave_polygon_shape_2d.h +++ b/scene/resources/concave_polygon_shape_2d.h @@ -39,6 +39,8 @@ protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_segments(const PoolVector<Vector2> &p_segments); PoolVector<Vector2> get_segments() const; diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 98ef2ca7c6..0402a70898 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -33,6 +33,11 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" +bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + return Geometry::is_point_in_polygon(p_point, points); +} + void ConvexPolygonShape2D::_update_shape() { Physics2DServer::get_singleton()->shape_set_data(get_rid(), points); diff --git a/scene/resources/convex_polygon_shape_2d.h b/scene/resources/convex_polygon_shape_2d.h index f492b7651b..320cf94a5e 100644 --- a/scene/resources/convex_polygon_shape_2d.h +++ b/scene/resources/convex_polygon_shape_2d.h @@ -42,6 +42,8 @@ protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_point_cloud(const Vector<Vector2> &p_points); void set_points(const Vector<Vector2> &p_points); Vector<Vector2> get_points() const; diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 4682ef5cb3..346599b25a 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -32,6 +32,13 @@ #include "servers/physics_2d_server.h" #include "servers/visual_server.h" +bool SegmentShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + Vector2 l[2] = { a, b }; + Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l); + return p_point.distance_to(closest) < p_tolerance; +} + void SegmentShape2D::_update_shape() { Rect2 r; diff --git a/scene/resources/segment_shape_2d.h b/scene/resources/segment_shape_2d.h index 1285ae4f82..39a71f61d5 100644 --- a/scene/resources/segment_shape_2d.h +++ b/scene/resources/segment_shape_2d.h @@ -44,6 +44,8 @@ protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_a(const Vector2 &p_a); void set_b(const Vector2 &p_b); diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index 5c2c24ed74..877a159aee 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -44,6 +44,8 @@ protected: Shape2D(const RID &p_rid); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { return true; } + void set_custom_solver_bias(real_t p_bias); real_t get_custom_solver_bias() const; diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp index c6cc3659f6..9548d35370 100644 --- a/scene/resources/shape_line_2d.cpp +++ b/scene/resources/shape_line_2d.cpp @@ -30,6 +30,21 @@ #include "shape_line_2d.h" #include "servers/physics_2d_server.h" #include "servers/visual_server.h" + +bool LineShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { + + Vector2 point = get_d() * get_normal(); + Vector2 l[2][2] = { { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }, { point, point + get_normal() * 30 } }; + + for (int i = 0; i < 2; i++) { + Vector2 closest = Geometry::get_closest_point_to_segment_2d(p_point, l[i]); + if (p_point.distance_to(closest) < p_tolerance) + return true; + } + + return false; +} + void LineShape2D::_update_shape() { Array arr; diff --git a/scene/resources/shape_line_2d.h b/scene/resources/shape_line_2d.h index 747500b0ac..fe6f2d675e 100644 --- a/scene/resources/shape_line_2d.h +++ b/scene/resources/shape_line_2d.h @@ -44,6 +44,8 @@ protected: static void _bind_methods(); public: + virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; + void set_normal(const Vector2 &p_normal); void set_d(real_t p_d); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 60530e48e2..b163402a07 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -102,9 +102,9 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor } if (ci->z_relative) - p_z = CLAMP(p_z + ci->z, VS::CANVAS_ITEM_Z_MIN, VS::CANVAS_ITEM_Z_MAX); + p_z = CLAMP(p_z + ci->z_index, VS::CANVAS_ITEM_Z_MIN, VS::CANVAS_ITEM_Z_MAX); else - p_z = ci->z; + p_z = ci->z_index; for (int i = 0; i < child_item_count; i++) { @@ -805,14 +805,14 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e canvas_item->sort_y = p_enable; } -void VisualServerCanvas::canvas_item_set_z(RID p_item, int p_z) { +void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { ERR_FAIL_COND(p_z < VS::CANVAS_ITEM_Z_MIN || p_z > VS::CANVAS_ITEM_Z_MAX); Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); - canvas_item->z = p_z; + canvas_item->z_index = p_z; } void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index b86dd0316c..320fc2fb0b 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -39,7 +39,7 @@ public: RID parent; // canvas it belongs to List<Item *>::Element *E; - int z; + int z_index; bool z_relative; bool sort_y; Color modulate; @@ -53,7 +53,7 @@ public: Item() { children_order_dirty = true; E = NULL; - z = 0; + z_index = 0; modulate = Color(1, 1, 1, 1); self_modulate = Color(1, 1, 1, 1); sort_y = false; @@ -187,7 +187,7 @@ public: void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); - void canvas_item_set_z(RID p_item, int p_z); + void canvas_item_set_z_index(RID p_item, int p_z); void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 95d7269d7a..864ae81140 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -586,7 +586,7 @@ public: BIND2(canvas_item_add_set_transform, RID, const Transform2D &) BIND2(canvas_item_add_clip_ignore, RID, bool) BIND2(canvas_item_set_sort_children_by_y, RID, bool) - BIND2(canvas_item_set_z, RID, int) + BIND2(canvas_item_set_z_index, RID, int) BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool) BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp index a8422b805e..67b83b7618 100644 --- a/servers/visual/visual_server_wrap_mt.cpp +++ b/servers/visual/visual_server_wrap_mt.cpp @@ -6,6 +6,7 @@ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 4062f91438..276e445f4d 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -6,6 +6,7 @@ /* https://godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -503,7 +504,7 @@ public: FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) FUNC2(canvas_item_add_clip_ignore, RID, bool) FUNC2(canvas_item_set_sort_children_by_y, RID, bool) - FUNC2(canvas_item_set_z, RID, int) + FUNC2(canvas_item_set_z_index, RID, int) FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool) FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index b4949b6093..bf6d425fb9 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1611,7 +1611,7 @@ void VisualServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform); ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore); ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y); - ClassDB::bind_method(D_METHOD("canvas_item_set_z", "item", "z"), &VisualServer::canvas_item_set_z); + ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &VisualServer::canvas_item_set_z_index); ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &VisualServer::canvas_item_set_z_as_relative_to_parent); ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &VisualServer::canvas_item_set_copy_to_backbuffer); ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &VisualServer::canvas_item_clear); diff --git a/servers/visual_server.h b/servers/visual_server.h index e1def0b713..eb2c56cd3a 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -847,7 +847,7 @@ public: virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0; - virtual void canvas_item_set_z(RID p_item, int p_z) = 0; + virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0; virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0; virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) = 0; diff --git a/thirdparty/thekla_atlas/godot-changes.patch b/thirdparty/thekla_atlas/godot-changes.patch new file mode 100644 index 0000000000..0e56403336 --- /dev/null +++ b/thirdparty/thekla_atlas/godot-changes.patch @@ -0,0 +1,154 @@ +diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp +index 5ce452c..11e635d 100644 +--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp ++++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp +@@ -142,9 +142,11 @@ AtlasPacker::AtlasPacker(Atlas * atlas) : m_atlas(atlas), m_bitmap(256, 256) + { + m_width = 0; + m_height = 0; +- +- m_debug_bitmap.allocate(256, 256); +- m_debug_bitmap.fill(Color32(0,0,0,0)); ++ ++ // -- GODOT start -- ++ //m_debug_bitmap.allocate(256, 256); ++ //m_debug_bitmap.fill(Color32(0,0,0,0)); ++ // -- GODOT end -- + } + + AtlasPacker::~AtlasPacker() +@@ -465,7 +467,11 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned + nvDebug("origin: %f %f\n", origin.x, origin.y); + nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y); + nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y); +- nvDebugBreak(); ++ // -- GODOT start -- ++ //nvDebugBreak(); ++ m_atlas->setFailed(); ++ return; ++ // -- GODOT end -- + } + //nvCheck(tmp.x >= 0 && tmp.y >= 0); + +@@ -597,8 +603,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned + m_bitmap.clearAll(); + if (approximateExtent > m_bitmap.width()) { + m_bitmap.resize(approximateExtent, approximateExtent, false); +- m_debug_bitmap.resize(approximateExtent, approximateExtent); +- m_debug_bitmap.fill(Color32(0,0,0,0)); ++ // -- GODOT start -- ++ //m_debug_bitmap.resize(approximateExtent, approximateExtent); ++ //m_debug_bitmap.fill(Color32(0,0,0,0)); ++ // -- GODOT end -- + } + + +@@ -680,20 +688,24 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned + { + //nvDebug("Resize bitmap (%d, %d).\n", nextPowerOfTwo(w), nextPowerOfTwo(h)); + m_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h)), false); +- m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h))); ++ // -- GODOT start -- ++ //m_debug_bitmap.resize(nextPowerOfTwo(U32(w)), nextPowerOfTwo(U32(h))); ++ // -- GODOT end -- + } + + //nvDebug("Add chart at (%d, %d).\n", best_x, best_y); + + addChart(&chart_bitmap, w, h, best_x, best_y, best_r, /*debugOutput=*/NULL); + ++ // -- GODOT start -- + // IC: Output chart again to debug bitmap. +- if (chart->isVertexMapped()) { ++ /*if (chart->isVertexMapped()) { + addChart(&chart_bitmap, w, h, best_x, best_y, best_r, &m_debug_bitmap); + } + else { + addChart(chart, w, h, best_x, best_y, best_r, &m_debug_bitmap); +- } ++ }*/ ++ // -- GODOT end -- + + //float best_angle = 2 * PI * best_r; + +@@ -842,8 +854,10 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned + nvCheck(isAligned(m_width, 4)); + nvCheck(isAligned(m_height, 4)); + +- m_debug_bitmap.resize(m_width, m_height); +- m_debug_bitmap.setFormat(Image::Format_ARGB); ++ // -- GODOT start -- ++ //m_debug_bitmap.resize(m_width, m_height); ++ //m_debug_bitmap.setFormat(Image::Format_ARGB); ++ // -- GODOT end -- + + #if DEBUG_OUTPUT + //outputDebugBitmap("debug_packer_final.tga", m_bitmap, w, h); +diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h +index 2d305f3..845dbfb 100644 +--- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h ++++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.h +@@ -48,7 +48,9 @@ namespace nv + + Atlas * m_atlas; + BitMap m_bitmap; +- Image m_debug_bitmap; ++ // -- GODOT start -- ++ //Image m_debug_bitmap; ++ // -- GODOT end -- + RadixSort m_radix; + + uint m_width; +diff --git a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp +index d6f0acc..de1953d 100644 +--- a/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp ++++ b/thirdparty/thekla_atlas/thekla/thekla_atlas.cpp +@@ -2,6 +2,9 @@ + #include "thekla_atlas.h" + + #include <cfloat> ++// -- GODOT start -- ++#include <stdio.h> ++// -- GODOT end -- + + #include "nvmesh/halfedge/Edge.h" + #include "nvmesh/halfedge/Mesh.h" +@@ -112,6 +115,8 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con + output->index_count = face_count * 3; + output->index_array = new int[face_count * 3]; + ++ // -- GODOT start -- ++ int face_ofs = 0; + // Set face indices. + for (int f = 0; f < face_count; f++) { + uint c = charts->faceChartAt(f); +@@ -121,14 +126,26 @@ static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, con + const Chart * chart = charts->chartAt(c); + nvDebugCheck(chart->faceAt(i) == f); + ++ if (i >= chart->chartMesh()->faceCount()) { ++ printf("WARNING: Faces may be missing in the final vertex, which could not be packed\n"); ++ continue; ++ } ++ + const HalfEdge::Face * face = chart->chartMesh()->faceAt(i); + const HalfEdge::Edge * edge = face->edge; + +- output->index_array[3*f+0] = vertexOffset + edge->vertex->id; +- output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id; +- output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id; ++ //output->index_array[3*f+0] = vertexOffset + edge->vertex->id; ++ //output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id; ++ //output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id; ++ output->index_array[3 * face_ofs + 0] = vertexOffset + edge->vertex->id; ++ output->index_array[3 * face_ofs + 1] = vertexOffset + edge->next->vertex->id; ++ output->index_array[3 * face_ofs + 2] = vertexOffset + edge->next->next->vertex->id; ++ face_ofs++; + } + ++ output->index_count = face_ofs * 3; ++ // -- GODOT end -- ++ + *error = Atlas_Error_Success; + output->atlas_width = w; + output->atlas_height = h; diff --git a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp index fd37b8c59c..11e635db17 100644 --- a/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp +++ b/thirdparty/thekla_atlas/nvmesh/param/AtlasPacker.cpp @@ -467,7 +467,11 @@ void AtlasPacker::packCharts(int quality, float texelsPerUnit, bool blockAligned nvDebug("origin: %f %f\n", origin.x, origin.y); nvDebug("majorAxis: %f %f\n", majorAxis.x, majorAxis.y); nvDebug("minorAxis: %f %f\n", minorAxis.x, minorAxis.y); - nvDebugBreak(); + // -- GODOT start -- + //nvDebugBreak(); + m_atlas->setFailed(); + return; + // -- GODOT end -- } //nvCheck(tmp.x >= 0 && tmp.y >= 0); |