summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ustring.cpp26
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant_call.cpp4
-rw-r--r--demos/misc/joysticks/joysticks.gd9
-rw-r--r--demos/misc/tween/main.gd2
-rw-r--r--doc/base/classes.xml160
-rw-r--r--drivers/builtin_openssl2/SCsub1
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/windows/os_windows.cpp20
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/node_2d.cpp48
-rw-r--r--scene/2d/node_2d.h5
-rw-r--r--scene/3d/spatial.cpp51
-rw-r--r--scene/3d/spatial.h7
-rw-r--r--scene/gui/control.cpp45
-rw-r--r--scene/gui/control.h7
-rw-r--r--scene/gui/item_list.cpp14
-rw-r--r--scene/gui/item_list.h1
-rw-r--r--scene/gui/text_edit.cpp84
-rw-r--r--scene/gui/text_edit.h13
-rw-r--r--scene/gui/tree.cpp253
-rw-r--r--scene/gui/tree.h32
-rw-r--r--scene/main/canvas_layer.cpp48
-rw-r--r--scene/main/canvas_layer.h7
-rw-r--r--scene/main/node.cpp2
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/viewport.cpp35
-rw-r--r--scene/main/viewport.h2
-rw-r--r--scene/resources/default_theme/default_theme.cpp1
-rw-r--r--tools/editor/editor_node.cpp126
-rw-r--r--tools/editor/editor_node.h10
-rw-r--r--tools/editor/editor_settings.cpp4
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp6
-rw-r--r--tools/editor/property_editor.cpp200
-rw-r--r--tools/editor/property_editor.h13
-rw-r--r--tools/editor/scene_tree_dock.cpp209
-rw-r--r--tools/editor/scene_tree_dock.h4
-rw-r--r--tools/editor/scene_tree_editor.cpp97
-rw-r--r--tools/editor/scene_tree_editor.h6
-rw-r--r--tools/editor/scenes_dock.cpp145
-rw-r--r--tools/editor/scenes_dock.h3
44 files changed, 1546 insertions, 170 deletions
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 730f7cfa3b..1f0eadc03f 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -2867,25 +2867,29 @@ CharType String::ord_at(int p_idx) const {
return operator[](p_idx);
}
-String String::strip_edges() const {
+String String::strip_edges(bool left, bool right) const {
int len=length();
int beg=0,end=len;
- for (int i=0;i<length();i++) {
+ if(left) {
+ for (int i=0;i<len;i++) {
- if (operator[](i)<=32)
- beg++;
- else
- break;
+ if (operator[](i)<=32)
+ beg++;
+ else
+ break;
+ }
}
- for (int i=(int)(length()-1);i>=0;i--) {
+ if(right) {
+ for (int i=(int)(len-1);i>=0;i--) {
- if (operator[](i)<=32)
- end--;
- else
- break;
+ if (operator[](i)<=32)
+ end--;
+ else
+ break;
+ }
}
if (beg==0 && end==len)
diff --git a/core/ustring.h b/core/ustring.h
index ec0932e54d..78c041fb92 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -169,7 +169,7 @@ public:
String left(int p_pos) const;
String right(int p_pos) const;
- String strip_edges() const;
+ String strip_edges(bool left = true, bool right = true) const;
String strip_escapes() const;
String extension() const;
String basename() const;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 01550a1593..4be763a511 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -257,7 +257,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(String,to_lower);
VCALL_LOCALMEM1R(String,left);
VCALL_LOCALMEM1R(String,right);
- VCALL_LOCALMEM0R(String,strip_edges);
+ VCALL_LOCALMEM2R(String,strip_edges);
VCALL_LOCALMEM0R(String,extension);
VCALL_LOCALMEM0R(String,basename);
VCALL_LOCALMEM1R(String,plus_file);
@@ -1277,7 +1277,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(STRING,STRING,String,left,INT,"pos",varray());
ADDFUNC1(STRING,STRING,String,right,INT,"pos",varray());
- ADDFUNC0(STRING,STRING,String,strip_edges,varray());
+ ADDFUNC2(STRING,STRING,String,strip_edges,BOOL,"left",BOOL,"right",varray(true,true));
ADDFUNC0(STRING,STRING,String,extension,varray());
ADDFUNC0(STRING,STRING,String,basename,varray());
ADDFUNC1(STRING,STRING,String,plus_file,STRING,"file",varray());
diff --git a/demos/misc/joysticks/joysticks.gd b/demos/misc/joysticks/joysticks.gd
index f5466012e6..a6b90241b2 100644
--- a/demos/misc/joysticks/joysticks.gd
+++ b/demos/misc/joysticks/joysticks.gd
@@ -12,7 +12,6 @@ extends Node2D
var joy_num
var cur_joy
var axis_value
-var btn_state
const DEADZONE = 0.2
@@ -26,11 +25,12 @@ func _fixed_process(delta):
get_node("joy_name").set_text(Input.get_joy_name(joy_num))
# Loop through the axes and show their current values
- for axis in range(0, 8):
+ for axis in range(JOY_ANALOG_0_X, JOY_AXIS_MAX):
axis_value = Input.get_joy_axis(joy_num, axis)
get_node("axis_prog" + str(axis)).set_value(100*axis_value)
get_node("axis_val" + str(axis)).set_text(str(axis_value))
- if (axis < 4):
+ # Show joystick direction indicators
+ if (axis <= JOY_ANALOG_1_Y):
if (abs(axis_value) < DEADZONE):
get_node("diagram/axes/" + str(axis) + "+").hide()
get_node("diagram/axes/" + str(axis) + "-").hide()
@@ -40,8 +40,7 @@ func _fixed_process(delta):
get_node("diagram/axes/" + str(axis) + "-").show()
# Loop through the buttons and highlight the ones that are pressed
- for btn in range(0, 16):
- btn_state = 1
+ for btn in range(JOY_BUTTON_0, JOY_BUTTON_MAX):
if (Input.is_joy_button_pressed(joy_num, btn)):
get_node("btn" + str(btn)).add_color_override("font_color", Color(1, 1, 1, 1))
get_node("diagram/buttons/" + str(btn)).show()
diff --git a/demos/misc/tween/main.gd b/demos/misc/tween/main.gd
index 512271311e..b899825d55 100644
--- a/demos/misc/tween/main.gd
+++ b/demos/misc/tween/main.gd
@@ -108,7 +108,7 @@ func reset_tween():
sprite.set_scale(Vector2(1,1))
if get_node("modes/rotate").is_pressed():
- tween.interpolate_method(sprite, "_set_rotd", 0, 360, 2, state.trans, state.eases)
+ tween.interpolate_method(sprite, "set_rotd", 0, 360, 2, state.trans, state.eases)
tween.interpolate_property(sprite, "transform/rot", 360, 0, 2, state.trans, state.eases, 2)
if get_node("modes/callback").is_pressed():
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 529601c741..643658fbb9 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -2680,6 +2680,22 @@
Get the list of names of the animations stored in the player.
</description>
</method>
+ <method name="animation_set_next">
+ <argument index="0" name="anim_from" type="String">
+ </argument>
+ <argument index="1" name="anim_to" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="animation_get_next" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="anim_from" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_blend_time">
<argument index="0" name="anim_from" type="String">
</argument>
@@ -6766,9 +6782,9 @@
</argument>
<argument index="1" name="colors" type="ColorArray">
</argument>
- <argument index="2" name="uvs" type="Vector2Array" default="Array()">
+ <argument index="2" name="uvs" type="Vector2Array">
</argument>
- <argument index="3" name="texture" type="Texture" default="Object()">
+ <argument index="3" name="texture" type="Texture" default="NULL">
</argument>
<argument index="4" name="width" type="float" default="1">
</argument>
@@ -6781,9 +6797,9 @@
</argument>
<argument index="1" name="colors" type="ColorArray">
</argument>
- <argument index="2" name="uvs" type="Vector2Array" default="Array()">
+ <argument index="2" name="uvs" type="Vector2Array" default="Vector2Array()">
</argument>
- <argument index="3" name="texture" type="Texture" default="Object()">
+ <argument index="3" name="texture" type="Texture" default="NULL">
</argument>
<description>
Draw a polygon of any amount of points, convex or concave.
@@ -6794,9 +6810,9 @@
</argument>
<argument index="1" name="color" type="Color">
</argument>
- <argument index="2" name="uvs" type="Vector2Array" default="Array()">
+ <argument index="2" name="uvs" type="Vector2Array" default="Vector2Array()">
</argument>
- <argument index="3" name="texture" type="Texture" default="Object()">
+ <argument index="3" name="texture" type="Texture" default="NULL">
</argument>
<description>
Draw a colored polygon of any amount of points, convex or concave.
@@ -7118,7 +7134,7 @@
</description>
</method>
<method name="set_rotation">
- <argument index="0" name="rotation" type="float">
+ <argument index="0" name="radians" type="float">
</argument>
<description>
Set the base rotation for this layer (helper).
@@ -7131,6 +7147,18 @@
Return the base rotation for this layer (helper).
</description>
</method>
+ <method name="set_rotationd">
+ <argument index="0" name="degrees" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_rotationd" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_scale">
<argument index="0" name="scale" type="Vector2">
</argument>
@@ -7146,7 +7174,7 @@
</description>
</method>
<method name="get_world_2d" qualifiers="const">
- <return type="Canvas">
+ <return type="World2D">
</return>
<description>
Return the [World2D] used by this layer.
@@ -8779,7 +8807,13 @@
</description>
</method>
<method name="set_rotation">
- <argument index="0" name="rotation" type="float">
+ <argument index="0" name="radians" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_rotation_deg">
+ <argument index="0" name="degrees" type="float">
</argument>
<description>
</description>
@@ -8832,6 +8866,12 @@
<description>
</description>
</method>
+ <method name="get_rotation_deg" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_scale" qualifiers="const">
<return type="Vector2">
</return>
@@ -9175,6 +9215,12 @@
<description>
</description>
</method>
+ <method name="set_drag_forwarding">
+ <argument index="0" name="target" type="Control">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_drag_preview">
<argument index="0" name="control" type="Control">
</argument>
@@ -14065,6 +14111,20 @@ Returns an empty String "" at the end of the list.
<description>
</description>
</method>
+ <method name="request_raw">
+ <return type="int">
+ </return>
+ <argument index="0" name="method" type="int">
+ </argument>
+ <argument index="1" name="url" type="String">
+ </argument>
+ <argument index="2" name="headers" type="StringArray">
+ </argument>
+ <argument index="3" name="body" type="RawArray" default="&quot;&quot;">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="request">
<return type="int">
</return>
@@ -14688,6 +14748,10 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
<description>
</description>
</method>
+ <method name="fix_alpha_edges">
+ <description>
+ </description>
+ </method>
<method name="get_data">
<return type="RawArray">
</return>
@@ -15208,13 +15272,13 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
</signals>
<constants>
<constant name="MOUSE_MODE_VISIBLE" value="0">
- Makes the mouse cursor visible if it is hidden.
+ Makes the mouse cursor visible if it is hidden.
</constant>
<constant name="MOUSE_MODE_HIDDEN" value="1">
- Makes the mouse cursor hidden if it is visible.
+ Makes the mouse cursor hidden if it is visible.
</constant>
<constant name="MOUSE_MODE_CAPTURED" value="2">
- Captures the mouse. The mouse will be hidden and unable to leave the game window. But it will still register movement and mouse button presses.
+ Captures the mouse. The mouse will be hidden and unable to leave the game window. But it will still register movement and mouse button presses.
</constant>
</constants>
</class>
@@ -16377,7 +16441,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
<method name="add_item">
<argument index="0" name="text" type="String">
</argument>
- <argument index="1" name="icon" type="Texture" default="Object()">
+ <argument index="1" name="icon" type="Texture" default="NULL">
</argument>
<argument index="2" name="selectable" type="bool" default="true">
</argument>
@@ -17963,38 +18027,38 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
</class>
<class name="LinkButton" inherits="BaseButton" category="Core">
<brief_description>
- Simple button used to represent a link to some resource
+ Simple button used to represent a link to some resource
</brief_description>
<description>
- This kind of buttons are primarily used when the interaction with the button causes a context change (like linking to a web page).
+ This kind of buttons are primarily used when the interaction with the button causes a context change (like linking to a web page).
</description>
<methods>
<method name="set_text">
<argument index="0" name="text" type="String">
</argument>
<description>
- Sets the text of the button.
+ Sets the text of the button.
</description>
</method>
<method name="get_text" qualifiers="const">
<return type="String">
</return>
<description>
- Returns the text of the button.
+ Returns the text of the button.
</description>
</method>
<method name="set_underline_mode">
<argument index="0" name="underline_mode" type="int">
</argument>
<description>
- Sets the underline mode for this button, the argument must be one of the [LinkButton] constants (see constants section).
+ Sets the underline mode for this button, the argument must be one of the [LinkButton] constants (see constants section).
</description>
</method>
<method name="get_underline_mode" qualifiers="const">
<return type="int">
</return>
<description>
- Returns the underline mode for this button.
+ Returns the underline mode for this button.
</description>
</method>
</methods>
@@ -20246,7 +20310,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
</description>
</method>
<method name="get_parent" qualifiers="const">
- <return type="Parent">
+ <return type="Node">
</return>
<description>
Return the parent [Node] of the current [Node], or an empty Object if the node lacks a parent.
@@ -20639,12 +20703,18 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
</description>
</method>
<method name="set_rot">
- <argument index="0" name="rot" type="float">
+ <argument index="0" name="radians" type="float">
</argument>
<description>
Set the rotation of the 2D node.
</description>
</method>
+ <method name="set_rotd">
+ <argument index="0" name="degrees" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_scale">
<argument index="0" name="scale" type="Vector2">
</argument>
@@ -20666,6 +20736,12 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
Return the rotation of the 2D node.
</description>
</method>
+ <method name="get_rotd" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_scale" qualifiers="const">
<return type="Vector2">
</return>
@@ -21029,7 +21105,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
<argument index="0" name="size" type="Vector2">
</argument>
<description>
- Sets the window size to the specified size.
+ Sets the window size to the specified size.
</description>
</method>
<method name="set_window_fullscreen">
@@ -21107,7 +21183,7 @@ Example: (content-length:12), (Content-Type:application/json; charset=UTF-8)
<return type="int">
</return>
<description>
- Returns the current screen orientation, the return value will be one of the SCREEN_ORIENTATION constants in this class.
+ Returns the current screen orientation, the return value will be one of the SCREEN_ORIENTATION constants in this class.
</description>
</method>
<method name="set_keep_screen_on">
@@ -25033,7 +25109,7 @@ This method controls whether the position between two cached points is interpola
</argument>
<argument index="1" name="param" type="int">
</argument>
- <argument index="2" name="value" type="float" default="RID()">
+ <argument index="2" name="value" type="float">
</argument>
<description>
</description>
@@ -33787,7 +33863,7 @@ This method controls whether the position between two cached points is interpola
</description>
</method>
<method name="set_rotation">
- <argument index="0" name="rotation" type="Vector3">
+ <argument index="0" name="rotation_rad" type="Vector3">
</argument>
<description>
</description>
@@ -33798,6 +33874,18 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="set_rotation_deg">
+ <argument index="0" name="rotation_deg" type="Vector3">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_rotation_deg" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_scale">
<argument index="0" name="scale" type="Vector3">
</argument>
@@ -34183,13 +34271,13 @@ This method controls whether the position between two cached points is interpola
</description>
<methods>
<method name="set_stream">
- <argument index="0" name="stream" type="Stream">
+ <argument index="0" name="stream" type="AudioStream">
</argument>
<description>
</description>
</method>
<method name="get_stream" qualifiers="const">
- <return type="Stream">
+ <return type="AudioStream">
</return>
<description>
</description>
@@ -36479,11 +36567,11 @@ This method controls whether the position between two cached points is interpola
<method name="add_triangle_fan">
<argument index="0" name="vertexes" type="Vector3Array">
</argument>
- <argument index="1" name="uvs" type="Vector2Array" default="[Vector2Array]">
+ <argument index="1" name="uvs" type="Vector2Array" default="Vector2Array()">
</argument>
<argument index="2" name="colors" type="ColorArray" default="ColorArray([ColorArray])">
</argument>
- <argument index="3" name="uv2s" type="Vector2Array" default="[Vector2Array]">
+ <argument index="3" name="uv2s" type="Vector2Array" default="Vector2Array()">
</argument>
<argument index="4" name="normals" type="Vector3Array" default="Vector3Array()">
</argument>
@@ -36513,7 +36601,7 @@ This method controls whether the position between two cached points is interpola
<method name="commit">
<return type="Mesh">
</return>
- <argument index="0" name="existing" type="Mesh" default="Object()">
+ <argument index="0" name="existing" type="Mesh" default="NULL">
</argument>
<description>
</description>
@@ -39130,7 +39218,7 @@ This method controls whether the position between two cached points is interpola
<method name="create_item">
<return type="TreeItem">
</return>
- <argument index="0" name="parent" type="TreeItem" default="Object()">
+ <argument index="0" name="parent" type="TreeItem" default="NULL">
</argument>
<description>
</description>
@@ -41264,13 +41352,13 @@ This method controls whether the position between two cached points is interpola
</description>
<methods>
<method name="set_stream">
- <argument index="0" name="stream" type="Stream">
+ <argument index="0" name="stream" type="VideoStream">
</argument>
<description>
</description>
</method>
<method name="get_stream" qualifiers="const">
- <return type="Stream">
+ <return type="VideoStream">
</return>
<description>
</description>
@@ -42087,6 +42175,12 @@ This method controls whether the position between two cached points is interpola
<description>
</description>
</method>
+ <method name="texture_set_shrink_all_x2_on_set_data">
+ <argument index="0" name="shrink" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="shader_create">
<return type="RID">
</return>
diff --git a/drivers/builtin_openssl2/SCsub b/drivers/builtin_openssl2/SCsub
index 38880030b1..a51b0a3ed6 100644
--- a/drivers/builtin_openssl2/SCsub
+++ b/drivers/builtin_openssl2/SCsub
@@ -650,6 +650,7 @@ env_ssl.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/asn1"])
env_ssl.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/modes"])
#env_ssl.Append(CPPPATH=["#drivers/builtin_openssl2/crypto/store"])
env_ssl.Append(CPPFLAGS=["-DOPENSSL_NO_ASM","-DOPENSSL_THREADS","-DL_ENDIAN"])
+env_ssl.Append(CFLAGS=["-Wno-error=implicit-function-declaration"]);
env_ssl.add_source_files(env.drivers_sources,openssl_sources)
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 29c652051a..d88dd89002 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -184,7 +184,7 @@ public:
virtual bool is_window_minimized() const;
virtual void set_window_maximized(bool p_enabled);
virtual bool is_window_maximized() const;
- Size2 get_screen_size(int p_screen);
+ Size2 get_screen_size(int p_screen=0) const;
void run();
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index c814932dc4..c443fc2d0e 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1354,7 +1354,7 @@ Point2 OS_OSX::get_screen_position(int p_screen) const {
return screens[p_screen].pos;
};
-Size2 OS_OSX::get_screen_size(int p_screen) {
+Size2 OS_OSX::get_screen_size(int p_screen) const {
ERR_FAIL_INDEX_V(p_screen, screens.size(), Point2());
return screens[p_screen].size;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 352b7d645f..c9c7780a2a 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -705,6 +705,25 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
joystick->probe_joysticks();
} break;
+ case WM_SETCURSOR: {
+
+ if(LOWORD(lParam) == HTCLIENT) {
+ if(mouse_mode == MOUSE_MODE_HIDDEN) {
+ //Hide the cursor
+ if(hCursor == NULL)
+ hCursor = SetCursor(NULL);
+ else
+ SetCursor(NULL);
+ }
+ else {
+ if(hCursor != NULL) {
+ SetCursor(hCursor);
+ hCursor = NULL;
+ }
+ }
+ }
+
+ } break;
default: {
@@ -1211,7 +1230,6 @@ void OS_Windows::set_mouse_mode(MouseMode p_mode) {
if (mouse_mode==p_mode)
return;
- ShowCursor(p_mode==MOUSE_MODE_VISIBLE);
mouse_mode=p_mode;
if (p_mode==MOUSE_MODE_CAPTURED) {
RECT clipRect;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 81cf313849..adea26308f 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -103,6 +103,8 @@ class OS_Windows : public OS {
HDC hDC; // Private GDI Device Context
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;
+
+ HCURSOR hCursor;
Size2 window_rect;
VideoMode video_mode;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 7ef81306b6..134e0153b3 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -148,15 +148,28 @@ void Node2D::set_pos(const Point2& p_pos) {
}
-void Node2D::set_rot(float p_angle) {
+void Node2D::set_rot(float p_radians) {
if (_xform_dirty)
((Node2D*)this)->_update_xform_values();
- angle=p_angle;
+ angle=p_radians;
_update_transform();
_change_notify("transform/rot");
}
+void Node2D::set_rotd(float p_degrees) {
+
+ set_rot(Math::deg2rad(p_degrees));
+}
+
+// Kept for compatibility after rename to set_rotd.
+// Could be removed after a couple releases.
+void Node2D::_set_rotd(float p_degrees) {
+
+ WARN_PRINT("Deprecated method Node2D._set_rotd(): This method was renamed to set_rotd. Please adapt your code accordingly, as the old method will be obsoleted.");
+ set_rotd(p_degrees);
+}
+
void Node2D::set_scale(const Size2& p_scale) {
if (_xform_dirty)
@@ -183,21 +196,22 @@ float Node2D::get_rot() const {
return angle;
}
-Size2 Node2D::get_scale() const {
- if (_xform_dirty)
- ((Node2D*)this)->_update_xform_values();
+float Node2D::get_rotd() const {
- return _scale;
+ return Math::rad2deg(get_rot());
}
+// Kept for compatibility after rename to get_rotd.
+// Could be removed after a couple releases.
+float Node2D::_get_rotd() const {
-void Node2D::_set_rotd(float p_angle) {
-
- set_rot(Math::deg2rad(p_angle));
+ WARN_PRINT("Deprecated method Node2D._get_rotd(): This method was renamed to get_rotd. Please adapt your code accordingly, as the old method will be obsoleted.");
+ return get_rotd();
}
+Size2 Node2D::get_scale() const {
+ if (_xform_dirty)
+ ((Node2D*)this)->_update_xform_values();
-float Node2D::_get_rotd() const {
-
- return Math::rad2deg(get_rot());
+ return _scale;
}
@@ -361,16 +375,18 @@ float Node2D::get_angle_to(const Vector2& p_pos) const {
void Node2D::_bind_methods() {
-
+ // TODO: Obsolete those two methods (old name) properly (GH-4397)
ObjectTypeDB::bind_method(_MD("_get_rotd"),&Node2D::_get_rotd);
- ObjectTypeDB::bind_method(_MD("_set_rotd"),&Node2D::_set_rotd);
+ ObjectTypeDB::bind_method(_MD("_set_rotd","degrees"),&Node2D::_set_rotd);
ObjectTypeDB::bind_method(_MD("set_pos","pos"),&Node2D::set_pos);
- ObjectTypeDB::bind_method(_MD("set_rot","rot"),&Node2D::set_rot);
+ ObjectTypeDB::bind_method(_MD("set_rot","radians"),&Node2D::set_rot);
+ ObjectTypeDB::bind_method(_MD("set_rotd","degrees"),&Node2D::set_rotd);
ObjectTypeDB::bind_method(_MD("set_scale","scale"),&Node2D::set_scale);
ObjectTypeDB::bind_method(_MD("get_pos"),&Node2D::get_pos);
ObjectTypeDB::bind_method(_MD("get_rot"),&Node2D::get_rot);
+ ObjectTypeDB::bind_method(_MD("get_rotd"),&Node2D::get_rotd);
ObjectTypeDB::bind_method(_MD("get_scale"),&Node2D::get_scale);
ObjectTypeDB::bind_method(_MD("rotate","radians"),&Node2D::rotate);
@@ -400,7 +416,7 @@ void Node2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_relative_transform_to_parent","parent"),&Node2D::get_relative_transform_to_parent);
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
- ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
+ ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("set_rotd"),_SCS("get_rotd"));
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale"));
ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"z/z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z"));
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"z/relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative"));
diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h
index 49d616fc1f..b0c628fd94 100644
--- a/scene/2d/node_2d.h
+++ b/scene/2d/node_2d.h
@@ -47,6 +47,7 @@ class Node2D : public CanvasItem {
void _update_transform();
+ // Deprecated, should be removed in a future version.
void _set_rotd(float p_angle);
float _get_rotd() const;
@@ -69,7 +70,8 @@ public:
virtual bool edit_has_pivot() const;
void set_pos(const Point2& p_pos);
- void set_rot(float p_angle);
+ void set_rot(float p_radians);
+ void set_rotd(float p_degrees);
void set_scale(const Size2& p_scale);
void rotate(float p_radians);
@@ -81,6 +83,7 @@ public:
Point2 get_pos() const;
float get_rot() const;
+ float get_rotd() const;
Size2 get_scale() const;
Point2 get_global_pos() const;
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index c2d318e8a7..6a9c655141 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -346,14 +346,14 @@ void Spatial::set_translation(const Vector3& p_translation) {
}
-void Spatial::set_rotation(const Vector3& p_euler){
+void Spatial::set_rotation(const Vector3& p_euler_rad){
if (data.dirty&DIRTY_VECTORS) {
data.scale=data.local_transform.basis.get_scale();
data.dirty&=~DIRTY_VECTORS;
}
- data.rotation=p_euler;
+ data.rotation=p_euler_rad;
data.dirty|=DIRTY_LOCAL;
_propagate_transform_changed(this);
if (data.notify_local_transform) {
@@ -361,6 +361,18 @@ void Spatial::set_rotation(const Vector3& p_euler){
}
}
+
+void Spatial::set_rotation_deg(const Vector3& p_euler_deg) {
+
+ set_rotation(p_euler_deg * Math_PI / 180.0);
+}
+
+void Spatial::_set_rotation_deg(const Vector3& p_euler_deg) {
+
+ WARN_PRINT("Deprecated method Spatial._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
+ set_rotation_deg(p_euler_deg);
+}
+
void Spatial::set_scale(const Vector3& p_scale){
if (data.dirty&DIRTY_VECTORS) {
@@ -381,6 +393,7 @@ Vector3 Spatial::get_translation() const{
return data.local_transform.origin;
}
+
Vector3 Spatial::get_rotation() const{
if (data.dirty&DIRTY_VECTORS) {
@@ -391,6 +404,20 @@ Vector3 Spatial::get_rotation() const{
return data.rotation;
}
+
+Vector3 Spatial::get_rotation_deg() const {
+
+ return get_rotation() * 180.0 / Math_PI;
+}
+
+// Kept for compatibility after rename to set_rotd.
+// Could be removed after a couple releases.
+Vector3 Spatial::_get_rotation_deg() const {
+
+ WARN_PRINT("Deprecated method Spatial._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
+ return get_rotation_deg();
+}
+
Vector3 Spatial::get_scale() const{
if (data.dirty&DIRTY_VECTORS) {
@@ -495,16 +522,6 @@ bool Spatial::is_set_as_toplevel() const{
return data.toplevel;
}
-void Spatial::_set_rotation_deg(const Vector3& p_deg) {
-
- set_rotation(p_deg * Math_PI / 180.0);
-}
-
-Vector3 Spatial::_get_rotation_deg() const {
-
- return get_rotation() * 180.0 / Math_PI;
-}
-
Ref<World> Spatial::get_world() const {
ERR_FAIL_COND_V(!is_inside_world(),Ref<World>());
@@ -722,8 +739,10 @@ void Spatial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_transform"), &Spatial::get_transform);
ObjectTypeDB::bind_method(_MD("set_translation","translation"), &Spatial::set_translation);
ObjectTypeDB::bind_method(_MD("get_translation"), &Spatial::get_translation);
- ObjectTypeDB::bind_method(_MD("set_rotation","rotation"), &Spatial::set_rotation);
+ ObjectTypeDB::bind_method(_MD("set_rotation","rotation_rad"), &Spatial::set_rotation);
ObjectTypeDB::bind_method(_MD("get_rotation"), &Spatial::get_rotation);
+ ObjectTypeDB::bind_method(_MD("set_rotation_deg","rotation_deg"), &Spatial::set_rotation_deg);
+ ObjectTypeDB::bind_method(_MD("get_rotation_deg"), &Spatial::get_rotation_deg);
ObjectTypeDB::bind_method(_MD("set_scale","scale"), &Spatial::set_scale);
ObjectTypeDB::bind_method(_MD("get_scale"), &Spatial::get_scale);
ObjectTypeDB::bind_method(_MD("set_global_transform","global"), &Spatial::set_global_transform);
@@ -732,9 +751,11 @@ void Spatial::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_ignore_transform_notification","enabled"), &Spatial::set_ignore_transform_notification);
ObjectTypeDB::bind_method(_MD("set_as_toplevel","enable"), &Spatial::set_as_toplevel);
ObjectTypeDB::bind_method(_MD("is_set_as_toplevel"), &Spatial::is_set_as_toplevel);
+ ObjectTypeDB::bind_method(_MD("get_world:World"), &Spatial::get_world);
+
+ // TODO: Obsolete those two methods (old name) properly (GH-4397)
ObjectTypeDB::bind_method(_MD("_set_rotation_deg","rotation_deg"), &Spatial::_set_rotation_deg);
ObjectTypeDB::bind_method(_MD("_get_rotation_deg"), &Spatial::_get_rotation_deg);
- ObjectTypeDB::bind_method(_MD("get_world:World"), &Spatial::get_world);
#ifdef TOOLS_ENABLED
ObjectTypeDB::bind_method(_MD("_update_gizmo"), &Spatial::_update_gizmo);
@@ -789,7 +810,7 @@ void Spatial::_bind_methods() {
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), _SCS("set_global_transform"), _SCS("get_global_transform") );
ADD_PROPERTYNZ( PropertyInfo(Variant::TRANSFORM,"transform/local",PROPERTY_HINT_NONE,""), _SCS("set_transform"), _SCS("get_transform") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/translation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_translation"), _SCS("get_translation") );
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("_set_rotation_deg"), _SCS("_get_rotation_deg") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_rotation_deg"), _SCS("get_rotation_deg") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation_rad",PROPERTY_HINT_NONE,"",0), _SCS("set_rotation"), _SCS("get_rotation") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/scale",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_scale"), _SCS("get_scale") );
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"), _SCS("_is_visible_") );
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 50123b2d81..fdc9f95f0b 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -110,7 +110,8 @@ class Spatial : public Node {
void _notify_dirty();
void _propagate_transform_changed(Spatial *p_origin);
- void _set_rotation_deg(const Vector3& p_deg);
+ // Deprecated, should be removed in a future version.
+ void _set_rotation_deg(const Vector3& p_euler_deg);
Vector3 _get_rotation_deg() const;
void _propagate_visibility_changed();
@@ -144,11 +145,13 @@ public:
Ref<World> get_world() const;
void set_translation(const Vector3& p_translation);
- void set_rotation(const Vector3& p_euler);
+ void set_rotation(const Vector3& p_euler_rad);
+ void set_rotation_deg(const Vector3& p_euler_deg);
void set_scale(const Vector3& p_scale);
Vector3 get_translation() const;
Vector3 get_rotation() const;
+ Vector3 get_rotation_deg() const;
Vector3 get_scale() const;
void set_transform(const Transform& p_transform);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 7b3ac2a815..73e7237058 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2156,17 +2156,9 @@ bool Control::is_text_field() const {
}
-void Control::_set_rotation_deg(float p_rot) {
- set_rotation(Math::deg2rad(p_rot));
-}
-
-float Control::_get_rotation_deg() const {
- return Math::rad2deg(get_rotation());
-}
+void Control::set_rotation(float p_radians) {
-void Control::set_rotation(float p_rotation) {
-
- data.rotation=p_rotation;
+ data.rotation=p_radians;
update();
_notify_transform();
}
@@ -2176,6 +2168,25 @@ float Control::get_rotation() const{
return data.rotation;
}
+void Control::set_rotation_deg(float p_degrees) {
+ set_rotation(Math::deg2rad(p_degrees));
+}
+
+float Control::get_rotation_deg() const {
+ return Math::rad2deg(get_rotation());
+}
+
+// Kept for compatibility after rename to {s,g}et_rotation_deg.
+// Could be removed after a couple releases.
+void Control::_set_rotation_deg(float p_degrees) {
+ WARN_PRINT("Deprecated method Control._set_rotation_deg(): This method was renamed to set_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
+ set_rotation_deg(p_degrees);
+}
+float Control::_get_rotation_deg() const {
+ WARN_PRINT("Deprecated method Control._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted.");
+ return get_rotation_deg();
+}
+
void Control::set_scale(const Vector2& p_scale){
data.scale=p_scale;
@@ -2231,8 +2242,10 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_size","size"),&Control::set_size);
ObjectTypeDB::bind_method(_MD("set_custom_minimum_size","size"),&Control::set_custom_minimum_size);
ObjectTypeDB::bind_method(_MD("set_global_pos","pos"),&Control::set_global_pos);
- ObjectTypeDB::bind_method(_MD("set_rotation","rotation"),&Control::set_rotation);
- ObjectTypeDB::bind_method(_MD("_set_rotation_deg","rotation"),&Control::_set_rotation_deg);
+ ObjectTypeDB::bind_method(_MD("set_rotation","radians"),&Control::set_rotation);
+ ObjectTypeDB::bind_method(_MD("set_rotation_deg","degrees"),&Control::set_rotation_deg);
+ // TODO: Obsolete this method (old name) properly (GH-4397)
+ ObjectTypeDB::bind_method(_MD("_set_rotation_deg","degrees"),&Control::_set_rotation_deg);
ObjectTypeDB::bind_method(_MD("set_scale","scale"),&Control::set_scale);
ObjectTypeDB::bind_method(_MD("get_margin","margin"),&Control::get_margin);
ObjectTypeDB::bind_method(_MD("get_begin"),&Control::get_begin);
@@ -2240,12 +2253,14 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_pos"),&Control::get_pos);
ObjectTypeDB::bind_method(_MD("get_size"),&Control::get_size);
ObjectTypeDB::bind_method(_MD("get_rotation"),&Control::get_rotation);
+ ObjectTypeDB::bind_method(_MD("get_rotation_deg"),&Control::get_rotation_deg);
+ // TODO: Obsolete this method (old name) properly (GH-4397)
+ ObjectTypeDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg);
ObjectTypeDB::bind_method(_MD("get_scale"),&Control::get_scale);
ObjectTypeDB::bind_method(_MD("get_custom_minimum_size"),&Control::get_custom_minimum_size);
ObjectTypeDB::bind_method(_MD("get_parent_area_size"),&Control::get_size);
ObjectTypeDB::bind_method(_MD("get_global_pos"),&Control::get_global_pos);
ObjectTypeDB::bind_method(_MD("get_rect"),&Control::get_rect);
- ObjectTypeDB::bind_method(_MD("_get_rotation_deg"),&Control::_get_rotation_deg);
ObjectTypeDB::bind_method(_MD("get_global_rect"),&Control::get_global_rect);
ObjectTypeDB::bind_method(_MD("set_area_as_parent_rect","margin"),&Control::set_area_as_parent_rect,DEFVAL(0));
ObjectTypeDB::bind_method(_MD("show_modal","exclusive"),&Control::show_modal,DEFVAL(false));
@@ -2304,7 +2319,7 @@ void Control::_bind_methods() {
ObjectTypeDB::bind_method(_MD("grab_click_focus"),&Control::grab_click_focus);
- ObjectTypeDB::bind_method(_MD("set_drag_forwarding;","target:Control"),&Control::set_drag_forwarding);
+ ObjectTypeDB::bind_method(_MD("set_drag_forwarding","target:Control"),&Control::set_drag_forwarding);
ObjectTypeDB::bind_method(_MD("set_drag_preview","control:Control"),&Control::set_drag_preview);
ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"),&Control::warp_mouse);
@@ -2324,7 +2339,7 @@ void Control::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/pos", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_pos"),_SCS("get_pos") );
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/size", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_size"),_SCS("get_size") );
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/min_size"), _SCS("set_custom_minimum_size"),_SCS("get_custom_minimum_size") );
- ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"rect/rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), _SCS("_set_rotation_deg"),_SCS("_get_rotation_deg") );
+ ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"rect/rotation",PROPERTY_HINT_RANGE,"-1080,1080,0.01"), _SCS("set_rotation_deg"),_SCS("get_rotation_deg") );
ADD_PROPERTYNO( PropertyInfo(Variant::VECTOR2,"rect/scale"), _SCS("set_scale"),_SCS("get_scale") );
ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint/tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT );
diff --git a/scene/gui/control.h b/scene/gui/control.h
index aa9a7612a5..f720185c9d 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -180,7 +180,8 @@ private:
void _size_changed();
String _get_tooltip() const;
- void _set_rotation_deg(float p_rot);
+ // Deprecated, should be removed in a future version.
+ void _set_rotation_deg(float p_degrees);
float _get_rotation_deg() const;
friend class Viewport;
@@ -275,8 +276,10 @@ public:
Rect2 get_global_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
- void set_rotation(float p_rotation);
+ void set_rotation(float p_radians);
+ void set_rotation_deg(float p_degrees);
float get_rotation() const;
+ float get_rotation_deg() const;
void set_scale(const Vector2& p_scale);
Vector2 get_scale() const;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 6a251a5ac5..64f1de42af 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1044,8 +1044,7 @@ void ItemList::_scroll_changed(double) {
update();
}
-
-String ItemList::get_tooltip(const Point2& p_pos) const {
+int ItemList::get_item_at_pos(const Point2& p_pos) const {
Vector2 pos=p_pos;
Ref<StyleBox> bg = get_stylebox("bg");
@@ -1074,6 +1073,13 @@ String ItemList::get_tooltip(const Point2& p_pos) const {
}
}
+ return closest;
+}
+
+String ItemList::get_tooltip(const Point2& p_pos) const {
+
+ int closest = get_item_at_pos(p_pos);
+
if (closest!=-1) {
if (items[closest].tooltip!="") {
return items[closest].tooltip;
@@ -1084,8 +1090,6 @@ String ItemList::get_tooltip(const Point2& p_pos) const {
}
return Control::get_tooltip(p_pos);
-
-
}
void ItemList::sort_items_by_text() {
@@ -1170,6 +1174,8 @@ void ItemList::_bind_methods(){
ObjectTypeDB::bind_method(_MD("set_min_icon_size","size"),&ItemList::set_min_icon_size);
ObjectTypeDB::bind_method(_MD("get_min_icon_size"),&ItemList::get_min_icon_size);
+ ObjectTypeDB::bind_method(_MD("get_item_at_pos","pos"),&ItemList::get_item_at_pos);
+
ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible);
ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 5aec946686..fcb4dfae5a 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -140,6 +140,7 @@ public:
int find_metadata(const Variant& p_metadata) const;
virtual String get_tooltip(const Point2& p_pos) const;
+ int get_item_at_pos(const Point2& p_pos) const;
ItemList();
~ItemList();
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index bf8aff0f44..1a465baf49 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -921,14 +921,18 @@ void TextEdit::_notification(int p_what) {
if (cursor.column==j && cursor.line==line) {
cursor_pos = Point2i( char_ofs+char_margin, ofs_y );
+
if (insert_mode) {
cursor_pos.y += get_row_height();
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color);
- } else {
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color);
}
-
+ if (draw_caret) {
+ if (insert_mode) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color);
+ }
+ }
}
char_ofs+=char_w;
@@ -937,12 +941,18 @@ void TextEdit::_notification(int p_what) {
if (cursor.column==str.length() && cursor.line==line && (char_ofs+char_margin)>=xmargin_beg) {
cursor_pos=Point2i( char_ofs+char_margin, ofs_y );
+
if (insert_mode) {
cursor_pos.y += get_row_height();
- int char_w = cache.font->get_char_size(' ').width;
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color);
- } else {
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color);
+ }
+
+ if (draw_caret) {
+ if (insert_mode) {
+ int char_w = cache.font->get_char_size(' ').width;
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color);
+ }
}
}
}
@@ -1390,6 +1400,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
}
if (mb.button_index==BUTTON_LEFT) {
+ _reset_caret_blink_timer();
+
int row,col;
_get_mouse_pos(Point2i(mb.x,mb.y), row,col);
@@ -1524,6 +1536,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (selection.selecting_mode!=Selection::MODE_NONE) {
+ _reset_caret_blink_timer();
+
int row,col;
_get_mouse_pos(Point2i(mm.x,mm.y), row,col);
@@ -1644,6 +1658,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (k.scancode==KEY_BACKSPACE) {
+ _reset_caret_blink_timer();
+
backspace_at_cursor();
_update_completion_candidates();
accept_event();
@@ -1659,6 +1675,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (k.unicode>32) {
+ _reset_caret_blink_timer();
+
const CharType chr[2] = {(CharType)k.unicode, 0};
if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
_consume_pair_symbol(chr[0]);
@@ -1705,6 +1723,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
k.mod.shift=false;
}
+ if (!k.mod.command) {
+ _reset_caret_blink_timer();
+ }
// save here for insert mode, just in case it is cleared in the following section
bool had_selection = selection.active;
@@ -2902,6 +2923,30 @@ int TextEdit::cursor_get_line() const {
return cursor.line;
}
+bool TextEdit::cursor_get_blink_enabled() const {
+ return caret_blink_enabled;
+}
+
+void TextEdit::cursor_set_blink_enabled(const bool p_enabled) {
+ caret_blink_enabled = p_enabled;
+
+ if (p_enabled) {
+ caret_blink_timer->start();
+ } else {
+ caret_blink_timer->stop();
+ }
+ draw_caret = true;
+}
+
+
+float TextEdit::cursor_get_blink_speed() const {
+ return caret_blink_timer->get_wait_time();
+}
+
+void TextEdit::cursor_set_blink_speed(const float p_speed) {
+ ERR_FAIL_COND(p_speed <= 0);
+ caret_blink_timer->set_wait_time(p_speed);
+}
void TextEdit::_scroll_moved(double p_to_val) {
@@ -3117,6 +3162,20 @@ void TextEdit::set_max_chars(int p_max_chars) {
max_chars=p_max_chars;
}
+void TextEdit::_reset_caret_blink_timer() {
+ if (caret_blink_enabled) {
+ caret_blink_timer->stop();
+ caret_blink_timer->start();
+ draw_caret = true;
+ update();
+ }
+}
+
+void TextEdit::_toggle_draw_caret() {
+ draw_caret = !draw_caret;
+ update();
+}
+
void TextEdit::_update_caches() {
cache.style_normal=get_stylebox("normal");
@@ -4096,6 +4155,7 @@ void TextEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit);
ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op);
ObjectTypeDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held);
+ ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret);
BIND_CONSTANT( SEARCH_MATCH_CASE );
BIND_CONSTANT( SEARCH_WHOLE_WORDS );
@@ -4165,6 +4225,7 @@ TextEdit::TextEdit() {
readonly=false;
setting_row=false;
draw_tabs=false;
+ draw_caret=true;
max_chars=0;
clear();
wrap=false;
@@ -4204,6 +4265,13 @@ TextEdit::TextEdit() {
selection.active=false;
syntax_coloring=false;
+ caret_blink_enabled=false;
+ caret_blink_timer = memnew(Timer);
+ add_child(caret_blink_timer);
+ caret_blink_timer->set_wait_time(0.65);
+ caret_blink_timer->connect("timeout", this,"_toggle_draw_caret");
+ cursor_set_blink_enabled(false);
+
custom_bg_color=Color(0,0,0,0);
idle_detect = memnew( Timer );
add_child(idle_detect);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 193dd236d1..ea4f148e91 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -210,6 +210,10 @@ class TextEdit : public Control {
bool syntax_coloring;
int tab_size;
+ Timer *caret_blink_timer;
+ bool caret_blink_enabled;
+ bool draw_caret;
+
bool setting_row;
bool wrap;
bool draw_tabs;
@@ -267,6 +271,9 @@ class TextEdit : public Control {
int get_row_height() const;
+ void _reset_caret_blink_timer();
+ void _toggle_draw_caret();
+
void _update_caches();
void _cursor_changed_emit();
void _text_changed_emit();
@@ -364,6 +371,12 @@ public:
int cursor_get_column() const;
int cursor_get_line() const;
+ bool cursor_get_blink_enabled() const;
+ void cursor_set_blink_enabled(const bool p_enabled);
+
+ float cursor_get_blink_speed() const;
+ void cursor_set_blink_speed(const float p_speed);
+
void set_readonly(bool p_readonly);
void set_max_chars(int p_max_chars);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index c4efe82eaa..c141635bbf 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -604,10 +604,11 @@ String TreeItem::get_tooltip(int p_column) const{
return cells[p_column].tooltip;
}
-void TreeItem::set_custom_bg_color(int p_column,const Color& p_color) {
+void TreeItem::set_custom_bg_color(int p_column,const Color& p_color,bool p_bg_outline) {
ERR_FAIL_INDEX( p_column, cells.size() );
cells[p_column].custom_bg_color=true;
+ cells[p_column].custom_bg_outline=p_bg_outline;
cells[p_column].bg_color=p_color;
_changed_notify(p_column);
}
@@ -685,7 +686,7 @@ void TreeItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_custom_color","column","color"),&TreeItem::set_custom_color);
ObjectTypeDB::bind_method(_MD("clear_custom_color","column"),&TreeItem::clear_custom_color);
- ObjectTypeDB::bind_method(_MD("set_custom_bg_color","column","color"),&TreeItem::set_custom_bg_color);
+ ObjectTypeDB::bind_method(_MD("set_custom_bg_color","column","color","just_outline"),&TreeItem::set_custom_bg_color,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("clear_custom_bg_color","column"),&TreeItem::clear_custom_bg_color);
ObjectTypeDB::bind_method(_MD("get_custom_bg_color","column"),&TreeItem::get_custom_bg_color);
@@ -757,6 +758,13 @@ TreeItem::~TreeItem() {
if (tree && tree->selected_item==this)
tree->selected_item=NULL;
+
+ if (tree && tree->drop_mode_over==this)
+ tree->drop_mode_over=NULL;
+
+ if (tree && tree->single_select_defer==this)
+ tree->single_select_defer=NULL;
+
if (tree && tree->edited_item==this) {
tree->edited_item=NULL;
tree->pressing_for_editor=false;
@@ -797,17 +805,13 @@ void Tree::update_cache() {
cache.font_color=get_color("font_color");
cache.font_color_selected=get_color("font_color_selected");
cache.guide_color=get_color("guide_color");
+ cache.drop_position_color=get_color("drop_position_color");
cache.hseparation=get_constant("hseparation");
cache.vseparation=get_constant("vseparation");
cache.item_margin=get_constant("item_margin");
cache.button_margin=get_constant("button_margin");
cache.guide_width=get_constant("guide_width");
- Ref<StyleBox> title_button;
- Ref<StyleBox> title_button_hover;
- Ref<StyleBox> title_button_pressed;
- Color title_button_color;
-
cache.title_button = get_stylebox("title_button_normal");
cache.title_button_pressed = get_stylebox("title_button_pressed");
cache.title_button_hover = get_stylebox("title_button_hover");
@@ -1087,7 +1091,34 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
Rect2 r=cell_rect;
r.pos.x-=cache.hseparation;
r.size.x+=cache.hseparation;
- VisualServer::get_singleton()->canvas_item_add_rect(ci,r,p_item->cells[i].bg_color);
+ if (p_item->cells[i].custom_bg_outline) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,r.size.x,1),p_item->cells[i].bg_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y+r.size.y-1,r.size.x,1),p_item->cells[i].bg_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,1,r.size.y),p_item->cells[i].bg_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x+r.size.x-1,r.pos.y,1,r.size.y),p_item->cells[i].bg_color);
+ } else {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,r,p_item->cells[i].bg_color);
+ }
+ }
+
+ if (drop_mode_flags && drop_mode_over==p_item) {
+
+ Rect2 r=cell_rect;
+
+ if (drop_mode_section==-1 || drop_mode_section==0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,r.size.x,1),cache.drop_position_color);
+
+ }
+
+ if (drop_mode_section==0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y,1,r.size.y),cache.drop_position_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x+r.size.x-1,r.pos.y,1,r.size.y),cache.drop_position_color);
+
+ }
+
+ if (drop_mode_section==1 || drop_mode_section==0) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(r.pos.x,r.pos.y+r.size.y,r.size.x,1),cache.drop_position_color);
+ }
}
Color col=p_item->cells[i].custom_color?p_item->cells[i].color:get_color( p_item->cells[i].selected?"font_color_selected":"font_color");
@@ -1280,6 +1311,25 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
}
+int Tree::_count_selected_items(TreeItem* p_from) const {
+
+ int count=0;
+ for(int i=0;i<columns.size();i++) {
+ if (p_from->is_selected(i))
+ count++;
+ }
+
+ if (p_from->get_children()) {
+ count+=_count_selected_items(p_from->get_children());
+ }
+
+ if (p_from->get_next()) {
+ count+=_count_selected_items(p_from->get_next());
+ }
+
+ return count;
+
+}
void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col,TreeItem *p_prev,bool *r_in_range) {
TreeItem::Cell &selected_cell=p_selected->cells[p_col];
@@ -1548,7 +1598,15 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
select_single_item( p_item, root, col,selected_item,&inrange );
} else {
- select_single_item( p_item, root, col );
+
+ int icount = _count_selected_items(root);
+
+ if (select_mode==SELECT_MULTI && icount>1) {
+ single_select_defer=p_item;
+ single_select_defer_column=col;
+ } else {
+ select_single_item( p_item, root, col );
+ }
}
//if (!c.selected && select_mode==SELECT_MULTI) {
@@ -2159,6 +2217,31 @@ void Tree::_input_event(InputEvent p_event) {
}
+ if (drop_mode_flags && root) {
+
+ Point2 mpos=Point2(b.x,b.y);
+ mpos -= cache.bg->get_offset();
+ mpos.y-=_get_title_button_height();
+ if (mpos.y>=0) {
+
+ if (h_scroll->is_visible())
+ mpos.x+=h_scroll->get_val();
+ if (v_scroll->is_visible())
+ mpos.y+=v_scroll->get_val();
+
+ int col,h,section;
+ TreeItem *it = _find_item_at_pos(root,mpos,col,h,section);
+
+ if (it!=drop_mode_over || section!=drop_mode_section) {
+ drop_mode_over=it;
+ drop_mode_section=section;
+ update();
+ }
+ }
+ }
+
+
+
if (cache.hover_type!=old_hover || cache.hover_index!=old_index) {
update();
}
@@ -2211,6 +2294,12 @@ void Tree::_input_event(InputEvent p_event) {
if (b.button_index==BUTTON_LEFT) {
+
+ if (single_select_defer) {
+ select_single_item( single_select_defer, root, single_select_defer_column );
+ single_select_defer=NULL;
+ }
+
range_click_timer->stop();
if (pressing_for_editor) {
@@ -2522,6 +2611,15 @@ void Tree::_notification(int p_what) {
update_cache();;
}
+ if (p_what==NOTIFICATION_DRAG_END) {
+
+ drop_mode_flags=0;
+ update();
+ }
+ if (p_what==NOTIFICATION_DRAG_BEGIN) {
+
+ single_select_defer=NULL;
+ }
if (p_what==NOTIFICATION_FIXED_PROCESS) {
if (drag_touching) {
@@ -3135,7 +3233,7 @@ void Tree::_do_incr_search(const String& p_add) {
}
-TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_column,int &h) const {
+TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_column,int &h,int &section) const {
Point2 pos = p_pos;
@@ -3145,15 +3243,33 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
h = compute_item_height(p_item)+cache.vseparation;;
if (pos.y<h) {
+ if (drop_mode_flags==DROP_MODE_ON_ITEM) {
+ section=0;
+ } else if (drop_mode_flags==DROP_MODE_INBETWEEN) {
+ section=pos.y<h/2?-1:1;
+ } else if (pos.y<h/4) {
+ section=-1;
+ } else if (pos.y>=(h*3/4)) {
+ section=1;
+ } else {
+ section=0;
+ }
+
for(int i=0;i<columns.size();i++) {
int w = get_column_width(i);
if (pos.x < w) {
r_column=i;
+
+
return p_item;
}
pos.x-=w;
}
+
+
+
+
return NULL;
} else {
@@ -3172,7 +3288,7 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
int ch;
- TreeItem *r = _find_item_at_pos(n,pos,r_column,ch);
+ TreeItem *r = _find_item_at_pos(n,pos,r_column,ch,section);
pos.y-=ch;
h+=ch;
if (r)
@@ -3184,6 +3300,88 @@ TreeItem* Tree::_find_item_at_pos(TreeItem*p_item, const Point2& p_pos,int& r_co
}
+int Tree::get_column_at_pos(const Point2& p_pos) const {
+
+ if (root) {
+
+ Point2 pos=p_pos;
+ pos -= cache.bg->get_offset();
+ pos.y-=_get_title_button_height();
+ if (pos.y<0)
+ return -1;
+
+ if (h_scroll->is_visible())
+ pos.x+=h_scroll->get_val();
+ if (v_scroll->is_visible())
+ pos.y+=v_scroll->get_val();
+
+ int col,h,section;
+ TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
+
+ if (it) {
+ return col;
+ }
+ }
+
+ return -1;
+
+}
+
+int Tree::get_drop_section_at_pos(const Point2& p_pos) const {
+
+ if (root) {
+
+ Point2 pos=p_pos;
+ pos -= cache.bg->get_offset();
+ pos.y-=_get_title_button_height();
+ if (pos.y<0)
+ return -100;
+
+ if (h_scroll->is_visible())
+ pos.x+=h_scroll->get_val();
+ if (v_scroll->is_visible())
+ pos.y+=v_scroll->get_val();
+
+ int col,h,section;
+ TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
+
+ if (it) {
+ return section;
+ }
+ }
+
+ return -100;
+
+}
+TreeItem* Tree::get_item_at_pos(const Point2& p_pos) const {
+
+
+ if (root) {
+
+ Point2 pos=p_pos;
+ pos -= cache.bg->get_offset();
+ pos.y-=_get_title_button_height();
+ if (pos.y<0)
+ return NULL;
+
+ if (h_scroll->is_visible())
+ pos.x+=h_scroll->get_val();
+ if (v_scroll->is_visible())
+ pos.y+=v_scroll->get_val();
+
+ int col,h,section;
+ TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
+
+ if (it) {
+
+ return it;
+ }
+ }
+
+ return NULL;
+
+}
+
String Tree::get_tooltip(const Point2& p_pos) const {
if (root) {
@@ -3199,8 +3397,8 @@ String Tree::get_tooltip(const Point2& p_pos) const {
if (v_scroll->is_visible())
pos.y+=v_scroll->get_val();
- int col,h;
- TreeItem *it = _find_item_at_pos(root,pos,col,h);
+ int col,h,section;
+ TreeItem *it = _find_item_at_pos(root,pos,col,h,section);
if (it) {
@@ -3241,6 +3439,20 @@ void Tree::set_value_evaluator(ValueEvaluator *p_evaluator) {
evaluator = p_evaluator;
}
+void Tree::set_drop_mode_flags(int p_flags) {
+ drop_mode_flags=p_flags;
+ if (drop_mode_flags==0) {
+ drop_mode_over=NULL;
+ }
+
+ update();
+}
+
+int Tree::get_drop_mode_flags() const {
+
+ return drop_mode_flags;
+}
+
void Tree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout);
@@ -3273,6 +3485,8 @@ void Tree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_edited_column"),&Tree::get_edited_column);
ObjectTypeDB::bind_method(_MD("get_custom_popup_rect"),&Tree::get_custom_popup_rect);
ObjectTypeDB::bind_method(_MD("get_item_area_rect","item:TreeItem","column"),&Tree::_get_item_rect,DEFVAL(-1));
+ ObjectTypeDB::bind_method(_MD("get_item_at_pos:TreeItem","pos"),&Tree::get_item_at_pos);
+ ObjectTypeDB::bind_method(_MD("get_column_at_pos","pos"),&Tree::get_column_at_pos);
ObjectTypeDB::bind_method(_MD("ensure_cursor_is_visible"),&Tree::ensure_cursor_is_visible);
@@ -3286,6 +3500,9 @@ void Tree::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_hide_folding","hide"),&Tree::set_hide_folding);
ObjectTypeDB::bind_method(_MD("is_folding_hidden"),&Tree::is_folding_hidden);
+ ObjectTypeDB::bind_method(_MD("set_drop_mode_flags","flags"),&Tree::set_drop_mode_flags);
+ ObjectTypeDB::bind_method(_MD("get_drop_mode_flags"),&Tree::get_drop_mode_flags);
+
ADD_SIGNAL( MethodInfo("item_selected"));
ADD_SIGNAL( MethodInfo("cell_selected"));
@@ -3300,6 +3517,11 @@ void Tree::_bind_methods() {
BIND_CONSTANT( SELECT_SINGLE );
BIND_CONSTANT( SELECT_ROW );
BIND_CONSTANT( SELECT_MULTI );
+
+ BIND_CONSTANT( DROP_MODE_DISABLED );
+ BIND_CONSTANT( DROP_MODE_ON_ITEM );
+ BIND_CONSTANT( DROP_MODE_INBETWEEN );
+
}
Tree::Tree() {
@@ -3381,6 +3603,11 @@ Tree::Tree() {
hide_folding=false;
evaluator=NULL;
+
+ drop_mode_flags=0;
+ drop_mode_over=NULL;
+ drop_mode_section=0;
+ single_select_defer=NULL;
}
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 75bcfd8e33..43a913392e 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -79,7 +79,9 @@ friend class Tree;
bool custom_color;
Color color;
bool custom_bg_color;
+ bool custom_bg_outline;
Color bg_color;
+
Variant meta;
String tooltip;
@@ -226,7 +228,7 @@ public:
Color get_custom_color(int p_column) const;
void clear_custom_color(int p_column);
- void set_custom_bg_color(int p_column,const Color& p_color);
+ void set_custom_bg_color(int p_column, const Color& p_color, bool p_bg_outline=false);
void clear_custom_bg_color(int p_column);
Color get_custom_bg_color(int p_column) const;
@@ -257,6 +259,12 @@ public:
SELECT_MULTI
};
+ enum DropModeFlags {
+ DROP_MODE_DISABLED=0,
+ DROP_MODE_ON_ITEM=1,
+ DROP_MODE_INBETWEEN=2
+ };
+
private:
friend class TreeItem;
@@ -265,6 +273,11 @@ friend class TreeItem;
TreeItem *selected_item;
TreeItem *edited_item;
+ TreeItem *drop_mode_over;
+ int drop_mode_section;
+
+ TreeItem *single_select_defer;
+ int single_select_defer_column;
int pressed_button;
bool pressing_for_editor;
@@ -289,6 +302,8 @@ friend class TreeItem;
int blocked;
+ int drop_mode_flags;
+
struct ColumnInfo {
int min_width;
@@ -361,6 +376,8 @@ friend class TreeItem;
Color font_color;
Color font_color_selected;
Color guide_color;
+ Color drop_position_color;
+
int hseparation;
int vseparation;
int item_margin;
@@ -405,7 +422,7 @@ friend class TreeItem;
TreeItem* _search_item_text(TreeItem *p_at, const String& p_find,int *r_col,bool p_selectable,bool p_backwards=false);
- TreeItem* _find_item_at_pos(TreeItem *p_current, const Point2& p_pos,int& r_column,int &h) const;
+ TreeItem* _find_item_at_pos(TreeItem *p_current, const Point2& p_pos, int& r_column, int &h, int &section) const;
/* float drag_speed;
float drag_accum;
@@ -426,6 +443,8 @@ friend class TreeItem;
ValueEvaluator *evaluator;
+ int _count_selected_items(TreeItem* p_from) const;
+
protected:
static void _bind_methods();
@@ -433,10 +452,16 @@ protected:
Object* _create_item(Object *p_parent) { return create_item(p_parent->cast_to<TreeItem>() ); }
TreeItem *_get_next_selected(Object *p_item) { return get_next_selected(p_item->cast_to<TreeItem>() ); }
Rect2 _get_item_rect(Object *p_item,int p_column) const { return get_item_rect(p_item->cast_to<TreeItem>(),p_column ); }
+
+
public:
virtual String get_tooltip(const Point2& p_pos) const;
+ TreeItem* get_item_at_pos(const Point2& p_pos) const;
+ int get_column_at_pos(const Point2& p_pos) const;
+ int get_drop_section_at_pos(const Point2& p_pos) const;
+
void clear();
TreeItem* create_item(TreeItem *p_parent=0);
@@ -486,6 +511,9 @@ public:
void set_hide_folding(bool p_hide);
bool is_folding_hidden() const;
+ void set_drop_mode_flags(int p_flags);
+ int get_drop_mode_flags() const;
+
void set_value_evaluator(ValueEvaluator *p_evaluator);
Tree();
diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index bc37cde4a2..c31a57f819 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -94,13 +94,13 @@ Vector2 CanvasLayer::get_offset() const {
}
-void CanvasLayer::set_rotation(real_t p_rotation) {
+void CanvasLayer::set_rotation(real_t p_radians) {
if (locrotscale_dirty)
_update_locrotscale();
- rot=p_rotation;
+ rot=p_radians;
_update_xform();
}
@@ -113,6 +113,29 @@ real_t CanvasLayer::get_rotation() const {
return rot;
}
+void CanvasLayer::set_rotationd(real_t p_degrees) {
+
+ set_rotation(Math::deg2rad(p_degrees));
+}
+
+real_t CanvasLayer::get_rotationd() const {
+
+ return Math::rad2deg(get_rotation());
+}
+
+// Kept for compatibility after rename to {s,g}et_rotationd.
+// Could be removed after a couple releases.
+void CanvasLayer::_set_rotationd(real_t p_degrees) {
+
+ WARN_PRINT("Deprecated method CanvasLayer._set_rotationd(): This method was renamed to set_rotationd. Please adapt your code accordingly, as the old method will be obsoleted.");
+ set_rotationd(p_degrees);
+}
+
+real_t CanvasLayer::_get_rotationd() const {
+
+ WARN_PRINT("Deprecated method CanvasLayer._get_rotationd(): This method was renamed to get_rotationd. Please adapt your code accordingly, as the old method will be obsoleted.");
+ return get_rotationd();
+}
void CanvasLayer::set_scale(const Vector2& p_scale) {
@@ -122,7 +145,6 @@ void CanvasLayer::set_scale(const Vector2& p_scale) {
scale=p_scale;
_update_xform();
-
}
Vector2 CanvasLayer::get_scale() const {
@@ -193,16 +215,6 @@ RID CanvasLayer::get_viewport() const {
return viewport;
}
-void CanvasLayer::_set_rotationd(real_t p_rotation) {
-
- set_rotation(Math::deg2rad(p_rotation));
-}
-
-real_t CanvasLayer::_get_rotationd() const {
-
- return Math::rad2deg(get_rotation());
-}
-
void CanvasLayer::_bind_methods() {
@@ -216,10 +228,14 @@ void CanvasLayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&CanvasLayer::set_offset);
ObjectTypeDB::bind_method(_MD("get_offset"),&CanvasLayer::get_offset);
- ObjectTypeDB::bind_method(_MD("set_rotation","rotation"),&CanvasLayer::set_rotation);
+ ObjectTypeDB::bind_method(_MD("set_rotation","radians"),&CanvasLayer::set_rotation);
ObjectTypeDB::bind_method(_MD("get_rotation"),&CanvasLayer::get_rotation);
- ObjectTypeDB::bind_method(_MD("_set_rotationd","rotationd"),&CanvasLayer::_set_rotationd);
+ ObjectTypeDB::bind_method(_MD("set_rotationd","degrees"),&CanvasLayer::set_rotationd);
+ ObjectTypeDB::bind_method(_MD("get_rotationd"),&CanvasLayer::get_rotationd);
+
+ // TODO: Obsolete those two methods (old name) properly (GH-4397)
+ ObjectTypeDB::bind_method(_MD("_set_rotationd","degrees"),&CanvasLayer::_set_rotationd);
ObjectTypeDB::bind_method(_MD("_get_rotationd"),&CanvasLayer::_get_rotationd);
ObjectTypeDB::bind_method(_MD("set_scale","scale"),&CanvasLayer::set_scale);
@@ -231,7 +247,7 @@ void CanvasLayer::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer",PROPERTY_HINT_RANGE,"-128,128,1"),_SCS("set_layer"),_SCS("get_layer") );
//ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"transform",PROPERTY_HINT_RANGE),_SCS("set_transform"),_SCS("get_transform") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset") );
- ADD_PROPERTY( PropertyInfo(Variant::REAL,"rotation"),_SCS("_set_rotationd"),_SCS("_get_rotationd") );
+ ADD_PROPERTY( PropertyInfo(Variant::REAL,"rotation"),_SCS("set_rotationd"),_SCS("get_rotationd") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"scale"),_SCS("set_scale"),_SCS("get_scale") );
}
diff --git a/scene/main/canvas_layer.h b/scene/main/canvas_layer.h
index 809b3fae7f..a3e8211a43 100644
--- a/scene/main/canvas_layer.h
+++ b/scene/main/canvas_layer.h
@@ -48,7 +48,7 @@ class CanvasLayer : public Node {
RID viewport;
Viewport *vp;
-
+ // Deprecated, should be removed in a future version.
void _set_rotationd(real_t p_rotation);
real_t _get_rotationd() const;
@@ -70,9 +70,12 @@ public:
void set_offset(const Vector2& p_offset);
Vector2 get_offset() const;
- void set_rotation(real_t p_rotation);
+ void set_rotation(real_t p_radians);
real_t get_rotation() const;
+ void set_rotationd(real_t p_degrees);
+ real_t get_rotationd() const;
+
void set_scale(const Vector2& p_scale);
Vector2 get_scale() const;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 8475ca0b39..da14fa1111 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2095,6 +2095,8 @@ void Node::_bind_methods() {
BIND_CONSTANT( NOTIFICATION_PAUSED );
BIND_CONSTANT( NOTIFICATION_UNPAUSED );
BIND_CONSTANT( NOTIFICATION_INSTANCED );
+ BIND_CONSTANT( NOTIFICATION_DRAG_BEGIN );
+ BIND_CONSTANT( NOTIFICATION_DRAG_END );
diff --git a/scene/main/node.h b/scene/main/node.h
index 560a2e588a..83086bb0cf 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -180,6 +180,8 @@ public:
NOTIFICATION_PARENTED=18,
NOTIFICATION_UNPARENTED=19,
NOTIFICATION_INSTANCED=20,
+ NOTIFICATION_DRAG_BEGIN=21,
+ NOTIFICATION_DRAG_END=22,
};
/* NODE/TREE */
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 5017ae61ff..265ee53e58 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -985,6 +985,16 @@ void Viewport::_propagate_enter_world(Node *p_node) {
}
}
+void Viewport::_propagate_viewport_notification(Node* p_node,int p_what) {
+
+ p_node->notification(p_what);
+ for(int i=0;i<p_node->get_child_count();i++) {
+ Node *c = p_node->get_child(i);
+ if (c->cast_to<Viewport>())
+ continue;
+ _propagate_viewport_notification(c,p_what);
+ }
+}
void Viewport::_propagate_exit_world(Node *p_node) {
@@ -1676,6 +1686,9 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (p_event.mouse_button.button_index==BUTTON_LEFT) {
gui.drag_accum=Vector2();
gui.drag_attempted=false;
+ if (gui.drag_data.get_type()!=Variant::NIL) {
+ _propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
+ }
gui.drag_data=Variant();
}
@@ -1736,6 +1749,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
gui.mouse_over->drop_data(pos,gui.drag_data);
gui.drag_data=Variant();
+ _propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
//change mouse accordingly
}
@@ -1759,6 +1773,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
}
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_button.button_index==BUTTON_LEFT) {
+ _propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
gui.drag_data=Variant(); //always clear
}
@@ -1790,6 +1805,10 @@ void Viewport::_gui_input_event(InputEvent p_event) {
gui.mouse_focus=NULL;
}
gui.drag_attempted=true;
+ if (gui.drag_data.get_type()!=Variant::NIL) {
+
+ _propagate_viewport_notification(this,NOTIFICATION_DRAG_BEGIN);
+ }
}
}
@@ -1814,6 +1833,8 @@ void Viewport::_gui_input_event(InputEvent p_event) {
}
}
+
+
if (over!=gui.mouse_over) {
if (gui.mouse_over)
@@ -1896,7 +1917,15 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (gui.drag_data.get_type()!=Variant::NIL && p_event.mouse_motion.button_mask&BUTTON_MASK_LEFT) {
- /*bool can_drop =*/ over->can_drop_data(pos,gui.drag_data);
+
+ bool can_drop = over->can_drop_data(pos,gui.drag_data);
+
+ if (!can_drop) {
+ OS::get_singleton()->set_cursor_shape( OS::CURSOR_FORBIDDEN );
+ } else {
+ OS::get_singleton()->set_cursor_shape( OS::CURSOR_CAN_DROP );
+
+ }
//change mouse accordingly i guess
}
@@ -2367,6 +2396,9 @@ bool Viewport::is_input_disabled() const {
return disable_input;
}
+Variant Viewport::gui_get_drag_data() const {
+ return gui.drag_data;
+}
void Viewport::_bind_methods() {
@@ -2452,6 +2484,7 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("warp_mouse","to_pos"), &Viewport::warp_mouse);
ObjectTypeDB::bind_method(_MD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
+ ObjectTypeDB::bind_method(_MD("gui_get_drag_data:Variant"), &Viewport::gui_get_drag_data);
ObjectTypeDB::bind_method(_MD("set_disable_input","disable"), &Viewport::set_disable_input);
ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index afabd499a9..6107cf570f 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -159,6 +159,7 @@ friend class RenderTargetTexture;
void _propagate_enter_world(Node *p_node);
void _propagate_exit_world(Node *p_node);
+ void _propagate_viewport_notification(Node *p_node, int p_what);
void _update_stretch_transform();
@@ -361,6 +362,7 @@ public:
bool gui_has_modal_stack() const;
+ Variant gui_get_drag_data() const;
Viewport();
~Viewport();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 727c8eee29..ade56c4f49 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -655,6 +655,7 @@ void make_default_theme() {
t->set_color("selection_color","Tree", Color(0.1,0.1,1,0.8) );
t->set_color("cursor_color","Tree", Color(0,0,0) );
t->set_color("guide_color","Tree", Color(0,0,0,0.1) );
+ t->set_color("drop_position_color","Tree", Color(1,0.3,0.2) );
t->set_constant("hseparation","Tree",4);
t->set_constant("vseparation","Tree",4);
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 2736a75ac3..8e5087b405 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -523,7 +523,7 @@ void EditorNode::save_resource(const Ref<Resource>& p_resource) {
}
}
-void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
+void EditorNode::save_resource_as(const Ref<Resource>& p_resource,const String& p_at_path) {
file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
bool relpaths = (p_resource->has_meta("__editor_relpaths__") && p_resource->get_meta("__editor_relpaths__").operator bool());
@@ -546,7 +546,21 @@ void EditorNode::save_resource_as(const Ref<Resource>& p_resource) {
}
//file->set_current_path(current_path);
- if (p_resource->get_path()!="") {
+
+ if (p_at_path!=String()) {
+
+ file->set_current_dir(p_at_path);
+ if (p_resource->get_path().is_resource_file()) {
+ file->set_current_file(p_resource->get_path().get_file());
+ } else {
+ if (extensions.size()) {
+ file->set_current_file("new_"+p_resource->get_type().to_lower()+"."+preferred.front()->get().to_lower());
+ } else {
+ file->set_current_file(String());
+ }
+ }
+ } else if (p_resource->get_path()!="") {
+
file->set_current_path(p_resource->get_path());
if (extensions.size()) {
String ext=p_resource->get_path().extension().to_lower();
@@ -4881,6 +4895,114 @@ void EditorNode::remove_control_from_dock(Control* p_control) {
_update_dock_slots_visibility();
}
+Variant EditorNode::drag_resource(const Ref<Resource>& p_res,Control* p_from) {
+
+
+ Control *drag_control = memnew( Control );
+ TextureFrame *drag_preview = memnew( TextureFrame );
+ Label* label=memnew( Label );
+
+ Ref<Texture> preview;
+
+ {
+ //todo make proper previews
+ Ref<ImageTexture> pic = gui_base->get_icon("FileBig","EditorIcons");
+ Image img = pic->get_data();
+ img.resize(48,48); //meh
+ Ref<ImageTexture> resized_pic = Ref<ImageTexture>( memnew( ImageTexture) );
+ resized_pic->create_from_image(img);
+ preview=resized_pic;
+ }
+
+ drag_preview->set_texture(preview);
+ drag_control->add_child(drag_preview);
+ if (p_res->get_path().is_resource_file()) {
+ label->set_text(p_res->get_path().get_file());
+ } else if (p_res->get_name()!="") {
+ label->set_text(p_res->get_name());
+ } else {
+ label->set_text(p_res->get_type());
+
+ }
+
+ drag_control->add_child(label);
+
+ p_from->set_drag_preview(drag_control); //wait until it enters scene
+
+ label->set_pos( Point2((preview->get_width()-label->get_minimum_size().width)/2,preview->get_height()) );
+
+ Dictionary drag_data;
+ drag_data["type"]="resource";
+ drag_data["resource"]=p_res;
+ drag_data["from"]=p_from;
+
+
+ return drag_data;
+
+}
+
+Variant EditorNode::drag_files(const Vector<String>& p_files, Control *p_from){
+
+ VBoxContainer *files = memnew( VBoxContainer );
+
+ int max_files=6;
+
+ for(int i=0;i<MIN(max_files,p_files.size());i++) {
+
+ Label* label=memnew( Label );
+ label->set_text(p_files[i].get_file());
+ files->add_child(label);
+ }
+
+ if (p_files.size()>max_files) {
+
+ Label* label=memnew( Label );
+ label->set_text(itos(p_files.size()-max_files)+" "+TTR("More File(s)"));
+ files->add_child(label);
+
+ }
+ Dictionary drag_data;
+ drag_data["type"]="files";
+ drag_data["files"]=p_files;
+ drag_data["from"]=p_from;
+
+ p_from->set_drag_preview(files); //wait until it enters scene
+
+ return drag_data;
+
+}
+
+Variant EditorNode::drag_files_and_dirs(const Vector<String>& p_files, Control *p_from){
+
+ VBoxContainer *files = memnew( VBoxContainer );
+
+ int max_files=6;
+
+ for(int i=0;i<MIN(max_files,p_files.size());i++) {
+
+ Label* label=memnew( Label );
+ label->set_text(p_files[i].get_file());
+ files->add_child(label);
+ }
+
+ if (p_files.size()>max_files) {
+
+ Label* label=memnew( Label );
+ label->set_text(itos(p_files.size()-max_files)+" "+TTR("More File(s) and/or Directory(s)"));
+ files->add_child(label);
+
+ }
+ Dictionary drag_data;
+ drag_data["type"]="files_and_dirs";
+ drag_data["files"]=p_files;
+ drag_data["from"]=p_from;
+
+ p_from->set_drag_preview(files); //wait until it enters scene
+
+ return drag_data;
+
+}
+
void EditorNode::_bind_methods() {
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index c3b7a817c5..b3faa21cf3 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -584,6 +584,9 @@ public:
static void add_editor_plugin(EditorPlugin *p_editor);
static void remove_editor_plugin(EditorPlugin *p_editor);
+
+
+
void add_control_to_dock(DockSlot p_slot,Control* p_control);
void remove_control_from_dock(Control* p_control);
@@ -599,7 +602,7 @@ public:
void save_resource_in_path(const Ref<Resource>& p_resource,const String& p_path);
void save_resource(const Ref<Resource>& p_resource);
- void save_resource_as(const Ref<Resource>& p_resource);
+ void save_resource_as(const Ref<Resource>& p_resource, const String &p_at_path=String());
static bool has_unsaved_changes() { return singleton->unsaved_cache; }
@@ -696,6 +699,11 @@ public:
void hide_bottom_panel();
void remove_bottom_panel_item(Control *p_item);
+ Variant drag_resource(const Ref<Resource>& p_res,Control* p_from);
+ Variant drag_files(const Vector<String>& p_files,Control* p_from);
+ Variant drag_files_and_dirs(const Vector<String>& p_files,Control* p_from);
+
+
EditorNode();
~EditorNode();
void get_singleton(const char* arg1, bool arg2);
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 4540419a19..b9b6dc5616 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -426,6 +426,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
set("text_editor/create_signal_callbacks",true);
set("text_editor/autosave_interval_secs",0);
+ set("text_editor/caret_blink", false);
+ set("text_editor/caret_blink_speed", 0.65);
+ hints["text_editor/caret_blink_speed"]=PropertyInfo(Variant::REAL,"text_editor/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1, 10, 0.1");
+
set("text_editor/font","");
hints["text_editor/font"]=PropertyInfo(Variant::STRING,"text_editor/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
set("text_editor/auto_brace_complete", false);
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index 7ece65e75a..0213dbda59 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -572,6 +572,8 @@ bool CanvasItemEditor::_select(CanvasItem *item, Point2 p_click_pos, bool p_appe
_append_canvas_item(item);
viewport->update();
+ return true;
+
} else {
//regular selection
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index eaf08ca1c0..d8d5fddfe9 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -1967,6 +1967,8 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
ste->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers"));
ste->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting"));
ste->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences"));
+ ste->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink"));
+ ste->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed"));
ste->get_text_edit()->set_callhint_settings(
EditorSettings::get_singleton()->get("text_editor/put_callhint_tooltip_below_current_line"),
EditorSettings::get_singleton()->get("text_editor/callhint_tooltip_offset"));
@@ -2114,6 +2116,8 @@ void ScriptEditor::_editor_settings_changed() {
ste->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers"));
ste->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting"));
ste->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences"));
+ ste->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink"));
+ ste->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed"));
}
}
diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp
index 3399114402..8a65a3641f 100644
--- a/tools/editor/plugins/shader_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_editor_plugin.cpp
@@ -368,6 +368,8 @@ void ShaderEditor::_editor_settings_changed() {
vertex_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers"));
vertex_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting"));
vertex_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences"));
+ vertex_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink"));
+ vertex_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed"));
fragment_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete"));
fragment_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file"));
@@ -376,6 +378,8 @@ void ShaderEditor::_editor_settings_changed() {
fragment_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers"));
fragment_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting"));
fragment_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences"));
+ fragment_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink"));
+ fragment_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed"));
light_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/auto_brace_complete"));
light_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/scroll_past_end_of_file"));
@@ -384,6 +388,8 @@ void ShaderEditor::_editor_settings_changed() {
light_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/show_line_numbers"));
light_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/syntax_highlighting"));
light_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlight_all_occurrences"));
+ light_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/caret_blink"));
+ light_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/caret_blink_speed"));
}
void ShaderEditor::_bind_methods() {
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 7c5aca579c..6f80910150 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -43,7 +43,8 @@
#include "array_property_edit.h"
#include "editor_help.h"
#include "scene/resources/packed_scene.h"
-
+#include "scene/main/viewport.h"
+#include "editor_file_system.h"
void CustomPropertyEditor::_notification(int p_what) {
@@ -224,6 +225,10 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
+void CustomPropertyEditor::hide_menu() {
+ menu->hide();
+}
+
Variant CustomPropertyEditor::get_variant() const {
return v;
@@ -2257,6 +2262,179 @@ void PropertyEditor::_check_reload_status(const String&p_name, TreeItem* item) {
}
}
+
+
+bool PropertyEditor::_is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const {
+
+ Dictionary d = p_item_data;
+
+ if (d.has("type")) {
+
+ int type = d["type"];
+ if (type==Variant::OBJECT && d.has("hint") && d.has("hint_text") && int(d["hint"])==PROPERTY_HINT_RESOURCE_TYPE) {
+
+
+ String allowed_type=d["hint_text"];
+
+ Dictionary drag_data = p_drag_data;
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+ for(int i=0;i<allowed_type.get_slice_count(",");i++) {
+ String at = allowed_type.get_slice(",",i).strip_edges();
+ if (res.is_valid() && ObjectTypeDB::is_type(res->get_type(),at)) {
+ return true;
+ }
+ }
+
+ }
+ if (drag_data.has("type") && String(drag_data["type"])=="files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size()==1) {
+ String file = files[0];
+ String ftype = EditorFileSystem::get_singleton()->get_file_type(file);
+ if (ftype!="") {
+
+ for(int i=0;i<allowed_type.get_slice_count(",");i++) {
+ String at = allowed_type.get_slice(",",i).strip_edges();
+ if (ObjectTypeDB::is_type(ftype,at)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ return false;
+
+}
+void PropertyEditor::_mark_drop_fields(TreeItem* p_at) {
+
+ if (_is_drop_valid(get_viewport()->gui_get_drag_data(),p_at->get_metadata(0)))
+ p_at->set_custom_bg_color(1,Color(0.7,0.5,0.2),true);
+
+ if (p_at->get_children()) {
+ _mark_drop_fields(p_at->get_children());
+ }
+
+ if (p_at->get_next()) {
+ _mark_drop_fields(p_at->get_next());
+ }
+}
+
+Variant PropertyEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return Variant();
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col!=1)
+ return Variant();
+
+
+ Dictionary d = item->get_metadata(0);
+ if (!d.has("name"))
+ return Variant();
+
+ Variant val = obj->get(d["name"]);
+
+ if (val.get_type()==Variant::OBJECT) {
+ RES res = val;
+ if (res.is_valid()) {
+
+ custom_editor->hide_menu();
+ return EditorNode::get_singleton()->drag_resource(res,p_from);
+ }
+ }
+
+ return Variant();
+}
+
+bool PropertyEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col!=1)
+ return false;
+
+ return _is_drop_valid(p_data,item->get_metadata(0));
+
+}
+void PropertyEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return;
+
+ int col = tree->get_column_at_pos(p_point);
+ if (col!=1)
+ return;
+
+ if (!_is_drop_valid(p_data,item->get_metadata(0)))
+ return;
+
+ Dictionary d = item->get_metadata(0);
+
+ if (!d.has("name"))
+ return;
+
+ String name=d["name"];
+
+ Dictionary drag_data = p_data;
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+ if (res.is_valid()) {
+ _edit_set(name,res);
+ return;
+ }
+ }
+
+ if (drag_data.has("type") && String(drag_data["type"])=="files") {
+
+ Vector<String> files = drag_data["files"];
+
+ if (files.size()==1) {
+ String file = files[0];
+ RES res = ResourceLoader::load(file);
+ if (res.is_valid()) {
+ _edit_set(name,res);
+ return;
+ }
+ }
+ }
+}
+
+
+void PropertyEditor::_clear_drop_fields(TreeItem* p_at) {
+
+ Dictionary d = p_at->get_metadata(0);
+
+ if (d.has("type")) {
+
+ int type = d["type"];
+ if (type==Variant::OBJECT) {
+ p_at->clear_custom_bg_color(1);
+ }
+
+ }
+
+ if (p_at->get_children()) {
+ _clear_drop_fields(p_at->get_children());
+ }
+
+ if (p_at->get_next()) {
+ _clear_drop_fields(p_at->get_next());
+ }
+}
+
void PropertyEditor::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
@@ -2270,6 +2448,20 @@ void PropertyEditor::_notification(int p_what) {
}
+ if (p_what==NOTIFICATION_DRAG_BEGIN) {
+
+ if (is_visible() && tree->get_root()) {
+ _mark_drop_fields(tree->get_root());
+ }
+ }
+
+ if (p_what==NOTIFICATION_DRAG_END) {
+ if (is_visible() && tree->get_root()) {
+ _clear_drop_fields(tree->get_root());
+ }
+
+ }
+
if (p_what==NOTIFICATION_FIXED_PROCESS) {
@@ -3661,6 +3853,10 @@ void PropertyEditor::_bind_methods() {
ObjectTypeDB::bind_method( "_filter_changed",&PropertyEditor::_filter_changed);
ObjectTypeDB::bind_method( "update_tree",&PropertyEditor::update_tree);
+ ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw);
+ ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw);
+ ObjectTypeDB::bind_method(_MD("drop_data_fw"), &PropertyEditor::drop_data_fw);
+
ADD_SIGNAL( MethodInfo("property_toggled",PropertyInfo( Variant::STRING, "property"),PropertyInfo( Variant::BOOL, "value")));
ADD_SIGNAL( MethodInfo("resource_selected", PropertyInfo( Variant::OBJECT, "res"),PropertyInfo( Variant::STRING, "prop") ) );
ADD_SIGNAL( MethodInfo("property_keyed",PropertyInfo( Variant::STRING, "property")));
@@ -3778,6 +3974,8 @@ PropertyEditor::PropertyEditor() {
tree->connect("item_edited", this,"_item_edited",varray(),CONNECT_DEFERRED);
tree->connect("cell_selected", this,"_item_selected");
+ tree->set_drag_forwarding(this);
+
set_fixed_process(true);
custom_editor = memnew( CustomPropertyEditor );
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
index 693bfb3efd..ac58011d43 100644
--- a/tools/editor/property_editor.h
+++ b/tools/editor/property_editor.h
@@ -137,6 +137,10 @@ protected:
static void _bind_methods();
public:
+
+
+ void hide_menu();
+
Variant get_variant() const;
String get_name() const;
@@ -219,6 +223,15 @@ class PropertyEditor : public Control {
void _filter_changed(const String& p_text);
+ void _mark_drop_fields(TreeItem* p_at);
+ void _clear_drop_fields(TreeItem* p_at);
+
+ bool _is_drop_valid(const Dictionary& p_drag_data, const Dictionary& p_item_data) const;
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
+
UndoRedo *undo_redo;
protected:
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index 113d18ea73..252e7c890c 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -40,6 +40,9 @@
#include "tools/editor/plugins/animation_player_editor_plugin.h"
#include "animation_editor.h"
+
+
+
void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
uint32_t sc = p_event.key.get_scancode_with_modifiers();
@@ -943,16 +946,37 @@ bool SceneTreeDock::_validate_no_foreign() {
void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
- Node *node = scene_tree->get_selected();
- ERR_FAIL_COND(!node);
- ERR_FAIL_COND(node==edited_scene);
Node *new_parent = scene_root->get_node(p_path);
ERR_FAIL_COND(!new_parent);
+ //ok all valid
+
+ List<Node*> selection = editor_selection->get_selected_node_list();
+
+ if (selection.empty())
+ return; //nothing to reparent
+
+ Vector<Node*> nodes;
+
+ for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+ nodes.push_back(E->get());
+ }
+
+ _do_reparent(new_parent,-1,nodes,p_keep_global_xform);
+
+}
+
+
+void SceneTreeDock::_do_reparent(Node* p_new_parent,int p_position_in_parent,Vector<Node*> p_nodes,bool p_keep_global_xform) {
+
+
+ Node *new_parent = p_new_parent;
+ ERR_FAIL_COND(!new_parent);
+
Node *validate=new_parent;
while(validate) {
- if (editor_selection->is_selected(validate)) {
+ if (p_nodes.find(validate)!=-1) {
ERR_EXPLAIN("Selection changed at some point.. can't reparent");
ERR_FAIL();
return;
@@ -964,20 +988,20 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
List<Node*> selection = editor_selection->get_selected_node_list();
- if (selection.empty())
+ if (p_nodes.size()==0)
return; //nothing to reparent
//sort by tree order, so re-adding is easy
- selection.sort_custom<Node::Comparator>();
+ p_nodes.sort_custom<Node::Comparator>();
editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
List<Pair<NodePath,NodePath> > path_renames;
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+ for(int ni=0;ni<p_nodes.size();ni++) {
//no undo for now, sorry
- Node *node = E->get();
+ Node *node = p_nodes[ni];
fill_path_renames(node,new_parent,&path_renames);
@@ -994,6 +1018,9 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node);
editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node);
+ if (p_position_in_parent>=0)
+ editor_data->get_undo_redo().add_do_method(new_parent,"move_child",node,p_position_in_parent+ni);
+
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
String new_name = new_parent->validate_child_name(node->get_name());
editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1);
@@ -1030,9 +1057,9 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
- for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
+ for(int ni=0;ni<p_nodes.size();ni++) {
- Node *node = E->get();
+ Node *node = p_nodes[ni];
List<Node*> owned;
node->get_owned_by(node->get_owner(),&owned);
@@ -1078,7 +1105,6 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) {
//node->set_owner(owner);
}
-
void SceneTreeDock::_script_created(Ref<Script> p_script) {
Node *selected = scene_tree->get_selected();
@@ -1431,6 +1457,161 @@ void SceneTreeDock::_new_scene_from(String p_file) {
}
+static bool _is_node_visible(Node* p_node) {
+
+ if (!p_node->get_owner())
+ return false;
+ if (p_node->get_owner()!=EditorNode::get_singleton()->get_edited_scene() && !EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node->get_owner()))
+ return false;
+
+ return true;
+
+}
+
+static bool _has_visible_children(Node* p_node) {
+
+ bool collapsed = p_node->has_meta("_editor_collapsed") ? (bool)p_node->get_meta("_editor_collapsed") : false;
+ if (collapsed)
+ return false;
+
+ for(int i=0;i<p_node->get_child_count();i++) {
+
+ Node* child = p_node->get_child(i);
+ if (!_is_node_visible(p_node))
+ continue;
+
+ return true;
+ }
+
+ return false;
+
+}
+
+
+static Node* _find_last_visible(Node*p_node) {
+
+ Node*last=NULL;
+ for(int i=0;i<p_node->get_child_count();i++) {
+ if (_is_node_visible(p_node->get_child(i))) {
+ last=p_node->get_child(i);
+ }
+ }
+
+ if (last) {
+ Node* lastc=_find_last_visible(last);
+ if (lastc)
+ last=lastc;
+
+
+ } else {
+ last=p_node;
+ }
+
+ return last;
+}
+
+void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) {
+
+ Vector<Node*> nodes;
+ Node *to_node;
+
+ for(int i=0;i<p_nodes.size();i++) {
+ Node *n=get_node((p_nodes[i]));
+ nodes.push_back(n);
+ }
+
+ if (nodes.size()==0)
+ return;
+
+ to_node=get_node(p_to);
+ if (!to_node)
+ return;
+
+
+ int to_pos=-1;
+
+ if (p_type==1 && to_node==EditorNode::get_singleton()->get_edited_scene()) {
+ //if at lower sibling of root node
+ to_pos=0; //just insert at begining of root node
+ } else if (p_type==-1) {
+ //drop at above selected node
+ ERR_FAIL_COND(to_node==EditorNode::get_singleton()->get_edited_scene());
+ Node* upper_sibling=NULL;
+
+ for(int i=0;i<to_node->get_index();i++) {
+ Node *c =to_node->get_parent()->get_child(i);
+ if (_is_node_visible(c)) {
+ upper_sibling=c;
+ }
+ }
+
+
+ if (upper_sibling) {
+ //quite complicated, look for next visible in tree
+ upper_sibling=_find_last_visible(upper_sibling);
+
+ if (upper_sibling->get_parent()==to_node->get_parent()) {
+ //just insert over this node because nothing is above at an upper level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ } else {
+ to_pos=-1; //insert last in whathever is up
+ to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
+ }
+
+
+ } else {
+ //just insert over this node because nothing is above at the same level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ }
+
+ } else if (p_type==1) {
+ //drop at below selected node
+ ERR_FAIL_COND(to_node==EditorNode::get_singleton()->get_edited_scene());
+
+
+ Node* lower_sibling=NULL;
+
+ for(int i=to_node->get_index()+1;i<to_node->get_parent()->get_child_count();i++) {
+ Node *c =to_node->get_parent()->get_child(i);
+ if (_is_node_visible(c)) {
+ lower_sibling=c;
+ }
+ }
+
+ if (lower_sibling) {
+ to_pos=lower_sibling->get_index();
+ }
+
+ to_node=to_node->get_parent();
+#if 0
+ //quite complicated, look for next visible in tree
+ upper_sibling=_find_last_visible(upper_sibling);
+
+ if (upper_sibling->get_parent()==to_node->get_parent()) {
+ //just insert over this node because nothing is above at an upper level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ } else {
+ to_pos=-1; //insert last in whathever is up
+ to_node=upper_sibling->get_parent(); //insert at a parent of whathever is up
+ }
+
+
+ } else {
+ //just insert over this node because nothing is above at the same level
+ to_pos=to_node->get_index();
+ to_node=to_node->get_parent();
+ }
+#endif
+
+ }
+
+ _do_reparent(to_node,to_pos,nodes,true);
+
+}
+
void SceneTreeDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_tool_selected"),&SceneTreeDock::_tool_selected);
@@ -1449,6 +1630,8 @@ void SceneTreeDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_import_subscene"),&SceneTreeDock::_import_subscene);
ObjectTypeDB::bind_method(_MD("_selection_changed"),&SceneTreeDock::_selection_changed);
ObjectTypeDB::bind_method(_MD("_new_scene_from"),&SceneTreeDock::_new_scene_from);
+ ObjectTypeDB::bind_method(_MD("_nodes_dragged"),&SceneTreeDock::_nodes_dragged);
+
ObjectTypeDB::bind_method(_MD("instance"),&SceneTreeDock::instance);
}
@@ -1518,6 +1701,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
scene_tree->connect("node_prerename", this,"_node_prerenamed");
scene_tree->connect("open",this,"_load_request");
scene_tree->connect("open_script",this,"_script_open_request");
+ scene_tree->connect("nodes_rearranged",this,"_nodes_dragged");
+
scene_tree->set_undo_redo(&editor_data->get_undo_redo());
scene_tree->set_editor_selection(editor_selection);
@@ -1612,6 +1797,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
add_child(new_scene_from_dialog);
new_scene_from_dialog->connect("file_selected",this,"_new_scene_from");
+
+
first_enter=true;
diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h
index 114e2c5c97..264a05e23e 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/tools/editor/scene_tree_dock.h
@@ -102,6 +102,8 @@ class SceneTreeDock : public VBoxContainer {
Node *_duplicate(Node *p_node, Map<Node*,Node*> &duplimap);
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
+ void _do_reparent(Node* p_new_parent, int p_position_in_parent, Vector<Node*> p_nodes, bool p_keep_global_xform);
+
void _set_owners(Node *p_owner, const Array& p_nodes);
void _load_request(const String& p_path);
void _script_open_request(const Ref<Script>& p_script);
@@ -128,6 +130,8 @@ class SceneTreeDock : public VBoxContainer {
void _fill_path_renames(Vector<StringName> base_path,Vector<StringName> new_base_path,Node * p_node, List<Pair<NodePath,NodePath> > *p_renames);
+ void _nodes_dragged(Array p_nodes,NodePath p_to,int p_type);
+
protected:
void _notification(int p_what);
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 6d13f74e4d..720516bd7e 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -784,6 +784,96 @@ void SceneTreeEditor::_cell_collapsed(Object *p_obj) {
}
+Variant SceneTreeEditor::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+ if (!can_rename)
+ return Variant(); //not editable tree
+
+ Vector<Node*> selected;
+ Vector<Ref<Texture> > icons;
+ TreeItem *next=tree->get_next_selected(NULL);
+ while (next) {
+
+ NodePath np = next->get_metadata(0);
+
+ Node *n=get_node(np);
+ if (n) {
+
+ selected.push_back(n);
+ icons.push_back(next->get_icon(0));
+ }
+ next=tree->get_next_selected(next);
+ }
+
+ if (selected.empty())
+ return Variant();
+
+ VBoxContainer *vb = memnew( VBoxContainer );
+ Array objs;
+ for(int i=0;i<selected.size();i++) {
+
+ HBoxContainer *hb = memnew( HBoxContainer );
+ TextureFrame *tf = memnew(TextureFrame);
+ tf->set_texture(icons[i]);
+ hb->add_child(tf);
+ Label *label = memnew( Label( selected[i]->get_name() ) );
+ hb->add_child(label);
+ vb->add_child(hb);
+ NodePath p = selected[i]->get_path();
+ objs.push_back(p);
+ }
+
+ set_drag_preview(vb);
+ Dictionary drag_data;
+ drag_data["type"]="nodes";
+ drag_data["nodes"]=objs;
+
+ tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN|Tree::DROP_MODE_ON_ITEM);
+
+
+ return drag_data;
+}
+
+bool SceneTreeEditor::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const {
+
+ if (!can_rename)
+ return false; //not editable tree
+
+ Dictionary d=p_data;
+ if (!d.has("type") || String(d["type"])!="nodes")
+ return false;
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return false;
+ int section = tree->get_drop_section_at_pos(p_point);
+ if (section<-1 || (section==-1 && !item->get_parent()))
+ return false;
+
+ return true;
+}
+void SceneTreeEditor::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) {
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+
+ TreeItem *item = tree->get_item_at_pos(p_point);
+ if (!item)
+ return;
+ int section = tree->get_drop_section_at_pos(p_point);
+ if (section<-1)
+ return;
+
+ NodePath np = item->get_metadata(0);
+ Node *n=get_node(np);
+ if (!n)
+ return;
+
+ Dictionary d=p_data;
+
+ Array nodes=d["nodes"];
+
+ emit_signal("nodes_rearranged",nodes,np,section);
+
+}
void SceneTreeEditor::_bind_methods() {
@@ -804,10 +894,15 @@ void SceneTreeEditor::_bind_methods() {
ObjectTypeDB::bind_method("_node_script_changed",&SceneTreeEditor::_node_script_changed);
ObjectTypeDB::bind_method("_node_visibility_changed",&SceneTreeEditor::_node_visibility_changed);
+ ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &SceneTreeEditor::get_drag_data_fw);
+ ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &SceneTreeEditor::can_drop_data_fw);
+ ObjectTypeDB::bind_method(_MD("drop_data_fw"), &SceneTreeEditor::drop_data_fw);
+
ADD_SIGNAL( MethodInfo("node_selected") );
ADD_SIGNAL( MethodInfo("node_renamed") );
ADD_SIGNAL( MethodInfo("node_prerename") );
ADD_SIGNAL( MethodInfo("node_changed") );
+ ADD_SIGNAL( MethodInfo("nodes_rearranged",PropertyInfo(Variant::ARRAY,"paths"),PropertyInfo(Variant::NODE_PATH,"to_path"),PropertyInfo(Variant::INT,"type") ) );
ADD_SIGNAL( MethodInfo("open") );
ADD_SIGNAL( MethodInfo("open_script") );
@@ -846,6 +941,8 @@ SceneTreeEditor::SceneTreeEditor(bool p_label,bool p_can_rename, bool p_can_open
add_child( tree );
+ tree->set_drag_forwarding(this);
+
tree->connect("cell_selected", this,"_selected_changed");
tree->connect("item_edited", this,"_renamed",varray(),CONNECT_DEFERRED);
tree->connect("multi_selected",this,"_cell_multi_selected");
diff --git a/tools/editor/scene_tree_editor.h b/tools/editor/scene_tree_editor.h
index 27ccaaae01..283db280ed 100644
--- a/tools/editor/scene_tree_editor.h
+++ b/tools/editor/scene_tree_editor.h
@@ -111,8 +111,14 @@ class SceneTreeEditor : public Control {
void _node_visibility_changed(Node *p_node);
void _subscene_option(int p_idx);
+
void _selection_changed();
Node *get_scene_node();
+
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
+
public:
diff --git a/tools/editor/scenes_dock.cpp b/tools/editor/scenes_dock.cpp
index 7cb0a094b2..f44435d9b3 100644
--- a/tools/editor/scenes_dock.cpp
+++ b/tools/editor/scenes_dock.cpp
@@ -451,7 +451,7 @@ void ScenesDock::_update_files(bool p_keep_selection) {
img.resize(thumbnail_size,thumbnail_size);
Ref<ImageTexture> resized_folder = Ref<ImageTexture>( memnew( ImageTexture));
resized_folder->create_from_image(img,0);
- Theme::get_default()->set_icon(TTR("ResizedFolder"),"EditorIcons",resized_folder);
+ Theme::get_default()->set_icon("ResizedFolder","EditorIcons",resized_folder);
}
folder_thumbnail = get_icon("ResizedFolder","EditorIcons");
@@ -462,7 +462,7 @@ void ScenesDock::_update_files(bool p_keep_selection) {
img.resize(thumbnail_size,thumbnail_size);
Ref<ImageTexture> resized_file = Ref<ImageTexture>( memnew( ImageTexture));
resized_file->create_from_image(img,0);
- Theme::get_default()->set_icon(TTR("ResizedFile"),"EditorIcons",resized_file);
+ Theme::get_default()->set_icon("ResizedFile","EditorIcons",resized_file);
}
file_thumbnail = get_icon("ResizedFile","EditorIcons");
@@ -1073,6 +1073,142 @@ void ScenesDock::set_use_thumbnails(bool p_use) {
display_mode->set_pressed(!p_use);
}
+
+Variant ScenesDock::get_drag_data_fw(const Point2& p_point,Control* p_from) {
+
+ if (p_from==files) {
+
+ List<int> seldirs;
+ List<int> selfiles;
+
+ for (int i = 0; i<files->get_item_count(); i++) {
+ if (files->is_selected(i)) {
+ String path = files->get_item_metadata(i);
+ if (path.ends_with("/"))
+ seldirs.push_back(i);
+ else
+ selfiles.push_back(i);
+ }
+ }
+
+ if (seldirs.empty() && selfiles.empty())
+ return Variant();
+ //if (seldirs.size() && selfiles.size())
+ // return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
+
+ /*if (selfiles.size()==1) {
+ Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
+ if (resource.is_valid()) {
+ return EditorNode::get_singleton()->drag_resource(resource,p_from);
+ }
+ }*/
+
+ if (selfiles.size()>0 && seldirs.size()==0) {
+ Vector<String> fnames;
+ for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ return EditorNode::get_singleton()->drag_files(fnames,p_from);
+ }
+
+ if (selfiles.size()>0 || seldirs.size()>0) {
+ Vector<String> fnames;
+ for(List<int>::Element *E=selfiles.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ for(List<int>::Element *E=seldirs.front();E;E=E->next()) {
+ fnames.push_back(files->get_item_metadata(E->get()));
+ }
+ return EditorNode::get_singleton()->drag_files_and_dirs(fnames,p_from);
+ }
+
+ }
+
+ return Variant();
+}
+
+bool ScenesDock::can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const{
+
+ Dictionary drag_data = p_data;
+
+ print_line("CAN IT DROP DATA?");
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ return true;
+ }
+
+ if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
+
+ Vector<String> fnames = drag_data["files"];
+
+ if (p_from==files) {
+
+ int at_pos = files->get_item_at_pos(p_point);
+ if (at_pos!=-1) {
+
+ String dir = files->get_item_metadata(at_pos);
+ if (dir.ends_with("/"))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void ScenesDock::drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from){
+
+ if (!can_drop_data_fw(p_point,p_data,p_from))
+ return;
+ Dictionary drag_data = p_data;
+
+ if (drag_data.has("type") && String(drag_data["type"])=="resource") {
+ Ref<Resource> res = drag_data["resource"];
+
+ if (!res.is_valid()) {
+ return;
+ }
+
+ String save_path=path;
+
+ int at_pos = files->get_item_at_pos(p_point);
+ if (at_pos!=-1) {
+ String to_dir = files->get_item_metadata(at_pos);
+ if (to_dir.ends_with("/")) {
+ save_path=to_dir;
+ if (save_path!="res://")
+ save_path=save_path.substr(0,save_path.length()-1);
+ }
+
+ }
+
+ EditorNode::get_singleton()->save_resource_as(res,save_path);
+ return;
+ }
+
+ if (drag_data.has("type") && ( String(drag_data["type"])=="files" || String(drag_data["type"])=="files_and_dirs")) {
+
+ int at_pos = files->get_item_at_pos(p_point);
+ ERR_FAIL_COND(at_pos==-1);
+ String to_dir = files->get_item_metadata(at_pos);
+ ERR_FAIL_COND(!to_dir.ends_with("/"));
+
+ Vector<String> fnames = drag_data["files"];
+ move_files.clear();
+ move_dirs.clear();
+
+ for(int i=0;i<fnames.size();i++) {
+ if (fnames[i].ends_with("/"))
+ move_dirs.push_back(fnames[i]);
+ else
+ move_files.push_back(fnames[i]);
+ }
+
+ _move_operation(to_dir);
+ }
+
+}
+
+
void ScenesDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_update_tree"),&ScenesDock::_update_tree);
@@ -1096,6 +1232,10 @@ void ScenesDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_move_operation"), &ScenesDock::_move_operation);
ObjectTypeDB::bind_method(_MD("_rename_operation"), &ScenesDock::_rename_operation);
+ ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &ScenesDock::get_drag_data_fw);
+ ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &ScenesDock::can_drop_data_fw);
+ ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ScenesDock::drop_data_fw);
+
ADD_SIGNAL(MethodInfo("instance"));
ADD_SIGNAL(MethodInfo("open"));
@@ -1199,6 +1339,7 @@ ScenesDock::ScenesDock(EditorNode *p_editor) {
files = memnew( ItemList );
files->set_v_size_flags(SIZE_EXPAND_FILL);
files->set_select_mode(ItemList::SELECT_MULTI);
+ files->set_drag_forwarding(this);
path_hb = memnew( HBoxContainer );
button_back = memnew( ToolButton );
diff --git a/tools/editor/scenes_dock.h b/tools/editor/scenes_dock.h
index a630d2506d..86196b7ccd 100644
--- a/tools/editor/scenes_dock.h
+++ b/tools/editor/scenes_dock.h
@@ -142,6 +142,9 @@ class ScenesDock : public VBoxContainer {
void _instance_pressed();
void _open_pressed();
+ Variant get_drag_data_fw(const Point2& p_point,Control* p_from);
+ bool can_drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from) const;
+ void drop_data_fw(const Point2& p_point,const Variant& p_data,Control* p_from);
protected:
void _notification(int p_what);