summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/math/quat.h2
-rw-r--r--core/os/os.cpp11
-rw-r--r--core/variant_call.cpp2
-rw-r--r--core/variant_op.cpp18
-rw-r--r--demos/2d/area_input/engine.cfg1
-rw-r--r--demos/2d/area_input/icon.pngbin0 -> 1684 bytes
-rw-r--r--demos/2d/dynamic_collision_shapes/engine.cfg1
-rw-r--r--demos/2d/dynamic_collision_shapes/icon.pngbin0 -> 844 bytes
-rw-r--r--demos/2d/fog_of_war/engine.cfg2
-rw-r--r--demos/2d/hdr/engine.cfg1
-rw-r--r--demos/2d/hdr/icon.pngbin0 -> 2670 bytes
-rw-r--r--demos/2d/isometric_light/engine.cfg1
-rw-r--r--demos/2d/isometric_light/icon.pngbin0 -> 3638 bytes
-rw-r--r--demos/2d/light_mask/engine.cfg1
-rw-r--r--demos/2d/light_mask/icon.pngbin0 -> 3344 bytes
-rw-r--r--demos/2d/lights_shadows/engine.cfg1
-rw-r--r--demos/2d/lights_shadows/icon.pngbin0 -> 2733 bytes
-rw-r--r--demos/2d/navpoly/engine.cfg1
-rw-r--r--demos/2d/navpoly/icon.pngbin0 -> 2420 bytes
-rw-r--r--demos/2d/normalmaps/engine.cfg1
-rw-r--r--demos/2d/normalmaps/icon.pngbin0 -> 4876 bytes
-rw-r--r--demos/2d/polygon_path_finder_demo/engine.cfg2
-rw-r--r--demos/2d/screen_space_shaders/engine.cfg1
-rw-r--r--demos/2d/screen_space_shaders/icon.pngbin0 -> 3341 bytes
-rw-r--r--demos/2d/sdf_font/engine.cfg1
-rw-r--r--demos/2d/sdf_font/icon.pngbin0 -> 1534 bytes
-rw-r--r--demos/2d/splash/engine.cfg1
-rw-r--r--demos/2d/splash/icon.pngbin0 -> 3408 bytes
-rw-r--r--demos/2d/sprite_shaders/engine.cfg1
-rw-r--r--demos/2d/sprite_shaders/icon.pngbin0 -> 3934 bytes
-rw-r--r--demos/3d/navmesh/icon.pngbin0 -> 2803 bytes
-rw-r--r--demos/3d/sat_test/engine.cfg1
-rw-r--r--demos/3d/sat_test/icon.pngbin0 -> 2699 bytes
-rw-r--r--demos/gui/input_mapping/engine.cfg1
-rw-r--r--demos/gui/rich_text_bbcode/engine.cfg1
-rw-r--r--demos/gui/rich_text_bbcode/icon.pngbin0 -> 2293 bytes
-rw-r--r--demos/misc/instancing/engine.cfg1
-rw-r--r--demos/misc/instancing/icon.pngbin0 -> 2185 bytes
-rw-r--r--demos/misc/regex/regex.gd18
-rw-r--r--demos/misc/regex/regex.scnbin1772 -> 1793 bytes
-rw-r--r--demos/misc/tween/engine.cfg2
-rw-r--r--demos/misc/window_management/engine.cfg2
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp116
-rw-r--r--drivers/gles2/rasterizer_gles2.h2
-rw-r--r--drivers/gles2/shader_compiler_gles2.cpp238
-rw-r--r--drivers/gles2/shader_compiler_gles2.h3
-rw-r--r--drivers/nrex/README.md57
-rw-r--r--drivers/nrex/nrex.cpp790
-rw-r--r--drivers/nrex/nrex.hpp10
-rw-r--r--drivers/nrex/regex.cpp10
-rw-r--r--drivers/nrex/regex.h2
-rw-r--r--drivers/opus/opus_config.h8
-rw-r--r--drivers/theora/video_stream_theora.cpp7
-rw-r--r--drivers/unix/os_unix.cpp28
-rw-r--r--drivers/vorbis/audio_stream_ogg_vorbis.h2
-rw-r--r--modules/gdscript/gd_parser.cpp8
-rw-r--r--modules/gdscript/gd_parser.h1
-rw-r--r--platform/android/export/export.cpp4
-rw-r--r--platform/android/java/res/values-fa/strings.xml16
-rw-r--r--platform/android/java/src/com/android/godot/GodotPaymentV3.java60
-rw-r--r--platform/android/java/src/com/android/godot/payments/PaymentsManager.java123
-rw-r--r--platform/android/java/src/com/android/godot/payments/PurchaseTask.java8
-rw-r--r--platform/bb10/os_bb10.cpp3
-rw-r--r--platform/haiku/os_haiku.cpp3
-rw-r--r--platform/server/os_server.cpp3
-rw-r--r--platform/windows/os_windows.cpp28
-rw-r--r--platform/winrt/os_winrt.cpp29
-rw-r--r--platform/x11/os_x11.cpp3
-rw-r--r--scene/2d/camera_2d.cpp2
-rw-r--r--scene/2d/tile_map.cpp5
-rw-r--r--scene/3d/skeleton.cpp2
-rw-r--r--scene/animation/animation_tree_player.cpp96
-rw-r--r--scene/animation/animation_tree_player.h19
-rw-r--r--scene/gui/button_group.cpp2
-rw-r--r--scene/gui/button_group.h6
-rw-r--r--scene/gui/item_list.cpp31
-rw-r--r--scene/gui/item_list.h1
-rw-r--r--scene/gui/line_edit.cpp159
-rw-r--r--scene/gui/line_edit.h21
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/popup_menu.cpp11
-rw-r--r--scene/gui/range.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp3
-rw-r--r--scene/gui/tabs.cpp35
-rw-r--r--scene/gui/text_edit.cpp113
-rw-r--r--scene/gui/texture_progress.cpp7
-rw-r--r--scene/gui/tree.cpp7
-rw-r--r--scene/gui/video_player.cpp2
-rw-r--r--scene/resources/concave_polygon_shape_2d.cpp1
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp3
-rw-r--r--scene/resources/default_theme/default_theme.cpp21
-rw-r--r--scene/resources/material.cpp6
-rw-r--r--scene/resources/shader_graph.cpp26
-rw-r--r--scene/resources/shape_line_2d.cpp1
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/rasterizer_dummy.h4
-rw-r--r--servers/visual/shader_language.cpp1
-rw-r--r--tools/editor/animation_editor.cpp57
-rw-r--r--tools/editor/animation_editor.h8
-rw-r--r--tools/editor/code_editor.cpp4
-rw-r--r--tools/editor/editor_help.cpp508
-rw-r--r--tools/editor/editor_help.h91
-rw-r--r--tools/editor/editor_log.cpp13
-rw-r--r--tools/editor/editor_log.h4
-rw-r--r--tools/editor/editor_node.cpp236
-rw-r--r--tools/editor/editor_node.h6
-rw-r--r--tools/editor/editor_settings.cpp2
-rw-r--r--tools/editor/icons/icon_class_list.pngbin0 -> 241 bytes
-rw-r--r--tools/editor/icons/icon_godot.pngbin0 -> 671 bytes
-rw-r--r--tools/editor/icons/icon_help.pngbin822 -> 841 bytes
-rw-r--r--tools/editor/icons/icon_multi_edit.pngbin0 -> 576 bytes
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.cpp171
-rw-r--r--tools/editor/plugins/animation_player_editor_plugin.h22
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp168
-rw-r--r--tools/editor/plugins/baked_light_baker.h6
-rw-r--r--tools/editor/plugins/canvas_item_editor_plugin.cpp60
-rw-r--r--tools/editor/plugins/collision_shape_2d_editor_plugin.cpp33
-rw-r--r--tools/editor/plugins/mesh_editor_plugin.cpp15
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.cpp20
-rw-r--r--tools/editor/plugins/multimesh_editor_plugin.h8
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp4
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp1370
-rw-r--r--tools/editor/plugins/script_editor_plugin.h49
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/spatial_editor_plugin.cpp42
-rw-r--r--tools/editor/plugins/theme_editor_plugin.cpp38
-rw-r--r--tools/editor/plugins/tile_set_editor_plugin.cpp12
-rw-r--r--tools/editor/project_manager.cpp33
-rw-r--r--tools/editor/scene_tree_editor.cpp16
-rw-r--r--tools/editor/script_editor_debugger.cpp1
-rw-r--r--tools/export/blender25/godot_export_manager.py4
132 files changed, 3602 insertions, 1631 deletions
diff --git a/core/math/quat.h b/core/math/quat.h
index de4aedaeec..f161e35074 100644
--- a/core/math/quat.h
+++ b/core/math/quat.h
@@ -73,7 +73,7 @@ public:
-x * v.x - y * v.y - z * v.z);
}
- _FORCE_INLINE_ Vector3 xform(const Vector3& v) {
+ _FORCE_INLINE_ Vector3 xform(const Vector3& v) const {
Quat q = *this * v;
q *= this->inverse();
diff --git a/core/os/os.cpp b/core/os/os.cpp
index ee9f12b79d..8caf95e4d1 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -61,9 +61,16 @@ void OS::debug_break() {
void OS::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
+ const char* err_type;
+ switch(p_type) {
+ case ERR_ERROR: err_type="**ERROR**"; break;
+ case ERR_WARNING: err_type="**WARNING**"; break;
+ case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break;
+ }
+
if (p_rationale && *p_rationale)
- print("**ERROR**: %s\n ",p_rationale);
- print("**ERROR**: At: %s:%i:%s() - %s\n",p_file,p_line,p_function,p_code);
+ print("%s: %s\n ",err_type,p_rationale);
+ print("%s: At: %s:%i:%s() - %s\n",err_type,p_file,p_line,p_function,p_code);
}
void OS::print(const char* p_format, ...) {
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 222618ffa0..7bbb18225d 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -409,6 +409,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(Quat,normalized);
VCALL_LOCALMEM0R(Quat,inverse);
VCALL_LOCALMEM1R(Quat,dot);
+ VCALL_LOCALMEM1R(Quat,xform);
VCALL_LOCALMEM2R(Quat,slerp);
VCALL_LOCALMEM2R(Quat,slerpni);
VCALL_LOCALMEM4R(Quat,cubic_slerp);
@@ -1361,6 +1362,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(QUAT,QUAT,Quat,normalized,varray());
ADDFUNC0(QUAT,QUAT,Quat,inverse,varray());
ADDFUNC1(QUAT,REAL,Quat,dot,QUAT,"b",varray());
+ ADDFUNC1(QUAT,VECTOR3,Quat,xform,VECTOR3,"v",varray());
ADDFUNC2(QUAT,QUAT,Quat,slerp,QUAT,"b",REAL,"t",varray());
ADDFUNC2(QUAT,QUAT,Quat,slerpni,QUAT,"b",REAL,"t",varray());
ADDFUNC4(QUAT,QUAT,Quat,cubic_slerp,QUAT,"b",QUAT,"pre_a",QUAT,"post_b",REAL,"t",varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 1cdf6d7319..eabd647837 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -586,7 +586,21 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
} break;
DEFAULT_OP_LOCALMEM_NUM(*,VECTOR3,Vector3);
DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
+ case QUAT: {
+
+ switch(p_b.type) {
+ case VECTOR3: {
+
+ _RETURN( reinterpret_cast<const Quat*>(p_a._data._mem)->xform( *(const Vector3*)p_b._data._mem) );
+ } break;
+ case QUAT: {
+
+ _RETURN( *reinterpret_cast<const Quat*>(p_a._data._mem) * *reinterpret_cast<const Quat*>(p_b._data._mem) );
+ } break;
+ };
+ r_valid=false;
+ return;
+ } break;
DEFAULT_OP_FAIL(_AABB);
case MATRIX3: {
@@ -2573,7 +2587,7 @@ bool Variant::in(const Variant& p_index, bool *r_valid) const {
String idx=p_index;
const String *str=reinterpret_cast<const String*>(_data._mem);
- return str->find("idx")!=-1;
+ return str->find(idx)!=-1;
}
} break;
diff --git a/demos/2d/area_input/engine.cfg b/demos/2d/area_input/engine.cfg
index 3227e9278f..8fa2e15beb 100644
--- a/demos/2d/area_input/engine.cfg
+++ b/demos/2d/area_input/engine.cfg
@@ -2,3 +2,4 @@
name="Area 2D Input Events"
main_scene="res://input.scn"
+icon="res://icon.png"
diff --git a/demos/2d/area_input/icon.png b/demos/2d/area_input/icon.png
new file mode 100644
index 0000000000..d9bb881693
--- /dev/null
+++ b/demos/2d/area_input/icon.png
Binary files differ
diff --git a/demos/2d/dynamic_collision_shapes/engine.cfg b/demos/2d/dynamic_collision_shapes/engine.cfg
index 536b75f2f2..76a074f346 100644
--- a/demos/2d/dynamic_collision_shapes/engine.cfg
+++ b/demos/2d/dynamic_collision_shapes/engine.cfg
@@ -2,3 +2,4 @@
name="Run-Time CollisionShape"
main_scene="res://dynamic_colobjs.scn"
+icon="res://icon.png"
diff --git a/demos/2d/dynamic_collision_shapes/icon.png b/demos/2d/dynamic_collision_shapes/icon.png
new file mode 100644
index 0000000000..ac01d401ba
--- /dev/null
+++ b/demos/2d/dynamic_collision_shapes/icon.png
Binary files differ
diff --git a/demos/2d/fog_of_war/engine.cfg b/demos/2d/fog_of_war/engine.cfg
index 5c4307b5bc..1f56851c58 100644
--- a/demos/2d/fog_of_war/engine.cfg
+++ b/demos/2d/fog_of_war/engine.cfg
@@ -2,7 +2,7 @@
name="Fog of War"
main_scene="res://fog.scn"
-icon="icon.png"
+icon="res://icon.png"
[input]
diff --git a/demos/2d/hdr/engine.cfg b/demos/2d/hdr/engine.cfg
index 3d8b4222d5..ab53a022f0 100644
--- a/demos/2d/hdr/engine.cfg
+++ b/demos/2d/hdr/engine.cfg
@@ -2,6 +2,7 @@
name="HDR for 2D"
main_scene="res://beach_cave.scn"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/hdr/icon.png b/demos/2d/hdr/icon.png
new file mode 100644
index 0000000000..2df0ec38e9
--- /dev/null
+++ b/demos/2d/hdr/icon.png
Binary files differ
diff --git a/demos/2d/isometric_light/engine.cfg b/demos/2d/isometric_light/engine.cfg
index 08393f1724..a5b053aa95 100644
--- a/demos/2d/isometric_light/engine.cfg
+++ b/demos/2d/isometric_light/engine.cfg
@@ -2,6 +2,7 @@
name="Isometric 2D + Lighting"
main_scene="res://map.scn"
+icon="res://icon.png"
[input]
diff --git a/demos/2d/isometric_light/icon.png b/demos/2d/isometric_light/icon.png
new file mode 100644
index 0000000000..3de9749729
--- /dev/null
+++ b/demos/2d/isometric_light/icon.png
Binary files differ
diff --git a/demos/2d/light_mask/engine.cfg b/demos/2d/light_mask/engine.cfg
index 8b0ae6f61d..39608669ab 100644
--- a/demos/2d/light_mask/engine.cfg
+++ b/demos/2d/light_mask/engine.cfg
@@ -2,6 +2,7 @@
name="Using Lights As Mask"
main_scene="res://lightmask.scn"
+icon="res://icon.png"
[rasterizer]
diff --git a/demos/2d/light_mask/icon.png b/demos/2d/light_mask/icon.png
new file mode 100644
index 0000000000..c12b045e62
--- /dev/null
+++ b/demos/2d/light_mask/icon.png
Binary files differ
diff --git a/demos/2d/lights_shadows/engine.cfg b/demos/2d/lights_shadows/engine.cfg
index 771288c209..80142633d3 100644
--- a/demos/2d/lights_shadows/engine.cfg
+++ b/demos/2d/lights_shadows/engine.cfg
@@ -2,6 +2,7 @@
name="2D Lighting"
main_scene="res://light_shadows.scn"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/lights_shadows/icon.png b/demos/2d/lights_shadows/icon.png
new file mode 100644
index 0000000000..c7f9e13bae
--- /dev/null
+++ b/demos/2d/lights_shadows/icon.png
Binary files differ
diff --git a/demos/2d/navpoly/engine.cfg b/demos/2d/navpoly/engine.cfg
index 40515dd3d2..b750419915 100644
--- a/demos/2d/navpoly/engine.cfg
+++ b/demos/2d/navpoly/engine.cfg
@@ -2,6 +2,7 @@
name="Navigation Polygon (2D)"
main_scene="res://navigation.scn"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/navpoly/icon.png b/demos/2d/navpoly/icon.png
new file mode 100644
index 0000000000..df7fb43633
--- /dev/null
+++ b/demos/2d/navpoly/icon.png
Binary files differ
diff --git a/demos/2d/normalmaps/engine.cfg b/demos/2d/normalmaps/engine.cfg
index f0002dc2b8..4f9f4f67f0 100644
--- a/demos/2d/normalmaps/engine.cfg
+++ b/demos/2d/normalmaps/engine.cfg
@@ -2,6 +2,7 @@
name="2D Normal Mapping"
main_scene="res://normalmap.scn"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/normalmaps/icon.png b/demos/2d/normalmaps/icon.png
new file mode 100644
index 0000000000..4e5d835005
--- /dev/null
+++ b/demos/2d/normalmaps/icon.png
Binary files differ
diff --git a/demos/2d/polygon_path_finder_demo/engine.cfg b/demos/2d/polygon_path_finder_demo/engine.cfg
index 41c4adf701..de5593c417 100644
--- a/demos/2d/polygon_path_finder_demo/engine.cfg
+++ b/demos/2d/polygon_path_finder_demo/engine.cfg
@@ -2,4 +2,4 @@
name="polygon_path_finder_demo"
main_scene="res://new_scene_poly_with_holes.scn"
-icon="icon.png"
+icon="res://icon.png"
diff --git a/demos/2d/screen_space_shaders/engine.cfg b/demos/2d/screen_space_shaders/engine.cfg
index 527e2f8f0a..383ca7bf11 100644
--- a/demos/2d/screen_space_shaders/engine.cfg
+++ b/demos/2d/screen_space_shaders/engine.cfg
@@ -2,6 +2,7 @@
name="Screen-Space Shaders"
main_scene="res://screen_shaders.scn"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/screen_space_shaders/icon.png b/demos/2d/screen_space_shaders/icon.png
new file mode 100644
index 0000000000..65247f9ae7
--- /dev/null
+++ b/demos/2d/screen_space_shaders/icon.png
Binary files differ
diff --git a/demos/2d/sdf_font/engine.cfg b/demos/2d/sdf_font/engine.cfg
index bdf26ce741..bf983041fa 100644
--- a/demos/2d/sdf_font/engine.cfg
+++ b/demos/2d/sdf_font/engine.cfg
@@ -2,3 +2,4 @@
name="Signed Distance Field Font"
main_scene="res://sdf.scn"
+icon="res://icon.png"
diff --git a/demos/2d/sdf_font/icon.png b/demos/2d/sdf_font/icon.png
new file mode 100644
index 0000000000..be9fefa8b0
--- /dev/null
+++ b/demos/2d/sdf_font/icon.png
Binary files differ
diff --git a/demos/2d/splash/engine.cfg b/demos/2d/splash/engine.cfg
index cb50c7b1be..e461426305 100644
--- a/demos/2d/splash/engine.cfg
+++ b/demos/2d/splash/engine.cfg
@@ -2,6 +2,7 @@
name="Splash Screen"
main_scene="res://splash.xml"
+icon="res://icon.png"
[display]
diff --git a/demos/2d/splash/icon.png b/demos/2d/splash/icon.png
new file mode 100644
index 0000000000..88620eb35b
--- /dev/null
+++ b/demos/2d/splash/icon.png
Binary files differ
diff --git a/demos/2d/sprite_shaders/engine.cfg b/demos/2d/sprite_shaders/engine.cfg
index 09f9a59566..17bdada188 100644
--- a/demos/2d/sprite_shaders/engine.cfg
+++ b/demos/2d/sprite_shaders/engine.cfg
@@ -2,3 +2,4 @@
name="2D Shaders for Sprites"
main_scene="res://sprite_shaders.scn"
+icon="res://icon.png"
diff --git a/demos/2d/sprite_shaders/icon.png b/demos/2d/sprite_shaders/icon.png
new file mode 100644
index 0000000000..b044b31f93
--- /dev/null
+++ b/demos/2d/sprite_shaders/icon.png
Binary files differ
diff --git a/demos/3d/navmesh/icon.png b/demos/3d/navmesh/icon.png
new file mode 100644
index 0000000000..5b354f931c
--- /dev/null
+++ b/demos/3d/navmesh/icon.png
Binary files differ
diff --git a/demos/3d/sat_test/engine.cfg b/demos/3d/sat_test/engine.cfg
index cc215c83e8..82c688635d 100644
--- a/demos/3d/sat_test/engine.cfg
+++ b/demos/3d/sat_test/engine.cfg
@@ -2,3 +2,4 @@
name="SAT Collision Test"
main_scene="res://sat_test.xml"
+icon="res://icon.png"
diff --git a/demos/3d/sat_test/icon.png b/demos/3d/sat_test/icon.png
new file mode 100644
index 0000000000..b89c5a7467
--- /dev/null
+++ b/demos/3d/sat_test/icon.png
Binary files differ
diff --git a/demos/gui/input_mapping/engine.cfg b/demos/gui/input_mapping/engine.cfg
index 959c0ac7d5..6470ec6cd8 100644
--- a/demos/gui/input_mapping/engine.cfg
+++ b/demos/gui/input_mapping/engine.cfg
@@ -2,7 +2,6 @@
name="Input Mapping GUI"
main_scene="res://controls.scn"
-icon="icon.png"
[display]
diff --git a/demos/gui/rich_text_bbcode/engine.cfg b/demos/gui/rich_text_bbcode/engine.cfg
index e0ea296f6d..5f68b6a0e6 100644
--- a/demos/gui/rich_text_bbcode/engine.cfg
+++ b/demos/gui/rich_text_bbcode/engine.cfg
@@ -2,3 +2,4 @@
name="Rich Text Label (BBCode)"
main_scene="res://rich_text_bbcode.scn"
+icon="res://icon.png"
diff --git a/demos/gui/rich_text_bbcode/icon.png b/demos/gui/rich_text_bbcode/icon.png
new file mode 100644
index 0000000000..78358ba71b
--- /dev/null
+++ b/demos/gui/rich_text_bbcode/icon.png
Binary files differ
diff --git a/demos/misc/instancing/engine.cfg b/demos/misc/instancing/engine.cfg
index 52a28a3fce..76b0c97721 100644
--- a/demos/misc/instancing/engine.cfg
+++ b/demos/misc/instancing/engine.cfg
@@ -2,6 +2,7 @@
name="Scene Instancing Demo"
main_scene="res://container.scn"
+icon="res://icon.png"
[physics_2d]
diff --git a/demos/misc/instancing/icon.png b/demos/misc/instancing/icon.png
new file mode 100644
index 0000000000..7a6de677c5
--- /dev/null
+++ b/demos/misc/instancing/icon.png
Binary files differ
diff --git a/demos/misc/regex/regex.gd b/demos/misc/regex/regex.gd
index e648c18093..409b4cab05 100644
--- a/demos/misc/regex/regex.gd
+++ b/demos/misc/regex/regex.gd
@@ -2,21 +2,23 @@ extends VBoxContainer
var regex = RegEx.new()
-func update_expression():
- regex.compile(get_node("Expression").get_text())
+func update_expression(text):
+ regex.compile(text)
update_text()
func update_text():
var text = get_node("Text").get_text()
- regex.find(text)
var list = get_node("List")
for child in list.get_children():
child.queue_free()
- for res in regex.get_captures():
- var label = Label.new()
- label.set_text(res)
- list.add_child(label)
+ if regex.is_valid():
+ regex.find(text)
+ for res in regex.get_captures():
+ var label = Label.new()
+ label.set_text(res)
+ list.add_child(label)
func _ready():
get_node("Text").set_text("They asked me \"What's going on \\\"in the manor\\\"?\"")
- update_expression()
+ update_expression(get_node("Expression").get_text())
+
diff --git a/demos/misc/regex/regex.scn b/demos/misc/regex/regex.scn
index 2b62d6b82a..1f46521d0d 100644
--- a/demos/misc/regex/regex.scn
+++ b/demos/misc/regex/regex.scn
Binary files differ
diff --git a/demos/misc/tween/engine.cfg b/demos/misc/tween/engine.cfg
index f97e540dbd..3d3d639964 100644
--- a/demos/misc/tween/engine.cfg
+++ b/demos/misc/tween/engine.cfg
@@ -2,7 +2,7 @@
name="Tween Demo"
main_scene="res://main.xml"
-icon="icon.png"
+icon="res://icon.png"
target_fps=60
[display]
diff --git a/demos/misc/window_management/engine.cfg b/demos/misc/window_management/engine.cfg
index 0a34231673..911d3fd4a1 100644
--- a/demos/misc/window_management/engine.cfg
+++ b/demos/misc/window_management/engine.cfg
@@ -2,7 +2,7 @@
name="Window Management"
main_scene="res://window_management.scn"
-icon="icon.png"
+icon="res://icon.png"
[display]
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index d84ee5a758..b473e8493f 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -4075,6 +4075,8 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int
glDeleteTextures(1,&rt->color);
rt->fbo=0;
+ rt->depth=0;
+ rt->color=0;
rt->width=0;
rt->height=0;
rt->texture_ptr->tex_id=0;
@@ -4094,12 +4096,14 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int
glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
//depth
- glGenRenderbuffers(1, &rt->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
+ if (!low_memory_2d) {
+ glGenRenderbuffers(1, &rt->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
- glRenderbufferStorage(GL_RENDERBUFFER, use_depth24?_DEPTH_COMPONENT24_OES:GL_DEPTH_COMPONENT16, rt->width,rt->height);
+ glRenderbufferStorage(GL_RENDERBUFFER, use_depth24?_DEPTH_COMPONENT24_OES:GL_DEPTH_COMPONENT16, rt->width,rt->height);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
//color
glGenTextures(1, &rt->color);
@@ -4641,6 +4645,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const {
enablers.push_back("#define USE_TIME\n");
uses_time=true;
}
+ if (vertex_flags.vertex_code_writes_position) {
+ enablers.push_back("#define VERTEX_SHADER_WRITE_POSITION\n");
+ }
material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers);
} else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) {
@@ -6526,80 +6533,84 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false);
material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,false);
- if (e->instance->sampled_light.is_valid()) {
+ if (material->flags[VS::MATERIAL_FLAG_UNSHADED] == false && current_debug != VS::SCENARIO_DEBUG_SHADELESS) {
- SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light);
- if (sl) {
+ if (e->instance->sampled_light.is_valid()) {
- baked_light=NULL; //can't mix
- material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER,true);
- glActiveTexture(GL_TEXTURE0+max_texture_units-3);
- glBindTexture(GL_TEXTURE_2D,sl->texture); //bind the texture
- sampled_light_dp_multiplier=sl->multiplier;
- bind_dp_sampler=true;
+ SampledLight *sl = sampled_light_owner.get(e->instance->sampled_light);
+ if (sl) {
+
+ baked_light = NULL; //can't mix
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_DP_SAMPLER, true);
+ glActiveTexture(GL_TEXTURE0 + max_texture_units - 3);
+ glBindTexture(GL_TEXTURE_2D, sl->texture); //bind the texture
+ sampled_light_dp_multiplier = sl->multiplier;
+ bind_dp_sampler = true;
+ }
}
- }
- if (!additive && baked_light) {
+ if (!additive && baked_light) {
- if (baked_light->mode==VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) {
- material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,true);
- bind_baked_light_octree=true;
- if (prev_baked_light!=baked_light) {
- Texture *tex=texture_owner.get(baked_light->octree_texture);
- if (tex) {
+ if (baked_light->mode == VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) {
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE, true);
+ bind_baked_light_octree = true;
+ if (prev_baked_light != baked_light) {
+ Texture *tex = texture_owner.get(baked_light->octree_texture);
+ if (tex) {
- glActiveTexture(GL_TEXTURE0+max_texture_units-3);
- glBindTexture(tex->target,tex->tex_id); //bind the texture
- }
- if (baked_light->light_texture.is_valid()) {
- Texture *texl=texture_owner.get(baked_light->light_texture);
- if (texl) {
- glActiveTexture(GL_TEXTURE0+max_texture_units-4);
- glBindTexture(texl->target,texl->tex_id); //bind the light texture
+ glActiveTexture(GL_TEXTURE0 + max_texture_units - 3);
+ glBindTexture(tex->target, tex->tex_id); //bind the texture
+ }
+ if (baked_light->light_texture.is_valid()) {
+ Texture *texl = texture_owner.get(baked_light->light_texture);
+ if (texl) {
+ glActiveTexture(GL_TEXTURE0 + max_texture_units - 4);
+ glBindTexture(texl->target, texl->tex_id); //bind the light texture
+ }
}
- }
+ }
}
- } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) {
+ else if (baked_light->mode == VS::BAKED_LIGHT_LIGHTMAPS) {
- int lightmap_idx = e->instance->baked_lightmap_id;
+ int lightmap_idx = e->instance->baked_lightmap_id;
- material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,false);
- bind_baked_lightmap=false;
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, false);
+ bind_baked_lightmap = false;
- if (baked_light->lightmaps.has(lightmap_idx)) {
+ if (baked_light->lightmaps.has(lightmap_idx)) {
- RID texid = baked_light->lightmaps[lightmap_idx];
+ RID texid = baked_light->lightmaps[lightmap_idx];
- if (prev_baked_light!=baked_light || texid!=prev_baked_light_texture) {
+ if (prev_baked_light != baked_light || texid != prev_baked_light_texture) {
- Texture *tex = texture_owner.get(texid);
- if (tex) {
+ Texture *tex = texture_owner.get(texid);
+ if (tex) {
+
+ glActiveTexture(GL_TEXTURE0 + max_texture_units - 3);
+ glBindTexture(tex->target, tex->tex_id); //bind the texture
+ }
- glActiveTexture(GL_TEXTURE0+max_texture_units-3);
- glBindTexture(tex->target,tex->tex_id); //bind the texture
+ prev_baked_light_texture = texid;
}
- prev_baked_light_texture=texid;
- }
+ if (texid.is_valid()) {
+ material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP, true);
+ bind_baked_lightmap = true;
+ }
- if (texid.is_valid()) {
- material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_LIGHTMAP,true);
- bind_baked_lightmap=true;
}
-
}
}
- }
- if (int(prev_baked_light!=NULL) ^ int(baked_light!=NULL)) {
- rebind=true;
+ if (int(prev_baked_light != NULL) ^ int(baked_light != NULL)) {
+ rebind = true;
+ }
}
}
@@ -10293,7 +10304,11 @@ void RasterizerGLES2::_update_framebuffer() {
framebuffer.fbo=0;
}
+#ifdef TOOLS_ENABLED
framebuffer.active=use_fbo;
+#else
+ framebuffer.active=use_fbo && !low_memory_2d;
+#endif
framebuffer.width=dwidth;
framebuffer.height=dheight;
framebuffer.scale=scale;
@@ -11203,6 +11218,7 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
use_fp16_fb=bool(GLOBAL_DEF("rasterizer/fp16_framebuffer",true));
use_shadow_mapping=true;
use_fast_texture_filter=!bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true));
+ low_memory_2d=bool(GLOBAL_DEF("rasterizer/low_memory_2d_mode",false));
skel_default.resize(1024*4);
for(int i=0;i<1024/3;i++) {
diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h
index 4b512cc3a9..d6d9593da8 100644
--- a/drivers/gles2/rasterizer_gles2.h
+++ b/drivers/gles2/rasterizer_gles2.h
@@ -105,7 +105,7 @@ class RasterizerGLES2 : public Rasterizer {
float anisotropic_level;
bool use_half_float;
-
+ bool low_memory_2d;
Vector<float> skel_default;
diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp
index d57512c936..c8f59ce22b 100644
--- a/drivers/gles2/shader_compiler_gles2.cpp
+++ b/drivers/gles2/shader_compiler_gles2.cpp
@@ -154,6 +154,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
if (vnode->name==vname_vertex && p_assign_left) {
vertex_code_writes_vertex=true;
}
+ if (vnode->name == vname_position && p_assign_left) {
+ vertex_code_writes_position = true;
+ }
if (vnode->name==vname_color_interp) {
flags->use_color_interp=true;
}
@@ -659,6 +662,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
uses_texpixel_size=false;
uses_worldvec=false;
vertex_code_writes_vertex=false;
+ vertex_code_writes_position = false;
uses_shadow_color=false;
uniforms=r_uniforms;
flags=&r_flags;
@@ -690,6 +694,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
r_flags.uses_texscreen=uses_texscreen;
r_flags.uses_texpos=uses_texpos;
r_flags.vertex_code_writes_vertex=vertex_code_writes_vertex;
+ r_flags.vertex_code_writes_position=vertex_code_writes_position;
r_flags.uses_discard=uses_discard;
r_flags.uses_screen_uv=uses_screen_uv;
r_flags.uses_light=uses_light;
@@ -778,125 +783,127 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
replace_table["texscreen"]= "texscreen";
replace_table["texpos"]= "texpos";
- mode_replace_table[0]["SRC_VERTEX"]="vertex_in.xyz";
- mode_replace_table[0]["SRC_NORMAL"]="normal_in";
- mode_replace_table[0]["SRC_TANGENT"]="tangent_in";
- mode_replace_table[0]["SRC_BINORMALF"]="binormalf";
-
- mode_replace_table[0]["VERTEX"]="vertex_interp";
- mode_replace_table[0]["NORMAL"]="normal_interp";
- mode_replace_table[0]["TANGENT"]="tangent_interp";
- mode_replace_table[0]["BINORMAL"]="binormal_interp";
- mode_replace_table[0]["UV"]="uv_interp.xy";
- mode_replace_table[0]["UV2"]="uv_interp.zw";
- mode_replace_table[0]["COLOR"]="color_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POSITION"] = "gl_Position";
+
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_VERTEX"] = "vertex_in.xyz";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_NORMAL"] = "normal_in";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_TANGENT"]="tangent_in";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SRC_BINORMALF"]="binormalf";
+
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VERTEX"]="vertex_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["NORMAL"]="normal_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["TANGENT"]="tangent_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["BINORMAL"]="binormal_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["UV"]="uv_interp.xy";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["UV2"]="uv_interp.zw";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["COLOR"]="color_interp";
//@TODO convert to glsl stuff
- mode_replace_table[0]["SPEC_EXP"]="vertex_specular_exp";
- mode_replace_table[0]["WORLD_MATRIX"]="world_transform";
- mode_replace_table[0]["INV_CAMERA_MATRIX"]="camera_inverse_transform";
- mode_replace_table[0]["PROJECTION_MATRIX"]="projection_transform";
- mode_replace_table[0]["MODELVIEW_MATRIX"]="modelview";
- mode_replace_table[0]["POINT_SIZE"]="gl_PointSize";
- mode_replace_table[0]["VAR1"]="var1_interp";
- mode_replace_table[0]["VAR2"]="var2_interp";
-
-// mode_replace_table[0]["SCREEN_POS"]="SCREEN_POS";
-// mode_replace_table[0]["SCREEN_SIZE"]="SCREEN_SIZE";
- mode_replace_table[0]["INSTANCE_ID"]="instance_id";
- mode_replace_table[0]["TIME"]="time";
-
- mode_replace_table[1]["VERTEX"]="vertex";
- //mode_replace_table[1]["POSITION"]="IN_POSITION";
- mode_replace_table[1]["NORMAL"]="normal";
- mode_replace_table[1]["TANGENT"]="tangent";
- mode_replace_table[1]["POSITION"]="gl_Position";
- mode_replace_table[1]["BINORMAL"]="binormal";
- mode_replace_table[1]["NORMALMAP"]="normalmap";
- mode_replace_table[1]["NORMALMAP_DEPTH"]="normaldepth";
- mode_replace_table[1]["VAR1"]="var1_interp";
- mode_replace_table[1]["VAR2"]="var2_interp";
- mode_replace_table[1]["UV"]="uv";
- mode_replace_table[1]["UV2"]="uv2";
- mode_replace_table[1]["SCREEN_UV"]="screen_uv";
- mode_replace_table[1]["VAR1"]="var1_interp";
- mode_replace_table[1]["VAR2"]="var2_interp";
- mode_replace_table[1]["COLOR"]="color";
- mode_replace_table[1]["DIFFUSE"]="diffuse.rgb";
- mode_replace_table[1]["DIFFUSE_ALPHA"]="diffuse";
- mode_replace_table[1]["SPECULAR"]="specular";
- mode_replace_table[1]["EMISSION"]="emission";
- mode_replace_table[1]["SHADE_PARAM"]="shade_param";
- mode_replace_table[1]["SPEC_EXP"]="specular_exp";
- mode_replace_table[1]["GLOW"]="glow";
- mode_replace_table[1]["DISCARD"]="discard_";
- mode_replace_table[1]["POINT_COORD"]="gl_PointCoord";
- mode_replace_table[1]["INV_CAMERA_MATRIX"]="camera_inverse_transform";
-
- //mode_replace_table[1]["SCREEN_POS"]="SCREEN_POS";
- //mode_replace_table[1]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE";
- mode_replace_table[1]["TIME"]="time";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SPEC_EXP"]="vertex_specular_exp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["WORLD_MATRIX"]="world_transform";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["INV_CAMERA_MATRIX"]="camera_inverse_transform";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["PROJECTION_MATRIX"]="projection_transform";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["MODELVIEW_MATRIX"]="modelview";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["POINT_SIZE"]="gl_PointSize";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["VAR2"]="var2_interp";
+
+// mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SCREEN_POS"]="SCREEN_POS";
+// mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["SCREEN_SIZE"]="SCREEN_SIZE";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["INSTANCE_ID"]="instance_id";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_VERTEX]["TIME"]="time";
+
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VERTEX"]="vertex";
+ //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POSITION"]="IN_POSITION";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMAL"]="normal";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["TANGENT"]="tangent";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POSITION"]="gl_Position";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["BINORMAL"]="binormal";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMALMAP"]="normalmap";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["NORMALMAP_DEPTH"]="normaldepth";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR2"]="var2_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["UV"]="uv";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["UV2"]="uv2";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_UV"]="screen_uv";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["VAR2"]="var2_interp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["COLOR"]="color";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DIFFUSE"]="diffuse.rgb";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DIFFUSE_ALPHA"]="diffuse";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SPECULAR"]="specular";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["EMISSION"]="emission";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SHADE_PARAM"]="shade_param";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SPEC_EXP"]="specular_exp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["GLOW"]="glow";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["DISCARD"]="discard_";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["POINT_COORD"]="gl_PointCoord";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["INV_CAMERA_MATRIX"]="camera_inverse_transform";
+
+ //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_POS"]="SCREEN_POS";
+ //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_FRAGMENT]["TIME"]="time";
//////////////
- mode_replace_table[2]["NORMAL"]="normal";
- //mode_replace_table[2]["POSITION"]="IN_POSITION";
- mode_replace_table[2]["LIGHT_DIR"]="light_dir";
- mode_replace_table[2]["LIGHT_DIFFUSE"]="light_diffuse";
- mode_replace_table[2]["LIGHT_SPECULAR"]="light_specular";
- mode_replace_table[2]["EYE_VEC"]="eye_vec";
- mode_replace_table[2]["DIFFUSE"]="mdiffuse";
- mode_replace_table[2]["SPECULAR"]="specular";
- mode_replace_table[2]["SPECULAR_EXP"]="specular_exp";
- mode_replace_table[2]["SHADE_PARAM"]="shade_param";
- mode_replace_table[2]["LIGHT"]="light";
- mode_replace_table[2]["POINT_COORD"]="gl_PointCoord";
- mode_replace_table[2]["TIME"]="time";
-
- mode_replace_table[3]["SRC_VERTEX"]="src_vtx";
- mode_replace_table[3]["VERTEX"]="outvec.xy";
- mode_replace_table[3]["WORLD_VERTEX"]="outvec.xy";
- mode_replace_table[3]["UV"]="uv_interp";
- mode_replace_table[3]["COLOR"]="color_interp";
- mode_replace_table[3]["VAR1"]="var1_interp";
- mode_replace_table[3]["VAR2"]="var2_interp";
- mode_replace_table[3]["POINT_SIZE"]="gl_PointSize";
- mode_replace_table[3]["WORLD_MATRIX"]="modelview_matrix";
- mode_replace_table[3]["PROJECTION_MATRIX"]="projection_matrix";
- mode_replace_table[3]["EXTRA_MATRIX"]="extra_matrix";
- mode_replace_table[3]["TIME"]="time";
-
- mode_replace_table[4]["POSITION"]="gl_Position";
- mode_replace_table[4]["NORMAL"]="normal";
- mode_replace_table[4]["NORMALMAP"]="normal_map";
- mode_replace_table[4]["NORMALMAP_DEPTH"]="normal_depth";
- mode_replace_table[4]["UV"]="uv_interp";
- mode_replace_table[4]["SRC_COLOR"]="color_interp";
- mode_replace_table[4]["COLOR"]="color";
- mode_replace_table[4]["TEXTURE"]="texture";
- mode_replace_table[4]["TEXTURE_PIXEL_SIZE"]="texpixel_size";
- mode_replace_table[4]["VAR1"]="var1_interp";
- mode_replace_table[4]["VAR2"]="var2_interp";
- mode_replace_table[4]["SCREEN_UV"]="screen_uv";
- mode_replace_table[4]["POINT_COORD"]="gl_PointCoord";
- mode_replace_table[4]["TIME"]="time";
-
- mode_replace_table[5]["POSITION"]="gl_Position";
- mode_replace_table[5]["NORMAL"]="normal";
- mode_replace_table[5]["UV"]="uv_interp";
- mode_replace_table[5]["COLOR"]="color";
- mode_replace_table[5]["TEXTURE"]="texture";
- mode_replace_table[5]["TEXTURE_PIXEL_SIZE"]="texpixel_size";
- mode_replace_table[5]["VAR1"]="var1_interp";
- mode_replace_table[5]["VAR2"]="var2_interp";
- mode_replace_table[5]["LIGHT_VEC"]="light_vec";
- mode_replace_table[5]["LIGHT_HEIGHT"]="light_height";
- mode_replace_table[5]["LIGHT_COLOR"]="light";
- mode_replace_table[5]["LIGHT_UV"]="light_uv";
- mode_replace_table[5]["LIGHT"]="light_out";
- mode_replace_table[5]["SHADOW"]="shadow_color";
- mode_replace_table[5]["SCREEN_UV"]="screen_uv";
- mode_replace_table[5]["POINT_COORD"]="gl_PointCoord";
- mode_replace_table[5]["TIME"]="time";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["NORMAL"]="normal";
+ //mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["POSITION"]="IN_POSITION";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_DIR"]="light_dir";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_DIFFUSE"]="light_diffuse";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT_SPECULAR"]="light_specular";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["EYE_VEC"]="eye_vec";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["DIFFUSE"]="mdiffuse";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SPECULAR"]="specular";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SPECULAR_EXP"]="specular_exp";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["SHADE_PARAM"]="shade_param";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["LIGHT"]="light";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["POINT_COORD"]="gl_PointCoord";
+ mode_replace_table[ShaderLanguage::SHADER_MATERIAL_LIGHT]["TIME"]="time";
+
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["SRC_VERTEX"]="src_vtx";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VERTEX"]="outvec.xy";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["WORLD_VERTEX"]="outvec.xy";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["UV"]="uv_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["COLOR"]="color_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["VAR2"]="var2_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["POINT_SIZE"]="gl_PointSize";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["WORLD_MATRIX"]="modelview_matrix";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["PROJECTION_MATRIX"]="projection_matrix";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["EXTRA_MATRIX"]="extra_matrix";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX]["TIME"]="time";
+
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POSITION"]="gl_Position";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMAL"]="normal";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMALMAP"]="normal_map";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["NORMALMAP_DEPTH"]="normal_depth";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["UV"]="uv_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SRC_COLOR"]="color_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["COLOR"]="color";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TEXTURE"]="texture";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TEXTURE_PIXEL_SIZE"]="texpixel_size";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["VAR2"]="var2_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["SCREEN_UV"]="screen_uv";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["POINT_COORD"]="gl_PointCoord";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT]["TIME"]="time";
+
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POSITION"]="gl_Position";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["NORMAL"]="normal";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["UV"]="uv_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["COLOR"]="color";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TEXTURE"]="texture";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TEXTURE_PIXEL_SIZE"]="texpixel_size";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["VAR1"]="var1_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["VAR2"]="var2_interp";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_VEC"]="light_vec";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_HEIGHT"]="light_height";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_COLOR"]="light";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT_UV"]="light_uv";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["LIGHT"]="light_out";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SHADOW"]="shadow_color";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["SCREEN_UV"]="screen_uv";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["POINT_COORD"]="gl_PointCoord";
+ mode_replace_table[ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT]["TIME"]="time";
@@ -917,6 +924,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
vname_var1_interp="VAR1";
vname_var2_interp="VAR2";
vname_vertex="VERTEX";
+ vname_position = "POSITION";
vname_light="LIGHT";
vname_time="TIME";
vname_normalmap="NORMALMAP";
diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h
index 19c24757ba..46ef2e035f 100644
--- a/drivers/gles2/shader_compiler_gles2.h
+++ b/drivers/gles2/shader_compiler_gles2.h
@@ -55,6 +55,7 @@ private:
bool uses_texpixel_size;
bool uses_worldvec;
bool vertex_code_writes_vertex;
+ bool vertex_code_writes_position;
bool uses_shadow_color;
bool sinh_used;
@@ -76,6 +77,7 @@ private:
StringName vname_var1_interp;
StringName vname_var2_interp;
StringName vname_vertex;
+ StringName vname_position;
StringName vname_light;
StringName vname_time;
StringName vname_normalmap;
@@ -107,6 +109,7 @@ public:
bool uses_texpos;
bool uses_normalmap;
bool vertex_code_writes_vertex;
+ bool vertex_code_writes_position;
bool uses_discard;
bool uses_screen_uv;
bool use_color_interp;
diff --git a/drivers/nrex/README.md b/drivers/nrex/README.md
index f150a5d76f..951b301c1e 100644
--- a/drivers/nrex/README.md
+++ b/drivers/nrex/README.md
@@ -18,47 +18,42 @@ More details about its use is documented in `nrex.hpp`
Currently supported features:
* Capturing `()` and non-capturing `(?:)` groups
- * Any character `.`
+ * Any character `.` (includes newlines)
* Shorthand caracter classes `\w\W\s\S\d\D`
- * User-defined character classes such as `[A-Za-z]`
+ * POSIX character classes such as `[[:alnum:]]`
+ * Bracket expressions such as `[A-Za-z]`
* Simple quantifiers `?`, `*` and `+`
* Range quantifiers `{0,1}`
* Lazy (non-greedy) quantifiers `*?`
* Begining `^` and end `$` anchors
+ * Word boundaries `\b`
* Alternation `|`
- * Backreferences `\1` to `\99`
-
-To do list:
+ * ASCII `\xFF` code points
* Unicode `\uFFFF` code points
+ * Positive `(?=)` and negative `(?!)` lookahead
+ * Positive `(?<=)` and negative `(?<!)` lookbehind (fixed length and no alternations)
+ * Backreferences `\1` to `\9` (with option to expand to `\99`)
## License
Copyright (c) 2015, Zher Huei Lee
All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would
+ be appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
diff --git a/drivers/nrex/nrex.cpp b/drivers/nrex/nrex.cpp
index 696d46240e..104e07f887 100644
--- a/drivers/nrex/nrex.cpp
+++ b/drivers/nrex/nrex.cpp
@@ -29,11 +29,13 @@
#include <wctype.h>
#include <wchar.h>
#define NREX_ISALPHANUM iswalnum
+#define NREX_ISSPACE iswspace
#define NREX_STRLEN wcslen
#else
#include <ctype.h>
#include <string.h>
#define NREX_ISALPHANUM isalnum
+#define NREX_ISSPACE isspace
#define NREX_STRLEN strlen
#endif
@@ -116,34 +118,72 @@ class nrex_array
}
};
-static nrex_char nrex_unescape(nrex_char repr)
+static int nrex_parse_hex(nrex_char c)
{
- switch (repr)
+ if ('0' <= c && c <= '9')
+ {
+ return int(c - '0');
+ }
+ else if ('a' <= c && c <= 'f')
+ {
+ return int(c - 'a') + 10;
+ }
+ else if ('A' <= c && c <= 'F')
{
- case '^': return '^';
- case '$': return '$';
- case '(': return '(';
- case ')': return ')';
- case '\\': return '\\';
- case '.': return '.';
- case '+': return '+';
- case '*': return '*';
- case '?': return '?';
- case '-': return '-';
- case 'a': return '\a';
- case 'e': return '\e';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case 'v': return '\v';
+ return int(c - 'A') + 10;
}
- return 0;
+ return -1;
+}
+
+static nrex_char nrex_unescape(const nrex_char*& c)
+{
+ switch (c[1])
+ {
+ case '0': ++c; return '\0';
+ case 'a': ++c; return '\a';
+ case 'e': ++c; return '\e';
+ case 'f': ++c; return '\f';
+ case 'n': ++c; return '\n';
+ case 'r': ++c; return '\r';
+ case 't': ++c; return '\t';
+ case 'v': ++c; return '\v';
+ case 'b': ++c; return '\b';
+ case 'x':
+ {
+ int point = 0;
+ for (int i = 2; i <= 3; ++i)
+ {
+ int res = nrex_parse_hex(c[i]);
+ if (res == -1)
+ {
+ return '\0';
+ }
+ point = (point << 4) + res;
+ }
+ c = &c[3];
+ return nrex_char(point);
+ }
+ case 'u':
+ {
+ int point = 0;
+ for (int i = 2; i <= 5; ++i)
+ {
+ int res = nrex_parse_hex(c[i]);
+ if (res == -1)
+ {
+ return '\0';
+ }
+ point = (point << 4) + res;
+ }
+ c = &c[5];
+ return nrex_char(point);
+ }
+ }
+ return (++c)[0];
}
struct nrex_search
{
- public:
const nrex_char* str;
nrex_result* captures;
int end;
@@ -168,12 +208,14 @@ struct nrex_node
nrex_node* previous;
nrex_node* parent;
bool quantifiable;
+ int length;
nrex_node(bool quantify = false)
: next(NULL)
, previous(NULL)
, parent(NULL)
, quantifiable(quantify)
+ , length(-1)
{
}
@@ -206,21 +248,57 @@ struct nrex_node
}
return pos;
}
+
+ void increment_length(int amount, bool subtract = false)
+ {
+ if (amount >= 0 && length >= 0)
+ {
+ if (!subtract)
+ {
+ length += amount;
+ }
+ else
+ {
+ length -= amount;
+ }
+ }
+ else
+ {
+ length = -1;
+ }
+ if (parent)
+ {
+ parent->increment_length(amount, subtract);
+ }
+ }
};
struct nrex_node_group : public nrex_node
{
- int capturing;
+ static const int NonCapture = -1;
+ static const int Bracket = -2;
+ static const int LookAhead = -3;
+ static const int LookBehind = -4;
+
+ int mode;
bool negate;
nrex_array<nrex_node*> childset;
nrex_node* back;
- nrex_node_group(int capturing)
+ nrex_node_group(int mode)
: nrex_node(true)
- , capturing(capturing)
+ , mode(mode)
, negate(false)
, back(NULL)
{
+ if (mode != Bracket)
+ {
+ length = 0;
+ }
+ else
+ {
+ length = 1;
+ }
}
virtual ~nrex_node_group()
@@ -234,14 +312,19 @@ struct nrex_node_group : public nrex_node
int test(nrex_search* s, int pos) const
{
- if (capturing >= 0)
+ if (mode >= 0)
{
- s->captures[capturing].start = pos;
+ s->captures[mode].start = pos;
}
for (unsigned int i = 0; i < childset.size(); ++i)
{
s->complete = false;
- int res = childset[i]->test(s, pos);
+ int offset = 0;
+ if (mode == LookBehind)
+ {
+ offset = length;
+ }
+ int res = childset[i]->test(s, pos - offset);
if (s->complete)
{
return res;
@@ -256,12 +339,20 @@ struct nrex_node_group : public nrex_node
{
return -1;
}
+ if (i + 1 < childset.size())
+ {
+ continue;
+ }
}
if (res >= 0)
{
- if (capturing >= 0)
+ if (mode >= 0)
{
- s->captures[capturing].length = res - pos;
+ s->captures[mode].length = res - pos;
+ }
+ else if (mode == LookAhead || mode == LookBehind)
+ {
+ res = pos;
}
return next ? next->test(s, res) : res;
}
@@ -271,15 +362,19 @@ struct nrex_node_group : public nrex_node
virtual int test_parent(nrex_search* s, int pos) const
{
- if (capturing >= 0)
+ if (mode >= 0)
{
- s->captures[capturing].length = pos - s->captures[capturing].start;
+ s->captures[mode].length = pos - s->captures[mode].start;
}
return nrex_node::test_parent(s, pos);
}
void add_childset()
{
+ if (childset.size() > 0 && mode != Bracket)
+ {
+ length = -1;
+ }
back = NULL;
}
@@ -287,7 +382,7 @@ struct nrex_node_group : public nrex_node
{
node->parent = this;
node->previous = back;
- if (back)
+ if (back && mode != Bracket)
{
back->next = node;
}
@@ -295,6 +390,10 @@ struct nrex_node_group : public nrex_node
{
childset.push(node);
}
+ if (mode != Bracket)
+ {
+ increment_length(node->length);
+ }
back = node;
}
@@ -310,10 +409,32 @@ struct nrex_node_group : public nrex_node
{
childset.pop();
}
+ if (mode != Bracket)
+ {
+ increment_length(old->length, true);
+ }
back = old->previous;
add_child(node);
return old;
}
+
+ void pop_back()
+ {
+ if (back)
+ {
+ nrex_node* old = back;
+ if (!old->previous)
+ {
+ childset.pop();
+ }
+ if (mode != Bracket)
+ {
+ increment_length(old->length, true);
+ }
+ back = old->previous;
+ NREX_DELETE(old);
+ }
+ }
};
struct nrex_node_char : public nrex_node
@@ -324,6 +445,7 @@ struct nrex_node_char : public nrex_node
: nrex_node(true)
, ch(c)
{
+ length = 1;
}
int test(nrex_search* s, int pos) const
@@ -346,6 +468,7 @@ struct nrex_node_range : public nrex_node
, start(s)
, end(e)
{
+ length = 1;
}
int test(nrex_search* s, int pos) const
@@ -363,20 +486,219 @@ struct nrex_node_range : public nrex_node
}
};
-static bool nrex_is_whitespace(nrex_char repr)
+enum nrex_class_type
{
- switch (repr)
+ nrex_class_none,
+ nrex_class_alnum,
+ nrex_class_alpha,
+ nrex_class_blank,
+ nrex_class_cntrl,
+ nrex_class_digit,
+ nrex_class_graph,
+ nrex_class_lower,
+ nrex_class_print,
+ nrex_class_punct,
+ nrex_class_space,
+ nrex_class_upper,
+ nrex_class_xdigit,
+ nrex_class_word
+};
+
+static bool nrex_compare_class(const nrex_char** pos, const char* text)
+{
+ unsigned int i = 0;
+ for (i = 0; text[i] != '\0'; ++i)
{
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case '\f':
- return true;
+ if ((*pos)[i] != text[i])
+ {
+ return false;
+ }
}
- return false;
+ if ((*pos)[i++] != ':' || (*pos)[i] != ']')
+ {
+ return false;
+ }
+ *pos = &(*pos)[i];
+ return true;
}
+#define NREX_COMPARE_CLASS(POS, NAME) if (nrex_compare_class(POS, #NAME)) return nrex_class_ ## NAME
+
+static nrex_class_type nrex_parse_class(const nrex_char** pos)
+{
+ NREX_COMPARE_CLASS(pos, alnum);
+ NREX_COMPARE_CLASS(pos, alpha);
+ NREX_COMPARE_CLASS(pos, blank);
+ NREX_COMPARE_CLASS(pos, cntrl);
+ NREX_COMPARE_CLASS(pos, digit);
+ NREX_COMPARE_CLASS(pos, graph);
+ NREX_COMPARE_CLASS(pos, lower);
+ NREX_COMPARE_CLASS(pos, print);
+ NREX_COMPARE_CLASS(pos, punct);
+ NREX_COMPARE_CLASS(pos, space);
+ NREX_COMPARE_CLASS(pos, upper);
+ NREX_COMPARE_CLASS(pos, xdigit);
+ NREX_COMPARE_CLASS(pos, word);
+ return nrex_class_none;
+}
+
+struct nrex_node_class : public nrex_node
+{
+ nrex_class_type type;
+
+ nrex_node_class(nrex_class_type t)
+ : nrex_node(true)
+ , type(t)
+ {
+ length = 1;
+ }
+
+ int test(nrex_search* s, int pos) const
+ {
+ if (s->end == pos)
+ {
+ return -1;
+ }
+ if (!test_class(s->at(pos)))
+ {
+ return -1;
+ }
+ return next ? next->test(s, pos + 1) : pos + 1;
+ }
+
+ bool test_class(nrex_char c) const
+ {
+ if ((0 <= c && c <= 0x1F) || c == 0x7F)
+ {
+ if (type == nrex_class_cntrl)
+ {
+ return true;
+ }
+ }
+ else if (c < 0x7F)
+ {
+ if (type == nrex_class_print)
+ {
+ return true;
+ }
+ else if (type == nrex_class_graph && c != ' ')
+ {
+ return true;
+ }
+ else if ('0' <= c && c <= '9')
+ {
+ switch (type)
+ {
+ case nrex_class_alnum:
+ case nrex_class_digit:
+ case nrex_class_xdigit:
+ case nrex_class_word:
+ return true;
+ default:
+ break;
+ }
+ }
+ else if ('A' <= c && c <= 'Z')
+ {
+ switch (type)
+ {
+ case nrex_class_alnum:
+ case nrex_class_alpha:
+ case nrex_class_upper:
+ case nrex_class_word:
+ return true;
+ case nrex_class_xdigit:
+ if (c <= 'F')
+ {
+ return true;
+ }
+ default:
+ break;
+ }
+ }
+ else if ('a' <= c && c <= 'z')
+ {
+ switch (type)
+ {
+ case nrex_class_alnum:
+ case nrex_class_alpha:
+ case nrex_class_lower:
+ case nrex_class_word:
+ return true;
+ case nrex_class_xdigit:
+ if (c <= 'f')
+ {
+ return true;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ if (type == nrex_class_blank)
+ {
+ return true;
+ }
+ case '\r':
+ case '\n':
+ case '\f':
+ if (type == nrex_class_space)
+ {
+ return true;
+ }
+ break;
+ case '_':
+ if (type == nrex_class_word)
+ {
+ return true;
+ }
+ case ']':
+ case '[':
+ case '!':
+ case '"':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '.':
+ case '/':
+ case ':':
+ case ';':
+ case '<':
+ case '=':
+ case '>':
+ case '?':
+ case '@':
+ case '\\':
+ case '^':
+ case '`':
+ case '{':
+ case '|':
+ case '}':
+ case '~':
+ case '-':
+ if (type == nrex_class_punct)
+ {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+};
+
static bool nrex_is_shorthand(nrex_char repr)
{
switch (repr)
@@ -400,6 +722,7 @@ struct nrex_node_shorthand : public nrex_node
: nrex_node(true)
, repr(c)
{
+ length = 1;
}
int test(nrex_search* s, int pos) const
@@ -435,7 +758,7 @@ struct nrex_node_shorthand : public nrex_node
case 'S':
invert = true;
case 's':
- if (nrex_is_whitespace(c))
+ if (NREX_ISSPACE(c))
{
found = true;
}
@@ -469,10 +792,10 @@ struct nrex_node_quantifier : public nrex_node
bool greedy;
nrex_node* child;
- nrex_node_quantifier()
+ nrex_node_quantifier(int min, int max)
: nrex_node()
- , min(0)
- , max(0)
+ , min(min)
+ , max(max)
, greedy(true)
, child(NULL)
{
@@ -488,17 +811,49 @@ struct nrex_node_quantifier : public nrex_node
int test(nrex_search* s, int pos) const
{
- nrex_array<int> backtrack;
- backtrack.push(pos);
- while (backtrack.top() <= s->end)
+ return test_step(s, pos, 1);
+ }
+
+ int test_step(nrex_search* s, int pos, int level) const
+ {
+ if (max == 0)
{
- if (max >= 1 && backtrack.size() > (unsigned int)max)
+ return pos;
+ }
+ if ((max >= 1 && level > max) || pos > s->end)
+ {
+ return -1;
+ }
+ if (!greedy && level > min)
+ {
+ int res = pos;
+ if (next)
{
- break;
+ res = next->test(s, res);
+ }
+ if (s->complete)
+ {
+ return res;
}
- if (!greedy && (unsigned int)min < backtrack.size())
+ if (res >= 0 && parent->test_parent(s, res) >= 0)
+ {
+ return res;
+ }
+ }
+ int res = child->test(s, pos);
+ if (s->complete)
+ {
+ return res;
+ }
+ if (res >= 0)
+ {
+ int res_step = test_step(s, res, level + 1);
+ if (res_step >= 0)
+ {
+ return res_step;
+ }
+ else if (greedy && level >= min)
{
- int res = backtrack.top();
if (next)
{
res = next->test(s, res);
@@ -512,33 +867,6 @@ struct nrex_node_quantifier : public nrex_node
return res;
}
}
- int res = child->test(s, backtrack.top());
- if (s->complete)
- {
- return res;
- }
- if (res < 0 || res == backtrack.top())
- {
- break;
- }
- backtrack.push(res);
- }
- while (greedy && (unsigned int) min < backtrack.size())
- {
- int res = backtrack.top();
- if (next)
- {
- res = next->test(s, res);
- }
- if (res >= 0 && parent->test_parent(s, res) >= 0)
- {
- return res;
- }
- if (s->complete)
- {
- return res;
- }
- backtrack.pop();
}
return -1;
}
@@ -552,6 +880,7 @@ struct nrex_node_anchor : public nrex_node
: nrex_node()
, end(end)
{
+ length = 0;
}
int test(nrex_search* s, int pos) const
@@ -568,6 +897,45 @@ struct nrex_node_anchor : public nrex_node
}
};
+struct nrex_node_word_boundary : public nrex_node
+{
+ bool inverse;
+
+ nrex_node_word_boundary(bool inverse)
+ : nrex_node()
+ , inverse(inverse)
+ {
+ length = 0;
+ }
+
+ int test(nrex_search* s, int pos) const
+ {
+ bool left = false;
+ bool right = false;
+ if (pos != 0)
+ {
+ nrex_char c = s->at(pos - 1);
+ if (c == '_' || NREX_ISALPHANUM(c))
+ {
+ left = true;
+ }
+ }
+ if (pos != s->end)
+ {
+ nrex_char c = s->at(pos);
+ if (c == '_' || NREX_ISALPHANUM(c))
+ {
+ right = true;
+ }
+ }
+ if ((left != right) == inverse)
+ {
+ return -1;
+ }
+ return next ? next->test(s, pos) : pos;
+ }
+};
+
struct nrex_node_backreference : public nrex_node
{
int ref;
@@ -576,6 +944,7 @@ struct nrex_node_backreference : public nrex_node
: nrex_node(true)
, ref(ref)
{
+ length = -1;
}
int test(nrex_search* s, int pos) const
@@ -596,6 +965,18 @@ struct nrex_node_backreference : public nrex_node
}
};
+bool nrex_has_lookbehind(nrex_array<nrex_node_group*>& stack)
+{
+ for (unsigned int i = 0; i < stack.size(); i++)
+ {
+ if (stack[i]->mode == nrex_node_group::LookBehind)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
nrex::nrex()
: _capturing(0)
, _root(NULL)
@@ -630,7 +1011,7 @@ int nrex::capture_size() const
return _capturing + 1;
}
-bool nrex::compile(const nrex_char* pattern)
+bool nrex::compile(const nrex_char* pattern, bool extended)
{
reset();
nrex_node_group* root = NREX_NEW(nrex_node_group(_capturing));
@@ -647,16 +1028,32 @@ bool nrex::compile(const nrex_char* pattern)
if (c[2] == ':')
{
c = &c[2];
- nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
+ nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::NonCapture));
+ stack.top()->add_child(group);
+ stack.push(group);
+ }
+ else if (c[2] == '!' || c[2] == '=')
+ {
+ c = &c[2];
+ nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::LookAhead));
+ group->negate = (c[0] == '!');
+ stack.top()->add_child(group);
+ stack.push(group);
+ }
+ else if (c[2] == '<' && (c[3] == '!' || c[3] == '='))
+ {
+ c = &c[3];
+ nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::LookBehind));
+ group->negate = (c[0] == '!');
stack.top()->add_child(group);
stack.push(group);
}
else
{
- NREX_COMPILE_ERROR("unrecognised qualifier for parenthesis");
+ NREX_COMPILE_ERROR("unrecognised qualifier for group");
}
}
- else if (_capturing < 99)
+ else if ((!extended && _capturing < 9) || (extended && _capturing < 99))
{
nrex_node_group* group = NREX_NEW(nrex_node_group(++_capturing));
stack.top()->add_child(group);
@@ -664,7 +1061,7 @@ bool nrex::compile(const nrex_char* pattern)
}
else
{
- nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
+ nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::NonCapture));
stack.top()->add_child(group);
stack.push(group);
}
@@ -682,152 +1079,233 @@ bool nrex::compile(const nrex_char* pattern)
}
else if (c[0] == '[')
{
- nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
+ nrex_node_group* group = NREX_NEW(nrex_node_group(nrex_node_group::Bracket));
stack.top()->add_child(group);
if (c[1] == '^')
{
group->negate = true;
++c;
}
+ bool first_child = true;
+ nrex_char previous_child;
+ bool previous_child_single = false;
while (true)
{
group->add_childset();
++c;
if (c[0] == '\0')
{
- NREX_COMPILE_ERROR("unclosed character class '[]'");
+ NREX_COMPILE_ERROR("unclosed bracket expression '['");
}
- if (c[0] == ']')
+ if (c[0] == '[' && c[1] == ':')
+ {
+ const nrex_char* d = &c[2];
+ nrex_class_type cls = nrex_parse_class(&d);
+ if (cls != nrex_class_none)
+ {
+ c = d;
+ group->add_child(NREX_NEW(nrex_node_class(cls)));
+ previous_child_single = false;
+ }
+ else
+ {
+ group->add_child(NREX_NEW(nrex_node_char('[')));
+ previous_child = '[';
+ previous_child_single = true;
+ }
+ }
+ else if (c[0] == ']' && !first_child)
{
break;
}
else if (c[0] == '\\')
{
- nrex_char unescaped = nrex_unescape(c[1]);
- if (unescaped)
- {
- group->add_child(NREX_NEW(nrex_node_char(unescaped)));
- ++c;
- }
- else if (nrex_is_shorthand(c[1]))
+ if (nrex_is_shorthand(c[1]))
{
group->add_child(NREX_NEW(nrex_node_shorthand(c[1])));
++c;
+ previous_child_single = false;
}
else
{
- NREX_COMPILE_ERROR("escape token not recognised");
+ const nrex_char* d = c;
+ nrex_char unescaped = nrex_unescape(d);
+ if (c == d)
+ {
+ NREX_COMPILE_ERROR("invalid escape token");
+ }
+ group->add_child(NREX_NEW(nrex_node_char(unescaped)));
+ c = d;
+ previous_child = unescaped;
+ previous_child_single = true;
}
}
- else
+ else if (previous_child_single && c[0] == '-')
{
- if (c[1] == '-' && c[2] != '\0')
+ bool is_range = false;
+ nrex_char next;
+ if (c[1] != '\0' && c[1] != ']')
{
- bool range = false;
- if ('A' <= c[0] && c[0] <= 'Z' && 'A' <= c[2] && c[2] <= 'Z')
+ if (c[1] == '\\')
{
- range = true;
+ const nrex_char* d = ++c;
+ next = nrex_unescape(d);
+ if (c == d)
+ {
+ NREX_COMPILE_ERROR("invalid escape token in range");
+ }
}
- if ('a' <= c[0] && c[0] <= 'z' && 'a' <= c[2] && c[2] <= 'z')
- {
- range = true;
- }
- if ('0' <= c[0] && c[0] <= '9' && '0' <= c[2] && c[2] <= '9')
+ else
{
- range = true;
+ next = c[1];
+ ++c;
}
- if (range)
+ is_range = true;
+ }
+ if (is_range)
+ {
+ if (next < previous_child)
{
- group->add_child(NREX_NEW(nrex_node_range(c[0], c[2])));
- c = &c[2];
- continue;
+ NREX_COMPILE_ERROR("text range out of order");
}
+ group->pop_back();
+ group->add_child(NREX_NEW(nrex_node_range(previous_child, next)));
+ previous_child_single = false;
+ }
+ else
+ {
+ group->add_child(NREX_NEW(nrex_node_char(c[0])));
+ previous_child = c[0];
+ previous_child_single = true;
}
+ }
+ else
+ {
group->add_child(NREX_NEW(nrex_node_char(c[0])));
+ previous_child = c[0];
+ previous_child_single = true;
}
-
+ first_child = false;
}
}
else if (nrex_is_quantifier(c[0]))
{
- nrex_node_quantifier* quant = NREX_NEW(nrex_node_quantifier);
- quant->child = stack.top()->swap_back(quant);
- if (quant->child == NULL || !quant->child->quantifiable)
+ if (stack.top()->back == NULL || !stack.top()->back->quantifiable)
{
+ if (c[0] == '{')
+ {
+ stack.top()->add_child(NREX_NEW(nrex_node_char('{')));
+ continue;
+ }
NREX_COMPILE_ERROR("element not quantifiable");
}
- quant->child->previous = NULL;
- quant->child->next = NULL;
- quant->child->parent = quant;
+ int min = 0;
+ int max = -1;
+ bool valid_quantifier = true;
if (c[0] == '?')
{
- quant->min = 0;
- quant->max = 1;
+ min = 0;
+ max = 1;
}
else if (c[0] == '+')
{
- quant->min = 1;
- quant->max = -1;
+ min = 1;
+ max = -1;
}
else if (c[0] == '*')
{
- quant->min = 0;
- quant->max = -1;
+ min = 0;
+ max = -1;
}
else if (c[0] == '{')
{
bool max_set = false;
- quant->min = 0;
- quant->max = -1;
+ const nrex_char* d = c;
while (true)
{
- ++c;
- if (c[0] == '\0')
+ ++d;
+ if (d[0] == '\0')
{
- NREX_COMPILE_ERROR("unclosed range quantifier '{}'");
+ valid_quantifier = false;
+ break;
}
- else if (c[0] == '}')
+ else if (d[0] == '}')
{
break;
}
- else if (c[0] == ',')
+ else if (d[0] == ',')
{
max_set = true;
continue;
}
- else if (c[0] < '0' || '9' < c[0])
+ else if (d[0] < '0' || '9' < d[0])
{
- NREX_COMPILE_ERROR("expected numeric digits, ',' or '}'");
+ valid_quantifier = false;
+ break;
}
if (max_set)
{
- if (quant->max < 0)
+ if (max < 0)
{
- quant->max = int(c[0] - '0');
+ max = int(d[0] - '0');
}
else
{
- quant->max = quant->max * 10 + int(c[0] - '0');
+ max = max * 10 + int(d[0] - '0');
}
}
else
{
- quant->min = quant->min * 10 + int(c[0] - '0');
+ min = min * 10 + int(d[0] - '0');
}
}
if (!max_set)
{
- quant->max = quant->min;
+ max = min;
+ }
+ if (valid_quantifier)
+ {
+ c = d;
}
}
- if (c[1] == '?')
+ if (valid_quantifier)
{
- quant->greedy = false;
- ++c;
+ nrex_node_quantifier* quant = NREX_NEW(nrex_node_quantifier(min, max));
+ if (min == max)
+ {
+ if (stack.top()->back->length >= 0)
+ {
+ quant->length = max * stack.top()->back->length;
+ }
+ }
+ else
+ {
+ if (nrex_has_lookbehind(stack))
+ {
+ NREX_COMPILE_ERROR("variable length quantifiers inside lookbehind not supported");
+ }
+ }
+ quant->child = stack.top()->swap_back(quant);
+ quant->child->previous = NULL;
+ quant->child->next = NULL;
+ quant->child->parent = quant;
+ if (c[1] == '?')
+ {
+ quant->greedy = false;
+ ++c;
+ }
+ }
+ else
+ {
+ stack.top()->add_child(NREX_NEW(nrex_node_char(c[0])));
}
}
else if (c[0] == '|')
{
+ if (nrex_has_lookbehind(stack))
+ {
+ NREX_COMPILE_ERROR("alternations inside lookbehind not supported");
+ }
stack.top()->add_childset();
}
else if (c[0] == '^' || c[0] == '$')
@@ -840,13 +1318,7 @@ bool nrex::compile(const nrex_char* pattern)
}
else if (c[0] == '\\')
{
- nrex_char unescaped = nrex_unescape(c[1]);
- if (unescaped)
- {
- stack.top()->add_child(NREX_NEW(nrex_node_char(unescaped)));
- ++c;
- }
- else if (nrex_is_shorthand(c[1]))
+ if (nrex_is_shorthand(c[1]))
{
stack.top()->add_child(NREX_NEW(nrex_node_shorthand(c[1])));
++c;
@@ -854,7 +1326,7 @@ bool nrex::compile(const nrex_char* pattern)
else if ('1' <= c[1] && c[1] <= '9')
{
int ref = 0;
- if ('0' <= c[2] && c[2] <= '9')
+ if (extended && '0' <= c[2] && c[2] <= '9')
{
ref = int(c[1] - '0') * 10 + int(c[2] - '0');
c = &c[2];
@@ -868,11 +1340,27 @@ bool nrex::compile(const nrex_char* pattern)
{
NREX_COMPILE_ERROR("backreference to non-existent capture");
}
+ if (nrex_has_lookbehind(stack))
+ {
+ NREX_COMPILE_ERROR("backreferences inside lookbehind not supported");
+ }
stack.top()->add_child(NREX_NEW(nrex_node_backreference(ref)));
}
+ else if (c[1] == 'b' || c[1] == 'B')
+ {
+ stack.top()->add_child(NREX_NEW(nrex_node_word_boundary(c[1] == 'B')));
+ ++c;
+ }
else
{
- NREX_COMPILE_ERROR("escape token not recognised");
+ const nrex_char* d = c;
+ nrex_char unescaped = nrex_unescape(d);
+ if (c == d)
+ {
+ NREX_COMPILE_ERROR("invalid escape token");
+ }
+ stack.top()->add_child(NREX_NEW(nrex_node_char(unescaped)));
+ c = d;
}
}
else
@@ -880,6 +1368,10 @@ bool nrex::compile(const nrex_char* pattern)
stack.top()->add_child(NREX_NEW(nrex_node_char(c[0])));
}
}
+ if (stack.size() > 1)
+ {
+ NREX_COMPILE_ERROR("unclosed group '('");
+ }
return true;
}
diff --git a/drivers/nrex/nrex.hpp b/drivers/nrex/nrex.hpp
index 2a6aa08e1d..e26a61c39a 100644
--- a/drivers/nrex/nrex.hpp
+++ b/drivers/nrex/nrex.hpp
@@ -79,7 +79,8 @@ class nrex
* This is used to provide the array size of the captures needed for
* nrex::match() to work. The size is actually the number of capture
* groups + one for the matching of the entire pattern. The result is
- * always capped at 100.
+ * always capped at 10 or 100, depending on the extend option given in
+ * nrex::compile() (default 10).
*
* \return The number of captures
*/
@@ -95,10 +96,13 @@ class nrex
* runtime error nrex_compile_error if it encounters a problem when
* parsing the pattern.
*
- * \param The regex pattern
+ * \param pattern The regex pattern
+ * \param extended If true, raises the limit on number of capture
+ * groups and back-references to 99. Otherwise limited
+ * to 9. Defaults to false.
* \return True if the pattern was succesfully compiled
*/
- bool compile(const nrex_char* pattern);
+ bool compile(const nrex_char* pattern, bool extended = false);
/*!
* \brief Uses the pattern to search through the provided string
diff --git a/drivers/nrex/regex.cpp b/drivers/nrex/regex.cpp
index 0a813c3490..246384b10a 100644
--- a/drivers/nrex/regex.cpp
+++ b/drivers/nrex/regex.cpp
@@ -15,7 +15,7 @@
void RegEx::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("compile","pattern"),&RegEx::compile);
+ ObjectTypeDB::bind_method(_MD("compile","pattern", "expanded"),&RegEx::compile, DEFVAL(true));
ObjectTypeDB::bind_method(_MD("find","text","start","end"),&RegEx::find, DEFVAL(0), DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("clear"),&RegEx::clear);
ObjectTypeDB::bind_method(_MD("is_valid"),&RegEx::is_valid);
@@ -54,7 +54,9 @@ bool RegEx::is_valid() const {
};
int RegEx::get_capture_count() const {
-
+
+ ERR_FAIL_COND_V( !exp.valid(), 0 );
+
return exp.capture_size();
}
@@ -66,11 +68,11 @@ String RegEx::get_capture(int capture) const {
}
-Error RegEx::compile(const String& p_pattern) {
+Error RegEx::compile(const String& p_pattern, bool expanded) {
clear();
- exp.compile(p_pattern.c_str());
+ exp.compile(p_pattern.c_str(), expanded);
ERR_FAIL_COND_V( !exp.valid(), FAILED );
diff --git a/drivers/nrex/regex.h b/drivers/nrex/regex.h
index 0626029705..be52da8149 100644
--- a/drivers/nrex/regex.h
+++ b/drivers/nrex/regex.h
@@ -36,7 +36,7 @@ public:
bool is_valid() const;
int get_capture_count() const;
String get_capture(int capture) const;
- Error compile(const String& p_pattern);
+ Error compile(const String& p_pattern, bool expanded = false);
int find(const String& p_text, int p_start = 0, int p_end = -1) const;
RegEx();
diff --git a/drivers/opus/opus_config.h b/drivers/opus/opus_config.h
index c6470e92c3..98c3e87cc6 100644
--- a/drivers/opus/opus_config.h
+++ b/drivers/opus/opus_config.h
@@ -7,12 +7,16 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
+#if (!defined( _MSC_VER ) || ( _MSC_VER >= 1800 ))
+
/* Define to 1 if you have the `lrint' function. */
#define HAVE_LRINT 1
/* Define to 1 if you have the `lrintf' function. */
#define HAVE_LRINTF 1
+#endif
+
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@@ -109,7 +113,11 @@
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
+#if (!defined( _MSC_VER ) || ( _MSC_VER >= 1800 ))
#define restrict __restrict
+#else
+#undef restrict
+#endif
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp
index 5b6bc5b41b..ed2565177a 100644
--- a/drivers/theora/video_stream_theora.cpp
+++ b/drivers/theora/video_stream_theora.cpp
@@ -243,7 +243,9 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
/* Only interested in Vorbis/Theora streams */
int stateflag = 0;
- int audio_track_skip=audio_track;
+ int audio_track_skip=audio_track;
+
+
while(!stateflag){
int ret=buffer_data();
if(ret==0)break;
@@ -280,9 +282,8 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
vorbis_comment_init(&vc);
audio_track_skip--;
-
} else {
- copymem(&vo,&test,sizeof(test));
+ copymem(&vo,&test,sizeof(test));
vorbis_p=1;
}
}else{
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 8617061ad4..fd8c26f6d9 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -65,15 +65,25 @@ void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,c
if (!_print_error_enabled)
return;
- if (p_rationale && p_rationale[0]) {
-
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
-
- } else {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
-
+ const char* err_details;
+ if (p_rationale && p_rationale[0])
+ err_details=p_rationale;
+ else
+ err_details=p_code;
+
+ switch(p_type) {
+ case ERR_ERROR:
+ print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;31m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_WARNING:
+ print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;33m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_SCRIPT:
+ print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
}
}
diff --git a/drivers/vorbis/audio_stream_ogg_vorbis.h b/drivers/vorbis/audio_stream_ogg_vorbis.h
index 827d8b0be3..5dbada962a 100644
--- a/drivers/vorbis/audio_stream_ogg_vorbis.h
+++ b/drivers/vorbis/audio_stream_ogg_vorbis.h
@@ -85,7 +85,7 @@ public:
virtual void stop();
virtual bool is_playing() const;
- virtual void set_loop_restart_time(float p_time) { loop_restart_time=0; }
+ virtual void set_loop_restart_time(float p_time) { loop_restart_time=p_time; }
virtual void set_paused(bool p_paused);
virtual bool is_paused(bool p_paused) const;
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 313fb57d0e..202ab76da0 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -1940,9 +1940,15 @@ void GDParser::_parse_extends(ClassNode *p_class) {
p_class->extends_used=true;
- //see if inheritance happens from a file
tokenizer->advance();
+ if (tokenizer->get_token()==GDTokenizer::TK_BUILT_IN_TYPE && tokenizer->get_token_type()==Variant::OBJECT) {
+ p_class->extends_class.push_back(Variant::get_type_name(Variant::OBJECT));
+ tokenizer->advance();
+ return;
+ }
+
+ // see if inheritance happens from a file
if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT) {
Variant constant = tokenizer->get_token_constant();
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 134279b6d8..04f3dff3de 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -276,7 +276,6 @@ public:
};
struct NewLineNode : public Node {
- int line;
NewLineNode() { type=TYPE_NEWLINE; }
};
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index f8fc03ec61..1deeb3457a 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1123,6 +1123,10 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
if (file=="lib/armeabi/libgodot_android.so" && !export_arm) {
skip=true;
}
+
+ if (file.begins_with("META-INF") && _signed) {
+ skip=true;
+ }
print_line("ADDING: "+file);
diff --git a/platform/android/java/res/values-fa/strings.xml b/platform/android/java/res/values-fa/strings.xml
new file mode 100644
index 0000000000..450f9fe212
--- /dev/null
+++ b/platform/android/java/res/values-fa/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="godot_project_name_string">godot-project-name-fa</string>
+ <string name="testuf8">سلام</string>
+ <string name="text_paused_cellular">آیا می خواهید بر روی اتصال داده همراه دانلود را شروع کنید؟ بر اساس نوع سطح داده شما این ممکن است برای شما هزینه مالی داشته باشد.</string>
+ <string name="text_paused_cellular_2">اگر نمی خواهید بر روی اتصال داده همراه دانلود را شروع کنید ، دانلود به صورت خودکار در زمان دسترسی به وای-فای شروع می شود.</string>
+ <string name="text_button_resume_cellular">ادامه دانلود</string>
+ <string name="text_button_wifi_settings">تنظیمات وای-فای</string>
+ <string name="text_verifying_download">درحال تایید دانلود</string>
+ <string name="text_validation_complete">تایید فایل XAPK تکمیل شد. برای خروج تایید کنید.</string>
+ <string name="text_validation_failed">اعتبارسنجی فایل XAPK ناموق.</string>
+ <string name="text_button_pause">توقف دانلود</string>
+ <string name="text_button_resume">ادامه دانلود</string>
+ <string name="text_button_cancel">انصراف</string>
+ <string name="text_button_cancel_verify">انصراف از تایید شدن</string>
+</resources>
diff --git a/platform/android/java/src/com/android/godot/GodotPaymentV3.java b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
index 0fd102ac55..0799e1e83d 100644
--- a/platform/android/java/src/com/android/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/com/android/godot/GodotPaymentV3.java
@@ -27,7 +27,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
activity.getPaymentsManager().requestPurchase(sku, transactionId);
}
});
- };
+ }
/* public string requestPurchasedTicket(){
activity.getPaymentsManager()
@@ -42,7 +42,7 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public GodotPaymentV3(Activity p_activity) {
- registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases"});
+ registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume"});
activity=(Godot) p_activity;
}
@@ -54,7 +54,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
activity.getPaymentsManager().consumeUnconsumedPurchases();
}
});
-
}
private String signature;
@@ -63,25 +62,26 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
}
- public void callbackSuccess(String ticket, String signature){
-// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
- GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature});
-// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
+ public void callbackSuccess(String ticket, String signature, String sku){
+// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
+ GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
+// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
}
public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
-// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
- GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
-// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
+// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
+ Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku);
+ GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
+// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
}
public void callbackSuccessNoUnconsumedPurchases(){
- GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
}
public void callbackFail(){
- GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
-// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
+// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
}
public void callbackCancel(){
@@ -89,6 +89,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
}
+ public void callbackAlreadyOwned(String sku){
+ GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
+ }
+
public int getPurchaseCallbackId() {
return purchaseCallbackId;
}
@@ -97,8 +101,6 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
this.purchaseCallbackId = purchaseCallbackId;
}
-
-
public String getPurchaseValidationUrlPrefix(){
return this.purchaseValidationUrlPrefix ;
}
@@ -107,12 +109,10 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
this.purchaseValidationUrlPrefix = url;
}
-
public String getAccessToken() {
return accessToken;
}
-
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
@@ -125,4 +125,30 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
return this.transactionId;
}
+ // request purchased items are not consumed
+ public void requestPurchased(){
+ activity.getPaymentsManager().setBaseSingleton(this);
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ activity.getPaymentsManager().requestPurchased();
+ }
+ });
+ }
+
+ // callback for requestPurchased()
+ public void callbackPurchased(String receipt, String signature, String sku){
+ GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku});
+ }
+
+ // consume item automatically after purchase. default is true.
+ public void setAutoConsume(boolean autoConsume){
+ activity.getPaymentsManager().setAutoConsume(autoConsume);
+ }
+
+ // consume a specific item
+ public void consume(String sku){
+ activity.getPaymentsManager().consume(sku);
+ }
}
+
diff --git a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
index 5bf86d0b69..189f7108c1 100644
--- a/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/com/android/godot/payments/PaymentsManager.java
@@ -25,10 +25,8 @@ import com.android.vending.billing.IInAppBillingService;
public class PaymentsManager {
public static final int BILLING_RESPONSE_RESULT_OK = 0;
-
-
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
-
+ private static boolean auto_consume = true;
private Activity activity;
IInAppBillingService mService;
@@ -69,13 +67,12 @@ public class PaymentsManager {
}
@Override
- public void onServiceConnected(ComponentName name,
- IBinder service) {
- mService = IInAppBillingService.Stub.asInterface(service);
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mService = IInAppBillingService.Stub.asInterface(service);
}
};
- public void requestPurchase(String sku, String transactionId){
+ public void requestPurchase(final String sku, String transactionId){
new PurchaseTask(mService, Godot.getInstance()) {
@Override
@@ -88,6 +85,12 @@ public class PaymentsManager {
protected void canceled() {
godotPaymentV3.callbackCancel();
}
+
+ @Override
+ protected void alreadyOwned() {
+ godotPaymentV3.callbackAlreadyOwned(sku);
+ }
+
}.purchase(sku, transactionId);
}
@@ -114,26 +117,82 @@ public class PaymentsManager {
}.consumeItAll();
}
+ public void requestPurchased(){
+ try{
+ PaymentsCache pc = new PaymentsCache(Godot.getInstance());
+
+// Log.d("godot", "requestPurchased for " + activity.getPackageName());
+ Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp",null);
+
+/*
+ for (String key : bundle.keySet()) {
+ Object value = bundle.get(key);
+ Log.d("godot", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
+ }
+*/
+
+ if (bundle.getInt("RESPONSE_CODE") == 0){
+
+ final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
+ final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
+
+
+ if (myPurchases == null || myPurchases.size() == 0){
+// Log.d("godot", "No purchases!");
+ godotPaymentV3.callbackPurchased("", "", "");
+ return;
+ }
+
+// Log.d("godot", "# products are purchased:" + myPurchases.size());
+ for (int i=0;i<myPurchases.size();i++)
+ {
+
+ try{
+ String receipt = myPurchases.get(i);
+ JSONObject inappPurchaseData = new JSONObject(receipt);
+ String sku = inappPurchaseData.getString("productId");
+ String token = inappPurchaseData.getString("purchaseToken");
+ String signature = mySignatures.get(i);
+// Log.d("godot", "purchased item:" + token + "\n" + receipt);
+
+ pc.setConsumableValue("ticket_signautre", sku, signature);
+ pc.setConsumableValue("ticket", sku, receipt);
+ pc.setConsumableFlag("block", sku, true);
+ pc.setConsumableValue("token", sku, token);
+
+ godotPaymentV3.callbackPurchased(receipt, signature, sku);
+ } catch (JSONException e) {
+ }
+ }
+
+ }
+ }catch(Exception e){
+ Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
+ }
+ }
+
public void processPurchaseResponse(int resultCode, Intent data) {
new HandlePurchaseTask(activity){
@Override
protected void success(final String sku, final String signature, final String ticket) {
- godotPaymentV3.callbackSuccess(ticket, signature);
- new ConsumeTask(mService, activity) {
+ godotPaymentV3.callbackSuccess(ticket, signature, sku);
+
+ if (auto_consume){
+ new ConsumeTask(mService, activity) {
- @Override
- protected void success(String ticket) {
-// godotPaymentV3.callbackSuccess("");
- }
+ @Override
+ protected void success(String ticket) {
+// godotPaymentV3.callbackSuccess("");
+ }
- @Override
- protected void error(String message) {
- godotPaymentV3.callbackFail();
+ @Override
+ protected void error(String message) {
+ godotPaymentV3.callbackFail();
- }
- }.consume(sku);
-
+ }
+ }.consume(sku);
+ }
// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
// godotPaymentV3.callbackSuccess(ticket);
@@ -151,7 +210,7 @@ public class PaymentsManager {
godotPaymentV3.callbackCancel();
}
- }.handlePurchaseRequest(resultCode, data);
+ }.handlePurchaseRequest(resultCode, data);
}
public void validatePurchase(String purchaseToken, final String sku){
@@ -165,7 +224,7 @@ public class PaymentsManager {
@Override
protected void success(String ticket) {
- godotPaymentV3.callbackSuccess(ticket, null);
+ godotPaymentV3.callbackSuccess(ticket, null, sku);
}
@@ -192,11 +251,31 @@ public class PaymentsManager {
}.validatePurchase(sku);
}
+ public void setAutoConsume(boolean autoConsume){
+ auto_consume = autoConsume;
+ }
+
+ public void consume(final String sku){
+ new ConsumeTask(mService, activity) {
+
+ @Override
+ protected void success(String ticket) {
+ godotPaymentV3.callbackSuccessProductMassConsumed(ticket, "", sku);
+
+ }
+
+ @Override
+ protected void error(String message) {
+ godotPaymentV3.callbackFail();
+
+ }
+ }.consume(sku);
+ }
+
private GodotPaymentV3 godotPaymentV3;
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
this.godotPaymentV3 = godotPaymentV3;
-
}
}
diff --git a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
index 75662a442e..c1f9d164a1 100644
--- a/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
+++ b/platform/android/java/src/com/android/godot/payments/PurchaseTask.java
@@ -62,7 +62,11 @@ abstract public class PurchaseTask {
// Log.d("XXX", "Buy intent response code: " + responseCode);
if(responseCode == 1 || responseCode == 3 || responseCode == 4){
canceled();
- return ;
+ return;
+ }
+ if(responseCode == 7){
+ alreadyOwned();
+ return;
}
@@ -92,6 +96,6 @@ abstract public class PurchaseTask {
abstract protected void error(String message);
abstract protected void canceled();
-
+ abstract protected void alreadyOwned();
}
diff --git a/platform/bb10/os_bb10.cpp b/platform/bb10/os_bb10.cpp
index d89033b1df..c8e7ae561e 100644
--- a/platform/bb10/os_bb10.cpp
+++ b/platform/bb10/os_bb10.cpp
@@ -195,9 +195,10 @@ void OSBB10::finalize() {
// memdelete(debugger_connection_console);
//}
+ memdelete(sample_manager);
+
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
visual_server->finish();
memdelete(visual_server);
diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp
index 1edb23d504..ef483657ca 100644
--- a/platform/haiku/os_haiku.cpp
+++ b/platform/haiku/os_haiku.cpp
@@ -137,9 +137,10 @@ void OS_Haiku::finalize() {
spatial_sound_2d_server->finish();
memdelete(spatial_sound_2d_server);
+ memdelete(sample_manager);
+
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
visual_server->finish();
memdelete(visual_server);
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index 75e0878bac..8b831140d6 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -107,9 +107,10 @@ void OS_Server::finalize() {
// memdelete(debugger_connection_console);
//}
+ memdelete(sample_manager);
+
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
visual_server->finish();
memdelete(visual_server);
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 55452052e4..baf85937c6 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1375,9 +1375,10 @@ void OS_Windows::finalize() {
// memdelete(debugger_connection_console);
//}
+ memdelete(sample_manager);
+
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
physics_server->finish();
memdelete(physics_server);
@@ -1768,15 +1769,26 @@ void OS_Windows::print_error(const char* p_function,const char* p_file,int p_lin
HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
if (!hCon || hCon==INVALID_HANDLE_VALUE) {
- if (p_rationale && p_rationale[0]) {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
-
- } else {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+ const char* err_details;
+ if (p_rationale && p_rationale[0])
+ err_details=p_rationale;
+ else
+ err_details=p_code;
+ switch(p_type) {
+ case ERR_ERROR:
+ print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;31m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_WARNING:
+ print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;33m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_SCRIPT:
+ print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m",p_function,err_details);
+ print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
}
} else {
diff --git a/platform/winrt/os_winrt.cpp b/platform/winrt/os_winrt.cpp
index 3e06d9d59b..80ed436b85 100644
--- a/platform/winrt/os_winrt.cpp
+++ b/platform/winrt/os_winrt.cpp
@@ -326,10 +326,11 @@ void OSWinrt::finalize() {
//if (debugger_connection_console) {
// memdelete(debugger_connection_console);
//}
+
+ memdelete(sample_manager);
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
memdelete(input);
@@ -424,15 +425,25 @@ void OSWinrt::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) con
void OSWinrt::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
- if (p_rationale && p_rationale[0]) {
-
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
-
- } else {
- print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
- print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
+ const char* err_details;
+ if (p_rationale && p_rationale[0])
+ err_details=p_rationale;
+ else
+ err_details=p_code;
+ switch(p_type) {
+ case ERR_ERROR:
+ print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;31m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_WARNING:
+ print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n",p_function,err_details);
+ print("\E[0;33m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
+ case ERR_SCRIPT:
+ print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m",p_function,err_details);
+ print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line);
+ break;
}
}
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 34bd1184a1..3218230d0b 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -452,9 +452,10 @@ void OS_X11::finalize() {
// memdelete(debugger_connection_console);
//}
+ memdelete(sample_manager);
+
audio_server->finish();
memdelete(audio_server);
- memdelete(sample_manager);
visual_server->finish();
memdelete(visual_server);
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 49683da226..52ae5d2954 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -57,7 +57,9 @@ void Camera2D::_update_scroll() {
void Camera2D::set_zoom(const Vector2 &p_zoom) {
zoom = p_zoom;
+ Point2 old_smoothed_camera_pos = smoothed_camera_pos;
_update_scroll();
+ smoothed_camera_pos = old_smoothed_camera_pos;
};
Vector2 Camera2D::get_zoom() const {
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 418ee192b2..167b637bdc 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1031,13 +1031,12 @@ Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
switch(half_offset) {
case HALF_OFFSET_X: {
- if (int(ret.y)&1) {
-
+ if ( ret.y > 0 ? int(ret.y)&1 : (int(ret.y)-1)&1 ) {
ret.x-=0.5;
}
} break;
case HALF_OFFSET_Y: {
- if (int(ret.x)&1) {
+ if ( ret.x > 0 ? int(ret.x)&1 : (int(ret.x)-1)&1) {
ret.y-=0.5;
}
} break;
diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp
index 4712ba308a..cb81228dff 100644
--- a/scene/3d/skeleton.cpp
+++ b/scene/3d/skeleton.cpp
@@ -250,7 +250,7 @@ void Skeleton::_notification(int p_what) {
ERR_CONTINUE(!obj);
Spatial *sp = obj->cast_to<Spatial>();
ERR_CONTINUE(!sp);
- sp->set_transform(b.pose_global * b.rest_global_inverse);
+ sp->set_transform(b.pose_global);
}
}
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 14f2110915..c7e259c3c6 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -29,6 +29,42 @@
#include "animation_tree_player.h"
#include "animation_player.h"
+#include "scene/scene_string_names.h"
+
+
+void AnimationTreePlayer::set_animation_process_mode(AnimationProcessMode p_mode) {
+
+ if (animation_process_mode == p_mode)
+ return;
+
+ bool pr = processing;
+ if (pr)
+ _set_process(false);
+ animation_process_mode = p_mode;
+ if (pr)
+ _set_process(true);
+
+}
+
+AnimationTreePlayer::AnimationProcessMode AnimationTreePlayer::get_animation_process_mode() const{
+
+ return animation_process_mode;
+}
+
+void AnimationTreePlayer::_set_process(bool p_process, bool p_force)
+{
+ if (processing == p_process && !p_force)
+ return;
+
+ switch (animation_process_mode) {
+
+ case ANIMATION_PROCESS_FIXED: set_fixed_process(p_process && active); break;
+ case ANIMATION_PROCESS_IDLE: set_process(p_process && active); break;
+ }
+
+ processing = p_process;
+}
+
bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) {
@@ -42,6 +78,11 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value)
return true;
}
+ if(String(p_name) == SceneStringNames::get_singleton()->playback_active) {
+ set_active(p_value);
+ return true;
+ }
+
if (String(p_name)!="data")
return false;
@@ -190,6 +231,11 @@ bool AnimationTreePlayer::_get(const StringName& p_name,Variant &r_ret) const {
return true;
}
+ if (String(p_name) == "playback/active") {
+ r_ret=is_active();
+ return true;
+ }
+
if (String(p_name)!="data")
return false;
@@ -342,11 +388,24 @@ void AnimationTreePlayer::_get_property_list( List<PropertyInfo> *p_list) const
p_list->push_back( PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_NETWORK) );
}
+void AnimationTreePlayer::advance(float p_time) {
+
+ _process_animation(p_time);
+}
void AnimationTreePlayer::_notification(int p_what) {
switch(p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+
+ if (!processing) {
+ //make sure that a previous process state was not saved
+ //only process if "processing" is set
+ set_fixed_process(false);
+ set_process(false);
+ }
+ } break;
case NOTIFICATION_READY: {
dirty_caches=true;
if (master!=NodePath()) {
@@ -354,7 +413,19 @@ void AnimationTreePlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_PROCESS: {
- _process_animation();
+ if (animation_process_mode==ANIMATION_PROCESS_FIXED)
+ break;
+
+ if (processing)
+ _process_animation( get_process_delta_time() );
+ } break;
+ case NOTIFICATION_FIXED_PROCESS: {
+
+ if (animation_process_mode==ANIMATION_PROCESS_IDLE)
+ break;
+
+ if (processing)
+ _process_animation(get_fixed_process_delta_time());
} break;
}
@@ -656,10 +727,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
}
-void AnimationTreePlayer::_process_animation() {
-
- if (!active)
- return;
+void AnimationTreePlayer::_process_animation(float p_delta) {
if (last_error!=CONNECT_OK)
return;
@@ -675,7 +743,7 @@ void AnimationTreePlayer::_process_animation() {
_process_node(out_name,&prev, 1.0, 0, true );
reset_request=false;
} else
- _process_node(out_name,&prev, 1.0, get_process_delta_time(), false );
+ _process_node(out_name,&prev, 1.0, p_delta, false );
if (dirty_caches) {
//some animation changed.. ignore this pass
@@ -1520,8 +1588,12 @@ void AnimationTreePlayer::recompute_caches() {
void AnimationTreePlayer::set_active(bool p_active) {
- active=p_active;
- set_process(active);
+ if (active == p_active)
+ return;
+
+ active = p_active;
+ processing = active;
+ _set_process(processing, true);
}
bool AnimationTreePlayer::is_active() const {
@@ -1743,13 +1815,18 @@ void AnimationTreePlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_node_list"),&AnimationTreePlayer::_get_node_list);
+ ObjectTypeDB::bind_method(_MD("set_animation_process_mode","mode"),&AnimationTreePlayer::set_animation_process_mode);
+ ObjectTypeDB::bind_method(_MD("get_animation_process_mode"),&AnimationTreePlayer::get_animation_process_mode);
+ ObjectTypeDB::bind_method(_MD("advance", "delta"), &AnimationTreePlayer::advance);
ObjectTypeDB::bind_method(_MD("reset"),&AnimationTreePlayer::reset);
ObjectTypeDB::bind_method(_MD("recompute_caches"),&AnimationTreePlayer::recompute_caches);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
+
BIND_CONSTANT( NODE_OUTPUT );
BIND_CONSTANT( NODE_ANIMATION );
BIND_CONSTANT( NODE_ONESHOT );
@@ -1770,6 +1847,9 @@ AnimationTreePlayer::AnimationTreePlayer() {
out_name="out";
out->pos=Point2(40,40);
node_map.insert( out_name , out);
+ AnimationProcessMode animation_process_mode;
+ animation_process_mode = ANIMATION_PROCESS_IDLE;
+ processing = false;
active=false;
dirty_caches=true;
reset_request=false;
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index 9e936304c6..9ea5ccf330 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -34,6 +34,7 @@
#include "scene/3d/spatial.h"
#include "scene/3d/skeleton.h"
#include "scene/main/misc.h"
+#include "animation_player.h"
class AnimationTreePlayer : public Node {
@@ -42,7 +43,10 @@ class AnimationTreePlayer : public Node {
OBJ_CATEGORY("Animation Nodes");
public:
-
+ enum AnimationProcessMode {
+ ANIMATION_PROCESS_FIXED,
+ ANIMATION_PROCESS_IDLE,
+ };
enum NodeType {
@@ -256,13 +260,15 @@ private:
ConnectError last_error;
AnimationNode *active_list;
+ AnimationProcessMode animation_process_mode;
+ bool processing;
bool active;
bool dirty_caches;
Map<StringName,NodeBase*> node_map;
// return time left to finish animation
float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0);
- void _process_animation();
+ void _process_animation(float p_delta);
bool reset_request;
ConnectError _cycle_test(const StringName &p_at_node);
@@ -409,12 +415,21 @@ public:
ConnectError get_last_error() const;
+ void set_animation_process_mode(AnimationProcessMode p_mode);
+ AnimationProcessMode get_animation_process_mode() const;
+
+ void _set_process(bool p_process, bool p_force = false);
+
+ void advance(float p_time);
+
AnimationTreePlayer();
~AnimationTreePlayer();
};
VARIANT_ENUM_CAST( AnimationTreePlayer::NodeType );
+VARIANT_ENUM_CAST( AnimationTreePlayer::AnimationProcessMode );
+
#endif // ANIMATION_TREE_PLAYER_H
diff --git a/scene/gui/button_group.cpp b/scene/gui/button_group.cpp
index 8d1fa80b84..c92d7f2696 100644
--- a/scene/gui/button_group.cpp
+++ b/scene/gui/button_group.cpp
@@ -155,6 +155,6 @@ void ButtonGroup::_bind_methods() {
}
-ButtonGroup::ButtonGroup()
+ButtonGroup::ButtonGroup() : BoxContainer(true)
{
}
diff --git a/scene/gui/button_group.h b/scene/gui/button_group.h
index 24edf94994..74e847e937 100644
--- a/scene/gui/button_group.h
+++ b/scene/gui/button_group.h
@@ -29,14 +29,14 @@
#ifndef BUTTON_GROUP_H
#define BUTTON_GROUP_H
-#include "scene/gui/control.h"
+#include "scene/gui/box_container.h"
class BaseButton;
-class ButtonGroup : public Control {
+class ButtonGroup : public BoxContainer {
- OBJ_TYPE(ButtonGroup,Control);
+ OBJ_TYPE(ButtonGroup,BoxContainer);
Set<BaseButton*> buttons;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 40fade840c..f035cb7722 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -235,6 +235,37 @@ int ItemList::get_current() const {
return current;
}
+void ItemList::move_item(int p_item,int p_to_pos) {
+
+ ERR_FAIL_INDEX(p_item,items.size());
+ ERR_FAIL_INDEX(p_to_pos,items.size()+1);
+
+ Item it=items[p_item];
+ items.remove(p_item);;
+
+ if (p_to_pos>p_item) {
+ p_to_pos--;
+ }
+
+ if (p_to_pos>=items.size()) {
+ items.push_back(it);
+ } else {
+ items.insert(p_to_pos,it);
+ }
+
+ if (current<0) {
+ //do none
+ } if (p_item==current) {
+ current=p_to_pos;
+ } else if (p_to_pos>p_item && current>p_item && current<p_to_pos) {
+ current--;
+ } else if (p_to_pos<p_item && current<p_item && current>p_to_pos) {
+ current++;
+ }
+
+
+ update();
+}
int ItemList::get_item_count() const{
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 7cf58a6426..bd3cf6484e 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -101,6 +101,7 @@ public:
void set_current(int p_current);
int get_current() const;
+ void move_item(int p_item,int p_to_pos);
int get_item_count() const;
void remove_item(int p_idx);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 2b4d7db01e..18de8ed568 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -145,6 +145,13 @@ void LineEdit::_input_event(InputEvent p_event) {
int old_cursor_pos = cursor_pos;
text = undo_text;
+
+ Ref<Font> font = get_font("font");
+
+ cached_width = 0;
+ for (int i = 0; i<text.length(); i++)
+ cached_width += font->get_char_size(text[i]).width;
+
if(old_cursor_pos > text.length()) {
set_cursor_pos(text.length());
} else {
@@ -164,6 +171,15 @@ void LineEdit::_input_event(InputEvent p_event) {
selection_clear();
undo_text = text;
text = text.substr(cursor_pos,text.length()-cursor_pos);
+
+ Ref<Font> font = get_font("font");
+
+ cached_width = 0;
+ if (font != NULL) {
+ for (int i = 0; i < text.length(); i++)
+ cached_width += font->get_char_size(text[i]).width;
+ }
+
set_cursor_pos(0);
emit_signal("text_changed",text);
_change_notify("text");
@@ -192,6 +208,9 @@ void LineEdit::_input_event(InputEvent p_event) {
}
} break;
+ case (KEY_A): { //Select All
+ select();
+ } break;
default: { handled=false;}
}
@@ -303,6 +322,18 @@ void LineEdit::_input_event(InputEvent p_event) {
}
}
+void LineEdit::set_align(Align p_align) {
+
+ ERR_FAIL_INDEX(p_align, 4);
+ align = p_align;
+ update();
+}
+
+LineEdit::Align LineEdit::get_align() const{
+
+ return align;
+}
+
Variant LineEdit::get_drag_data(const Point2& p_point) {
if (selection.drag_attempt && selection.enabled) {
@@ -325,7 +356,15 @@ void LineEdit::drop_data(const Point2& p_point,const Variant& p_data){
if (p_data.get_type()==Variant::STRING) {
set_cursor_at_pixel_pos(p_point.x);
int selected = selection.end - selection.begin;
+
+ Ref<Font> font = get_font("font");
+ if (font != NULL) {
+ for (int i = selection.begin; i < selection.end; i++)
+ cached_width -= font->get_char_size(text[i]).width;
+ }
+
text.erase(selection.begin, selected);
+
append_at_cursor(p_data);
selection.begin = cursor_pos-selected;
selection.end = cursor_pos;
@@ -365,8 +404,25 @@ void LineEdit::_notification(int p_what) {
get_stylebox("focus")->draw( ci, Rect2( Point2(), size ) );
}
-
- int ofs=style->get_offset().x;
+ int x_ofs=0;
+
+ switch (align) {
+
+ case ALIGN_FILL:
+ case ALIGN_LEFT: {
+
+ x_ofs=style->get_offset().x;
+ } break;
+ case ALIGN_CENTER: {
+
+ x_ofs=x_ofs=int(size.width-(cached_width))/2;
+ } break;
+ case ALIGN_RIGHT: {
+
+ x_ofs=x_ofs=int(size.width-style->get_offset().x-(cached_width));
+ } break;
+ }
+
int ofs_max=width-style->get_minimum_size().width;
int char_ofs=window_pos;
@@ -391,29 +447,29 @@ void LineEdit::_notification(int p_what) {
int char_width=font->get_char_size( cchar,next ).width;
// end of widget, break!
- if ( (ofs+char_width) > ofs_max )
+ if ((x_ofs + char_width) > ofs_max)
break;
bool selected=selection.enabled && char_ofs>=selection.begin && char_ofs<selection.end;
if (selected)
- VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2( Point2( ofs , y_ofs ),Size2( char_width, y_area )),selection_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, y_area)), selection_color);
- font->draw_char(ci,Point2( ofs , y_ofs+font_ascent ), cchar, next,selected?font_color_selected:font_color );
+ font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, selected ? font_color_selected : font_color);
if (char_ofs==cursor_pos && has_focus())
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
- Point2( ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
+ Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
- ofs+=char_width;
+ x_ofs+=char_width;
char_ofs++;
}
if (char_ofs==cursor_pos && has_focus()) //may be at the end
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(
- Point2( ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
+ Point2( x_ofs , y_ofs ), Size2( 1, y_area ) ), cursor_color );
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -484,13 +540,36 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
void LineEdit::set_cursor_at_pixel_pos(int p_x) {
- int ofs=window_pos;
- int pixel_ofs=get_stylebox("normal")->get_offset().x;
- Ref<Font> font=get_font("font");
+ Ref<Font> font = get_font("font");
+ int ofs = window_pos;
+ Ref<StyleBox> style = get_stylebox("normal");
+ int pixel_ofs = 0;
+ Size2 size = get_size();
+
+ switch (align) {
+
+ case ALIGN_FILL:
+ case ALIGN_LEFT: {
+
+ pixel_ofs = int(style->get_offset().x);
+ } break;
+ case ALIGN_CENTER: {
+
+ pixel_ofs=int(size.width-(cached_width))/2;
+ } break;
+ case ALIGN_RIGHT: {
+
+ pixel_ofs=int(size.width-style->get_offset().x-(cached_width));
+ } break;
+ }
+
while (ofs<text.length()) {
- int char_w=font->get_char_size( text[ofs] ).width;
+ int char_w = 0;
+ if (font != NULL) {
+ int char_w = font->get_char_size(text[ofs]).width;
+ }
pixel_ofs+=char_w;
if (pixel_ofs > p_x) { //found what we look for
@@ -523,6 +602,10 @@ void LineEdit::delete_char() {
if ((text.length()<=0) || (cursor_pos==0)) return;
+ Ref<Font> font = get_font("font");
+ if (font != NULL) {
+ cached_width -= font->get_char_size(text[cursor_pos - 1]).width;
+ }
text.erase( cursor_pos-1, 1 );
@@ -593,13 +676,15 @@ void LineEdit::set_cursor_pos(int p_pos) {
int width_to_cursor=0;
int wp=window_pos;
- for (int i=window_pos;i<cursor_pos;i++)
- width_to_cursor+=font->get_char_size( text[i] ).width;
+ if (font != NULL) {
+ for (int i=window_pos;i<cursor_pos;i++)
+ width_to_cursor+=font->get_char_size( text[i] ).width;
- while(width_to_cursor>=window_width && wp<text.length()) {
-
- width_to_cursor-=font->get_char_size( text[ wp ] ).width;
- wp++;
+ while (width_to_cursor >= window_width && wp < text.length()) {
+
+ width_to_cursor -= font->get_char_size(text[wp]).width;
+ wp++;
+ }
}
if (wp!=window_pos)
@@ -626,17 +711,26 @@ void LineEdit::append_at_cursor(String p_text) {
if ( ( max_length <= 0 ) || (text.length()+p_text.length() <= max_length)) {
undo_text = text;
+
+ Ref<Font> font = get_font("font");
+ if (font != NULL) {
+ for (int i = 0; i < p_text.length(); i++)
+ cached_width += font->get_char_size(p_text[i]).width;
+ }
+ else {
+ cached_width = 0;
+ }
+
String pre = text.substr( 0, cursor_pos );
String post = text.substr( cursor_pos, text.length()-cursor_pos );
text=pre+p_text+post;
set_cursor_pos(cursor_pos+p_text.length());
-
}
-
}
void LineEdit::clear_internal() {
+ cached_width = 0;
cursor_pos=0;
window_pos=0;
undo_text="";
@@ -676,6 +770,20 @@ void LineEdit::selection_delete() {
if (selection.enabled) {
undo_text = text;
+
+ if (text.size() > 0)
+ {
+ Ref<Font> font = get_font("font");
+ if (font != NULL) {
+ for (int i = selection.begin; i < selection.end; i++)
+ cached_width -= font->get_char_size(text[i]).width;
+ }
+ }
+ else
+ {
+ cached_width = 0;
+ }
+
text.erase(selection.begin,selection.end-selection.begin);
cursor_pos-=CLAMP( cursor_pos-selection.begin, 0, selection.end-selection.begin);
@@ -789,6 +897,8 @@ bool LineEdit::is_text_field() const {
void LineEdit::_bind_methods() {
+ ObjectTypeDB::bind_method(_MD("set_align", "align"), &LineEdit::set_align);
+ ObjectTypeDB::bind_method(_MD("get_align"), &LineEdit::get_align);
ObjectTypeDB::bind_method(_MD("_input_event"),&LineEdit::_input_event);
ObjectTypeDB::bind_method(_MD("clear"),&LineEdit::clear);
@@ -809,15 +919,22 @@ void LineEdit::_bind_methods() {
ADD_SIGNAL( MethodInfo("text_changed", PropertyInfo( Variant::STRING, "text" )) );
ADD_SIGNAL( MethodInfo("text_entered", PropertyInfo( Variant::STRING, "text" )) );
+ BIND_CONSTANT(ALIGN_LEFT);
+ BIND_CONSTANT(ALIGN_CENTER);
+ BIND_CONSTANT(ALIGN_RIGHT);
+ BIND_CONSTANT(ALIGN_FILL);
+
ADD_PROPERTY( PropertyInfo( Variant::STRING, "text" ), _SCS("set_text"),_SCS("get_text") );
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), _SCS("set_align"), _SCS("get_align"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") );
-
}
LineEdit::LineEdit() {
+ align = ALIGN_LEFT;
+ cached_width = 0;
cursor_pos=0;
window_pos=0;
max_length = 0;
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index b1c4c8f616..f28136d66e 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -36,7 +36,18 @@
class LineEdit : public Control {
OBJ_TYPE( LineEdit, Control );
-
+
+public:
+ enum Align {
+
+ ALIGN_LEFT,
+ ALIGN_CENTER,
+ ALIGN_RIGHT,
+ ALIGN_FILL
+ };
+private:
+ Align align;
+
bool editable;
bool pass;
@@ -46,6 +57,8 @@ class LineEdit : public Control {
int cursor_pos;
int window_pos;
int max_length; // 0 for no maximum
+
+ int cached_width;
struct Selection {
@@ -83,7 +96,8 @@ class LineEdit : public Control {
protected:
static void _bind_methods();
public:
-
+ void set_align(Align p_align);
+ Align get_align() const;
virtual Variant get_drag_data(const Point2& p_point);
virtual bool can_drop_data(const Point2& p_point,const Variant& p_data) const;
@@ -119,4 +133,7 @@ public:
};
+
+VARIANT_ENUM_CAST(LineEdit::Align);
+
#endif
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 13ff7074ea..be7a6b468a 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -54,6 +54,8 @@ void MenuButton::_unhandled_key_input(InputEvent p_event) {
int item = popup->find_item_by_accelerator(code);
+
+
if (item>=0 && ! popup->is_item_disabled(item))
popup->activate_item(item);
/*
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 6c21ea639f..99663fb2e2 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -323,11 +323,14 @@ void PopupMenu::_input_event(const InputEvent &p_event) {
invalidated_click=false;
break;
}
- if (over<0 || items[over].separator || items[over].disabled) {
+ if (over<0) {
hide();
break; //non-activable
}
+ if (items[over].separator || items[over].disabled)
+ break;
+
if (items[over].submenu!="") {
_activate_submenu(over);
@@ -362,8 +365,11 @@ void PopupMenu::_input_event(const InputEvent &p_event) {
int over=_get_mouse_over(Point2(m.x,m.y));
int id = (over<0 || items[over].separator || items[over].disabled)?-1:items[over].ID;
- if (id<0)
+ if (id<0) {
+ mouse_over=-1;
+ update();
break;
+ }
if (items[over].submenu!="" && submenu_over!=over) {
submenu_over=over;
@@ -774,6 +780,7 @@ void PopupMenu::add_separator() {
void PopupMenu::clear() {
items.clear();
+ mouse_over=-1;
update();
idcount=0;
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index ad708d16f0..7103ee651f 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -243,7 +243,7 @@ void Range::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/step" ), _SCS("set_step"), _SCS("get_step") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/page" ), _SCS("set_page"), _SCS("get_page") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/value" ), _SCS("set_val"), _SCS("get_val") );
- ADD_PROPERTY( PropertyInfo( Variant::REAL, "range/exp_edit" ), _SCS("set_exp_unit_value"), _SCS("is_unit_value_exp") );
+ ADD_PROPERTY( PropertyInfo( Variant::BOOL, "range/exp_edit" ), _SCS("set_exp_unit_value"), _SCS("is_unit_value_exp") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "rounded_values" ), _SCS("set_rounded_values"), _SCS("get_rounded_values") );
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index ef6a2ba6aa..b98fec1bde 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -719,7 +719,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
case InputEvent::KEY: {
const InputEventKey &k=p_event.key;
- if (k.pressed) {
+ if (k.pressed && !k.mod.alt && !k.mod.shift && !k.mod.command && !k.mod.meta) {
bool handled=true;
switch(k.scancode) {
case KEY_PAGEUP: {
@@ -765,6 +765,7 @@ void RichTextLabel::_input_event(InputEvent p_event) {
default: handled=false;
}
+
if (handled)
accept_event();
}
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 6d84f028b3..47a55e0716 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -58,7 +58,7 @@ Size2 Tabs::get_minimum_size() const {
if (tabs[i].right_button.is_valid()) {
Ref<Texture> rb=tabs[i].right_button;
- Size2 bms = rb->get_size()+get_stylebox("button")->get_minimum_size();
+ Size2 bms = rb->get_size();//+get_stylebox("button")->get_minimum_size();
bms.width+=get_constant("hseparation");
ms.width+=bms.width;
@@ -67,9 +67,8 @@ Size2 Tabs::get_minimum_size() const {
if (tabs[i].close_button.is_valid()) {
Ref<Texture> cb=tabs[i].close_button;
- Size2 bms = cb->get_size()+get_stylebox("button")->get_minimum_size();
+ Size2 bms = cb->get_size();//+get_stylebox("button")->get_minimum_size();
bms.width+=get_constant("hseparation");
-
ms.width+=bms.width;
ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height);
}
@@ -103,11 +102,13 @@ void Tabs::_input_event(const InputEvent& p_event) {
// test hovering right button and close button
if (tabs[i].rb_rect.has_point(pos)) {
rb_hover=i;
+ cb_hover=-1;
hover_buttons = i;
break;
}
else if (tabs[i].cb_rect.has_point(pos)) {
cb_hover=i;
+ rb_hover=-1;
hover_buttons = i;
break;
}
@@ -262,9 +263,9 @@ void Tabs::_notification(int p_what) {
Ref<Texture> rb=tabs[i].right_button;
lsize+=get_constant("hseparation");
- lsize+=style->get_margin(MARGIN_LEFT);
+ //lsize+=style->get_margin(MARGIN_LEFT);
lsize+=rb->get_width();
- lsize+=style->get_margin(MARGIN_RIGHT);
+ //lsize+=style->get_margin(MARGIN_RIGHT);
}
@@ -276,9 +277,9 @@ void Tabs::_notification(int p_what) {
Ref<Texture> rb=tabs[i].close_button;
lsize+=get_constant("hseparation");
- lsize+=style->get_margin(MARGIN_LEFT);
+ //lsize+=style->get_margin(MARGIN_LEFT);
lsize+=rb->get_width();
- lsize+=style->get_margin(MARGIN_RIGHT);
+ //lsize+=style->get_margin(MARGIN_RIGHT);
}
} break;
@@ -289,9 +290,9 @@ void Tabs::_notification(int p_what) {
Ref<Texture> rb=tabs[i].close_button;
lsize+=get_constant("hseparation");
- lsize+=style->get_margin(MARGIN_LEFT);
+ //lsize+=style->get_margin(MARGIN_LEFT);
lsize+=rb->get_width();
- lsize+=style->get_margin(MARGIN_RIGHT);
+ //lsize+=style->get_margin(MARGIN_RIGHT);
}
}
@@ -303,9 +304,9 @@ void Tabs::_notification(int p_what) {
Ref<Texture> rb=tabs[i].close_button;
lsize+=get_constant("hseparation");
- lsize+=style->get_margin(MARGIN_LEFT);
+ //lsize+=style->get_margin(MARGIN_LEFT);
lsize+=rb->get_width();
- lsize+=style->get_margin(MARGIN_RIGHT);
+ //lsize+=style->get_margin(MARGIN_RIGHT);
}
}
@@ -404,11 +405,11 @@ void Tabs::_notification(int p_what) {
style->draw(ci,cb_rect);
}
- w+=style->get_margin(MARGIN_LEFT);
+ //w+=style->get_margin(MARGIN_LEFT);
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
w+=cb->get_width();
- w+=style->get_margin(MARGIN_RIGHT);
+ //w+=style->get_margin(MARGIN_RIGHT);
tabs[i].cb_rect=cb_rect;
}
} break;
@@ -432,11 +433,11 @@ void Tabs::_notification(int p_what) {
style->draw(ci,cb_rect);
}
- w+=style->get_margin(MARGIN_LEFT);
+ //w+=style->get_margin(MARGIN_LEFT);
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
w+=cb->get_width();
- w+=style->get_margin(MARGIN_RIGHT);
+ //w+=style->get_margin(MARGIN_RIGHT);
tabs[i].cb_rect=cb_rect;
}
}
@@ -461,11 +462,11 @@ void Tabs::_notification(int p_what) {
style->draw(ci,cb_rect);
}
- w+=style->get_margin(MARGIN_LEFT);
+ //w+=style->get_margin(MARGIN_LEFT);
cb->draw(ci,Point2i( w,cb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
w+=cb->get_width();
- w+=style->get_margin(MARGIN_RIGHT);
+ //w+=style->get_margin(MARGIN_RIGHT);
tabs[i].cb_rect=cb_rect;
}
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index be6c0d0a8b..d081e84df4 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1647,8 +1647,60 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
case KEY_BACKSPACE: {
if (readonly)
break;
- backspace_at_cursor();
-
+
+#ifdef APPLE_STYLE_KEYS
+ if (k.mod.alt) {
+#else
+ if (k.mod.alt) {
+ scancode_handled=false;
+ break;
+ } else if (k.mod.command) {
+#endif
+ int line=cursor.line;
+ int column=cursor.column;
+
+ bool prev_char=false;
+ bool only_whitespace=true;
+
+ while (only_whitespace && line > 0) {
+
+ while (column>0) {
+ CharType c=text[line][column-1];
+
+ if (c != '\t' && c != ' ') {
+ only_whitespace=false;
+ break;
+ }
+
+ column--;
+ }
+
+ if (only_whitespace) {
+ line--;
+ column=text[line].length();
+ }
+ }
+
+ while (column>0) {
+ bool ischar=_is_text_char(text[line][column-1]);
+
+ if (prev_char && !ischar)
+ break;
+
+ prev_char=ischar;
+ column--;
+
+ }
+
+ _remove_text(line, column, cursor.line, cursor.column);
+
+ cursor_set_line(line);
+ cursor_set_column(column);
+
+ } else {
+ backspace_at_cursor();
+ }
+
} break;
case KEY_LEFT: {
@@ -1789,10 +1841,63 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (cursor.line==text.size()-1 && cursor.column==curline_len)
break; //nothing to do
- int next_line = cursor.column<curline_len?cursor.line:cursor.line+1;
- int next_column = cursor.column<curline_len?(cursor.column+1):0;
+ int next_line=cursor.column<curline_len?cursor.line:cursor.line+1;
+ int next_column;
+
+#ifdef APPLE_STYLE_KEYS
+ if (k.mod.alt) {
+#else
+ if (k.mod.alt) {
+ scancode_handled=false;
+ break;
+ } else if (k.mod.command) {
+#endif
+ int last_line=text.size()-1;
+
+ int line=cursor.line;
+ int column=cursor.column;
+
+ bool prev_char=false;
+ bool only_whitespace=true;
+
+ while (only_whitespace && line < last_line) {
+
+ while (column<text[line].length()) {
+ CharType c=text[line][column];
+
+ if (c != '\t' && c != ' ') {
+ only_whitespace=false;
+ break;
+ }
+
+ column++;
+ }
+
+ if (only_whitespace) {
+ line++;
+ column=0;
+ }
+ }
+
+ while (column<text[line].length()) {
+
+ bool ischar=_is_text_char(text[line][column]);
+
+ if (prev_char && !ischar)
+ break;
+ prev_char=ischar;
+ column++;
+ }
+
+ next_line=line;
+ next_column=column;
+ } else {
+ next_column=cursor.column<curline_len?(cursor.column+1):0;
+ }
+
_remove_text(cursor.line,cursor.column,next_line,next_column);
update();
+
} break;
#ifdef APPLE_STYLE_KEYS
case KEY_HOME: {
diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp
index 0d549108fa..c8930add6e 100644
--- a/scene/gui/texture_progress.cpp
+++ b/scene/gui/texture_progress.cpp
@@ -233,11 +233,7 @@ float TextureProgress::get_radial_initial_angle()
void TextureProgress::set_fill_degrees(float p_angle)
{
- while(p_angle>360)
- p_angle-=360;
- while (p_angle<0)
- p_angle+=360;
- rad_max_degrees=p_angle;
+ rad_max_degrees=CLAMP(p_angle,0,360);
update();
}
@@ -302,4 +298,5 @@ TextureProgress::TextureProgress()
{
mode=FILL_LEFT_TO_RIGHT;
rad_center_off=Point2();
+ rad_max_degrees=360;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index a27918cf52..16a12fe407 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2271,9 +2271,12 @@ bool Tree::edit_selected() {
TreeItem::Cell &c = s->cells[col];
+ if (c.mode==TreeItem::CELL_MODE_CHECK) {
-
- if (c.mode==TreeItem::CELL_MODE_CUSTOM) {
+ s->set_checked(col, !c.checked);
+ item_edited(col,s);
+ return true;
+ } else if (c.mode==TreeItem::CELL_MODE_CUSTOM) {
edited_item=s;
edited_col=col;
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index b4cd437d35..9b9c797ed9 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -384,12 +384,12 @@ void VideoPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_buffering_msec","msec"),&VideoPlayer::set_buffering_msec);
ObjectTypeDB::bind_method(_MD("get_buffering_msec"),&VideoPlayer::get_buffering_msec);
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") );
ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "stream/stream", PROPERTY_HINT_RESOURCE_TYPE,"VideoStream"), _SCS("set_stream"), _SCS("get_stream") );
// ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/loop"), _SCS("set_loop"), _SCS("has_loop") );
ADD_PROPERTY( PropertyInfo(Variant::REAL, "stream/volume_db", PROPERTY_HINT_RANGE,"-80,24,0.01"), _SCS("set_volume_db"), _SCS("get_volume_db") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/autoplay"), _SCS("set_autoplay"), _SCS("has_autoplay") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL, "stream/paused"), _SCS("set_paused"), _SCS("is_paused") );
- ADD_PROPERTY( PropertyInfo(Variant::INT, "stream/audio_track",PROPERTY_HINT_RANGE,"0,128,1"), _SCS("set_audio_track"), _SCS("get_audio_track") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") );
}
diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp
index 923e2817ef..01b7531f14 100644
--- a/scene/resources/concave_polygon_shape_2d.cpp
+++ b/scene/resources/concave_polygon_shape_2d.cpp
@@ -34,6 +34,7 @@
void ConcavePolygonShape2D::set_segments(const DVector<Vector2>& p_segments) {
Physics2DServer::get_singleton()->shape_set_data(get_rid(),p_segments);
+ emit_changed();
}
DVector<Vector2> ConcavePolygonShape2D::get_segments() const {
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index dac39fc846..a1137ba614 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -33,6 +33,7 @@
void ConvexPolygonShape2D::_update_shape() {
Physics2DServer::get_singleton()->shape_set_data(get_rid(),points);
+ emit_changed();
}
@@ -62,7 +63,7 @@ void ConvexPolygonShape2D::_bind_methods() {
- ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"points"),_SCS("set_points"),_SCS("get_points") );
+ ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"points"),_SCS("set_points"),_SCS("get_points") );
}
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 0f4c2ecd23..a82fc2a5e7 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -188,6 +188,7 @@ void make_default_theme() {
// Font Colors
Color control_font_color = Color::html("e0e0e0");
+ Color control_font_color_lower = Color::html("a0a0a0");
Color control_font_color_low = Color::html("b0b0b0");
Color control_font_color_hover = Color::html("f0f0f0");
Color control_font_color_disabled = Color(0.9,0.9,0.9,0.2);
@@ -212,8 +213,8 @@ void make_default_theme() {
// Button
- Ref<StyleBox> sb_button_normal = sb_expand( make_stylebox( button_normal_png,4,4,4,4,6,2,6,2),2,2,2,2);
- Ref<StyleBox> sb_button_pressed = sb_expand( make_stylebox( button_pressed_png,4,4,4,4,6,2,6,2),2,2,2,2);
+ Ref<StyleBox> sb_button_normal = sb_expand( make_stylebox( button_normal_png,4,4,4,4,6,3,6,3),2,2,2,2);
+ Ref<StyleBox> sb_button_pressed = sb_expand( make_stylebox( button_pressed_png,4,4,4,4,6,3,6,3),2,2,2,2);
Ref<StyleBox> sb_button_hover = sb_expand( make_stylebox( button_hover_png,4,4,4,4,6,2,6,2),2,2,2,2);
Ref<StyleBox> sb_button_disabled = sb_expand( make_stylebox( button_disabled_png,4,4,4,4,6,2,6,2),2,2,2,2);
Ref<StyleBox> sb_button_focus = sb_expand( make_stylebox( button_focus_png,4,4,4,4,6,2,6,2),2,2,2,2);
@@ -273,14 +274,14 @@ void make_default_theme() {
t->set_color("font_color_hover","ToolButton", control_font_color_hover );
t->set_color("font_color_disabled","ToolButton", Color(0.9,0.95,1,0.3) );
- t->set_constant("hseparation","ToolButton", 0 );
+ t->set_constant("hseparation","ToolButton", 3 );
// OptionButton
- Ref<StyleBox> sb_optbutton_normal = sb_expand( make_stylebox( option_button_normal_png,4,4,21,4,6,2,21,2),2,2,2,2);
- Ref<StyleBox> sb_optbutton_pressed = sb_expand( make_stylebox( option_button_pressed_png,4,4,21,4,6,2,21,2),2,2,2,2);
+ Ref<StyleBox> sb_optbutton_normal = sb_expand( make_stylebox( option_button_normal_png,4,4,21,4,6,3,21,3),2,2,2,2);
+ Ref<StyleBox> sb_optbutton_pressed = sb_expand( make_stylebox( option_button_pressed_png,4,4,21,4,6,3,21,3),2,2,2,2);
Ref<StyleBox> sb_optbutton_hover = sb_expand( make_stylebox( option_button_hover_png,4,4,21,4,6,2,21,2),2,2,2,2);
Ref<StyleBox> sb_optbutton_disabled = sb_expand( make_stylebox( option_button_disabled_png,4,4,21,4,6,2,21,2),2,2,2,2);
Ref<StyleBox> sb_optbutton_focus = sb_expand( make_stylebox( button_focus_png,4,4,4,4,6,2,6,2),2,2,2,2);
@@ -321,6 +322,10 @@ void make_default_theme() {
t->set_constant("hseparation","MenuButton", 3 );
+ // ButtonGroup
+
+ t->set_stylebox("panel","ButtonGroup", memnew( StyleBoxEmpty ));
+
// CheckBox
Ref<StyleBox> cbx_empty = memnew( StyleBoxEmpty );
@@ -649,7 +654,7 @@ void make_default_theme() {
t->set_constant("icon_margin","ItemList",4);
t->set_constant("line_separation","ItemList",2);
t->set_font("font","ItemList", default_font );
- t->set_color("font_color","ItemList", control_font_color_low );
+ t->set_color("font_color","ItemList", control_font_color_lower );
t->set_color("font_color_selected","ItemList", control_font_color_pressed );
t->set_color("guide_color","ItemList", Color(0,0,0,0.1) );
t->set_stylebox("selected","ItemList", item_selected_oof );
@@ -697,8 +702,8 @@ void make_default_theme() {
// Tabs
- t->set_stylebox("tab_fg","Tabs", sb_expand( make_stylebox( tab_current_png,4,4,4,1,16,4,16,4),2,2,2,2) );
- t->set_stylebox("tab_bg","Tabs", sb_expand( make_stylebox( tab_behind_png,5,5,5,1,16,6,16,4),3,3,3,3) );
+ t->set_stylebox("tab_fg","Tabs", sb_expand( make_stylebox( tab_current_png,4,3,4,1,16,3,16,2),2,2,2,2) );
+ t->set_stylebox("tab_bg","Tabs", sb_expand( make_stylebox( tab_behind_png,5,4,5,1,16,5,16,2),3,3,3,3) );
t->set_stylebox("panel","Tabs",tc_sb );
t->set_stylebox("button_pressed","Tabs", make_stylebox( button_pressed_png,4,4,4,4) );
t->set_stylebox("button","Tabs", make_stylebox( button_normal_png,4,4,4,4) );
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index bbb2a386f3..55bb4e9073 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -406,7 +406,6 @@ void FixedMaterial::_bind_methods() {
BIND_CONSTANT( PARAM_SHADE_PARAM );
BIND_CONSTANT( PARAM_MAX );
-
BIND_CONSTANT( TEXCOORD_SPHERE );
BIND_CONSTANT( TEXCOORD_UV );
BIND_CONSTANT( TEXCOORD_UV_TRANSFORM );
@@ -417,6 +416,11 @@ void FixedMaterial::_bind_methods() {
BIND_CONSTANT( FLAG_USE_POINT_SIZE );
BIND_CONSTANT( FLAG_DISCARD_ALPHA );
+ BIND_CONSTANT( LIGHT_SHADER_LAMBERT );
+ BIND_CONSTANT( LIGHT_SHADER_WRAP );
+ BIND_CONSTANT( LIGHT_SHADER_VELVET );
+ BIND_CONSTANT( LIGHT_SHADER_TOON );
+
}
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 49a1bdccb1..d5204f45d5 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -2083,7 +2083,7 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
#define DEF_MATRIX(slot) \
if (p_inputs[slot].ends_with("def")){\
Transform xf = p_node->defaults[slot]; \
- code+=String(typestr[3])+" "+p_inputs[slot]+"=mat4(\n";\
+ code+=String(typestr[2])+" "+p_inputs[slot]+"=mat4(\n";\
code+="\tvec4(vec3("+rtos(xf.basis.get_axis(0).x)+","+rtos(xf.basis.get_axis(0).y)+","+rtos(xf.basis.get_axis(0).z)+"),0),\n";\
code+="\tvec4(vec3("+rtos(xf.basis.get_axis(1).x)+","+rtos(xf.basis.get_axis(1).y)+","+rtos(xf.basis.get_axis(1).z)+"),0),\n";\
code+="\tvec4(vec3("+rtos(xf.basis.get_axis(2).x)+","+rtos(xf.basis.get_axis(2).y)+","+rtos(xf.basis.get_axis(2).z)+"),0),\n";\
@@ -2393,15 +2393,29 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str
DEF_VEC(1);
DEF_VEC(2);
DEF_VEC(3);
- code += OUTNAME(p_node->id,0)+"=xform("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+","+","+p_inputs[3]+");\n";
+ code += OUTNAME(p_node->id, 0) + "=mat4(" +
+ "vec4(" + p_inputs[0] + ".x," + p_inputs[0] + ".y," + p_inputs[0] + ".z, 0.0),"
+ "vec4(" + p_inputs[1] + ".x," + p_inputs[1] + ".y," + p_inputs[1] + ".z, 0.0),"
+ "vec4(" + p_inputs[2] + ".x," + p_inputs[2] + ".y," + p_inputs[2] + ".z, 0.0),"
+ "vec4(" + p_inputs[3] + ".x," + p_inputs[3] + ".y," + p_inputs[3] + ".z, 1.0));\n";
}break;
case NODE_XFORM_TO_VEC: {
DEF_MATRIX(0);
- code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+".x;\n";
- code += OUTNAME(p_node->id,1)+"="+p_inputs[0]+".y;\n";
- code += OUTNAME(p_node->id,2)+"="+p_inputs[0]+".z;\n";
- code += OUTNAME(p_node->id,3)+"="+p_inputs[0]+".o;\n";
+ code += OUTNAME(p_node->id, 0) + ";\n";
+ code += OUTNAME(p_node->id, 1) + ";\n";
+ code += OUTNAME(p_node->id, 2) + ";\n";
+ code += OUTNAME(p_node->id, 3) + ";\n";
+ code += "{\n";
+ code += "\tvec4 xform_row_01=" + p_inputs[0] + ".x;\n";
+ code += "\tvec4 xform_row_02=" + p_inputs[0] + ".y;\n";
+ code += "\tvec4 xform_row_03=" + p_inputs[0] + ".z;\n";
+ code += "\tvec4 xform_row_04=" + p_inputs[0] + ".w;\n";
+ code += "\t" + OUTVAR(p_node->id, 0) + "=vec3(xform_row_01.x, xform_row_01.y, xform_row_01.z);\n";
+ code += "\t" + OUTVAR(p_node->id, 1) + "=vec3(xform_row_02.x, xform_row_02.y, xform_row_02.z);\n";
+ code += "\t" + OUTVAR(p_node->id, 2) + "=vec3(xform_row_03.x, xform_row_03.y, xform_row_03.z);\n";
+ code += "\t" + OUTVAR(p_node->id, 3) + "=vec3(xform_row_04.x, xform_row_04.y, xform_row_04.z);\n";
+ code += "}\n";
}break;
case NODE_SCALAR_INTERP: {
DEF_SCALAR(0);
diff --git a/scene/resources/shape_line_2d.cpp b/scene/resources/shape_line_2d.cpp
index c660b604f3..97e9985754 100644
--- a/scene/resources/shape_line_2d.cpp
+++ b/scene/resources/shape_line_2d.cpp
@@ -35,6 +35,7 @@ void LineShape2D::_update_shape() {
arr.push_back(normal);
arr.push_back(d);
Physics2DServer::get_singleton()->shape_set_data(get_rid(),arr);
+ emit_changed();
}
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index d8d9c5b675..3b1f1d2346 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -374,7 +374,7 @@ World2D::World2D() {
Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98));
Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1)));
Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_LINEAR_DAMP,GLOBAL_DEF("physics_2d/default_density",0.1));
- Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics_2d/default_density",1));
+ Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics_2d/default_angular_damp",1));
Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS,1.0);
Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION,1.5);
Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,0.3);
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index e22b3c3a6c..aca301e0a8 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -693,7 +693,7 @@ public:
Rect2 rect;
RID texture;
float margin[4];
- float draw_center;
+ bool draw_center;
Color color;
CommandStyle() { draw_center=true; type = TYPE_STYLE; }
};
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
index f582fbd8ee..2c503249fe 100644
--- a/servers/visual/rasterizer_dummy.h
+++ b/servers/visual/rasterizer_dummy.h
@@ -162,10 +162,6 @@ class RasterizerDummy : public Rasterizer {
uint32_t format;
uint32_t morph_format;
- RID material;
- bool material_owned;
-
-
Surface() {
packed=false;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index ea56306241..6532c3f0ac 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -1043,6 +1043,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={
{ "SRC_TANGENT", TYPE_VEC3},
{ "SRC_BINORMALF", TYPE_FLOAT},
+ { "POSITION", TYPE_VEC4 },
{ "VERTEX", TYPE_VEC3},
{ "NORMAL", TYPE_VEC3},
{ "TANGENT", TYPE_VEC3},
diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp
index 5df49bd327..ace6fda696 100644
--- a/tools/editor/animation_editor.cpp
+++ b/tools/editor/animation_editor.cpp
@@ -627,31 +627,41 @@ public:
};
-void AnimationKeyEditor::_menu_track(int p_type) {
+void AnimationKeyEditor::_menu_add_track(int p_type) {
ERR_FAIL_COND(!animation.is_valid());
- last_menu_track_opt=p_type;
switch(p_type) {
- case TRACK_MENU_ADD_CALL_TRACK: {
+ case ADD_TRACK_MENU_ADD_CALL_TRACK: {
if (root) {
call_select->popup_centered_ratio();
break;
}
} break;
- case TRACK_MENU_ADD_VALUE_TRACK:
- case TRACK_MENU_ADD_TRANSFORM_TRACK: {
+ case ADD_TRACK_MENU_ADD_VALUE_TRACK:
+ case ADD_TRACK_MENU_ADD_TRANSFORM_TRACK: {
undo_redo->create_action("Anim Add Track");
- undo_redo->add_do_method(animation.ptr(),"add_track",p_type);
+ undo_redo->add_do_method(animation.ptr(),"add_track",p_type);
undo_redo->add_do_method(animation.ptr(),"track_set_path",animation->get_track_count(),".");
undo_redo->add_undo_method(animation.ptr(),"remove_track",animation->get_track_count());
undo_redo->commit_action();
} break;
+ }
+}
+
+void AnimationKeyEditor::_menu_track(int p_type) {
+
+ ERR_FAIL_COND(!animation.is_valid());
+
+
+ last_menu_track_opt=p_type;
+ switch(p_type) {
+
case TRACK_MENU_SCALE:
case TRACK_MENU_SCALE_PIVOT: {
@@ -999,6 +1009,7 @@ void AnimationKeyEditor::_track_editor_draw() {
if (!animation.is_valid()) {
v_scroll->hide();
h_scroll->hide();
+ menu_add_track->set_disabled(true);
menu_track->set_disabled(true);
edit_button->set_disabled(true);
key_editor_tab->hide();
@@ -1008,6 +1019,7 @@ void AnimationKeyEditor::_track_editor_draw() {
return;
}
+ menu_add_track->set_disabled(false);
menu_track->set_disabled(false);
edit_button->set_disabled(false);
move_up_button->set_disabled(false);
@@ -2659,12 +2671,14 @@ void AnimationKeyEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
- zoomicon->set_texture( get_icon("Zoom","EditorIcons") );
- //menu_track->set_icon(get_icon("AddTrack","EditorIcons"));
- menu_track->get_popup()->add_icon_item(get_icon("KeyValue","EditorIcons"),"Add Normal Track",TRACK_MENU_ADD_VALUE_TRACK);
- menu_track->get_popup()->add_icon_item(get_icon("KeyXform","EditorIcons"),"Add Transform Track",TRACK_MENU_ADD_TRANSFORM_TRACK);
- menu_track->get_popup()->add_icon_item(get_icon("KeyCall","EditorIcons"),"Add Call Func Track",TRACK_MENU_ADD_CALL_TRACK);
- menu_track->get_popup()->add_separator();
+ zoomicon->set_texture( get_icon("Zoom","EditorIcons") );
+
+ menu_add_track->set_icon(get_icon("AddTrack","EditorIcons"));
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue","EditorIcons"),"Add Normal Track",ADD_TRACK_MENU_ADD_VALUE_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform","EditorIcons"),"Add Transform Track",ADD_TRACK_MENU_ADD_TRANSFORM_TRACK);
+ menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall","EditorIcons"),"Add Call Func Track",ADD_TRACK_MENU_ADD_CALL_TRACK);
+
+ menu_track->set_icon(get_icon("Tools","EditorIcons"));
menu_track->get_popup()->add_item("Scale Selection",TRACK_MENU_SCALE);
menu_track->get_popup()->add_item("Scale From Cursor",TRACK_MENU_SCALE_PIVOT);
menu_track->get_popup()->add_separator();
@@ -3511,6 +3525,7 @@ void AnimationKeyEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_track_editor_input_event"),&AnimationKeyEditor::_track_editor_input_event);
ObjectTypeDB::bind_method(_MD("_track_name_changed"),&AnimationKeyEditor::_track_name_changed);
ObjectTypeDB::bind_method(_MD("_track_menu_selected"),&AnimationKeyEditor::_track_menu_selected);
+ ObjectTypeDB::bind_method(_MD("_menu_add_track"),&AnimationKeyEditor::_menu_add_track);
ObjectTypeDB::bind_method(_MD("_menu_track"),&AnimationKeyEditor::_menu_track);
ObjectTypeDB::bind_method(_MD("_clear_selection_for_anim"),&AnimationKeyEditor::_clear_selection_for_anim);
ObjectTypeDB::bind_method(_MD("_select_at_anim"),&AnimationKeyEditor::_select_at_anim);
@@ -3563,15 +3578,6 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
//menu->set_pos(Point2());
//add_child(menu);
- menu_track = memnew( MenuButton );
- menu_track->set_text("Tracks");
- hb->add_child(menu_track);
- menu_track->get_popup()->connect("item_pressed",this,"_menu_track");
-
-
-
- hb->add_child( memnew( VSeparator ) );
-
zoomicon = memnew( TextureFrame );
hb->add_child(zoomicon);
zoomicon->set_tooltip("Animation zoom.");
@@ -3629,6 +3635,10 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
hb->add_child( memnew( VSeparator ) );
+ menu_add_track = memnew( MenuButton );
+ hb->add_child(menu_add_track);
+ menu_add_track->get_popup()->connect("item_pressed",this,"_menu_add_track");
+ menu_add_track->set_tooltip("Add new tracks.");
move_up_button = memnew( ToolButton );
hb->add_child(move_up_button);
@@ -3653,6 +3663,11 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h
hb->add_child(memnew( VSeparator ));
+ menu_track = memnew( MenuButton );
+ hb->add_child(menu_track);
+ menu_track->get_popup()->connect("item_pressed",this,"_menu_track");
+ menu_track->set_tooltip("Track tools");
+
edit_button = memnew( ToolButton );
edit_button->set_toggle_mode(true);
edit_button->set_focus_mode(FOCUS_NONE);
diff --git a/tools/editor/animation_editor.h b/tools/editor/animation_editor.h
index 4a1cc21154..629377d78e 100644
--- a/tools/editor/animation_editor.h
+++ b/tools/editor/animation_editor.h
@@ -70,9 +70,9 @@ class AnimationKeyEditor : public VBoxContainer {
enum {
- TRACK_MENU_ADD_VALUE_TRACK,
- TRACK_MENU_ADD_TRANSFORM_TRACK,
- TRACK_MENU_ADD_CALL_TRACK,
+ ADD_TRACK_MENU_ADD_VALUE_TRACK,
+ ADD_TRACK_MENU_ADD_TRANSFORM_TRACK,
+ ADD_TRACK_MENU_ADD_CALL_TRACK,
TRACK_MENU_SCALE,
TRACK_MENU_SCALE_PIVOT,
TRACK_MENU_MOVE_UP,
@@ -192,6 +192,7 @@ class AnimationKeyEditor : public VBoxContainer {
SpinBox *step;
+ MenuButton *menu_add_track;
MenuButton *menu_track;
HScrollBar *h_scroll;
@@ -286,6 +287,7 @@ class AnimationKeyEditor : public VBoxContainer {
void _scroll_changed(double);
+ void _menu_add_track(int p_type);
void _menu_track(int p_type);
void _clear_selection_for_anim(const Ref<Animation>& p_anim);
diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp
index 2ed03a1858..685763cadb 100644
--- a/tools/editor/code_editor.cpp
+++ b/tools/editor/code_editor.cpp
@@ -618,7 +618,7 @@ CodeTextEditor::CodeTextEditor() {
line_col = memnew( Label );
add_child(line_col);
line_col->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,135);
- line_col->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,20);
+ line_col->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
line_col->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,1);
line_col->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
//line_col->set_align(Label::ALIGN_RIGHT);
@@ -637,7 +637,7 @@ CodeTextEditor::CodeTextEditor() {
error = memnew( Label );
add_child(error);
error->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
- error->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,20);
+ error->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
error->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,1);
error->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,130);
error->hide();
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 46ed2194a8..4f44331b0b 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -300,9 +300,9 @@ void EditorHelpSearch::_bind_methods() {
}
-EditorHelpSearch::EditorHelpSearch(EditorNode *p_editor) {
+EditorHelpSearch::EditorHelpSearch() {
- editor=p_editor;
+ editor=EditorNode::get_singleton();
VBoxContainer *vbc = memnew( VBoxContainer );
add_child(vbc);
set_child_rect(vbc);
@@ -318,17 +318,138 @@ EditorHelpSearch::EditorHelpSearch(EditorNode *p_editor) {
search_box->connect("input_event",this,"_sbox_input");
search_options = memnew( Tree );
vbc->add_margin_child("Matches:",search_options,true);
- get_ok()->set_text("View");
+ get_ok()->set_text("Open");
get_ok()->set_disabled(true);
register_text_enter(search_box);
set_hide_on_ok(false);
search_options->connect("item_activated",this,"_confirmed");
set_title("Search Classes");
+
// search_options->set_hide_root(true);
}
+/////////////////////////////////
+
+////////////////////////////////////
+/// /////////////////////////////////
+
+
+
+void EditorHelpIndex::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
+
+ if (p_types.has(p_type))
+ return;
+// if (!ObjectTypeDB::is_type(p_type,base) || p_type==base)
+// return;
+
+ String inherits=EditorHelp::get_doc_data()->class_list[p_type].inherits;
+
+ TreeItem *parent=p_root;
+
+
+ if (inherits.length()) {
+
+ if (!p_types.has(inherits)) {
+
+ add_type(inherits,p_types,p_root);
+ }
+
+ if (p_types.has(inherits) )
+ parent=p_types[inherits];
+ }
+
+ TreeItem *item = class_list->create_item(parent);
+ item->set_metadata(0,p_type);
+ item->set_tooltip(0,EditorHelp::get_doc_data()->class_list[p_type].brief_description);
+ item->set_text(0,p_type);
+
+
+ if (has_icon(p_type,"EditorIcons")) {
+
+ item->set_icon(0, get_icon(p_type,"EditorIcons"));
+ }
+
+ p_types[p_type]=item;
+}
+
+
+void EditorHelpIndex::_tree_item_selected() {
+
+
+ TreeItem *s=class_list->get_selected();
+ if (!s)
+ return;
+
+ emit_signal("open_class",s->get_text(0));
+
+ hide();
+
+ //_goto_desc(s->get_text(0));
+
+}
+
+void EditorHelpIndex::select_class(const String& p_class) {
+
+ if (!tree_item_map.has(p_class))
+ return;
+ tree_item_map[p_class]->select(0);
+ class_list->ensure_cursor_is_visible();
+}
+
+void EditorHelpIndex::_notification(int p_what) {
+
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+
+ class_list->clear();
+ tree_item_map.clear();
+ TreeItem *root = class_list->create_item();
+ class_list->set_hide_root(true);
+ connect("confirmed",this,"_tree_item_selected");
+
+
+ for(Map<String,DocData::ClassDoc>::Element *E=EditorHelp::get_doc_data()->class_list.front();E;E=E->next()) {
+
+ add_type(E->key(),tree_item_map,root);
+ }
+
+ }
+}
+
+void EditorHelpIndex::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_tree_item_selected",&EditorHelpIndex::_tree_item_selected);
+ ObjectTypeDB::bind_method("select_class",&EditorHelpIndex::select_class);
+ ADD_SIGNAL( MethodInfo("open_class"));
+}
+
+
+
+EditorHelpIndex::EditorHelpIndex() {
+
+
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ add_child(vbc);
+ set_child_rect(vbc);
+
+ class_list = memnew( Tree );
+ vbc->add_margin_child("Class List: ",class_list,true);
+ class_list->set_v_size_flags(SIZE_EXPAND_FILL);
+
+
+ class_list->connect("item_activated",this,"_tree_item_selected");
+
+
+ get_ok()->set_text("Open");
+}
+
+
+
+/////////////////////////////////
+
+////////////////////////////////////
+/// /////////////////////////////////
DocData *EditorHelp::doc=NULL;
void EditorHelp::_unhandled_key_input(const InputEvent& p_ev) {
@@ -339,8 +460,6 @@ void EditorHelp::_unhandled_key_input(const InputEvent& p_ev) {
search->grab_focus();
search->select_all();
- } else if (p_ev.key.mod.shift && p_ev.key.scancode==KEY_F1) {
- class_search->popup();
}
}
@@ -351,17 +470,19 @@ void EditorHelp::_search(const String&) {
String stext=search->get_text();
- bool keep = prev_search==stext && class_list->get_selected() && prev_search_page==class_list->get_selected()->get_text(0);
+ bool keep = prev_search==stext;
- class_desc->search(stext, keep);
+ bool ret = class_desc->search(stext, keep);
+ if (!ret) {
+ class_desc->search(stext, false);
+ }
prev_search=stext;
- if (class_list->get_selected())
- prev_search_page=class_list->get_selected()->get_text(0);
}
+#if 0
void EditorHelp::_button_pressed(int p_idx) {
if (p_idx==PAGE_CLASS_LIST) {
@@ -399,16 +520,11 @@ void EditorHelp::_button_pressed(int p_idx) {
} else if (p_idx==PAGE_SEARCH) {
_search("");
- } else if (p_idx==CLASS_SEARCH) {
-
- class_search->popup();
}
-
-
}
-
+#endif
void EditorHelp::_class_list_select(const String& p_select) {
@@ -417,16 +533,28 @@ void EditorHelp::_class_list_select(const String& p_select) {
void EditorHelp::_class_desc_select(const String& p_select) {
+
+
+// print_line("LINK: "+p_select);
if (p_select.begins_with("#")) {
- _goto_desc(p_select.substr(1,p_select.length()));
+ //_goto_desc(p_select.substr(1,p_select.length()));
+ emit_signal("go_to_help","class_name:"+p_select.substr(1,p_select.length()));
return;
} else if (p_select.begins_with("@")) {
String m = p_select.substr(1,p_select.length());
- if (!method_line.has(m))
- return;
- class_desc->scroll_to_line(method_line[m]);
- return;
+
+ if (m.find(".")!=-1) {
+ //must go somewhere else
+
+ emit_signal("go_to_help","class_method:"+m.get_slice(".",0)+":"+m.get_slice(".",0));
+ } else {
+
+ if (!method_line.has(m))
+ return;
+ class_desc->scroll_to_line(method_line[m]);
+ }
+
}
@@ -449,68 +577,40 @@ void EditorHelp::_add_type(const String& p_type) {
}
-void EditorHelp::_update_history_buttons() {
-
- back->set_disabled(history_pos<2);
- forward->set_disabled(history_pos>=history.size());
-
-}
-
-
void EditorHelp::_scroll_changed(double p_scroll) {
if (scroll_locked)
return;
- int p = history_pos -1;
- if (p<0 || p>=history.size())
- return;
-
if (class_desc->get_v_scroll()->is_hidden())
p_scroll=0;
- history[p].scroll=p_scroll;
+ //history[p].scroll=p_scroll;
}
-Error EditorHelp::_goto_desc(const String& p_class,bool p_update_history,int p_vscr) {
+Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
//ERR_FAIL_COND(!doc->class_list.has(p_class));
if (!doc->class_list.has(p_class))
return ERR_DOES_NOT_EXIST;
- if (tree_item_map.has(p_class)) {
+ //if (tree_item_map.has(p_class)) {
select_locked = true;
- tree_item_map[p_class]->select(0);
- class_list->ensure_cursor_is_visible();
- }
+ //}
class_desc->show();
//tabs->set_current_tab(PAGE_CLASS_DESC);
- edited_class->set_pressed(true);
- class_list_button->set_pressed(false);
description_line=0;
- if (p_class==edited_class->get_text())
+ if (p_class==edited_class)
return OK; //already there
scroll_locked=true;
- if (p_update_history) {
-
- history.resize(history_pos);
- history_pos++;
- History h;
- h.c=p_class;
- h.scroll=0;
- history.push_back(h);
- _update_history_buttons();
- class_desc->get_v_scroll()->set_val(0);
- }
-
class_desc->clear();
method_line.clear();
- edited_class->set_text(p_class);
+ edited_class=p_class;
//edited_class->show();
@@ -925,10 +1025,7 @@ Error EditorHelp::_goto_desc(const String& p_class,bool p_update_history,int p_v
}
- if (!p_update_history) {
- class_desc->get_v_scroll()->set_val(history[history_pos-1].scroll);
- }
scroll_locked=false;
@@ -939,8 +1036,6 @@ void EditorHelp::_request_help(const String& p_string) {
Error err = _goto_desc(p_string);
if (err==OK) {
editor->call("_editor_select",3);
- } else {
- class_search->popup(p_string);
}
//100 palabras
}
@@ -1209,315 +1304,158 @@ void EditorHelp::_add_text(const String& p_bbcode) {
}
-void EditorHelp::add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root) {
-
- if (p_types.has(p_type))
- return;
-// if (!ObjectTypeDB::is_type(p_type,base) || p_type==base)
-// return;
-
- String inherits=doc->class_list[p_type].inherits;
-
- TreeItem *parent=p_root;
- if (inherits.length()) {
+void EditorHelp::_update_doc() {
- if (!p_types.has(inherits)) {
- add_type(inherits,p_types,p_root);
- }
- if (p_types.has(inherits) )
- parent=p_types[inherits];
- }
+}
- TreeItem *item = class_list->create_item(parent);
- item->set_metadata(0,p_type);
- item->set_tooltip(0,doc->class_list[p_type].brief_description);
- item->set_text(0,p_type);
+void EditorHelp::generate_doc() {
- if (has_icon(p_type,"EditorIcons")) {
+ doc = memnew( DocData );
+ doc->generate(true);
+ DocData compdoc;
+ compdoc.load_compressed(_doc_data_compressed,_doc_data_compressed_size,_doc_data_uncompressed_size);
+ doc->merge_from(compdoc); //ensure all is up to date
- item->set_icon(0, get_icon(p_type,"EditorIcons"));
- }
- p_types[p_type]=item;
}
+void EditorHelp::_notification(int p_what) {
-void EditorHelp::_update_doc() {
+ switch(p_what) {
+ case NOTIFICATION_READY: {
- class_list->clear();
- List<StringName> type_list;
+// forward->set_icon(get_icon("Forward","EditorIcons"));
+// back->set_icon(get_icon("Back","EditorIcons"));
+ _update_doc();
+ editor->connect("request_help",this,"_request_help");
- tree_item_map.clear();
+ } break;
+ }
+}
- TreeItem *root = class_list->create_item();
- class_list->set_hide_root(true);
- List<StringName>::Element *I=type_list.front();
- for(Map<String,DocData::ClassDoc>::Element *E=doc->class_list.front();E;E=E->next()) {
- add_type(E->key(),tree_item_map,root);
- }
+void EditorHelp::go_to_help(const String& p_help) {
+ _help_callback(p_help);
}
+void EditorHelp::go_to_class(const String& p_class,int p_scroll) {
-void EditorHelp::generate_doc() {
+ _goto_desc(p_class,p_scroll);
+}
- doc = memnew( DocData );
- doc->generate(true);
- DocData compdoc;
- compdoc.load_compressed(_doc_data_compressed,_doc_data_compressed_size,_doc_data_uncompressed_size);
- doc->merge_from(compdoc); //ensure all is up to date
+void EditorHelp::popup_search() {
+ search_dialog->popup_centered(Size2(250,80));
+ search->grab_focus();
}
-void EditorHelp::_notification(int p_what) {
+void EditorHelp::_search_cbk() {
+ _search(search->get_text());
+}
- switch(p_what) {
+String EditorHelp::get_class_name() {
- case NOTIFICATION_READY: {
+ return edited_class;
+}
+void EditorHelp::search_again() {
+ _search(prev_search);
+}
- forward->set_icon(get_icon("Forward","EditorIcons"));
- back->set_icon(get_icon("Back","EditorIcons"));
- _update_doc();
- editor->connect("request_help",this,"_request_help");
+int EditorHelp::get_scroll() const {
- } break;
- }
+ return class_desc->get_v_scroll()->get_val();
}
+void EditorHelp::set_scroll(int p_scroll) {
-void EditorHelp::_tree_item_selected() {
- if (select_locked) {
- select_locked = false;
- return;
- }
- TreeItem *s=class_list->get_selected();
- if (!s)
- return;
- select_locked=true;
- _goto_desc(s->get_text(0));
- select_locked=false;
+ class_desc->get_v_scroll()->set_val(p_scroll);
+
}
void EditorHelp::_bind_methods() {
ObjectTypeDB::bind_method("_class_list_select",&EditorHelp::_class_list_select);
ObjectTypeDB::bind_method("_class_desc_select",&EditorHelp::_class_desc_select);
- ObjectTypeDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
+// ObjectTypeDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
ObjectTypeDB::bind_method("_scroll_changed",&EditorHelp::_scroll_changed);
ObjectTypeDB::bind_method("_request_help",&EditorHelp::_request_help);
ObjectTypeDB::bind_method("_unhandled_key_input",&EditorHelp::_unhandled_key_input);
ObjectTypeDB::bind_method("_search",&EditorHelp::_search);
- ObjectTypeDB::bind_method("_tree_item_selected",&EditorHelp::_tree_item_selected);
+ ObjectTypeDB::bind_method("_search_cbk",&EditorHelp::_search_cbk);
+
ObjectTypeDB::bind_method("_help_callback",&EditorHelp::_help_callback);
+ ADD_SIGNAL(MethodInfo("go_to_help"));
+
}
-EditorHelp::EditorHelp(EditorNode *p_editor) {
+EditorHelp::EditorHelp() {
- editor=p_editor;
+ editor=EditorNode::get_singleton();
VBoxContainer *vbc = this;
- HBoxContainer *panel_hb = memnew( HBoxContainer );
-
- Button *b = memnew( Button );
- b->set_text("Class List");
- panel_hb->add_child(b);
- vbc->add_child(panel_hb);
- b->set_toggle_mode(true);
- b->set_pressed(true);
- b->connect("pressed",this,"_button_pressed",make_binds(PAGE_CLASS_LIST));
- class_list_button=b;
- class_list_button->hide();
-
- b = memnew( Button );
- b->set_text("Class");
- panel_hb->add_child(b);
- edited_class=b;
- edited_class->hide();
- b->set_toggle_mode(true);
- b->connect("pressed",this,"_button_pressed",make_binds(PAGE_CLASS_DESC));
-
- b = memnew( Button );
- b->set_text("Search in Classes");
- panel_hb->add_child(b);
- b->connect("pressed",this,"_button_pressed",make_binds(CLASS_SEARCH));
-
- Control *expand = memnew( Control );
- expand->set_h_size_flags(SIZE_EXPAND_FILL);
- panel_hb->add_child(expand);
-
- b = memnew( Button );
- panel_hb->add_child(b);
- back=b;
- b->connect("pressed",this,"_button_pressed",make_binds(PAGE_CLASS_PREV));
-
- b = memnew( Button );
- panel_hb->add_child(b);
- forward=b;
- b->connect("pressed",this,"_button_pressed",make_binds(PAGE_CLASS_NEXT));
-
- Separator *hs = memnew( VSeparator );
- panel_hb->add_child(hs);
- Control *ec = memnew( Control );
- ec->set_custom_minimum_size(Size2(200,1));
- panel_hb->add_child(ec);
- search = memnew( LineEdit );
- ec->add_child(search);
- search->set_area_as_parent_rect();
- search->connect("text_entered",this,"_search");
-
- b = memnew( Button );
- b->set_text("Find");
- panel_hb->add_child(b);
- b->connect("pressed",this,"_button_pressed",make_binds(PAGE_SEARCH));
-
- hs = memnew( VSeparator );
- panel_hb->add_child(hs);
- h_split = memnew( HSplitContainer );
- h_split->set_v_size_flags(SIZE_EXPAND_FILL);
-
-
- vbc->add_child(h_split);
-
- class_list = memnew( Tree );
- h_split->add_child(class_list);
//class_list->connect("meta_clicked",this,"_class_list_select");
//class_list->set_selection_enabled(true);
{
- PanelContainer *pc = memnew( PanelContainer );
+ Panel *pc = memnew( Panel );
Ref<StyleBoxFlat> style( memnew( StyleBoxFlat ) );
style->set_bg_color( EditorSettings::get_singleton()->get("text_editor/background_color") );
- style->set_default_margin(MARGIN_LEFT,20);
- style->set_default_margin(MARGIN_TOP,20);
+ pc->set_v_size_flags(SIZE_EXPAND_FILL);
pc->add_style_override("panel", style); //get_stylebox("normal","TextEdit"));
- h_split->add_child(pc);
+ vbc->add_child(pc);
class_desc = memnew( RichTextLabel );
pc->add_child(class_desc);
+ class_desc->set_area_as_parent_rect(8);
class_desc->connect("meta_clicked",this,"_class_desc_select");
}
class_desc->get_v_scroll()->connect("value_changed",this,"_scroll_changed");
class_desc->set_selection_enabled(true);
- editor=p_editor;
- history_pos=0;
+
scroll_locked=false;
select_locked=false;
set_process_unhandled_key_input(true);
- h_split->set_split_offset(200);
- class_list->connect("cell_selected",this,"_tree_item_selected");
class_desc->hide();
- class_search = memnew( EditorHelpSearch(editor) );
- editor->get_gui_base()->add_child(class_search);
- class_search->connect("go_to_help",this,"_help_callback");
-// prev_search_page=-1;
-}
-
-EditorHelp::~EditorHelp() {
- if (doc)
- memdelete(doc);
-}
-
-
-void EditorHelpPlugin::edit(Object *p_object) {
-
- if (!p_object->cast_to<Script>())
- return;
-
- //editor_help->edit(p_object->cast_to<Script>());
-}
-
-bool EditorHelpPlugin::handles(Object *p_object) const {
-
- return false;
-}
-
-void EditorHelpPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
- editor_help->show();
- } else {
-
- editor_help->hide();
- }
-
-}
-
-void EditorHelpPlugin::selected_notify() {
-
- //editor_help->ensure_select_current();
-}
-
-Dictionary EditorHelpPlugin::get_state() const {
-
- return Dictionary();
-}
-
-void EditorHelpPlugin::set_state(const Dictionary& p_state) {
-
- //editor_help->set_state(p_state);
-}
-void EditorHelpPlugin::clear() {
-
- //editor_help->clear();
-}
-
-void EditorHelpPlugin::save_external_data() {
-
- //editor_help->save_external_data();
-}
-
-void EditorHelpPlugin::apply_changes() {
-
- //editor_help->apply_helps();
-}
-
-void EditorHelpPlugin::restore_global_state() {
-
- //if (bool(EDITOR_DEF("text_editor/restore_helps_on_load",true))) {
-// editor_help->_load_files_state();
- //}
-
-}
+ search_dialog = memnew( ConfirmationDialog );
+ add_child(search_dialog);
+ VBoxContainer *search_vb = memnew( VBoxContainer );
+ search_dialog->add_child(search_vb);
+ search_dialog->set_child_rect(search_vb);
+ search = memnew( LineEdit );
+ search_dialog->register_text_enter(search);
+ search_vb->add_margin_child("Search Text",search);
+ search_dialog->get_ok()->set_text("Find");
+ search_dialog->connect("confirmed",this,"_search_cbk");
+ search_dialog->set_hide_on_ok(false);
+ search_dialog->set_self_opacity(0.8);
-void EditorHelpPlugin::save_global_state() {
- //if (bool(EDITOR_DEF("text_editor/restore_helps_on_load",true))) {
-// editor_help->_save_files_state();
-// }
+ /*class_search = memnew( EditorHelpSearch(editor) );
+ editor->get_gui_base()->add_child(class_search);
+ class_search->connect("go_to_help",this,"_help_callback");*/
+// prev_search_page=-1;
}
-
-EditorHelpPlugin::EditorHelpPlugin(EditorNode *p_node) {
-
- editor=p_node;
- editor_help = memnew( EditorHelp(p_node) );
- editor->get_viewport()->add_child(editor_help);
- editor_help->set_area_as_parent_rect();
- editor_help->hide();
-
+EditorHelp::~EditorHelp() {
}
-
-EditorHelpPlugin::~EditorHelpPlugin()
-{
-}
diff --git a/tools/editor/editor_help.h b/tools/editor/editor_help.h
index d4066d076a..b5ee6eca6c 100644
--- a/tools/editor/editor_help.h
+++ b/tools/editor/editor_help.h
@@ -70,9 +70,29 @@ public:
void popup(const String& p_term="");
- EditorHelpSearch(EditorNode *p_editor);
+ EditorHelpSearch();
};
+class EditorHelpIndex : public ConfirmationDialog {
+ OBJ_TYPE( EditorHelpIndex, ConfirmationDialog );
+
+
+ Tree *class_list;
+ HashMap<String,TreeItem*> tree_item_map;
+
+ void _tree_item_selected();
+ void add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root);
+protected:
+
+ void _notification(int p_what);
+ static void _bind_methods();
+
+public:
+
+ void select_class(const String& p_class);
+
+ EditorHelpIndex();
+};
class EditorHelp : public VBoxContainer {
@@ -91,17 +111,11 @@ class EditorHelp : public VBoxContainer {
};
- struct History {
- String c;
- int scroll;
- };
-
- Vector<History> history;
- int history_pos;
bool select_locked;
String prev_search;
- String prev_search_page;
+
+ String edited_class;
EditorNode *editor;
Map<String,int> method_line;
@@ -111,21 +125,17 @@ class EditorHelp : public VBoxContainer {
Map<String,int> constant_line;
int description_line;
- Tree *class_list;
RichTextLabel *class_desc;
HSplitContainer *h_split;
static DocData *doc;
- Button *class_list_button;
- Button *edited_class;
- Button *back;
- Button *forward;
+
+ ConfirmationDialog *search_dialog;
LineEdit *search;
- String base_path;
- HashMap<String,TreeItem*> tree_item_map;
+ String base_path;
void _help_callback(const String& p_topic);
@@ -133,25 +143,24 @@ class EditorHelp : public VBoxContainer {
void _add_text(const String& p_text);
bool scroll_locked;
- void _button_pressed(int p_idx);
+ //void _button_pressed(int p_idx);
void _add_type(const String& p_type);
void _scroll_changed(double p_scroll);
void _class_list_select(const String& p_select);
void _class_desc_select(const String& p_select);
- Error _goto_desc(const String& p_class,bool p_update_history=true,int p_vscr=-1);
- void _update_history_buttons();
+ Error _goto_desc(const String& p_class, int p_vscr=-1);
+ //void _update_history_buttons();
void _update_doc();
void _request_help(const String& p_string);
void _search(const String& p_str);
+ void _search_cbk();
void _unhandled_key_input(const InputEvent& p_ev);
- void add_type(const String& p_type,HashMap<String,TreeItem*>& p_types,TreeItem *p_root);
- void _tree_item_selected();
- EditorHelpSearch *class_search;
+
protected:
@@ -163,41 +172,25 @@ public:
static void generate_doc();
static DocData *get_doc_data() { return doc; }
- EditorHelp(EditorNode *p_editor=NULL);
- ~EditorHelp();
-};
-
-
+ void go_to_help(const String& p_help);
+ void go_to_class(const String& p_class,int p_scroll=0);
-class EditorHelpPlugin : public EditorPlugin {
+ void popup_search();
+ void search_again();
- OBJ_TYPE( EditorHelpPlugin, EditorPlugin );
+ String get_class_name();
- EditorHelp *editor_help;
- EditorNode *editor;
-public:
+ void set_focused() { class_desc->grab_focus(); }
- virtual String get_name() const { return "Help"; }
- bool has_main_screen() const { return true; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
- virtual void make_visible(bool p_visible);
- virtual void selected_notify();
+ int get_scroll() const;
+ void set_scroll(int p_scroll);
- Dictionary get_state() const;
- virtual void set_state(const Dictionary& p_state);
- virtual void clear();
-
- virtual void save_external_data();
- virtual void apply_changes();
+ EditorHelp();
+ ~EditorHelp();
+};
- virtual void restore_global_state();
- virtual void save_global_state();
- EditorHelpPlugin(EditorNode *p_node);
- ~EditorHelpPlugin();
-};
#endif // EDITOR_HELP_H
diff --git a/tools/editor/editor_log.cpp b/tools/editor/editor_log.cpp
index 2d26490a8a..264117eecd 100644
--- a/tools/editor/editor_log.cpp
+++ b/tools/editor/editor_log.cpp
@@ -81,6 +81,7 @@ void EditorLog::_notification(int p_what) {
log->add_color_override("default_color",get_color("font_color","Tree"));
tb->set_normal_texture( get_icon("Collapse","EditorIcons"));
tb->set_hover_texture( get_icon("CollapseHl","EditorIcons"));
+ //button->set_icon(get_icon("Console","EditorIcons"));
}
@@ -125,6 +126,7 @@ void EditorLog::add_message(const String& p_msg,bool p_error) {
log->push_color(get_color("fg_error","Editor"));
} else {
button->set_icon(Ref<Texture>());
+
}
@@ -154,17 +156,20 @@ void EditorLog::_dragged(const Point2& p_ofs) {
*/
-ToolButton *EditorLog::get_button() {
+Button *EditorLog::get_button() {
return button;
}
void EditorLog::_flip_request() {
- if (is_visible())
+ if (is_visible()) {
hide();
- else
+ button->show();
+ } else {
show();
+ button->hide();
+ }
}
void EditorLog::_undo_redo_cbk(void *p_self,const String& p_name) {
@@ -200,7 +205,7 @@ EditorLog::EditorLog() {
hb->add_child(title);
- button = memnew( ToolButton );
+ button = memnew( Button );
button->set_text_align(Button::ALIGN_LEFT);
button->connect("pressed",this,"_flip_request");
button->set_focus_mode(FOCUS_NONE);
diff --git a/tools/editor/editor_log.h b/tools/editor/editor_log.h
index 6950ffa1a0..93044f9a2d 100644
--- a/tools/editor/editor_log.h
+++ b/tools/editor/editor_log.h
@@ -44,7 +44,7 @@ class EditorLog : public PanelContainer {
OBJ_TYPE( EditorLog, PanelContainer );
- ToolButton *button;
+ Button *button;
Button *clearbutton;
Label *title;
RichTextLabel *log;
@@ -73,7 +73,7 @@ public:
void add_message(const String& p_msg, bool p_error=false);
void deinit();
- ToolButton *get_button();
+ Button *get_button();
void clear();
EditorLog();
~EditorLog();
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index 8b2eb603e5..5412211b28 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -111,6 +111,8 @@ EditorNode *EditorNode::singleton=NULL;
void EditorNode::_update_scene_tabs() {
+ bool show_rb = EditorSettings::get_singleton()->get("global/show_script_in_scene_tabs");
+
scene_tabs->clear_tabs();
Ref<Texture> script_icon = gui_base->get_icon("Script","EditorIcons");
for(int i=0;i<editor_data.get_edited_scene_count();i++) {
@@ -133,7 +135,7 @@ void EditorNode::_update_scene_tabs() {
bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0;
scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""),icon);
- if (editor_data.get_scene_root_script(i).is_valid()) {
+ if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
scene_tabs->set_tab_right_button(i,script_icon);
}
@@ -163,13 +165,13 @@ void EditorNode::_unhandled_input(const InputEvent& p_event) {
switch(p_event.key.scancode) {
- case KEY_F1:
+ /*case KEY_F1:
if (!p_event.key.mod.shift && !p_event.key.mod.command)
_editor_select(3);
- break;
- case KEY_F2: _editor_select(0); break;
- case KEY_F3: _editor_select(1); break;
- case KEY_F4: _editor_select(2); break;
+ break;*/
+ case KEY_F1: _editor_select(0); break;
+ case KEY_F2: _editor_select(1); break;
+ case KEY_F3: _editor_select(2); break;
case KEY_F5: _menu_option_confirm((p_event.key.mod.control&&p_event.key.mod.shift)?RUN_PLAY_CUSTOM_SCENE:RUN_PLAY,true); break;
case KEY_F6: _menu_option_confirm(RUN_PLAY_SCENE,true); break;
case KEY_F7: _menu_option_confirm(RUN_PAUSE,true); break;
@@ -1617,10 +1619,8 @@ void EditorNode::_edit_current() {
for(int i=0;i<editor_table.size();i++) {
- if (editor_table[i]==main_plugin) {
- main_editor_tabs->set_current_tab(i);
- break;
- }
+
+ main_editor_buttons[i]->set_pressed(editor_table[i]==main_plugin);
}
}
@@ -2846,7 +2846,7 @@ Control* EditorNode::get_viewport() {
void EditorNode::_editor_select(int p_which) {
static bool selecting=false;
- if (selecting)
+ if (selecting || changing_scene)
return;
selecting=true;
@@ -2854,7 +2854,9 @@ void EditorNode::_editor_select(int p_which) {
ERR_FAIL_INDEX(p_which,editor_table.size());
- main_editor_tabs->set_current_tab(p_which);
+ for(int i=0;i<main_editor_buttons.size();i++) {
+ main_editor_buttons[i]->set_pressed(i==p_which);
+ }
selecting=false;
@@ -2872,6 +2874,8 @@ void EditorNode::_editor_select(int p_which) {
editor_plugin_screen=new_editor;
editor_plugin_screen->make_visible(true);
editor_plugin_screen->selected_notify();
+
+
}
void EditorNode::add_editor_plugin(EditorPlugin *p_editor) {
@@ -2879,7 +2883,12 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor) {
if (p_editor->has_main_screen()) {
- singleton->main_editor_tabs->add_tab(p_editor->get_name());
+ ToolButton *tb = memnew( ToolButton );
+ tb->set_toggle_mode(true);
+ tb->connect("pressed",singleton,"_editor_select",varray(singleton->main_editor_buttons.size()));
+ tb->set_text(p_editor->get_name());
+ singleton->main_editor_buttons.push_back(tb);
+ singleton->main_editor_button_vb->add_child(tb);
singleton->editor_table.push_back(p_editor);
}
singleton->editor_data.add_editor_plugin( p_editor );
@@ -2891,16 +2900,18 @@ void EditorNode::remove_editor_plugin(EditorPlugin *p_editor) {
if (p_editor->has_main_screen()) {
- for(int i=0;i<singleton->main_editor_tabs->get_tab_count();i++) {
+ for(int i=0;i<singleton->main_editor_buttons.size();i++) {
- if (p_editor->get_name()==singleton->main_editor_tabs->get_tab_title(i)) {
+ if (p_editor->get_name()==singleton->main_editor_buttons[i]->get_name()) {
+
+ memdelete( singleton->main_editor_buttons[i] );
+ singleton->main_editor_buttons.remove(i);
- singleton->main_editor_tabs->remove_tab(i);
break;
}
}
- singleton->main_editor_tabs->add_tab(p_editor->get_name());
+ //singleton->main_editor_tabs->add_tab(p_editor->get_name());
singleton->editor_table.erase(p_editor);
}
singleton->remove_child(p_editor);
@@ -3209,10 +3220,20 @@ Error EditorNode::save_optimized_copy(const String& p_scene,const String& p_pres
}
+int EditorNode::_get_current_main_editor() {
+
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_table[i]==editor_plugin_screen)
+ return i;
+ }
+
+ return 0;
+}
+
Dictionary EditorNode::_get_main_scene_state() {
Dictionary state;
- state["main_tab"]=main_editor_tabs->get_current_tab();
+ state["main_tab"]=_get_current_main_editor();
state["scene_tree_offset"]=scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->get_val();
state["property_edit_offset"]=get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_val();
state["saved_version"]=saved_version;
@@ -3223,9 +3244,14 @@ Dictionary EditorNode::_get_main_scene_state() {
void EditorNode::_set_main_scene_state(Dictionary p_state) {
//print_line("set current 7 ");
+ changing_scene=false;
+#if 0
if (p_state.has("main_tab")) {
int idx = p_state["main_tab"];
+
+
+ print_line("comes with tab: "+itos(idx));
int current=-1;
for(int i=0;i<editor_table.size();i++) {
if (editor_plugin_screen==editor_table[i]) {
@@ -3234,12 +3260,41 @@ void EditorNode::_set_main_scene_state(Dictionary p_state) {
}
}
+
if (idx<2 && current<2) {
//only set tab for 2D and 3D
- _editor_select(p_state["main_tab"]);
+ _editor_select(idx);
//print_line(" setting main tab: "+itos(p_state["main_tab"]));
}
}
+#else
+
+ if (get_edited_scene()) {
+
+ int current=-1;
+ for(int i=0;i<editor_table.size();i++) {
+ if (editor_plugin_screen==editor_table[i]) {
+ current=i;
+ break;
+ }
+ }
+
+ if (current<2) {
+ //use heuristic instead
+
+ int n2d=0,n3d=0;
+ _find_node_types(get_edited_scene(),n2d,n3d);
+ if (n2d>n3d) {
+ _editor_select(0);
+ } else if (n3d>n2d) {
+ _editor_select(1);
+
+ }
+ }
+
+ }
+#endif
+
if (p_state.has("scene_tree_offset"))
scene_tree_dock->get_tree_editor()->get_scene_tree()->get_vscroll_bar()->set_val(p_state["scene_tree_offset"]);
@@ -3248,6 +3303,12 @@ void EditorNode::_set_main_scene_state(Dictionary p_state) {
//print_line("set current 8 ");
+ //this should only happen at the very end
+
+ //changing_scene=true; //avoid script change from opening editor
+ ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
+ ScriptEditor::get_singleton()->set_scene_root_script( editor_data.get_scene_root_script(editor_data.get_edited_scene()) );
+ //changing_scene=false;
}
@@ -3312,8 +3373,6 @@ void EditorNode::set_current_scene(int p_idx) {
call_deferred("_set_main_scene_state",state); //do after everything else is done setting up
//print_line("set current 6 ");
- changing_scene=false;
- ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
}
@@ -4551,6 +4610,7 @@ EditorNode::EditorNode() {
gui_base->add_child(main_vbox);
main_vbox->set_area_as_parent_rect(8);
+#if 0
PanelContainer *top_dark_panel = memnew( PanelContainer );
Ref<StyleBoxTexture> top_dark_sb;
top_dark_sb.instance();;
@@ -4566,21 +4626,14 @@ EditorNode::EditorNode() {
VBoxContainer *top_dark_vb = memnew( VBoxContainer );
main_vbox->add_child(top_dark_panel);
top_dark_panel->add_child(top_dark_vb);
-
+#endif
menu_hb = memnew( HBoxContainer );
- top_dark_vb->add_child(menu_hb);
+ main_vbox->add_child(menu_hb);
- scene_tabs=memnew( Tabs );
- scene_tabs->add_tab("unsaved");
- scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
- scene_tabs->set_tab_close_display_policy(Tabs::SHOW_HOVER);
- scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
- scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
- scene_tabs->connect("tab_close", this, "_scene_tab_closed");
- top_dark_vb->add_child(scene_tabs);
+// top_dark_vb->add_child(scene_tabs);
//left
left_l_hsplit = memnew( HSplitContainer );
main_vbox->add_child(left_l_hsplit);
@@ -4613,11 +4666,15 @@ EditorNode::EditorNode() {
main_hsplit = memnew( HSplitContainer );
left_r_hsplit->add_child(main_hsplit);
//main_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ VBoxContainer * center_vb = memnew( VBoxContainer);
+ main_hsplit->add_child(center_vb);
+ center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
center_split = memnew( VSplitContainer );
- main_hsplit->add_child(center_split);
- center_split->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ //main_hsplit->add_child(center_split);
+ center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
center_split->set_collapsed(false);
+ center_vb->add_child(center_split);
right_hsplit = memnew( HSplitContainer );
main_hsplit->add_child(right_hsplit);
@@ -4714,20 +4771,19 @@ EditorNode::EditorNode() {
srt->add_constant_override("separation",0);
- main_editor_tabs = memnew( Tabs );
+/* main_editor_tabs = memnew( Tabs );
main_editor_tabs->connect("tab_changed",this,"_editor_select");
main_editor_tabs->set_tab_close_display_policy(Tabs::SHOW_NEVER);
- HBoxContainer *srth = memnew( HBoxContainer );
- srt->add_child( srth );
- Control *tec = memnew( Control );
- tec->set_custom_minimum_size(Size2(100,0));
- tec->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- srth->add_child(tec);
- srth->add_child(main_editor_tabs);
- tec = memnew( Control );
- tec->set_custom_minimum_size(Size2(100,0));
- srth->add_child(tec);
- tec->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+*/
+ scene_tabs=memnew( Tabs );
+ scene_tabs->add_tab("unsaved");
+ scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
+ scene_tabs->set_tab_close_display_policy(Tabs::SHOW_ACTIVE_ONLY);
+ scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
+ scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
+ scene_tabs->connect("tab_close", this, "_scene_tab_closed");
+
+ srt->add_child(scene_tabs);
scene_root_parent = memnew( Panel );
@@ -4804,6 +4860,8 @@ EditorNode::EditorNode() {
anim_close->set_pressed_texture( anim_close->get_icon("Close","EditorIcons"));
+
+
PanelContainer *top_region = memnew( PanelContainer );
top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
HBoxContainer *left_menu_hb = memnew( HBoxContainer );
@@ -4880,6 +4938,18 @@ EditorNode::EditorNode() {
p->add_child(recent_scenes);
recent_scenes->connect("item_pressed",this,"_open_recent_scene");
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0));
+ menu_hb->add_child(sp);
+ }
+
+ PanelContainer *editor_region = memnew( PanelContainer );
+ editor_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ main_editor_button_vb = memnew( HBoxContainer );
+ editor_region->add_child(main_editor_button_vb);
+ menu_hb->add_child(editor_region);
+
//menu_hb->add_spacer();
#if 0
node_menu = memnew( MenuButton );
@@ -5040,6 +5110,39 @@ EditorNode::EditorNode() {
*/
+ progress_hb = memnew( BackgroundProgress );
+ menu_hb->add_child(progress_hb);
+
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0));
+ menu_hb->add_child(sp);
+ }
+
+
+ PanelContainer *vu_cont = memnew( PanelContainer );
+ vu_cont->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
+ menu_hb->add_child(vu_cont);
+
+ audio_vu = memnew( TextureProgress );
+ CenterContainer *vu_cc = memnew( CenterContainer );
+ vu_cc->add_child(audio_vu);
+ vu_cont->add_child(vu_cc);
+ audio_vu->set_under_texture(gui_base->get_icon("VuEmpty","EditorIcons"));
+ audio_vu->set_progress_texture(gui_base->get_icon("VuFull","EditorIcons"));
+ audio_vu->set_max(24);
+ audio_vu->set_min(-80);
+ audio_vu->set_step(0.01);
+ audio_vu->set_val(0);
+
+ {
+ Control *sp = memnew( Control );
+ sp->set_custom_minimum_size(Size2(30,0));
+ menu_hb->add_child(sp);
+ }
+
+
+
top_region = memnew( PanelContainer );
top_region->add_style_override("panel",gui_base->get_stylebox("hover","Button"));
HBoxContainer *right_menu_hb = memnew( HBoxContainer );
@@ -5071,6 +5174,15 @@ EditorNode::EditorNode() {
sources_button->connect("pressed",this,"_menu_option",varray(SOURCES_REIMPORT));
sources_button->set_tooltip("Alerts when an external resource has changed.");
+ update_menu = memnew( MenuButton );
+ update_menu->set_tooltip("Spins when the editor window repaints!");
+ right_menu_hb->add_child(update_menu);
+ update_menu->set_icon(gui_base->get_icon("Progress1","EditorIcons"));
+ p=update_menu->get_popup();
+ p->add_check_item("Update Always",SETTINGS_UPDATE_ALWAYS);
+ p->add_check_item("Update Changes",SETTINGS_UPDATE_CHANGES);
+ p->set_item_checked(1,true);
+
//sources_button->connect();
/*
@@ -5173,6 +5285,7 @@ EditorNode::EditorNode() {
editor_history_menu = memnew( MenuButton );
+ editor_history_menu->set_tooltip("History of recently edited objects");
editor_history_menu->set_icon( gui_base->get_icon("History","EditorIcons"));
prop_editor_hb->add_child(editor_history_menu);
editor_history_menu->connect("about_to_show",this,"_prepare_history");
@@ -5224,6 +5337,8 @@ EditorNode::EditorNode() {
log->connect("close_request",this,"_close_messages");
log->connect("show_request",this,"_show_messages");
//left_split->set_dragger_visible(false);
+
+
old_split_ofs=0;
@@ -5241,37 +5356,18 @@ EditorNode::EditorNode() {
animation_editor->hide();
- PanelContainer *bottom_pc = memnew( PanelContainer );
- main_vbox->add_child(bottom_pc);
+ /*PanelContainer *bottom_pc = memnew( PanelContainer );
+ srt->add_child(bottom_pc);
bottom_hb = memnew( HBoxContainer );
- bottom_pc->add_child(bottom_hb);
+ bottom_pc->add_child(bottom_hb);*/
- bottom_hb->add_child( log->get_button() );
+ center_vb->add_child( log->get_button() );
log->get_button()->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- progress_hb = memnew( BackgroundProgress );
- bottom_hb->add_child(progress_hb);
+
//progress_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- audio_vu = memnew( TextureProgress );
- CenterContainer *vu_cc = memnew( CenterContainer );
- vu_cc->add_child(audio_vu);
- bottom_hb->add_child(vu_cc);
- audio_vu->set_under_texture(gui_base->get_icon("VuEmpty","EditorIcons"));
- audio_vu->set_progress_texture(gui_base->get_icon("VuFull","EditorIcons"));
- audio_vu->set_max(24);
- audio_vu->set_min(-80);
- audio_vu->set_step(0.01);
- audio_vu->set_val(0);
- update_menu = memnew( MenuButton );
- update_menu->set_tooltip("Spins when the editor window repaints!");
- bottom_hb->add_child(update_menu);
- update_menu->set_icon(gui_base->get_icon("Progress1","EditorIcons"));
- p=update_menu->get_popup();
- p->add_check_item("Update Always",SETTINGS_UPDATE_ALWAYS);
- p->add_check_item("Update Changes",SETTINGS_UPDATE_CHANGES);
- p->set_item_checked(1,true);
/*
animation_menu = memnew( ToolButton );
@@ -5493,7 +5589,6 @@ EditorNode::EditorNode() {
add_editor_plugin( memnew( CanvasItemEditorPlugin(this) ) );
add_editor_plugin( memnew( SpatialEditorPlugin(this) ) );
add_editor_plugin( memnew( ScriptEditorPlugin(this) ) );
- add_editor_plugin( memnew( EditorHelpPlugin(this) ) );
add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) );
add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) );
add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) );
@@ -5669,6 +5764,7 @@ EditorNode::EditorNode() {
EditorNode::~EditorNode() {
+ memdelete( EditorHelp::get_doc_data() );
memdelete(editor_selection);
memdelete(file_server);
EditorSettings::destroy();
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 56e455c9c0..bd88e1a4b9 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -314,7 +314,9 @@ class EditorNode : public Node {
CenterContainer *tabs_center;
EditorQuickOpen *quick_open;
EditorQuickOpen *quick_run;
- Tabs *main_editor_tabs;
+
+ HBoxContainer *main_editor_button_vb;
+ Vector<ToolButton*> main_editor_buttons;
Vector<EditorPlugin*> editor_table;
EditorReImportDialog *reimport_dialog;
@@ -508,6 +510,8 @@ class EditorNode : public Node {
Dictionary _get_main_scene_state();
void _set_main_scene_state(Dictionary p_state);
+ int _get_current_main_editor();
+
void _save_docks();
void _load_docks();
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 651b30c724..15de6e7266 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -447,7 +447,7 @@ void EditorSettings::_load_defaults() {
hints["global/default_project_path"]=PropertyInfo(Variant::STRING,"global/default_project_path",PROPERTY_HINT_GLOBAL_DIR);
set("global/default_project_export_path","");
hints["global/default_project_export_path"]=PropertyInfo(Variant::STRING,"global/default_project_export_path",PROPERTY_HINT_GLOBAL_DIR);
-
+ set("global/show_script_in_scene_tabs",false);
set("text_editor/background_color",Color::html("3b000000"));
set("text_editor/text_color",Color::html("aaaaaa"));
set("text_editor/text_selected_color",Color::html("000000"));
diff --git a/tools/editor/icons/icon_class_list.png b/tools/editor/icons/icon_class_list.png
new file mode 100644
index 0000000000..fb756c0fe1
--- /dev/null
+++ b/tools/editor/icons/icon_class_list.png
Binary files differ
diff --git a/tools/editor/icons/icon_godot.png b/tools/editor/icons/icon_godot.png
new file mode 100644
index 0000000000..e80820fc10
--- /dev/null
+++ b/tools/editor/icons/icon_godot.png
Binary files differ
diff --git a/tools/editor/icons/icon_help.png b/tools/editor/icons/icon_help.png
index 3f4f8453a7..d2085589ae 100644
--- a/tools/editor/icons/icon_help.png
+++ b/tools/editor/icons/icon_help.png
Binary files differ
diff --git a/tools/editor/icons/icon_multi_edit.png b/tools/editor/icons/icon_multi_edit.png
new file mode 100644
index 0000000000..70faee3d6a
--- /dev/null
+++ b/tools/editor/icons/icon_multi_edit.png
Binary files differ
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp
index f8c484e886..6542fc8b4a 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.cpp
+++ b/tools/editor/plugins/animation_player_editor_plugin.cpp
@@ -27,7 +27,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "animation_player_editor_plugin.h"
+#include "globals.h"
#include "io/resource_loader.h"
+#include "io/resource_saver.h"
#include "os/keyboard.h"
#include "tools/editor/editor_settings.h"
@@ -98,6 +100,8 @@ void AnimationPlayerEditor::_notification(int p_what) {
duplicate_anim->set_icon( get_icon("Duplicate","EditorIcons") );
autoplay->set_icon( get_icon("AutoPlay","EditorIcons") );
load_anim->set_icon( get_icon("Folder","EditorIcons") );
+ save_anim->set_icon(get_icon("Save", "EditorIcons"));
+ save_anim->get_popup()->connect("item_pressed", this, "_animation_save_menu");
remove_anim->set_icon( get_icon("Remove","EditorIcons") );
edit_anim->set_icon( get_icon("Edit","EditorIcons") );
blend_anim->set_icon( get_icon("Blend","EditorIcons") );
@@ -367,8 +371,78 @@ void AnimationPlayerEditor::_animation_load() {
}
file->popup_centered_ratio();
+ current_option = RESOURCE_LOAD;
+}
+
+
+void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path) {
+
+ int flg = 0;
+ if (EditorSettings::get_singleton()->get("on_save/compress_binary_resources"))
+ flg |= ResourceSaver::FLAG_COMPRESS;
+ if (EditorSettings::get_singleton()->get("on_save/save_paths_as_relative"))
+ flg |= ResourceSaver::FLAG_RELATIVE_PATHS;
+
+ String path = Globals::get_singleton()->localize_path(p_path);
+ Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
+
+ if (err != OK) {
+ accept->set_text("Error saving resource!");
+ accept->popup_centered_minsize();
+ return;
+ }
+ // EditorFileSystem::get_singleton()->update_file(path,p_resource->get_type());
+
+ ((Resource*)p_resource.ptr())->set_path(path);
+ editor->emit_signal("resource_saved", p_resource);
+
+}
+
+void AnimationPlayerEditor::_animation_save(const Ref<Resource>& p_resource) {
+
+ if (p_resource->get_path().is_resource_file()) {
+ _animation_save_in_path(p_resource, p_resource->get_path());
+ }
+ else {
+ _animation_save_as(p_resource);
+ }
+}
+
+void AnimationPlayerEditor::_animation_save_as(const Ref<Resource>& p_resource) {
+
+ file->set_mode(EditorFileDialog::MODE_SAVE_FILE);
+ bool relpaths = (p_resource->has_meta("__editor_relpaths__") && p_resource->get_meta("__editor_relpaths__").operator bool());
+
+ List<String> extensions;
+ ResourceSaver::get_recognized_extensions(p_resource, &extensions);
+ file->clear_filters();
+ for (int i = 0; i<extensions.size(); i++) {
+
+ file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
+ }
+ //file->set_current_path(current_path);
+ 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();
+ if (extensions.find(ext) == NULL) {
+ file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get()));
+ }
+ }
+ }
+ else {
+ String existing;
+ if (extensions.size()) {
+ existing = "new_" + p_resource->get_type().to_lower() + "." + extensions.front()->get().to_lower();
+ }
+ file->set_current_path(existing);
+
+ }
+ file->popup_centered_ratio();
+ file->set_title("Save Resource As..");
+ current_option = RESOURCE_SAVE;
}
void AnimationPlayerEditor::_animation_remove() {
@@ -635,38 +709,55 @@ void AnimationPlayerEditor::_animation_edit() {
//get_scene()->get_root_node()->call("_resource_selected",anim,"");
}
-void AnimationPlayerEditor::_file_selected(String p_file) {
+void AnimationPlayerEditor::_dialog_action(String p_file) {
- ERR_FAIL_COND(!player);
+ switch (current_option) {
+ case RESOURCE_LOAD: {
+ ERR_FAIL_COND(!player);
- Ref<Resource> res = ResourceLoader::load(p_file,"Animation");
- ERR_FAIL_COND(res.is_null());
- ERR_FAIL_COND( !res->is_type("Animation") );
- if (p_file.find_last("/")!=-1) {
+ Ref<Resource> res = ResourceLoader::load(p_file, "Animation");
+ ERR_FAIL_COND(res.is_null());
+ ERR_FAIL_COND(!res->is_type("Animation"));
+ if (p_file.find_last("/") != -1) {
- p_file=p_file.substr( p_file.find_last("/")+1, p_file.length() );
+ p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length());
- }
- if (p_file.find_last("\\")!=-1) {
+ }
+ if (p_file.find_last("\\") != -1) {
- p_file=p_file.substr( p_file.find_last("\\")+1, p_file.length() );
+ p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length());
- }
+ }
- if (p_file.find(".")!=-1)
- p_file=p_file.substr(0,p_file.find("."));
+ if (p_file.find(".") != -1)
+ p_file = p_file.substr(0, p_file.find("."));
- undo_redo->create_action("Load Animation");
- undo_redo->add_do_method(player,"add_animation",p_file,res);
- undo_redo->add_undo_method(player,"remove_animation",p_file);
- if (player->has_animation(p_file)) {
- undo_redo->add_undo_method(player,"add_animation",p_file,player->get_animation(p_file));
+ undo_redo->create_action("Load Animation");
+ undo_redo->add_do_method(player, "add_animation", p_file, res);
+ undo_redo->add_undo_method(player, "remove_animation", p_file);
+ if (player->has_animation(p_file)) {
+ undo_redo->add_undo_method(player, "add_animation", p_file, player->get_animation(p_file));
- }
- undo_redo->add_do_method(this,"_animation_player_changed",player);
- undo_redo->add_undo_method(this,"_animation_player_changed",player);
- undo_redo->commit_action();
+ }
+ undo_redo->add_do_method(this, "_animation_player_changed", player);
+ undo_redo->add_undo_method(this, "_animation_player_changed", player);
+ undo_redo->commit_action();
+ break;
+ }
+ case RESOURCE_SAVE: {
+
+ String current = animation->get_item_text(animation->get_selected());
+ if (current != "") {
+ Ref<Animation> anim = player->get_animation(current);
+
+ ERR_FAIL_COND(!anim->cast_to<Resource>())
+
+ RES current_res = RES(anim->cast_to<Resource>());
+ _animation_save_in_path(current_res, p_file);
+ }
+ }
+ }
}
void AnimationPlayerEditor::_scale_changed(const String& p_scale) {
@@ -730,6 +821,8 @@ void AnimationPlayerEditor::_update_player() {
blend_anim->set_disabled(animlist.size()==0);
remove_anim->set_disabled(animlist.size()==0);
resource_edit_anim->set_disabled(animlist.size()==0);
+ save_anim->set_disabled(animlist.size() == 0);
+
int active_idx=-1;
for (List<StringName>::Element *E=animlist.front();E;E=E->next()) {
@@ -1072,6 +1165,23 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
}
}
+void AnimationPlayerEditor::_animation_save_menu(int p_option) {
+
+ String current = animation->get_item_text(animation->get_selected());
+ if (current != "") {
+ Ref<Animation> anim = player->get_animation(current);
+
+ switch (p_option) {
+ case ANIM_SAVE:
+ _animation_save(anim);
+ break;
+ case ANIM_SAVE_AS:
+ _animation_save_as(anim);
+ break;
+ }
+ }
+}
+
void AnimationPlayerEditor::_unhandled_key_input(const InputEvent& p_ev) {
if (is_visible() && p_ev.type==InputEvent::KEY && p_ev.key.pressed && !p_ev.key.echo && !p_ev.key.mod.alt && !p_ev.key.mod.control && !p_ev.key.mod.meta) {
@@ -1117,7 +1227,7 @@ void AnimationPlayerEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_animation_blend"),&AnimationPlayerEditor::_animation_blend);
ObjectTypeDB::bind_method(_MD("_animation_edit"),&AnimationPlayerEditor::_animation_edit);
ObjectTypeDB::bind_method(_MD("_animation_resource_edit"),&AnimationPlayerEditor::_animation_resource_edit);
- ObjectTypeDB::bind_method(_MD("_file_selected"),&AnimationPlayerEditor::_file_selected);
+ ObjectTypeDB::bind_method(_MD("_dialog_action"),&AnimationPlayerEditor::_dialog_action);
ObjectTypeDB::bind_method(_MD("_seek_value_changed"),&AnimationPlayerEditor::_seek_value_changed);
ObjectTypeDB::bind_method(_MD("_animation_player_changed"),&AnimationPlayerEditor::_animation_player_changed);
ObjectTypeDB::bind_method(_MD("_blend_edited"),&AnimationPlayerEditor::_blend_edited);
@@ -1133,6 +1243,7 @@ void AnimationPlayerEditor::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_blend_editor_next_changed"),&AnimationPlayerEditor::_blend_editor_next_changed);
ObjectTypeDB::bind_method(_MD("_unhandled_key_input"),&AnimationPlayerEditor::_unhandled_key_input);
ObjectTypeDB::bind_method(_MD("_animation_tool_menu"),&AnimationPlayerEditor::_animation_tool_menu);
+ ObjectTypeDB::bind_method(_MD("_animation_save_menu"), &AnimationPlayerEditor::_animation_save_menu);
@@ -1170,6 +1281,17 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
load_anim->set_tooltip("Load an animation from disk.");
hb->add_child(load_anim);
+ save_anim = memnew(MenuButton);
+ save_anim->set_tooltip("Save the current animation");
+ save_anim->get_popup()->add_item("Save", ANIM_SAVE);
+ save_anim->get_popup()->add_item("Save As..", ANIM_SAVE_AS);
+ save_anim->set_focus_mode(Control::FOCUS_NONE);
+ hb->add_child(save_anim);
+
+ accept = memnew(AcceptDialog);
+ add_child(accept);
+ accept->connect("confirmed", this, "_menu_confirm_current");
+
duplicate_anim = memnew( ToolButton );
hb->add_child(duplicate_anim);
duplicate_anim->set_tooltip("Duplicate Animation");
@@ -1279,6 +1401,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
add_child(file);
name_dialog = memnew( ConfirmationDialog );
+ name_dialog->set_title("Create New Animation");
name_dialog->set_hide_on_ok(false);
add_child(name_dialog);
name = memnew( LineEdit );
@@ -1339,7 +1462,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor) {
remove_anim->connect("pressed", this,"_animation_remove");
animation->connect("item_selected", this,"_animation_selected",Vector<Variant>(),true);
resource_edit_anim->connect("pressed", this,"_animation_resource_edit");
- file->connect("file_selected", this,"_file_selected");
+ file->connect("file_selected", this,"_dialog_action");
seek->connect("value_changed", this, "_seek_value_changed",Vector<Variant>(),true);
scale->connect("text_entered", this, "_scale_changed",Vector<Variant>(),true);
editor->get_animation_editor()->connect("timeline_changed",this,"_animation_key_editor_seek");
diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h
index 5705742565..ac4d1ab6ba 100644
--- a/tools/editor/plugins/animation_player_editor_plugin.h
+++ b/tools/editor/plugins/animation_player_editor_plugin.h
@@ -55,6 +55,17 @@ class AnimationPlayerEditor : public VBoxContainer {
TOOL_EDIT_RESOURCE
};
+ enum {
+ ANIM_SAVE,
+ ANIM_SAVE_AS
+ };
+
+ enum {
+ RESOURCE_LOAD,
+ RESOURCE_SAVE
+ };
+
+
OptionButton *animation;
Button *stop;
Button *play;
@@ -70,6 +81,7 @@ class AnimationPlayerEditor : public VBoxContainer {
Button *edit_anim;
Button *resource_edit_anim;
Button *load_anim;
+ MenuButton *save_anim;
Button *blend_anim;
Button *remove_anim;
MenuButton *tool_anim;
@@ -85,6 +97,8 @@ class AnimationPlayerEditor : public VBoxContainer {
bool last_active;
EditorFileDialog *file;
+ AcceptDialog *accept;
+ int current_option;
struct BlendEditor {
@@ -116,13 +130,18 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_rename();
void _animation_name_edited();
void _animation_load();
+
+ void _animation_save_in_path(const Ref<Resource>& p_resource, const String& p_path);
+ void _animation_save(const Ref<Resource>& p_resource);
+ void _animation_save_as(const Ref<Resource>& p_resource);
+
void _animation_remove();
void _animation_blend();
void _animation_edit();
void _animation_duplicate();
void _animation_resource_edit();
void _scale_changed(const String& p_scale);
- void _file_selected(String p_file);
+ void _dialog_action(String p_file);
void _seek_frame_changed(const String& p_frame);
void _seek_value_changed(float p_value);
void _blend_editor_next_changed(const String& p_string);
@@ -141,6 +160,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_key_editor_anim_len_changed(float p_new);
void _unhandled_key_input(const InputEvent& p_ev);
void _animation_tool_menu(int p_option);
+ void _animation_save_menu(int p_option);
AnimationPlayerEditor();
protected:
diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp
index 4599dbfb54..261d862b37 100644
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ b/tools/editor/plugins/baked_light_baker.cpp
@@ -115,6 +115,8 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
if (!mat_map.has(mat)) {
MeshMaterial mm;
+ mm.is_double_sided = mat->get_flag(Material::FLAG_DOUBLE_SIDED);
+ mm.use_alpha = false;
Ref<FixedMaterial> fm = mat;
if (fm.is_valid()) {
@@ -128,6 +130,8 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
mm.specular.color=mm.specular.color.to_linear();
mm.specular.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_SPECULAR));
+
+ mm.use_alpha = fm->get_fixed_flag(FixedMaterial::FLAG_USE_ALPHA);
} else {
mm.diffuse.color=Color(1,1,1,1);
@@ -311,7 +315,12 @@ void BakedLightBaker::_parse_geometry(Node* p_node) {
lights.push_back(dirl);
}
- } else if (p_node->cast_to<Spatial>()){
+ }
+ else if (p_node->cast_to<BakedLightSampler>()){
+ // Ignore meshes and lights contained in baked light samplers
+ return;
+ }
+ else if (p_node->cast_to<Spatial>()){
Spatial *sp = p_node->cast_to<Spatial>();
@@ -472,6 +481,7 @@ BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size,
BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth);
BVH *_new = memnew(BVH);
+ _new->id=-1;
_new->aabb=aabb;
_new->center=aabb.pos+aabb.size*0.5;
_new->children[0]=left;
@@ -488,6 +498,7 @@ void BakedLightBaker::_make_bvh() {
int max_depth=0;
for(int i=0;i<triangles.size();i++) {
bases[i]=memnew( BVH );
+ bases[i]->id=i;
bases[i]->leaf=&triangles[i];
bases[i]->aabb.pos=triangles[i].vertices[0];
bases[i]->aabb.expand_to(triangles[i].vertices[1]);
@@ -949,7 +960,7 @@ void BakedLightBaker::_plot_light(ThreadStack& thread_stack,const Vector3& p_plo
}
-float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce,bool p_only_dist) {
+float BakedLightBaker::_throw_ray(ThreadStack& thread_stack, bool p_bake_direct, const Vector3& p_begin, const Vector3& p_end, float p_rest, const Color& p_light, float *p_att_curve, float p_att_pos, int p_att_curve_len, int p_bounces, bool p_first_bounce, bool p_only_dist, Vector<int> &p_ignore_list) {
uint32_t* stack = thread_stack.ray_stack;
@@ -978,6 +989,7 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
Vector3 r_point;
Vector3 end=p_end;
+ int triangle_id = -1;
Triangle *triangle=NULL;
//for(int i=0;i<max_depth;i++)
@@ -986,7 +998,7 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
int level=0;
//AABB ray_aabb;
//ray_aabb.pos=p_begin;
- //ray_aabb.expand_to(p_end);
+ //ray_aabb.expand_to(end);
const BVH *bvhptr = bvh;
@@ -1004,47 +1016,53 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
switch(mode) {
case TEST_AABB_BIT: {
- if (b.leaf) {
+ if (p_ignore_list.find(b.id)==-1) {
+ if (b.leaf) {
- Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
+ Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
- Vector3 res;
+ Vector3 res;
- if (f3.intersects_segment(p_begin,end,&res)) {
+ if (f3.intersects_segment(p_begin,end,&res)) {
- float nd = n.dot(res);
- if (nd<d) {
+ float nd = n.dot(res);
+ if (nd<d) {
- d=nd;
- r_point=res;
- end=res;
- len=(p_begin-end).length();
- r_normal=f3.get_plane().get_normal();
- triangle=b.leaf;
- inters=true;
- }
+ d=nd;
+ r_point=res;
+ end=res;
+ len=(p_begin-end).length();
+ r_normal=f3.get_plane().get_normal();
+ triangle=b.leaf;
+ triangle_id=b.id;
+ inters=true;
+ }
- }
+ }
- stack[level]=VISIT_DONE_BIT;
- } else {
+ stack[level]=VISIT_DONE_BIT;
+ } else {
- bool valid = b.aabb.smits_intersect_ray(p_begin,n,0,len);
- //bool valid = b.aabb.intersects_segment(p_begin,p_end);
- // bool valid = b.aabb.intersects(ray_aabb);
+ bool valid = b.aabb.smits_intersect_ray(p_begin,n,0,len);
+ //bool valid = b.aabb.intersects_segment(p_begin,end);
+ // bool valid = b.aabb.intersects(ray_aabb);
- if (!valid) {
+ if (!valid) {
- stack[level]=VISIT_DONE_BIT;
+ stack[level]=VISIT_DONE_BIT;
- } else {
+ } else {
- stack[level]=VISIT_LEFT_BIT;
- }
+ stack[level]=VISIT_LEFT_BIT;
+ }
+ }
+ }
+ else {
+ stack[level] = VISIT_DONE_BIT;
}
} continue;
@@ -1099,17 +1117,36 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
}
- if (n.dot(r_normal)>0)
- return -1;
-
- if (n.dot(r_normal)>0)
- r_normal=-r_normal;
+ bool passthrough = false;
//ok...
Color diffuse_at_point(0.8,0.8,0.8);
Color specular_at_point(0.0,0.0,0.0);
+ if (triangle->material) {
+
+ if ((triangle->material->is_double_sided == true || triangle->material->use_alpha == true) && use_translucency == true) {
+ if (n.dot(r_normal)>0)
+ r_normal = -r_normal;
+
+ if (triangle->material->use_alpha == true)
+ passthrough = true;
+ }
+ else {
+ if (n.dot(r_normal)>0)
+ return -1;
+ }
+
+ //triangle->get_uv(r_point);
+
+ diffuse_at_point = triangle->material->diffuse.get_color(uv);
+ specular_at_point = triangle->material->specular.get_color(uv);
+ }
+ else {
+ if (n.dot(r_normal)>0)
+ return -1;
+ }
float dist = p_begin.distance_to(r_point);
@@ -1139,23 +1176,18 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
//the multiplication can happen with more detail in the shader
-
- if (triangle->material) {
-
- //triangle->get_uv(r_point);
-
- diffuse_at_point=triangle->material->diffuse.get_color(uv);
- specular_at_point=triangle->material->specular.get_color(uv);
- }
-
-
diffuse_at_point.r=res_light.r*diffuse_at_point.r;
diffuse_at_point.g=res_light.g*diffuse_at_point.g;
diffuse_at_point.b=res_light.b*diffuse_at_point.b;
float ret=1e6;
- if (p_bounces>0) {
+ if (passthrough == true && triangle_id !=-1)
+ {
+ p_ignore_list.push_back(triangle_id);
+ ret=_throw_ray(thread_stack, p_bake_direct, r_point, p_end, p_rest, p_light, p_att_curve, p_att_pos, p_att_curve_len, p_bounces, p_first_bounce, p_only_dist, p_ignore_list);
+ }
+ else if (p_bounces>0 ) {
p_rest-=dist;
@@ -1226,33 +1258,37 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c
bool skip=false;
- if (!p_first_bounce || p_bake_direct) {
-
+ if (passthrough == false) {
+ if (!p_first_bounce || p_bake_direct) {
- float r = plot_size * cell_size*2;
- if (dist<r) {
- //avoid accumulaiton of light on corners
- //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
- skip=true;
- } else {
-
-
- Vector3 c1=r_normal.cross(n).normalized();
- Vector3 c2=r_normal.cross(c1).normalized();
- double r1 = double(rand())/RAND_MAX;
- double r2 = double(rand())/RAND_MAX;
- double r3 = double(rand())/RAND_MAX;
- Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.25)).normalized();
- float d =_throw_ray(thread_stack,p_bake_direct,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1,false,true);
- r = plot_size*cell_size*ao_radius;
- if (d>0 && d<r) {
+ float r = plot_size * cell_size * 2;
+ if (dist < r) {
//avoid accumulaiton of light on corners
//plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
- skip=true;
+ skip = true;
- } else {
- //plot_light=Color(0,0,0,0);
+ }
+ else {
+
+
+ Vector3 c1 = r_normal.cross(n).normalized();
+ Vector3 c2 = r_normal.cross(c1).normalized();
+ double r1 = double(rand()) / RAND_MAX;
+ double r2 = double(rand()) / RAND_MAX;
+ double r3 = double(rand()) / RAND_MAX;
+ Vector3 rn = ((c1*(r1 - 0.5)) + (c2*(r2 - 0.5)) + (r_normal*r3*0.25)).normalized();
+ float d = _throw_ray(thread_stack, p_bake_direct, r_point, r_point + rn*p_rest, p_rest, diffuse_at_point, p_att_curve, p_att_pos, p_att_curve_len, p_bounces - 1, false, true);
+ r = plot_size*cell_size*ao_radius;
+ if (d > 0 && d < r) {
+ //avoid accumulaiton of light on corners
+ //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size);
+ skip = true;
+
+ }
+ else {
+ //plot_light=Color(0,0,0,0);
+ }
}
}
}
diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h
index 8fbeeddc6a..58197283a2 100644
--- a/tools/editor/plugins/baked_light_baker.h
+++ b/tools/editor/plugins/baked_light_baker.h
@@ -92,6 +92,9 @@ public:
Param diffuse;
Param specular;
Param emission;
+
+ bool is_double_sided;
+ bool use_alpha;
};
struct Triangle {
@@ -154,6 +157,7 @@ public:
struct BVH {
+ int id;
AABB aabb;
Vector3 center;
Triangle *leaf;
@@ -307,7 +311,7 @@ public:
void _plot_light(ThreadStack& thread_stack,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Color& p_tint_light,bool p_only_full,const Plane& p_plane);
//void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light);
- float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false);
+ float _throw_ray(ThreadStack& thread_stack,bool p_bake_direct,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false,bool p_only_dist=false, Vector<int>&p_ignore_list=Vector<int>());
float total_light_area;
diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp
index d318f6f6fa..b03eed77b1 100644
--- a/tools/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp
@@ -41,9 +41,9 @@
class SnapDialog : public ConfirmationDialog {
OBJ_TYPE(SnapDialog,ConfirmationDialog);
-
-protected:
- friend class CanvasItemEditor;
+
+friend class CanvasItemEditor;
+
SpinBox *grid_offset_x;
SpinBox *grid_offset_y;
SpinBox *grid_step_x;
@@ -58,63 +58,75 @@ public:
Label *label;
VBoxContainer *container;
GridContainer *child_container;
-
+
set_title("Configure Snap");
get_ok()->set_text("Close");
- container = memnew(VBoxContainer);
+
+ container = memnew( VBoxContainer );
add_child(container);
-
- child_container = memnew(GridContainer);
+ set_child_rect(container);
+
+ child_container = memnew( GridContainer );
child_container->set_columns(3);
container->add_child(child_container);
-
- label = memnew(Label);
+
+ label = memnew( Label );
label->set_text("Grid Offset:");
child_container->add_child(label);
- grid_offset_x=memnew(SpinBox);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grid_offset_x = memnew( SpinBox );
grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_x->set_suffix("px");
child_container->add_child(grid_offset_x);
- grid_offset_y=memnew(SpinBox);
+
+ grid_offset_y = memnew( SpinBox );
grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_y->set_suffix("px");
child_container->add_child(grid_offset_y);
- label = memnew(Label);
+ label = memnew( Label );
label->set_text("Grid Step:");
child_container->add_child(label);
- grid_step_x=memnew(SpinBox);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grid_step_x = memnew( SpinBox );
grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
grid_step_x->set_suffix("px");
child_container->add_child(grid_step_x);
- grid_step_y=memnew(SpinBox);
+
+ grid_step_y = memnew( SpinBox );
grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
grid_step_y->set_suffix("px");
child_container->add_child(grid_step_y);
-
- container->add_child(memnew(HSeparator));
- child_container = memnew(GridContainer);
+ container->add_child( memnew( HSeparator ) );
+
+ child_container = memnew( GridContainer );
child_container->set_columns(2);
container->add_child(child_container);
- label = memnew(Label);
+ label = memnew( Label );
label->set_text("Rotation Offset:");
child_container->add_child(label);
- rotation_offset=memnew(SpinBox);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ rotation_offset = memnew( SpinBox );
rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_suffix("deg");
child_container->add_child(rotation_offset);
-
- label = memnew(Label);
+
+ label = memnew( Label );
label->set_text("Rotation Step:");
child_container->add_child(label);
- rotation_step=memnew(SpinBox);
+ label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ rotation_step = memnew( SpinBox );
rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_step->set_suffix("deg");
@@ -2278,7 +2290,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
} break;
case SNAP_CONFIGURE: {
((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
- snap_dialog->popup_centered(Size2(200,160));
+ snap_dialog->popup_centered(Size2(220,160));
} break;
case ZOOM_IN: {
zoom=zoom*(1.0/0.5);
@@ -3173,7 +3185,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_item("Paste Pose",ANIM_PASTE_POSE);
p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K);
- snap_dialog = memnew(SnapDialog);
+ snap_dialog = memnew( SnapDialog );
snap_dialog->connect("confirmed",this,"_snap_changed");
add_child(snap_dialog);
diff --git a/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp b/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 62cf1b4acb..f56b9a2fd9 100644
--- a/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -115,6 +115,18 @@ void CollisionShape2DEditor::set_handle(int idx, Point2& p_point) {
} break;
case LINE_SHAPE: {
+ if (idx<2) {
+ Ref<LineShape2D> line = node->get_shape();
+
+ if (idx==0){
+ line->set_d(p_point.length());
+ }else{
+ line->set_normal(p_point/30.0);
+ }
+
+ canvas_item_editor->get_viewport_control()->update();
+ }
+
} break;
@@ -200,6 +212,19 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant& p_org) {
} break;
case LINE_SHAPE: {
+ Ref<LineShape2D> line = node->get_shape();
+
+ if (idx==0) {
+ undo_redo->add_do_method(line.ptr(),"set_d",line->get_d());
+ undo_redo->add_do_method(c,"update");
+ undo_redo->add_undo_method(line.ptr(),"set_d",p_org);
+ undo_redo->add_undo_method(c,"update");
+ } else {
+ undo_redo->add_do_method(line.ptr(),"set_normal",line->get_normal());
+ undo_redo->add_do_method(c,"update");
+ undo_redo->add_undo_method(line.ptr(),"set_normal",p_org);
+ undo_redo->add_undo_method(c,"update");
+ }
} break;
@@ -418,6 +443,14 @@ void CollisionShape2DEditor::_canvas_draw() {
} break;
case LINE_SHAPE: {
+ Ref<LineShape2D> shape = node->get_shape();
+
+ handles.resize(2);
+ handles[0] = shape->get_normal() * shape->get_d();
+ handles[1] = shape->get_normal() * (shape->get_d() + 30.0);
+
+ c->draw_texture(h,gt.xform(handles[0])-size);
+ c->draw_texture(h,gt.xform(handles[1])-size);
} break;
diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp
index 13d4c8db5a..cea774f94b 100644
--- a/tools/editor/plugins/mesh_editor_plugin.cpp
+++ b/tools/editor/plugins/mesh_editor_plugin.cpp
@@ -160,7 +160,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CREATE_OUTLINE_MESH: {
- outline_dialog->popup_centered_minsize();
+ outline_dialog->popup_centered(Vector2(200, 90));
} break;
}
@@ -212,7 +212,6 @@ MeshInstanceEditor::MeshInstanceEditor() {
options = memnew( MenuButton );
- //add_child(options);
SpatialEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text("Mesh");
@@ -231,14 +230,20 @@ MeshInstanceEditor::MeshInstanceEditor() {
options->get_popup()->connect("item_pressed", this,"_menu_option");
outline_dialog = memnew( ConfirmationDialog );
- outline_dialog->set_title("Outline Size: ");
+ outline_dialog->set_title("Create Outline Mesh");
+ outline_dialog->get_ok()->set_text("Create");
+
+ VBoxContainer *outline_dialog_vbc = memnew( VBoxContainer );
+ outline_dialog->add_child(outline_dialog_vbc);
+ outline_dialog->set_child_rect(outline_dialog_vbc);
+
outline_size = memnew( SpinBox );
outline_size->set_min(0.001);
outline_size->set_max(1024);
outline_size->set_step(0.001);
outline_size->set_val(0.05);
- outline_dialog->add_child(outline_size);
- outline_dialog->set_child_rect(outline_size);
+ outline_dialog_vbc->add_margin_child("Outline Size:",outline_size);
+
add_child(outline_dialog);
outline_dialog->connect("confirmed",this,"_create_outline_mesh");
diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp
index 3c88b1d3a8..a5c823f8bd 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.cpp
+++ b/tools/editor/plugins/multimesh_editor_plugin.cpp
@@ -289,7 +289,7 @@ void MultiMeshEditor::_menu_option(int p_option) {
_last_pp_node=node;
}
- populate_dialog->popup_centered(Size2(250,395));
+ populate_dialog->popup_centered(Size2(250,380));
} break;
}
@@ -325,10 +325,8 @@ MultiMeshEditor::MultiMeshEditor() {
options = memnew( MenuButton );
- //add_child(options);
SpatialEditor::get_singleton()->add_control_to_menu_panel(options);
- options->set_area_as_parent_rect();
-
+
options->set_text("MultiMesh");
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MultiMeshInstance","EditorIcons"));
@@ -373,12 +371,12 @@ MultiMeshEditor::MultiMeshEditor() {
populate_axis->select(2);
vbc->add_margin_child("Mesh Up Axis:",populate_axis);
- populate_rotate_random = memnew( HScrollBar );
+ populate_rotate_random = memnew( HSlider );
populate_rotate_random->set_max(1);
populate_rotate_random->set_step(0.01);
vbc->add_margin_child("Random Rotation:",populate_rotate_random);
- populate_tilt_random = memnew( HScrollBar );
+ populate_tilt_random = memnew( HSlider );
populate_tilt_random->set_max(1);
populate_tilt_random->set_step(0.01);
vbc->add_margin_child("Random Tilt:",populate_tilt_random);
@@ -416,8 +414,7 @@ MultiMeshEditor::MultiMeshEditor() {
std->connect("selected",this,"_browsed");
_last_pp_node=NULL;
- //options->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
- //options->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
+
err_dialog = memnew( AcceptDialog );
add_child(err_dialog);
}
@@ -451,13 +448,6 @@ MultiMeshEditorPlugin::MultiMeshEditorPlugin(EditorNode *p_node) {
multimesh_editor = memnew( MultiMeshEditor );
editor->get_viewport()->add_child(multimesh_editor);
-// multimesh_editor->set_anchor(MARGIN_LEFT,Control::ANCHOR_END);
-// multimesh_editor->set_anchor(MARGIN_RIGHT,Control::ANCHOR_END);
- multimesh_editor->set_margin(MARGIN_LEFT,253);
- multimesh_editor->set_margin(MARGIN_RIGHT,310);
- multimesh_editor->set_margin(MARGIN_TOP,0);
- multimesh_editor->set_margin(MARGIN_BOTTOM,10);
-
multimesh_editor->options->hide();
}
diff --git a/tools/editor/plugins/multimesh_editor_plugin.h b/tools/editor/plugins/multimesh_editor_plugin.h
index 4f0c0d008b..edc3dfd55f 100644
--- a/tools/editor/plugins/multimesh_editor_plugin.h
+++ b/tools/editor/plugins/multimesh_editor_plugin.h
@@ -42,10 +42,10 @@ class MultiMeshEditor : public Control {
OBJ_TYPE(MultiMeshEditor, Control );
- friend class MultiMeshEditorPlugin;
+friend class MultiMeshEditorPlugin;
AcceptDialog *err_dialog;
- MenuButton * options;
+ MenuButton * options;
MultiMeshInstance *_last_pp_node;
bool browsing_source;
@@ -59,8 +59,8 @@ class MultiMeshEditor : public Control {
ConfirmationDialog *populate_dialog;
OptionButton *populate_axis;
- HScrollBar *populate_rotate_random;
- HScrollBar *populate_tilt_random;
+ HSlider *populate_rotate_random;
+ HSlider *populate_tilt_random;
SpinBox *populate_scale_random;
SpinBox *populate_scale;
SpinBox *populate_amount;
diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp
index cf9a6c41a4..b497458a2a 100644
--- a/tools/editor/plugins/sample_library_editor_plugin.cpp
+++ b/tools/editor/plugins/sample_library_editor_plugin.cpp
@@ -49,9 +49,13 @@ void SampleLibraryEditor::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
play->set_icon( get_icon("Play","EditorIcons") );
+ play->set_tooltip("Play Sample");
stop->set_icon( get_icon("Stop","EditorIcons") );
+ stop->set_tooltip("Stop Sample");
load->set_icon( get_icon("Folder","EditorIcons") );
+ load->set_tooltip("Open Sample File(s)");
_delete->set_icon( get_icon("Del","EditorIcons") );
+ _delete->set_tooltip("Remove Sample");
}
if (p_what==NOTIFICATION_READY) {
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index bd0f580a34..65ed420a51 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -572,28 +572,119 @@ void ScriptEditor::_goto_script_line(REF p_script,int p_line) {
}
+
+void ScriptEditor::_update_history_arrows() {
+
+ script_back->set_disabled( history_pos<=0 );
+ script_forward->set_disabled( history_pos>=history.size()-1 );
+}
+
+
+void ScriptEditor::_go_to_tab(int p_idx) {
+
+ Node *cn = tab_container->get_child(p_idx);
+ if (!cn)
+ return;
+ Control *c = cn->cast_to<Control>();
+ if (!c)
+ return;
+
+ if (history_pos>=0 && history_pos<history.size() && history[history_pos].control==tab_container->get_current_tab_control()) {
+
+ Node *n = tab_container->get_current_tab_control();
+
+ if (n->cast_to<ScriptTextEditor>()) {
+
+ history[history_pos].scroll_pos=n->cast_to<ScriptTextEditor>()->get_text_edit()->get_v_scroll();
+ history[history_pos].cursor_column=n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_get_column();
+ history[history_pos].cursor_row=n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_get_line();
+ }
+ if (n->cast_to<EditorHelp>()) {
+
+ history[history_pos].scroll_pos=n->cast_to<EditorHelp>()->get_scroll();
+ }
+ }
+
+ history.resize(history_pos+1);
+ ScriptHistory sh;
+ sh.control=c;
+ sh.scroll_pos=0;
+
+ history.push_back(sh);
+ history_pos++;
+
+
+ tab_container->set_current_tab(p_idx);
+
+ c = tab_container->get_current_tab_control();
+
+ if (c->cast_to<ScriptTextEditor>()) {
+
+ script_name_label->set_text(c->cast_to<ScriptTextEditor>()->get_name());
+ script_icon->set_texture(c->cast_to<ScriptTextEditor>()->get_icon());
+ if (is_visible())
+ c->cast_to<ScriptTextEditor>()->get_text_edit()->grab_focus();
+ }
+ if (c->cast_to<EditorHelp>()) {
+
+ script_name_label->set_text(c->cast_to<EditorHelp>()->get_class_name());
+ script_icon->set_texture(get_icon("Help","EditorIcons"));
+ if (is_visible())
+ c->cast_to<EditorHelp>()->set_focused();
+ }
+
+
+
+ c->set_meta("__editor_pass",++edit_pass);
+ _update_history_arrows();
+ _update_script_colors();
+}
+
void ScriptEditor::_close_current_tab() {
int selected = tab_container->get_current_tab();
if (selected<0 || selected>=tab_container->get_child_count())
return;
+ Node *tselected = tab_container->get_child(selected);
ScriptTextEditor *current = tab_container->get_child(selected)->cast_to<ScriptTextEditor>();
- if (!current)
- return;
+ if (current) {
+ apply_scripts();
+ }
- apply_scripts();
+ //remove from history
+ history.resize(history_pos+1);
+
+ for(int i=0;i<history.size();i++) {
+ if (history[i].control==tselected) {
+ history.remove(i);
+ i--;
+ history_pos--;
+ }
+ }
+
+ if (history_pos>=history.size()) {
+ history_pos=history.size()-1;
+ }
int idx = tab_container->get_current_tab();
- memdelete(current);
+ memdelete(tselected);
if (idx>=tab_container->get_child_count())
idx=tab_container->get_child_count()-1;
if (idx>=0) {
+
+ if (history_pos>=0) {
+ idx = history[history_pos].control->get_index();
+ }
tab_container->set_current_tab(idx);
+
//script_list->select(idx);
}
+ _update_history_arrows();
+
+
_update_script_names();
EditorNode::get_singleton()->save_layout();
@@ -755,33 +846,15 @@ void ScriptEditor::swap_lines(TextEdit *tx, int line1, int line2)
void ScriptEditor::_menu_option(int p_option) {
- if (p_option==FILE_OPEN) {
- editor->open_resource("Script");
- return;
- }
- int selected = tab_container->get_current_tab();
- if (selected<0 || selected>=tab_container->get_child_count())
- return;
-
- ScriptTextEditor *current = tab_container->get_child(selected)->cast_to<ScriptTextEditor>();
- if (!current)
- return;
-
switch(p_option) {
case FILE_NEW: {
script_create_dialog->config("Node", ".gd");
script_create_dialog->popup_centered(Size2(300, 300));
} break;
- case FILE_SAVE: {
- if (!_test_script_times_on_disk())
- return;
- editor->save_resource( current->get_edited_script() );
-
- } break;
- case FILE_SAVE_AS: {
-
- editor->save_resource_as( current->get_edited_script() );
+ case FILE_OPEN: {
+ editor->open_resource("Script");
+ return;
} break;
case FILE_SAVE_ALL: {
@@ -806,387 +879,470 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
- case EDIT_UNDO: {
- current->get_text_edit()->undo();
- current->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_REDO: {
- current->get_text_edit()->redo();
- current->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_CUT: {
-
- current->get_text_edit()->cut();
- current->get_text_edit()->call_deferred("grab_focus");
- } break;
- case EDIT_COPY: {
- current->get_text_edit()->copy();
- current->get_text_edit()->call_deferred("grab_focus");
-
- } break;
- case EDIT_PASTE: {
- current->get_text_edit()->paste();
- current->get_text_edit()->call_deferred("grab_focus");
+ case SEARCH_HELP: {
+ help_search_dialog->popup("current");
} break;
- case EDIT_SELECT_ALL: {
-
- current->get_text_edit()->select_all();
- current->get_text_edit()->call_deferred("grab_focus");
+ case SEARCH_CLASSES: {
- } break;
- case EDIT_MOVE_LINE_UP: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
-
- if (tx->is_selection_active())
- {
- int from_line = tx->get_selection_from_line();
- int from_col = tx->get_selection_from_column();
- int to_line = tx->get_selection_to_line();
- int to_column = tx->get_selection_to_column();
-
- for (int i = from_line; i <= to_line; i++)
- {
- int line_id = i;
- int next_id = i - 1;
-
- if (line_id == 0 || next_id < 0)
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- int from_line_up = from_line > 0 ? from_line-1 : from_line;
- int to_line_up = to_line > 0 ? to_line-1 : to_line;
- tx->select(from_line_up, from_col, to_line_up, to_column);
- }
- else
- {
- int line_id = tx->cursor_get_line();
- int next_id = line_id - 1;
-
- if (line_id == 0 || next_id < 0)
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- tx->update();
-
- } break;
- case EDIT_MOVE_LINE_DOWN: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
-
- if (tx->is_selection_active())
- {
- int from_line = tx->get_selection_from_line();
- int from_col = tx->get_selection_from_column();
- int to_line = tx->get_selection_to_line();
- int to_column = tx->get_selection_to_column();
-
- for (int i = to_line; i >= from_line; i--)
- {
- int line_id = i;
- int next_id = i + 1;
-
- if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- int from_line_down = from_line < tx->get_line_count() ? from_line+1 : from_line;
- int to_line_down = to_line < tx->get_line_count() ? to_line+1 : to_line;
- tx->select(from_line_down, from_col, to_line_down, to_column);
- }
- else
- {
- int line_id = tx->cursor_get_line();
- int next_id = line_id + 1;
-
- if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
- return;
-
- swap_lines(tx, line_id, next_id);
- }
- tx->update();
-
- } break;
- case EDIT_INDENT_LEFT: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
-
-
- if (tx->is_selection_active())
- {
- int begin = tx->get_selection_from_line();
- int end = tx->get_selection_to_line();
- for (int i = begin; i <= end; i++)
- {
- String line_text = tx->get_line(i);
- // begins with tab
- if (line_text.begins_with("\t"))
- {
- line_text = line_text.substr(1, line_text.length());
- tx->set_line(i, line_text);
- }
- // begins with 4 spaces
- else if (line_text.begins_with(" "))
- {
- line_text = line_text.substr(4, line_text.length());
- tx->set_line(i, line_text);
- }
- }
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
- // begins with tab
- if (line_text.begins_with("\t"))
- {
- line_text = line_text.substr(1, line_text.length());
- tx->set_line(begin, line_text);
- }
- // begins with 4 spaces
- else if (line_text.begins_with(" "))
- {
- line_text = line_text.substr(4, line_text.length());
- tx->set_line(begin, line_text);
- }
- }
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_INDENT_RIGHT: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
-
- if (tx->is_selection_active())
- {
- int begin = tx->get_selection_from_line();
- int end = tx->get_selection_to_line();
- for (int i = begin; i <= end; i++)
- {
- String line_text = tx->get_line(i);
- line_text = '\t' + line_text;
- tx->set_line(i, line_text);
- }
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
- line_text = '\t' + line_text;
- tx->set_line(begin, line_text);
- }
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_CLONE_DOWN: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
- int line = tx->cursor_get_line();
- int next_line = line + 1;
-
- if (line == tx->get_line_count() || next_line > tx->get_line_count())
- return;
-
- String line_clone = tx->get_line(line);
- tx->insert_at(line_clone, next_line);
- tx->update();
-
- } break;
- case EDIT_TOGGLE_COMMENT: {
-
- TextEdit *tx = current->get_text_edit();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
-
-
-
- if (tx->is_selection_active())
- {
- int begin = tx->get_selection_from_line();
- int end = tx->get_selection_to_line();
- for (int i = begin; i <= end; i++)
- {
- String line_text = tx->get_line(i);
-
- if (line_text.begins_with("#"))
- line_text = line_text.substr(1, line_text.length());
- else
- line_text = "#" + line_text;
- tx->set_line(i, line_text);
- }
- }
- else
- {
- int begin = tx->cursor_get_line();
- String line_text = tx->get_line(begin);
-
- if (line_text.begins_with("#"))
- line_text = line_text.substr(1, line_text.length());
- else
- line_text = "#" + line_text;
- tx->set_line(begin, line_text);
- }
- tx->update();
- //tx->deselect();
-
- } break;
- case EDIT_COMPLETE: {
-
- current->get_text_edit()->query_code_comple();
+ if (tab_container->get_tab_count()==0)
+ break;
- } break;
- case EDIT_AUTO_INDENT: {
+ String current;
- TextEdit *te = current->get_text_edit();
- String text = te->get_text();
- Ref<Script> scr = current->get_edited_script();
- if (scr.is_null())
- return;
- int begin,end;
- if (te->is_selection_active()) {
- begin=te->get_selection_from_line();
- end=te->get_selection_to_line();
- } else {
- begin=0;
- end=te->get_line_count()-1;
+ EditorHelp *eh = tab_container->get_child( tab_container->get_current_tab() )->cast_to<EditorHelp>();
+ if (eh) {
+ current=eh->get_class_name();
}
- scr->get_language()->auto_indent_code(text,begin,end);
- te->set_text(text);
+ help_index->popup_centered_ratio(0.6);
+ if (current!="") {
+ help_index->call_deferred("select_class",current);
+ }
} break;
- case SEARCH_FIND: {
+ case SEARCH_WEBSITE: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_search();
+ OS::get_singleton()->shell_open("http://www.godotengine.org/projects/godot-engine/wiki/Documentation#Tutorials");
} break;
- case SEARCH_FIND_NEXT: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->search_next();
- } break;
- case SEARCH_REPLACE: {
+ case WINDOW_NEXT: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_replace();
+ _history_forward();
} break;
- case SEARCH_LOCATE_FUNCTION: {
-
- if (!current)
- return;
- quick_open->popup(current->get_functions());
+ case WINDOW_PREV: {
+ _history_back();
} break;
- case SEARCH_GOTO_LINE: {
- goto_line_dialog->popup_find_line(current->get_text_edit());
- } break;
- case DEBUG_TOGGLE_BREAKPOINT: {
- int line=current->get_text_edit()->cursor_get_line();
- bool dobreak = !current->get_text_edit()->is_line_set_as_breakpoint(line);
- current->get_text_edit()->set_line_as_breakpoint(line,dobreak);
- get_debugger()->set_breakpoint(current->get_edited_script()->get_path(),line+1,dobreak);
- } break;
- case DEBUG_NEXT: {
+ }
- if (debugger)
- debugger->debug_next();
- } break;
- case DEBUG_STEP: {
- if (debugger)
- debugger->debug_step();
+ int selected = tab_container->get_current_tab();
+ if (selected<0 || selected>=tab_container->get_child_count())
+ return;
- } break;
- case DEBUG_BREAK: {
+ ScriptTextEditor *current = tab_container->get_child(selected)->cast_to<ScriptTextEditor>();
+ if (current) {
+
+ switch(p_option) {
+ case FILE_NEW: {
+ script_create_dialog->config("Node", ".gd");
+ script_create_dialog->popup_centered(Size2(300, 300));
+ } break;
+ case FILE_SAVE: {
+ if (!_test_script_times_on_disk())
+ return;
+ editor->save_resource( current->get_edited_script() );
+
+ } break;
+ case FILE_SAVE_AS: {
+
+ editor->save_resource_as( current->get_edited_script() );
+
+ } break;
+ case EDIT_UNDO: {
+ current->get_text_edit()->undo();
+ current->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_REDO: {
+ current->get_text_edit()->redo();
+ current->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_CUT: {
+
+ current->get_text_edit()->cut();
+ current->get_text_edit()->call_deferred("grab_focus");
+ } break;
+ case EDIT_COPY: {
+ current->get_text_edit()->copy();
+ current->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_PASTE: {
+ current->get_text_edit()->paste();
+ current->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_SELECT_ALL: {
+
+ current->get_text_edit()->select_all();
+ current->get_text_edit()->call_deferred("grab_focus");
+
+ } break;
+ case EDIT_MOVE_LINE_UP: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+
+ if (tx->is_selection_active())
+ {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = from_line; i <= to_line; i++)
+ {
+ int line_id = i;
+ int next_id = i - 1;
+
+ if (line_id == 0 || next_id < 0)
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ int from_line_up = from_line > 0 ? from_line-1 : from_line;
+ int to_line_up = to_line > 0 ? to_line-1 : to_line;
+ tx->select(from_line_up, from_col, to_line_up, to_column);
+ }
+ else
+ {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id - 1;
- if (debugger)
- debugger->debug_break();
+ if (line_id == 0 || next_id < 0)
+ return;
- } break;
- case DEBUG_CONTINUE: {
+ swap_lines(tx, line_id, next_id);
+ }
+ tx->update();
+
+ } break;
+ case EDIT_MOVE_LINE_DOWN: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+
+ if (tx->is_selection_active())
+ {
+ int from_line = tx->get_selection_from_line();
+ int from_col = tx->get_selection_from_column();
+ int to_line = tx->get_selection_to_line();
+ int to_column = tx->get_selection_to_column();
+
+ for (int i = to_line; i >= from_line; i--)
+ {
+ int line_id = i;
+ int next_id = i + 1;
+
+ if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
+ return;
+
+ swap_lines(tx, line_id, next_id);
+ }
+ int from_line_down = from_line < tx->get_line_count() ? from_line+1 : from_line;
+ int to_line_down = to_line < tx->get_line_count() ? to_line+1 : to_line;
+ tx->select(from_line_down, from_col, to_line_down, to_column);
+ }
+ else
+ {
+ int line_id = tx->cursor_get_line();
+ int next_id = line_id + 1;
- if (debugger)
- debugger->debug_continue();
+ if (line_id == tx->get_line_count()-1 || next_id > tx->get_line_count())
+ return;
- } break;
- case DEBUG_SHOW: {
- if (debugger) {
- bool visible = debug_menu->get_popup()->is_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW) );
- debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), !visible);
- if (visible)
- debugger->hide();
+ swap_lines(tx, line_id, next_id);
+ }
+ tx->update();
+
+ } break;
+ case EDIT_INDENT_LEFT: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+
+
+ if (tx->is_selection_active())
+ {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+ for (int i = begin; i <= end; i++)
+ {
+ String line_text = tx->get_line(i);
+ // begins with tab
+ if (line_text.begins_with("\t"))
+ {
+ line_text = line_text.substr(1, line_text.length());
+ tx->set_line(i, line_text);
+ }
+ // begins with 4 spaces
+ else if (line_text.begins_with(" "))
+ {
+ line_text = line_text.substr(4, line_text.length());
+ tx->set_line(i, line_text);
+ }
+ }
+ }
else
- debugger->show();
- }
- } break;
- case HELP_CONTEXTUAL: {
- String text = current->get_text_edit()->get_selection_text();
- if (text == "")
- text = current->get_text_edit()->get_word_under_cursor();
- if (text != "")
- editor->emit_signal("request_help", text);
- } break;
- case FILE_CLOSE: {
- if (current->get_text_edit()->get_version()!=current->get_text_edit()->get_saved_version()) {
- erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\"");
- erase_tab_confirm->popup_centered_minsize();
- } else {
- _close_current_tab();
- }
- } break;
- case WINDOW_MOVE_LEFT: {
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ // begins with tab
+ if (line_text.begins_with("\t"))
+ {
+ line_text = line_text.substr(1, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ // begins with 4 spaces
+ else if (line_text.begins_with(" "))
+ {
+ line_text = line_text.substr(4, line_text.length());
+ tx->set_line(begin, line_text);
+ }
+ }
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_INDENT_RIGHT: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+
+ if (tx->is_selection_active())
+ {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+ for (int i = begin; i <= end; i++)
+ {
+ String line_text = tx->get_line(i);
+ line_text = '\t' + line_text;
+ tx->set_line(i, line_text);
+ }
+ }
+ else
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+ line_text = '\t' + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_CLONE_DOWN: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+ int line = tx->cursor_get_line();
+ int next_line = line + 1;
+
+ if (line == tx->get_line_count() || next_line > tx->get_line_count())
+ return;
+
+ String line_clone = tx->get_line(line);
+ tx->insert_at(line_clone, next_line);
+ tx->update();
+
+ } break;
+ case EDIT_TOGGLE_COMMENT: {
+
+ TextEdit *tx = current->get_text_edit();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+
+
+
+ if (tx->is_selection_active())
+ {
+ int begin = tx->get_selection_from_line();
+ int end = tx->get_selection_to_line();
+ for (int i = begin; i <= end; i++)
+ {
+ String line_text = tx->get_line(i);
+
+ if (line_text.begins_with("#"))
+ line_text = line_text.substr(1, line_text.length());
+ else
+ line_text = "#" + line_text;
+ tx->set_line(i, line_text);
+ }
+ }
+ else
+ {
+ int begin = tx->cursor_get_line();
+ String line_text = tx->get_line(begin);
+
+ if (line_text.begins_with("#"))
+ line_text = line_text.substr(1, line_text.length());
+ else
+ line_text = "#" + line_text;
+ tx->set_line(begin, line_text);
+ }
+ tx->update();
+ //tx->deselect();
+
+ } break;
+ case EDIT_COMPLETE: {
+
+ current->get_text_edit()->query_code_comple();
+
+ } break;
+ case EDIT_AUTO_INDENT: {
+
+ TextEdit *te = current->get_text_edit();
+ String text = te->get_text();
+ Ref<Script> scr = current->get_edited_script();
+ if (scr.is_null())
+ return;
+ int begin,end;
+ if (te->is_selection_active()) {
+ begin=te->get_selection_from_line();
+ end=te->get_selection_to_line();
+ } else {
+ begin=0;
+ end=te->get_line_count()-1;
+ }
+ scr->get_language()->auto_indent_code(text,begin,end);
+ te->set_text(text);
+
+
+ } break;
+ case SEARCH_FIND: {
+
+ find_replace_dialog->set_text_edit(current->get_text_edit());
+ find_replace_dialog->popup_search();
+ } break;
+ case SEARCH_FIND_NEXT: {
+
+ find_replace_dialog->set_text_edit(current->get_text_edit());
+ find_replace_dialog->search_next();
+ } break;
+ case SEARCH_REPLACE: {
+
+ find_replace_dialog->set_text_edit(current->get_text_edit());
+ find_replace_dialog->popup_replace();
+ } break;
+ case SEARCH_LOCATE_FUNCTION: {
+
+ if (!current)
+ return;
+ quick_open->popup(current->get_functions());
+ } break;
+ case SEARCH_GOTO_LINE: {
+
+ goto_line_dialog->popup_find_line(current->get_text_edit());
+ } break;
+ case DEBUG_TOGGLE_BREAKPOINT: {
+ int line=current->get_text_edit()->cursor_get_line();
+ bool dobreak = !current->get_text_edit()->is_line_set_as_breakpoint(line);
+ current->get_text_edit()->set_line_as_breakpoint(line,dobreak);
+ get_debugger()->set_breakpoint(current->get_edited_script()->get_path(),line+1,dobreak);
+ } break;
+ case DEBUG_NEXT: {
+
+ if (debugger)
+ debugger->debug_next();
+ } break;
+ case DEBUG_STEP: {
+
+ if (debugger)
+ debugger->debug_step();
+
+ } break;
+ case DEBUG_BREAK: {
+
+ if (debugger)
+ debugger->debug_break();
+
+ } break;
+ case DEBUG_CONTINUE: {
+
+ if (debugger)
+ debugger->debug_continue();
+
+ } break;
+ case DEBUG_SHOW: {
+ if (debugger) {
+ bool visible = debug_menu->get_popup()->is_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW) );
+ debug_menu->get_popup()->set_item_checked( debug_menu->get_popup()->get_item_index(DEBUG_SHOW), !visible);
+ if (visible)
+ debugger->hide();
+ else
+ debugger->show();
+ }
+ } break;
+ case HELP_CONTEXTUAL: {
+ String text = current->get_text_edit()->get_selection_text();
+ if (text == "")
+ text = current->get_text_edit()->get_word_under_cursor();
+ if (text != "")
+ help_search_dialog->popup(text);
+ } break;
+ case FILE_CLOSE: {
+ if (current->get_text_edit()->get_version()!=current->get_text_edit()->get_saved_version()) {
+ erase_tab_confirm->set_text("Close and save changes?\n\""+current->get_name()+"\"");
+ erase_tab_confirm->popup_centered_minsize();
+ } else {
+ _close_current_tab();
+ }
+ } break;
+ case WINDOW_MOVE_LEFT: {
+
+ if (tab_container->get_current_tab()>0) {
+ tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1);
+ script_list->call_deferred("select",tab_container->get_current_tab()-1);
+ tab_container->move_child(current,tab_container->get_current_tab()-1);
+ _update_script_names();
+ }
+ } break;
+ case WINDOW_MOVE_RIGHT: {
+
+ if (tab_container->get_current_tab()<tab_container->get_child_count()-1) {
+ tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1);
+ script_list->call_deferred("select",tab_container->get_current_tab()+1);
+ tab_container->move_child(current,tab_container->get_current_tab()+1);
+ _update_script_names();
+ }
- if (tab_container->get_current_tab()>0) {
- tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()-1);
- script_list->call_deferred("select",tab_container->get_current_tab()-1);
- tab_container->move_child(current,tab_container->get_current_tab()-1);
- _update_script_names();
- }
- } break;
- case WINDOW_MOVE_RIGHT: {
- if (tab_container->get_current_tab()<tab_container->get_child_count()-1) {
- tab_container->call_deferred("set_current_tab",tab_container->get_current_tab()+1);
- script_list->call_deferred("select",tab_container->get_current_tab()+1);
- tab_container->move_child(current,tab_container->get_current_tab()+1);
- _update_script_names();
+ } break;
+
+ default: {
+
+ if (p_option>=WINDOW_SELECT_BASE) {
+
+ tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE);
+ script_list->select(p_option-WINDOW_SELECT_BASE);
+
+ }
}
+ }
+ }
+ EditorHelp *help = tab_container->get_child(selected)->cast_to<EditorHelp>();
+ if (help) {
- } break;
- default: {
+ switch(p_option) {
- if (p_option>=WINDOW_SELECT_BASE) {
+ case SEARCH_FIND: {
+ help->popup_search();
+ } break;
+ case SEARCH_FIND_NEXT: {
+ help->search_again();
+ } break;
+ case FILE_CLOSE: {
+ _close_current_tab();
+ } break;
- tab_container->set_current_tab(p_option-WINDOW_SELECT_BASE);
- script_list->select(p_option-WINDOW_SELECT_BASE);
- }
}
}
+
}
void ScriptEditor::_tab_changed(int p_which) {
@@ -1217,6 +1373,14 @@ void ScriptEditor::_notification(int p_what) {
}
EditorSettings::get_singleton()->connect("settings_changed",this,"_editor_settings_changed");
+ help_search->set_icon(get_icon("Help","EditorIcons"));
+ site_search->set_icon(get_icon("Godot","EditorIcons"));
+ class_search->set_icon(get_icon("ClassList","EditorIcons"));
+
+ script_forward->set_icon(get_icon("Forward","EditorIcons"));
+ script_back->set_icon(get_icon("Back","EditorIcons"));
+
+
}
@@ -1346,7 +1510,7 @@ void ScriptEditor::set_state(const Dictionary& p_state) {
}
void ScriptEditor::clear() {
-
+#if 0
List<ScriptTextEditor*> stes;
for(int i=0;i<tab_container->get_child_count();i++) {
@@ -1371,7 +1535,7 @@ void ScriptEditor::clear() {
script_list->select( script_list->find_metadata(idx) );
}
-
+#endif
}
@@ -1402,31 +1566,6 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) {
-void ScriptEditor::_bind_methods() {
-
- ObjectTypeDB::bind_method("_tab_changed",&ScriptEditor::_tab_changed);
- ObjectTypeDB::bind_method("_menu_option",&ScriptEditor::_menu_option);
- ObjectTypeDB::bind_method("_close_current_tab",&ScriptEditor::_close_current_tab);
- ObjectTypeDB::bind_method("_editor_play",&ScriptEditor::_editor_play);
- ObjectTypeDB::bind_method("_editor_pause",&ScriptEditor::_editor_pause);
- ObjectTypeDB::bind_method("_editor_stop",&ScriptEditor::_editor_stop);
- ObjectTypeDB::bind_method("_add_callback",&ScriptEditor::_add_callback);
- ObjectTypeDB::bind_method("_reload_scripts",&ScriptEditor::_reload_scripts);
- ObjectTypeDB::bind_method("_resave_scripts",&ScriptEditor::_resave_scripts);
- ObjectTypeDB::bind_method("_res_saved_callback",&ScriptEditor::_res_saved_callback);
- ObjectTypeDB::bind_method("_goto_script_line",&ScriptEditor::_goto_script_line);
- ObjectTypeDB::bind_method("_goto_script_line2",&ScriptEditor::_goto_script_line2);
- ObjectTypeDB::bind_method("_breaked",&ScriptEditor::_breaked);
- ObjectTypeDB::bind_method("_show_debugger",&ScriptEditor::_show_debugger);
- ObjectTypeDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip);
- ObjectTypeDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts);
- ObjectTypeDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed);
- ObjectTypeDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names);
- ObjectTypeDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed);
- ObjectTypeDB::bind_method("_script_selected",&ScriptEditor::_script_selected);
- ObjectTypeDB::bind_method("_script_created",&ScriptEditor::_script_created);
- ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
-}
void ScriptEditor::ensure_focus_current() {
@@ -1448,7 +1587,8 @@ void ScriptEditor::ensure_focus_current() {
void ScriptEditor::_script_selected(int p_idx) {
grab_focus_block = !Input::get_singleton()->is_mouse_button_pressed(1); //amazing hack, simply amazing
- tab_container->set_current_tab(script_list->get_item_metadata(p_idx));
+
+ _go_to_tab(script_list->get_item_metadata(p_idx));
grab_focus_block=false;
}
@@ -1457,16 +1597,38 @@ void ScriptEditor::ensure_select_current() {
if (tab_container->get_child_count() && tab_container->get_current_tab()>=0) {
- ScriptTextEditor *ste = tab_container->get_child(tab_container->get_current_tab())->cast_to<ScriptTextEditor>();
- if (!ste)
- return;
- Ref<Script> script = ste->get_edited_script();
+ Node *current = tab_container->get_child(tab_container->get_current_tab());
+
+
+ ScriptTextEditor *ste = current->cast_to<ScriptTextEditor>();
+ if (ste) {
+
+ Ref<Script> script = ste->get_edited_script();
+
+ if (!grab_focus_block && is_inside_tree())
+ ste->get_text_edit()->grab_focus();
+
+ edit_menu->show();
+ search_menu->show();
+ script_search_menu->hide();
+
+
+ }
+
+ EditorHelp *eh = current->cast_to<EditorHelp>();
- if (!grab_focus_block && is_inside_tree())
- ste->get_text_edit()->grab_focus();
+ if (eh) {
+ edit_menu->hide();
+ search_menu->hide();
+ script_search_menu->show();
+
+ }
}
+
+
+
}
void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script> > &used) {
@@ -1485,6 +1647,57 @@ void ScriptEditor::_find_scripts(Node* p_base, Node* p_current, Set<Ref<Script>
}
+struct _ScriptEditorItemData {
+
+ String name;
+ Ref<Texture> icon;
+ int index;
+ String tooltip;
+ bool used;
+ int category;
+
+
+ bool operator<(const _ScriptEditorItemData& id) const {
+
+ return category==id.category?name.nocasecmp_to(id.name)<0:category<id.category;
+ }
+
+};
+
+
+void ScriptEditor::_update_script_colors() {
+
+ bool enabled = EditorSettings::get_singleton()->get("text_editor/script_temperature_enabled");
+ if (!enabled)
+ return;
+
+ int hist_size = EditorSettings::get_singleton()->get("text_editor/script_temperature_history_size");
+ Color hot_color=EditorSettings::get_singleton()->get("text_editor/script_temperature_hot_color");
+ Color cold_color=EditorSettings::get_singleton()->get("text_editor/script_temperature_cold_color");
+
+ for(int i=0;i<script_list->get_item_count();i++) {
+
+ int c = script_list->get_item_metadata(i);
+ Node *n = tab_container->get_child(c);
+ if (!n)
+ continue;
+
+ script_list->set_item_custom_bg_color(i,Color(0,0,0,0));
+ if (!n->has_meta("__editor_pass")) {
+ continue;
+ }
+
+ int pass=n->get_meta("__editor_pass");
+ int h = edit_pass - pass;
+ if (h>hist_size) {
+ continue;
+ }
+ float v = Math::ease((edit_pass-pass)/float_t(hist_size),0.4);
+
+
+ script_list->set_item_custom_bg_color(i,hot_color.linear_interpolate(cold_color,v));
+ }
+}
void ScriptEditor::_update_script_names() {
@@ -1496,31 +1709,75 @@ void ScriptEditor::_update_script_names() {
}
script_list->clear();
+ bool split_script_help = EditorSettings::get_singleton()->get("text_editor/group_help_pages");
+
+ Vector<_ScriptEditorItemData> sedata;
+
for(int i=0;i<tab_container->get_child_count();i++) {
+
ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
- if (!ste)
- continue;
+ if (ste) {
- String script = ste->get_name();
- Ref<Texture> icon = ste->get_icon();
- String path = ste->get_edited_script()->get_path();
- script_list->add_item(script,icon);
+ String name = ste->get_name();
+ Ref<Texture> icon = ste->get_icon();
+ String tooltip = ste->get_edited_script()->get_path();
- int index = script_list->get_item_count()-1;
+ _ScriptEditorItemData sd;
+ sd.icon=icon;
+ sd.name=name;
+ sd.tooltip=tooltip;
+ sd.index=i;
+ sd.used=used.has(ste->get_edited_script());
+ sd.category=0;
+
+ sedata.push_back(sd);
+ }
- script_list->set_item_tooltip(index,path);
- script_list->set_item_metadata(index,i);
- if (used.has(ste->get_edited_script())) {
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+ if (eh) {
+
+ String name = eh->get_class_name();
+ Ref<Texture> icon = get_icon("Help","EditorIcons");
+ String tooltip = name+" Class Reference";
+
+ _ScriptEditorItemData sd;
+ sd.icon=icon;
+ sd.name=name;
+ sd.tooltip=tooltip;
+ sd.index=i;
+ sd.used=false;
+ sd.category=split_script_help?1:0;
+ sedata.push_back(sd);
+
+ }
+
+ }
+
+ sedata.sort();
+
+ for(int i=0;i<sedata.size();i++) {
+
+ script_list->add_item(sedata[i].name,sedata[i].icon);
+ int index = script_list->get_item_count()-1;
+ script_list->set_item_tooltip(index,sedata[i].tooltip);
+ script_list->set_item_metadata(index,sedata[i].index);
+ if (sedata[i].used) {
script_list->set_item_custom_bg_color(index,Color(88/255.0,88/255.0,60/255.0));
}
- if (tab_container->get_current_tab()==index) {
+ if (tab_container->get_current_tab()==sedata[i].index) {
script_list->select(index);
+ script_name_label->set_text(sedata[i].name);
+ script_icon->set_texture(sedata[i].icon);
+
}
}
- script_list->sort_items_by_text();
+ _update_script_colors();
+
+
+
}
@@ -1531,6 +1788,8 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
// see if already has it
+ bool open_dominant = EditorSettings::get_singleton()->get("text_editor/open_dominant_script_on_scene_change");
+
if (p_script->get_path().is_resource_file() && bool(EditorSettings::get_singleton()->get("external_editor/use_external_editor"))) {
String path = EditorSettings::get_singleton()->get("external_editor/exec_path");
@@ -1559,12 +1818,13 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
if (ste->get_edited_script()==p_script) {
- if (!EditorNode::get_singleton()->is_changing_scene()) {
+ if (open_dominant || !EditorNode::get_singleton()->is_changing_scene()) {
if (tab_container->get_current_tab()!=i) {
- tab_container->set_current_tab(i);
+ _go_to_tab(i);
script_list->select( script_list->find_metadata(i) );
}
- ste->get_text_edit()->grab_focus();
+ if (is_visible())
+ ste->get_text_edit()->grab_focus();
}
return;
}
@@ -1576,7 +1836,8 @@ void ScriptEditor::edit(const Ref<Script>& p_script) {
ste->set_edited_script(p_script);
ste->get_text_edit()->set_tooltip_request_func(this,"_get_debug_tooltip",ste);
tab_container->add_child(ste);
- tab_container->set_current_tab(tab_container->get_tab_count()-1);
+ _go_to_tab(tab_container->get_tab_count()-1);
+
@@ -1675,7 +1936,7 @@ void ScriptEditor::_add_callback(Object *p_obj, const String& p_function, const
ste->get_text_edit()->insert_text_at_cursor("\n\n"+func);
}
- tab_container->set_current_tab(i);
+ _go_to_tab(i);
ste->get_text_edit()->cursor_set_line(pos);
ste->get_text_edit()->cursor_set_column(1);
@@ -1726,10 +1987,13 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
return;
}
- if (!p_layout->has_section_key("ScriptEditor","open_scripts"))
+ if (!p_layout->has_section_key("ScriptEditor","open_scripts") && !p_layout->has_section_key("ScriptEditor","open_help"))
return;
Array scripts = p_layout->get_value("ScriptEditor","open_scripts");
+ Array helps;
+ if (p_layout->has_section_key("ScriptEditor","open_help"))
+ helps=p_layout->get_value("ScriptEditor","open_help");
restoring_layout=true;
@@ -1742,6 +2006,18 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
}
}
+
+ for(int i=0;i<helps.size();i++) {
+
+ String path = helps[i];
+ _help_class_open(path);
+ }
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+ tab_container->get_child(i)->set_meta("__editor_pass",Variant());
+ }
+
+
if (p_layout->has_section_key("ScriptEditor","split_offset")) {
script_split->set_split_offset(p_layout->get_value("ScriptEditor","split_offset"));
}
@@ -1754,27 +2030,184 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
Array scripts;
+ Array helps;
for(int i=0;i<tab_container->get_child_count();i++) {
ScriptTextEditor *ste = tab_container->get_child(i)->cast_to<ScriptTextEditor>();
- if (!ste)
- continue;
+ if (ste) {
- String path = ste->get_edited_script()->get_path();
- if (!path.is_resource_file())
- continue;
+ String path = ste->get_edited_script()->get_path();
+ if (!path.is_resource_file())
+ continue;
+
+ scripts.push_back(path);
+ }
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh) {
+
+ helps.push_back(eh->get_class_name());
+ }
- scripts.push_back(path);
}
p_layout->set_value("ScriptEditor","open_scripts",scripts);
+ p_layout->set_value("ScriptEditor","open_help",helps);
p_layout->set_value("ScriptEditor","split_offset",script_split->get_split_offset());
}
+void ScriptEditor::_help_class_open(const String& p_class) {
+
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh && eh->get_class_name()==p_class) {
+
+ _go_to_tab(i);
+ _update_script_names();
+ return;
+ }
+ }
+
+ EditorHelp * eh = memnew( EditorHelp );
+
+
+ eh->set_name(p_class);
+ tab_container->add_child(eh);
+ _go_to_tab(tab_container->get_tab_count()-1);
+ eh->go_to_class(p_class,0);
+ eh->connect("go_to_help",this,"_help_class_goto");
+ _update_script_names();
+
+}
+
+void ScriptEditor::_help_class_goto(const String& p_desc) {
+
+
+ String cname=p_desc.get_slice(":",1);
+
+ for(int i=0;i<tab_container->get_child_count();i++) {
+
+ EditorHelp *eh = tab_container->get_child(i)->cast_to<EditorHelp>();
+
+ if (eh && eh->get_class_name()==cname) {
+
+ _go_to_tab(i);
+ eh->go_to_help(p_desc);
+ _update_script_names();
+ return;
+ }
+ }
+
+ EditorHelp * eh = memnew( EditorHelp );
+
+ eh->set_name(cname);
+ tab_container->add_child(eh);
+ _go_to_tab(tab_container->get_tab_count()-1);
+ eh->go_to_help(p_desc);
+ eh->connect("go_to_help",this,"_help_class_goto");
+ _update_script_names();
+
+}
+
+void ScriptEditor::_update_history_pos(int p_new_pos) {
+
+ Node *n = tab_container->get_current_tab_control();
+
+ if (n->cast_to<ScriptTextEditor>()) {
+
+ history[history_pos].scroll_pos=n->cast_to<ScriptTextEditor>()->get_text_edit()->get_v_scroll();
+ history[history_pos].cursor_column=n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_get_column();
+ history[history_pos].cursor_row=n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_get_line();
+ }
+ if (n->cast_to<EditorHelp>()) {
+
+ history[history_pos].scroll_pos=n->cast_to<EditorHelp>()->get_scroll();
+ }
+
+ history_pos=p_new_pos;
+ tab_container->set_current_tab(history[history_pos].control->get_index());
+
+ n = history[history_pos].control;
+
+ if (n->cast_to<ScriptTextEditor>()) {
+
+ n->cast_to<ScriptTextEditor>()->get_text_edit()->set_v_scroll(history[history_pos].scroll_pos);
+ n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_set_column( history[history_pos].cursor_column );
+ n->cast_to<ScriptTextEditor>()->get_text_edit()->cursor_set_line( history[history_pos].cursor_row );
+ n->cast_to<ScriptTextEditor>()->get_text_edit()->grab_focus();
+ }
+
+ if (n->cast_to<EditorHelp>()) {
+
+ n->cast_to<EditorHelp>()->set_scroll(history[history_pos].scroll_pos);
+ n->cast_to<EditorHelp>()->set_focused();
+ }
+
+ n->set_meta("__editor_pass",++edit_pass);
+ _update_script_names();
+ _update_history_arrows();
+
+}
+
+void ScriptEditor::_history_forward() {
+
+ if (history_pos<history.size()-1) {
+ _update_history_pos(history_pos+1);
+ }
+}
+
+void ScriptEditor::_history_back(){
+
+ if (history_pos>0) {
+ _update_history_pos(history_pos-1);
+ }
+
+}
+void ScriptEditor::set_scene_root_script( Ref<Script> p_script ) {
+
+ bool open_dominant = EditorSettings::get_singleton()->get("text_editor/open_dominant_script_on_scene_change");
+ if (open_dominant && p_script.is_valid()) {
+ edit(p_script);
+ }
+}
+
+void ScriptEditor::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_tab_changed",&ScriptEditor::_tab_changed);
+ ObjectTypeDB::bind_method("_menu_option",&ScriptEditor::_menu_option);
+ ObjectTypeDB::bind_method("_close_current_tab",&ScriptEditor::_close_current_tab);
+ ObjectTypeDB::bind_method("_editor_play",&ScriptEditor::_editor_play);
+ ObjectTypeDB::bind_method("_editor_pause",&ScriptEditor::_editor_pause);
+ ObjectTypeDB::bind_method("_editor_stop",&ScriptEditor::_editor_stop);
+ ObjectTypeDB::bind_method("_add_callback",&ScriptEditor::_add_callback);
+ ObjectTypeDB::bind_method("_reload_scripts",&ScriptEditor::_reload_scripts);
+ ObjectTypeDB::bind_method("_resave_scripts",&ScriptEditor::_resave_scripts);
+ ObjectTypeDB::bind_method("_res_saved_callback",&ScriptEditor::_res_saved_callback);
+ ObjectTypeDB::bind_method("_goto_script_line",&ScriptEditor::_goto_script_line);
+ ObjectTypeDB::bind_method("_goto_script_line2",&ScriptEditor::_goto_script_line2);
+ ObjectTypeDB::bind_method("_breaked",&ScriptEditor::_breaked);
+ ObjectTypeDB::bind_method("_show_debugger",&ScriptEditor::_show_debugger);
+ ObjectTypeDB::bind_method("_get_debug_tooltip",&ScriptEditor::_get_debug_tooltip);
+ ObjectTypeDB::bind_method("_autosave_scripts",&ScriptEditor::_autosave_scripts);
+ ObjectTypeDB::bind_method("_editor_settings_changed",&ScriptEditor::_editor_settings_changed);
+ ObjectTypeDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names);
+ ObjectTypeDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed);
+ ObjectTypeDB::bind_method("_script_selected",&ScriptEditor::_script_selected);
+ ObjectTypeDB::bind_method("_script_created",&ScriptEditor::_script_created);
+ ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged);
+ ObjectTypeDB::bind_method("_help_class_open",&ScriptEditor::_help_class_open);
+ ObjectTypeDB::bind_method("_help_class_goto",&ScriptEditor::_help_class_goto);
+ ObjectTypeDB::bind_method("_history_forward",&ScriptEditor::_history_forward);
+ ObjectTypeDB::bind_method("_history_back",&ScriptEditor::_history_back);
+}
ScriptEditor::ScriptEditor(EditorNode *p_editor) {
@@ -1816,6 +2249,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
file_menu->get_popup()->add_item("Save As..",FILE_SAVE_AS);
file_menu->get_popup()->add_item("Save All",FILE_SAVE_ALL,KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_S);
file_menu->get_popup()->add_separator();
+ file_menu->get_popup()->add_item("History Prev",WINDOW_PREV,KEY_MASK_CTRL|KEY_MASK_ALT|KEY_LEFT);
+ file_menu->get_popup()->add_item("History Next",WINDOW_NEXT,KEY_MASK_CTRL|KEY_MASK_ALT|KEY_RIGHT);
+ file_menu->get_popup()->add_separator();
file_menu->get_popup()->add_item("Close",FILE_CLOSE,KEY_MASK_CMD|KEY_W);
file_menu->get_popup()->connect("item_pressed", this,"_menu_option");
@@ -1851,13 +2287,22 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
menu_hb->add_child(search_menu);
search_menu->set_text("Search");
search_menu->get_popup()->add_item("Find..",SEARCH_FIND,KEY_MASK_CMD|KEY_F);
- search_menu->get_popup()->add_item("Find Next",SEARCH_FIND_NEXT,KEY_MASK_CMD|KEY_G);
+ search_menu->get_popup()->add_item("Find Next",SEARCH_FIND_NEXT,KEY_F3);
search_menu->get_popup()->add_item("Replace..",SEARCH_REPLACE,KEY_MASK_CMD|KEY_R);
search_menu->get_popup()->add_separator();
search_menu->get_popup()->add_item("Goto Function..",SEARCH_LOCATE_FUNCTION,KEY_MASK_SHIFT|KEY_MASK_CMD|KEY_F);
search_menu->get_popup()->add_item("Goto Line..",SEARCH_GOTO_LINE,KEY_MASK_CMD|KEY_L);
search_menu->get_popup()->connect("item_pressed", this,"_menu_option");
+ script_search_menu = memnew( MenuButton );
+ menu_hb->add_child(script_search_menu);
+ script_search_menu->set_text("Search");
+ script_search_menu->get_popup()->add_item("Find..",SEARCH_FIND,KEY_MASK_CMD|KEY_F);
+ script_search_menu->get_popup()->add_item("Find Next",SEARCH_FIND_NEXT,KEY_F3);
+ script_search_menu->get_popup()->connect("item_pressed", this,"_menu_option");
+ script_search_menu->hide();
+
+
debug_menu = memnew( MenuButton );
menu_hb->add_child(debug_menu);
debug_menu->set_text("Debug");
@@ -1897,6 +2342,53 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
help_menu->get_popup()->add_item("Contextual", HELP_CONTEXTUAL, KEY_MASK_SHIFT|KEY_F1);
help_menu->get_popup()->connect("item_pressed", this,"_menu_option");
+ menu_hb->add_spacer();
+
+
+ script_icon = memnew( TextureFrame );
+ menu_hb->add_child(script_icon);
+ script_name_label = memnew( Label );
+ menu_hb->add_child(script_name_label);
+
+ script_icon->hide();
+ script_name_label->hide();
+
+ menu_hb->add_spacer();
+
+ site_search = memnew( ToolButton );
+ site_search->set_text("Tutorials");
+ site_search->connect("pressed",this,"_menu_option",varray(SEARCH_WEBSITE));
+ menu_hb->add_child(site_search);
+ site_search->set_tooltip("Open http://www.godotengine.org at tutorials section.");
+
+ class_search = memnew( ToolButton );
+ class_search->set_text("Classes");
+ class_search->connect("pressed",this,"_menu_option",varray(SEARCH_CLASSES));
+ menu_hb->add_child(class_search);
+ class_search->set_tooltip("Search the class hierarchy.");
+
+ help_search = memnew( ToolButton );
+ help_search->set_text("Search Help");
+ help_search->connect("pressed",this,"_menu_option",varray(SEARCH_HELP));
+ menu_hb->add_child(help_search);
+ help_search->set_tooltip("Search the reference documentation.");
+
+ menu_hb->add_child( memnew( VSeparator) );
+
+ script_back = memnew( ToolButton );
+ script_back->connect("pressed",this,"_history_back");
+ menu_hb->add_child(script_back);
+ script_back->set_disabled(true);
+ help_search->set_tooltip("Go to previous edited document.");
+
+ script_forward = memnew( ToolButton );
+ script_forward->connect("pressed",this,"_history_forward");
+ menu_hb->add_child(script_forward);
+ script_forward->set_disabled(true);
+ help_search->set_tooltip("Go to next edited document.");
+
+
+
tab_container->connect("tab_changed", this,"_tab_changed");
find_replace_dialog = memnew(FindReplaceDialog);
@@ -1959,8 +2451,20 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
grab_focus_block=false;
+ help_search_dialog = memnew( EditorHelpSearch );
+ add_child(help_search_dialog);
+ help_search_dialog->connect("go_to_help",this,"_help_class_goto");
+
+
+ help_index = memnew( EditorHelpIndex );
+ add_child(help_index);
+ help_index->connect("open_class",this,"_help_class_open");
+
+ history_pos=-1;
// debugger_gui->hide();
+ edit_pass=0;
+
}
@@ -2062,8 +2566,14 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) {
script_editor->hide();
EDITOR_DEF("text_editor/auto_reload_changed_scripts",false);
+ EDITOR_DEF("text_editor/open_dominant_script_on_scene_change",true);
EDITOR_DEF("external_editor/use_external_editor",false);
EDITOR_DEF("external_editor/exec_path","");
+ EDITOR_DEF("text_editor/script_temperature_enabled",true);
+ EDITOR_DEF("text_editor/script_temperature_history_size",15);
+ EDITOR_DEF("text_editor/script_temperature_hot_color",Color(1,0,0,0.3));
+ EDITOR_DEF("text_editor/script_temperature_cold_color",Color(0,0,1,0.3));
+ EDITOR_DEF("text_editor/group_help_pages",false);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,"external_editor/exec_path",PROPERTY_HINT_GLOBAL_FILE));
EDITOR_DEF("external_editor/exec_flags","");
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index e635a1974b..e755f570ef 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -41,6 +41,7 @@
#include "tools/editor/code_editor.h"
#include "scene/gui/split_container.h"
#include "scene/gui/item_list.h"
+#include "tools/editor/editor_help.h"
class ScriptEditorQuickOpen : public ConfirmationDialog {
@@ -141,6 +142,9 @@ class ScriptEditor : public VBoxContainer {
SEARCH_REPLACE,
SEARCH_LOCATE_FUNCTION,
SEARCH_GOTO_LINE,
+ SEARCH_HELP,
+ SEARCH_CLASSES,
+ SEARCH_WEBSITE,
DEBUG_TOGGLE_BREAKPOINT,
DEBUG_NEXT,
DEBUG_STEP,
@@ -150,6 +154,8 @@ class ScriptEditor : public VBoxContainer {
HELP_CONTEXTUAL,
WINDOW_MOVE_LEFT,
WINDOW_MOVE_RIGHT,
+ WINDOW_NEXT,
+ WINDOW_PREV,
WINDOW_SELECT_BASE=100
};
@@ -157,11 +163,17 @@ class ScriptEditor : public VBoxContainer {
MenuButton *file_menu;
MenuButton *edit_menu;
MenuButton *search_menu;
+ MenuButton *script_search_menu;
MenuButton *debug_menu;
MenuButton *help_menu;
Timer *autosave_timer;
uint64_t idle;
+ Button *help_search;
+ Button *site_search;
+ Button *class_search;
+ EditorHelpSearch *help_search_dialog;
+
ItemList *script_list;
HSplitContainer *script_split;
TabContainer *tab_container;
@@ -172,6 +184,27 @@ class ScriptEditor : public VBoxContainer {
ScriptEditorDebugger* debugger;
ToolButton *scripts_visible;
+ TextureFrame *script_icon;
+ Label *script_name_label;
+
+ ToolButton *script_back;
+ ToolButton *script_forward;
+
+
+ struct ScriptHistory {
+
+ Control *control;
+ int scroll_pos;
+ int cursor_column;
+ int cursor_row;
+ };
+
+ Vector<ScriptHistory> history;
+ int history_pos;
+
+
+ EditorHelpIndex *help_index;
+
void _tab_changed(int p_which);
void _menu_option(int p_optin);
@@ -201,6 +234,8 @@ class ScriptEditor : public VBoxContainer {
void _editor_pause();
void _editor_stop();
+ int edit_pass;
+
void _add_callback(Object *p_obj, const String& p_function, const StringArray& p_args);
void _res_saved_callback(const Ref<Resource>& p_res);
@@ -224,8 +259,20 @@ class ScriptEditor : public VBoxContainer {
void _script_split_dragged(float);
+
+ void _history_forward();
+ void _history_back();
+
bool waiting_update_names;
+ void _help_class_open(const String& p_class);
+ void _help_class_goto(const String& p_desc);
+ void _update_history_arrows();
+ void _go_to_tab(int p_idx);
+ void _update_history_pos(int p_new_pos);
+ void _update_script_colors();
+
+
static ScriptEditor *script_editor;
protected:
void _notification(int p_what);
@@ -253,6 +300,8 @@ public:
void set_window_layout(Ref<ConfigFile> p_layout);
void get_window_layout(Ref<ConfigFile> p_layout);
+ void set_scene_root_script( Ref<Script> p_script );
+
ScriptEditorDebugger *get_debugger() { return debugger; }
ScriptEditor(EditorNode *p_editor);
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
index 684e7e32ef..3a7dc26466 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -2542,7 +2542,7 @@ void ShaderGraphView::_notification(int p_what) {
void ShaderGraphView::add_node(int p_type, const Vector2 &location) {
- if ((p_type==ShaderGraph::NODE_INPUT||p_type==ShaderGraph::NODE_INPUT) && graph->node_count(type, p_type)>0)
+ if (p_type==ShaderGraph::NODE_INPUT && graph->node_count(type, p_type)>0)
return;
List<int> existing;
diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp
index 3ab9339265..f3458a768a 100644
--- a/tools/editor/plugins/spatial_editor_plugin.cpp
+++ b/tools/editor/plugins/spatial_editor_plugin.cpp
@@ -2725,7 +2725,7 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
} break;
case MENU_TRANSFORM_CONFIGURE_SNAP: {
- snap_dialog->popup_centered(Size2(200,160));
+ snap_dialog->popup_centered(Size2(200,180));
} break;
case MENU_TRANSFORM_LOCAL_COORDS: {
@@ -3793,46 +3793,24 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
snap_dialog = memnew( ConfirmationDialog );
snap_dialog->set_title("Snap Settings");
add_child(snap_dialog);
- Label *l = memnew(Label);
- l->set_text("Translate Snap:");
- l->set_pos(Point2(5,5));
- snap_dialog->add_child(l);
+
+ VBoxContainer *snap_dialog_vbc = memnew( VBoxContainer );
+ snap_dialog->add_child(snap_dialog_vbc);
+ snap_dialog->set_child_rect(snap_dialog_vbc);
snap_translate = memnew( LineEdit );
- snap_translate->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- snap_translate->set_begin( Point2(15,22) );
- snap_translate->set_end( Point2(15,35) );
snap_translate->set_text("1");
- snap_dialog->add_child(snap_translate);
-
- l = memnew(Label);
- l->set_text("Rotate Snap (deg.):");
- l->set_pos(Point2(5,45));
- snap_dialog->add_child(l);
+ snap_dialog_vbc->add_margin_child("Translate Snap:",snap_translate);
snap_rotate = memnew( LineEdit );
- snap_rotate->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- snap_rotate->set_begin( Point2(15,62) );
- snap_rotate->set_end( Point2(15,75) );
snap_rotate->set_text("5");
- snap_dialog->add_child(snap_rotate);
-
-
- l = memnew(Label);
- l->set_text("Scale Snap (%):");
- l->set_pos(Point2(5,85));
- snap_dialog->add_child(l);
+ snap_dialog_vbc->add_margin_child("Rotate Snap (deg.):",snap_rotate);
snap_scale = memnew( LineEdit );
- snap_scale->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- snap_scale->set_begin( Point2(15,102) );
- snap_scale->set_end( Point2(15,115) );
snap_scale->set_text("5");
- snap_dialog->add_child(snap_scale);
+ snap_dialog_vbc->add_margin_child("Scale Snap (%):",snap_scale);
- //snap_dialog->get_cancel()->hide();
-
- /* SNAP DIALOG */
+ /* SETTINGS DIALOG */
settings_dialog = memnew( ConfirmationDialog );
settings_dialog->set_title("Viewport Settings");
@@ -3906,7 +3884,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
xform_dialog = memnew( ConfirmationDialog );
xform_dialog->set_title("Transform Change");
add_child(xform_dialog);
- l = memnew(Label);
+ Label *l = memnew(Label);
l->set_text("Translate:");
l->set_pos(Point2(5,5));
xform_dialog->add_child(l);
diff --git a/tools/editor/plugins/theme_editor_plugin.cpp b/tools/editor/plugins/theme_editor_plugin.cpp
index 55e8f164d6..63ba57bfc0 100644
--- a/tools/editor/plugins/theme_editor_plugin.cpp
+++ b/tools/editor/plugins/theme_editor_plugin.cpp
@@ -568,26 +568,24 @@ ThemeEditor::ThemeEditor() {
CheckButton *cb = memnew( CheckButton );
cb->set_text("CheckButton");
first_vb->add_child(cb );
- CheckBox *cbx = memnew( CheckBox );
- cbx->set_text("CheckBox");
- first_vb->add_child(cbx );
-
- /* TODO: This is not working properly, controls are overlapping*/
- /*
- ButtonGroup *bg = memnew( ButtonGroup );
- bg->set_v_size_flags(SIZE_EXPAND_FILL);
- VBoxContainer *gbvb = memnew( VBoxContainer );
- gbvb->set_v_size_flags(SIZE_EXPAND_FILL);
- CheckBox *rbx1 = memnew( CheckBox );
- rbx1->set_text("CheckBox Radio1");
- rbx1->set_pressed(true);
- gbvb->add_child(rbx1);
- CheckBox *rbx2 = memnew( CheckBox );
- rbx2->set_text("CheckBox Radio2");
- gbvb->add_child(rbx2);
- bg->add_child(gbvb);
- first_vb->add_child(bg);
- */
+ CheckBox *cbx = memnew( CheckBox );
+ cbx->set_text("CheckBox");
+ first_vb->add_child(cbx );
+
+
+ ButtonGroup *bg = memnew( ButtonGroup );
+ bg->set_v_size_flags(SIZE_EXPAND_FILL);
+ VBoxContainer *gbvb = memnew( VBoxContainer );
+ gbvb->set_v_size_flags(SIZE_EXPAND_FILL);
+ CheckBox *rbx1 = memnew( CheckBox );
+ rbx1->set_text("CheckBox Radio1");
+ rbx1->set_pressed(true);
+ gbvb->add_child(rbx1);
+ CheckBox *rbx2 = memnew( CheckBox );
+ rbx2->set_text("CheckBox Radio2");
+ gbvb->add_child(rbx2);
+ bg->add_child(gbvb);
+ first_vb->add_child(bg);
MenuButton* test_menu_button = memnew( MenuButton );
test_menu_button->set_text("MenuButton");
diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp
index 39b0ef3c75..09115472a8 100644
--- a/tools/editor/plugins/tile_set_editor_plugin.cpp
+++ b/tools/editor/plugins/tile_set_editor_plugin.cpp
@@ -110,11 +110,15 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
if (!child2->cast_to<StaticBody2D>())
continue;
StaticBody2D *sb = child2->cast_to<StaticBody2D>();
- if (sb->get_shape_count()==0)
+ int shape_count = sb->get_shape_count();
+ if (shape_count==0)
continue;
- Ref<Shape2D> collision=sb->get_shape(0);
- if (collision.is_valid()) {
- collisions.push_back(collision);
+ for (int shape_index=0; shape_index<shape_count; ++shape_index)
+ {
+ Ref<Shape2D> collision=sb->get_shape(shape_index);
+ if (collision.is_valid()) {
+ collisions.push_back(collision);
+ }
}
}
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index 9f47291433..bc1af52858 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -193,7 +193,7 @@ class NewProjectDialog : public ConfirmationDialog {
f->store_line("\n");
f->store_line("[application]");
f->store_line("name=\""+project_name->get_text()+"\"");
- f->store_line("icon=\"icon.png\"");
+ f->store_line("icon=\"res://icon.png\"");
memdelete(f);
@@ -480,20 +480,25 @@ void ProjectManager::_load_recent_projects() {
bool favorite = (_name.begins_with("favorite_projects/"))?true:false;
uint64_t last_modified = 0;
- if (FileAccess::exists(conf))
+ if (FileAccess::exists(conf)) {
last_modified = FileAccess::get_modified_time(conf);
- String fscache = path.plus_file(".fscache");
- if (FileAccess::exists(fscache)) {
- uint64_t cache_modified = FileAccess::get_modified_time(fscache);
- if ( cache_modified > last_modified )
- last_modified = cache_modified;
- }
- ProjectItem item(project, path, conf, last_modified, favorite);
- if (favorite)
- favorite_projects.push_back(item);
- else
- projects.push_back(item);
+ String fscache = path.plus_file(".fscache");
+ if (FileAccess::exists(fscache)) {
+ uint64_t cache_modified = FileAccess::get_modified_time(fscache);
+ if ( cache_modified > last_modified )
+ last_modified = cache_modified;
+ }
+
+ ProjectItem item(project, path, conf, last_modified, favorite);
+ if (favorite)
+ favorite_projects.push_back(item);
+ else
+ projects.push_back(item);
+ } else {
+ //project doesn't exist on disk but it's in the XML settings file
+ EditorSettings::get_singleton()->erase(_name); //remove it
+ }
}
projects.sort();
@@ -601,6 +606,8 @@ void ProjectManager::_load_recent_projects() {
erase_btn->set_disabled(selected_list.size()<1);
open_btn->set_disabled(selected_list.size()<1);
run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main==""));
+
+ EditorSettings::get_singleton()->save();
}
void ProjectManager::_open_project_confirm() {
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 60395d5ff5..ac2f76acdc 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -649,20 +649,28 @@ void SceneTreeEditor::_rename_node(ObjectID p_node,const String& p_name) {
void SceneTreeEditor::_renamed() {
TreeItem *which=tree->get_edited();
-
+
ERR_FAIL_COND(!which);
NodePath np = which->get_metadata(0);
Node *n=get_node(np);
ERR_FAIL_COND(!n);
+ String new_name=which->get_text(0);
+ if (new_name.find(".") != -1 || new_name.find("/") != -1) {
+
+ error->set_text("Invalid node name, the following characters are not allowed:\n \".\", \"/\"");
+ error->popup_centered_minsize();
+ new_name=n->get_name();
+ }
+
if (!undo_redo) {
- n->set_name( which->get_text(0) );
+ n->set_name( new_name );
which->set_metadata(0,n->get_path());
emit_signal("node_renamed");
} else {
undo_redo->create_action("Rename Node");
- emit_signal("node_prerename",n,which->get_text(0));
- undo_redo->add_do_method(this,"_rename_node",n->get_instance_ID(),which->get_text(0));
+ emit_signal("node_prerename",n,new_name);
+ undo_redo->add_do_method(this,"_rename_node",n->get_instance_ID(),new_name);
undo_redo->add_undo_method(this,"_rename_node",n->get_instance_ID(),n->get_name());
undo_redo->commit_action();
}
diff --git a/tools/editor/script_editor_debugger.cpp b/tools/editor/script_editor_debugger.cpp
index 8e0e7ddb49..60f2afa2c2 100644
--- a/tools/editor/script_editor_debugger.cpp
+++ b/tools/editor/script_editor_debugger.cpp
@@ -1376,7 +1376,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
vmem_refresh->connect("pressed",this,"_video_mem_request");
MarginContainer *vmmc = memnew( MarginContainer );
- vmmc = memnew( MarginContainer );
vmem_tree = memnew( Tree );
vmem_tree->set_v_size_flags(SIZE_EXPAND_FILL);
vmem_tree->set_h_size_flags(SIZE_EXPAND_FILL);
diff --git a/tools/export/blender25/godot_export_manager.py b/tools/export/blender25/godot_export_manager.py
index e390ae6ce3..582d76f94f 100644
--- a/tools/export/blender25/godot_export_manager.py
+++ b/tools/export/blender25/godot_export_manager.py
@@ -107,7 +107,6 @@ class godot_export_manager(bpy.types.Panel):
col.prop(group,"use_triangles")
col.prop(group,"use_copy_images")
col.prop(group,"use_active_layers")
- col.prop(group,"use_exclude_ctrl_bones")
col.prop(group,"use_anim")
col.prop(group,"use_anim_action_all")
col.prop(group,"use_anim_skip_noexp")
@@ -351,7 +350,7 @@ class export_group(bpy.types.Operator):
bpy.data.objects[object.name].select = True
bpy.ops.object.transform_apply(location=group[self.idx].apply_loc, rotation=group[self.idx].apply_rot, scale=group[self.idx].apply_scale)
- bpy.ops.export_scene.dae(check_existing=True, filepath=path, filter_glob="*.dae", object_types=group[self.idx].object_types, use_export_selected=group[self.idx].use_export_selected, use_mesh_modifiers=group[self.idx].use_mesh_modifiers, use_tangent_arrays=group[self.idx].use_tangent_arrays, use_triangles=group[self.idx].use_triangles, use_copy_images=group[self.idx].use_copy_images, use_active_layers=group[self.idx].use_active_layers, use_exclude_ctrl_bones=group[self.idx].use_exclude_ctrl_bones, use_anim=group[self.idx].use_anim, use_anim_action_all=group[self.idx].use_anim_action_all, use_anim_skip_noexp=group[self.idx].use_anim_skip_noexp, use_anim_optimize=group[self.idx].use_anim_optimize, anim_optimize_precision=group[self.idx].anim_optimize_precision, use_metadata=group[self.idx].use_metadata)
+ bpy.ops.export_scene.dae(check_existing=True, filepath=path, filter_glob="*.dae", object_types=group[self.idx].object_types, use_export_selected=group[self.idx].use_export_selected, use_mesh_modifiers=group[self.idx].use_mesh_modifiers, use_tangent_arrays=group[self.idx].use_tangent_arrays, use_triangles=group[self.idx].use_triangles, use_copy_images=group[self.idx].use_copy_images, use_active_layers=group[self.idx].use_active_layers, use_anim=group[self.idx].use_anim, use_anim_action_all=group[self.idx].use_anim_action_all, use_anim_skip_noexp=group[self.idx].use_anim_skip_noexp, use_anim_optimize=group[self.idx].use_anim_optimize, anim_optimize_precision=group[self.idx].anim_optimize_precision, use_metadata=group[self.idx].use_metadata)
self.report({'INFO'}, '"'+group[self.idx].name+'"' + " Group exported." )
msg = "Export Group "+group[self.idx].name
@@ -422,7 +421,6 @@ class godot_export_groups(bpy.types.PropertyGroup):
use_copy_images = BoolProperty(name="Copy Images",description="Copy Images (create images/ subfolder)",default=False)
use_active_layers = BoolProperty(name="Active Layers",description="Export only objects on the active layers.",default=True)
- use_exclude_ctrl_bones = BoolProperty(name="Exclude Control Bones",description="Exclude skeleton bones with names that begin with 'ctrl'.",default=True)
use_anim = BoolProperty(name="Export Animation",description="Export keyframe animation",default=False)
use_anim_action_all = BoolProperty(name="All Actions",description=("Export all actions for the first armature found in separate DAE files"),default=False)
use_anim_skip_noexp = BoolProperty(name="Skip (-noexp) Actions",description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",default=True)