summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct1
-rw-r--r--core/global_constants.cpp37
-rw-r--r--core/math/a_star.cpp2
-rw-r--r--core/math/math_2d.cpp63
-rw-r--r--core/math/math_2d.h67
-rw-r--r--core/math/matrix3.cpp9
-rw-r--r--core/math/matrix3.h3
-rw-r--r--core/os/input_event.cpp18
-rw-r--r--core/os/input_event.h4
-rw-r--r--core/os/threaded_array_processor.cpp2
-rw-r--r--core/os/threaded_array_processor.h80
-rw-r--r--doc/classes/ColorPickerButton.xml4
-rw-r--r--doc/classes/MenuButton.xml2
-rw-r--r--doc/classes/OptionButton.xml7
-rw-r--r--doc/classes/Physics2DDirectSpaceState.xml67
-rw-r--r--doc/classes/PhysicsDirectSpaceState.xml28
-rw-r--r--doc/classes/TextEdit.xml17
-rw-r--r--doc/classes/Transform2D.xml30
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp17
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp14
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp3
-rw-r--r--drivers/gles3/shaders/scene.glsl4
-rw-r--r--editor/create_dialog.cpp27
-rw-r--r--editor/editor_about.cpp2
-rw-r--r--editor/editor_data.cpp9
-rw-r--r--editor/editor_data.h1
-rw-r--r--editor/editor_file_dialog.cpp63
-rw-r--r--editor/editor_file_dialog.h1
-rw-r--r--editor/editor_fonts.cpp15
-rw-r--r--editor/editor_help.cpp91
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/editor_themes.cpp6
-rw-r--r--editor/filesystem_dock.cpp55
-rw-r--r--editor/filesystem_dock.h1
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp52
-rw-r--r--editor/plugins/script_text_editor.cpp80
-rw-r--r--editor/plugins/shader_editor_plugin.cpp28
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp244
-rw-r--r--editor/plugins/spatial_editor_plugin.h7
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp2
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp12
-rw-r--r--editor/project_manager.cpp6
-rw-r--r--editor/project_settings_editor.cpp2
-rw-r--r--editor/property_editor.cpp52
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--editor/spatial_editor_gizmos.cpp845
-rw-r--r--editor/spatial_editor_gizmos.h51
-rw-r--r--modules/bullet/godot_result_callbacks.cpp5
-rw-r--r--modules/bullet/rigid_body_bullet.cpp39
-rw-r--r--modules/bullet/rigid_body_bullet.h1
-rw-r--r--modules/mono/csharp_script.cpp2
-rw-r--r--modules/mono/editor/bindings_generator.cpp818
-rw-r--r--modules/mono/editor/bindings_generator.h162
-rw-r--r--modules/mono/editor/csharp_project.cpp6
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp2
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp18
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp6
-rw-r--r--modules/mono/glue/cs_files/Error.cs47
-rw-r--r--modules/mono/glue/cs_files/ExportAttribute.cs8
-rw-r--r--modules/mono/glue/cs_files/GD.cs4
-rw-r--r--modules/mono/glue/cs_files/Rect2.cs12
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp5
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h9
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
-rw-r--r--modules/opus/register_types.cpp15
-rw-r--r--platform/osx/detect.py3
-rw-r--r--platform/windows/detect.py5
-rw-r--r--platform/x11/detect.py4
-rw-r--r--platform/x11/os_x11.cpp4
-rw-r--r--scene/2d/tile_map.cpp2
-rw-r--r--scene/3d/baked_lightmap.cpp4
-rw-r--r--scene/3d/camera.cpp5
-rw-r--r--scene/3d/spatial.cpp8
-rw-r--r--scene/3d/voxel_light_baker.cpp74
-rw-r--r--scene/3d/voxel_light_baker.h5
-rw-r--r--scene/animation/animation_tree_player.cpp21
-rw-r--r--scene/animation/animation_tree_player.h1
-rw-r--r--scene/gui/button.h3
-rw-r--r--scene/gui/color_picker.cpp18
-rw-r--r--scene/gui/color_picker.h4
-rw-r--r--scene/gui/menu_button.cpp28
-rw-r--r--scene/gui/menu_button.h5
-rw-r--r--scene/gui/option_button.cpp77
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/split_container.cpp66
-rw-r--r--scene/gui/split_container.h4
-rw-r--r--scene/gui/text_edit.cpp58
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/gui/tree.cpp52
-rw-r--r--scene/gui/tree.h8
-rw-r--r--scene/main/node.cpp3
-rw-r--r--scene/main/scene_tree.cpp15
-rw-r--r--scene/main/scene_tree.h9
-rw-r--r--scene/main/viewport.cpp10
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/register_scene_types.cpp16
-rw-r--r--scene/resources/material.cpp2
-rw-r--r--scene/resources/shader.cpp77
-rw-r--r--scene/resources/shader.h17
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--scene/resources/tile_set.cpp4
-rw-r--r--servers/physics_2d_server.cpp4
-rw-r--r--servers/visual/shader_types.cpp1
110 files changed, 2546 insertions, 1393 deletions
diff --git a/SConstruct b/SConstruct
index dbce94f296..88b29695cb 100644
--- a/SConstruct
+++ b/SConstruct
@@ -168,7 +168,6 @@ opts.Add(BoolVariable('vsproj', "Generate Visual Studio Project.", False))
opts.Add(EnumVariable('warnings', "Set the level of warnings emitted during compilation", 'no', ('extra', 'all', 'moderate', 'no')))
opts.Add(BoolVariable('progress', "Show a progress indicator during build", True))
opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=all", False))
-opts.Add(BoolVariable('openmp', "If yes, enable OpenMP", True))
opts.Add(EnumVariable('macports_clang', "Build using clang from MacPorts", 'no', ('no', '5.0', 'devel')))
# Thirdparty libraries
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index a8f6e4da6c..b390590cf2 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -98,6 +98,11 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(MARGIN_RIGHT);
BIND_GLOBAL_ENUM_CONSTANT(MARGIN_BOTTOM);
+ BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(CORNER_BOTTOM_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(CORNER_BOTTOM_LEFT);
+
BIND_GLOBAL_ENUM_CONSTANT(VERTICAL);
BIND_GLOBAL_ENUM_CONSTANT(HORIZONTAL);
@@ -573,6 +578,38 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::POOL_VECTOR3_ARRAY);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::POOL_COLOR_ARRAY);
BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX);
+
+ //comparation
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS_EQUAL", Variant::OP_LESS_EQUAL);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_GREATER", Variant::OP_GREATER);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_GREATER_EQUAL", Variant::OP_GREATER_EQUAL);
+ //mathematic
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_ADD", Variant::OP_ADD);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SUBTRACT", Variant::OP_SUBTRACT);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MULTIPLY", Variant::OP_MULTIPLY);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_DIVIDE", Variant::OP_DIVIDE);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_STRING_CONCAT", Variant::OP_STRING_CONCAT);
+ //bitwise
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_AND", Variant::OP_BIT_AND);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_OR", Variant::OP_BIT_OR);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_XOR", Variant::OP_BIT_XOR);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_NEGATE", Variant::OP_BIT_NEGATE);
+ //logic
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_AND", Variant::OP_AND);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_OR", Variant::OP_OR);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_XOR", Variant::OP_XOR);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT", Variant::OP_NOT);
+ //containment
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_IN", Variant::OP_IN);
+ BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MAX", Variant::OP_MAX);
}
void unregister_global_constants() {
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 4498efeb41..7c5dbc895a 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -459,7 +459,7 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point);
ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points);
- ClassDB::bind_method(D_METHOD("get_point_connections"), &AStar::get_point_connections);
+ ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar::get_point_connections);
ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points);
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index 11003c1cd5..8ad164d4dc 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -102,69 +102,6 @@ Vector2 Vector2::cross(real_t p_other) const {
return Vector2(p_other * y, -p_other * x);
}
-Vector2 Vector2::operator+(const Vector2 &p_v) const {
-
- return Vector2(x + p_v.x, y + p_v.y);
-}
-void Vector2::operator+=(const Vector2 &p_v) {
-
- x += p_v.x;
- y += p_v.y;
-}
-Vector2 Vector2::operator-(const Vector2 &p_v) const {
-
- return Vector2(x - p_v.x, y - p_v.y);
-}
-void Vector2::operator-=(const Vector2 &p_v) {
-
- x -= p_v.x;
- y -= p_v.y;
-}
-
-Vector2 Vector2::operator*(const Vector2 &p_v1) const {
-
- return Vector2(x * p_v1.x, y * p_v1.y);
-};
-
-Vector2 Vector2::operator*(const real_t &rvalue) const {
-
- return Vector2(x * rvalue, y * rvalue);
-};
-void Vector2::operator*=(const real_t &rvalue) {
-
- x *= rvalue;
- y *= rvalue;
-};
-
-Vector2 Vector2::operator/(const Vector2 &p_v1) const {
-
- return Vector2(x / p_v1.x, y / p_v1.y);
-};
-
-Vector2 Vector2::operator/(const real_t &rvalue) const {
-
- return Vector2(x / rvalue, y / rvalue);
-};
-
-void Vector2::operator/=(const real_t &rvalue) {
-
- x /= rvalue;
- y /= rvalue;
-};
-
-Vector2 Vector2::operator-() const {
-
- return Vector2(-x, -y);
-}
-
-bool Vector2::operator==(const Vector2 &p_vec2) const {
-
- return x == p_vec2.x && y == p_vec2.y;
-}
-bool Vector2::operator!=(const Vector2 &p_vec2) const {
-
- return x != p_vec2.x || y != p_vec2.y;
-}
Vector2 Vector2::floor() const {
return Vector2(Math::floor(x), Math::floor(y));
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index 60351445c0..4635a4da55 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -187,6 +187,70 @@ _FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
+_FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const {
+
+ return Vector2(x + p_v.x, y + p_v.y);
+}
+_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) {
+
+ x += p_v.x;
+ y += p_v.y;
+}
+_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const {
+
+ return Vector2(x - p_v.x, y - p_v.y);
+}
+_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) {
+
+ x -= p_v.x;
+ y -= p_v.y;
+}
+
+_FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const {
+
+ return Vector2(x * p_v1.x, y * p_v1.y);
+};
+
+_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const {
+
+ return Vector2(x * rvalue, y * rvalue);
+};
+_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) {
+
+ x *= rvalue;
+ y *= rvalue;
+};
+
+_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const {
+
+ return Vector2(x / p_v1.x, y / p_v1.y);
+};
+
+_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const {
+
+ return Vector2(x / rvalue, y / rvalue);
+};
+
+_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) {
+
+ x /= rvalue;
+ y /= rvalue;
+};
+
+_FORCE_INLINE_ Vector2 Vector2::operator-() const {
+
+ return Vector2(-x, -y);
+}
+
+_FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const {
+
+ return x == p_vec2.x && y == p_vec2.y;
+}
+_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
+
+ return x != p_vec2.x || y != p_vec2.y;
+}
+
Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const {
Vector2 res = *this;
@@ -336,9 +400,10 @@ struct Rect2 {
g.size.height += p_by * 2;
return g;
}
+
inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const {
Rect2 g = *this;
- g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
+ g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0,
(MARGIN_TOP == p_margin) ? p_amount : 0,
(MARGIN_RIGHT == p_margin) ? p_amount : 0,
(MARGIN_BOTTOM == p_margin) ? p_amount : 0);
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index ab3bca79ae..5346141470 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -311,6 +311,15 @@ void Basis::rotate(const Vector3 &p_axis, real_t p_phi) {
*this = rotated(p_axis, p_phi);
}
+void Basis::rotate_local(const Vector3 &p_axis, real_t p_phi) {
+
+ *this = rotated_local(p_axis, p_phi);
+}
+Basis Basis::rotated_local(const Vector3 &p_axis, real_t p_phi) const {
+
+ return (*this) * Basis(p_axis, p_phi);
+}
+
Basis Basis::rotated(const Vector3 &p_euler) const {
return Basis(p_euler) * (*this);
}
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index 9a33b8203d..9a75308f08 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -75,6 +75,9 @@ public:
void rotate(const Vector3 &p_axis, real_t p_phi);
Basis rotated(const Vector3 &p_axis, real_t p_phi) const;
+ void rotate_local(const Vector3 &p_axis, real_t p_phi);
+ Basis rotated_local(const Vector3 &p_axis, real_t p_phi) const;
+
void rotate(const Vector3 &p_euler);
Basis rotated(const Vector3 &p_euler) const;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 9b2bd30868..0cab8c10ef 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -32,14 +32,6 @@
#include "input_map.h"
#include "os/keyboard.h"
-void InputEvent::set_id(uint32_t p_id) {
- id = p_id;
-}
-
-uint32_t InputEvent::get_id() const {
- return id;
-}
-
void InputEvent::set_device(int p_device) {
device = p_device;
}
@@ -99,9 +91,6 @@ bool InputEvent::is_action_type() const {
void InputEvent::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_id", "id"), &InputEvent::set_id);
- ClassDB::bind_method(D_METHOD("get_id"), &InputEvent::get_id);
-
ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device);
@@ -125,7 +114,6 @@ void InputEvent::_bind_methods() {
InputEvent::InputEvent() {
- id = 0;
device = 0;
}
@@ -441,7 +429,6 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
Ref<InputEventMouseButton> mb;
mb.instance();
- mb->set_id(get_id());
mb->set_device(get_device());
mb->set_modifiers_from_event(this);
@@ -557,7 +544,6 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co
Ref<InputEventMouseMotion> mm;
mm.instance();
- mm->set_id(get_id());
mm->set_device(get_device());
mm->set_modifiers_from_event(this);
@@ -764,7 +750,6 @@ Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, co
Ref<InputEventScreenTouch> st;
st.instance();
- st->set_id(get_id());
st->set_device(get_device());
st->set_index(index);
st->set_position(p_xform.xform(pos + p_local_ofs));
@@ -845,7 +830,6 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con
sd.instance();
- sd->set_id(get_id());
sd->set_device(get_device());
sd->set_index(index);
@@ -968,7 +952,6 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform,
Ref<InputEventMagnifyGesture> ev;
ev.instance();
- ev->set_id(get_id());
ev->set_device(get_device());
ev->set_modifiers_from_event(this);
@@ -1006,7 +989,6 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con
Ref<InputEventPanGesture> ev;
ev.instance();
- ev->set_id(get_id());
ev->set_device(get_device());
ev->set_modifiers_from_event(this);
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 614a3289ba..9b1a2736b1 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -144,16 +144,12 @@ enum JoystickList {
class InputEvent : public Resource {
GDCLASS(InputEvent, Resource)
- uint32_t id;
int device;
protected:
static void _bind_methods();
public:
- void set_id(uint32_t p_id);
- uint32_t get_id() const;
-
void set_device(int p_device);
int get_device() const;
diff --git a/core/os/threaded_array_processor.cpp b/core/os/threaded_array_processor.cpp
new file mode 100644
index 0000000000..8e92508ea5
--- /dev/null
+++ b/core/os/threaded_array_processor.cpp
@@ -0,0 +1,2 @@
+#include "threaded_array_processor.h"
+
diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h
new file mode 100644
index 0000000000..e584fbb193
--- /dev/null
+++ b/core/os/threaded_array_processor.h
@@ -0,0 +1,80 @@
+#ifndef THREADED_ARRAY_PROCESSOR_H
+#define THREADED_ARRAY_PROCESSOR_H
+
+#include "os/mutex.h"
+#include "os/os.h"
+#include "os/thread.h"
+#include "safe_refcount.h"
+#include "thread_safe.h"
+
+template <class C, class U>
+struct ThreadArrayProcessData {
+ uint32_t elements;
+ uint32_t index;
+ C *instance;
+ U userdata;
+ void (C::*method)(uint32_t, U);
+
+ void process(uint32_t p_index) {
+ (instance->*method)(p_index, userdata);
+ }
+};
+
+#ifndef NO_THREADS
+
+template <class T>
+void process_array_thread(void *ud) {
+
+ T &data = *(T *)ud;
+ while (true) {
+ uint32_t index = atomic_increment(&data.index);
+ if (index >= data.elements)
+ break;
+ data.process(index);
+ }
+}
+
+template <class C, class M, class U>
+void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
+
+ ThreadArrayProcessData<C, U> data;
+ data.method = p_method;
+ data.instance = p_instance;
+ data.userdata = p_userdata;
+ data.index = 0;
+ data.elements = p_elements;
+ data.process(data.index); //process first, let threads increment for next
+
+ Vector<Thread *> threads;
+
+ threads.resize(OS::get_singleton()->get_processor_count());
+
+ for (int i = 0; i < threads.size(); i++) {
+ threads[i] = Thread::create(process_array_thread<ThreadArrayProcessData<C, U> >, &data);
+ }
+
+ for (int i = 0; i < threads.size(); i++) {
+ Thread::wait_to_finish(threads[i]);
+ memdelete(threads[i]);
+ }
+}
+
+#else
+
+template <class C, class M, class U>
+void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
+
+ ThreadArrayProcessData<C, U> data;
+ data.method = p_method;
+ data.instance = p_instance;
+ data.userdata = p_userdata;
+ data.index = 0;
+ data.elements = p_elements;
+ for (uint32_t i = 0; i < p_elements; i++) {
+ data.process(i);
+ }
+}
+
+#endif
+
+#endif // THREADED_ARRAY_PROCESSOR_H
diff --git a/doc/classes/ColorPickerButton.xml b/doc/classes/ColorPickerButton.xml
index 185460eef2..87d00b7600 100644
--- a/doc/classes/ColorPickerButton.xml
+++ b/doc/classes/ColorPickerButton.xml
@@ -11,14 +11,14 @@
<demos>
</demos>
<methods>
- <method name="get_picker">
+ <method name="get_picker" qualifiers="const">
<return type="ColorPicker">
</return>
<description>
Returns the [code]ColorPicker[/code] that this [code]ColorPickerButton[/code] toggles.
</description>
</method>
- <method name="get_popup">
+ <method name="get_popup" qualifiers="const">
<return type="PopupPanel">
</return>
<description>
diff --git a/doc/classes/MenuButton.xml b/doc/classes/MenuButton.xml
index c41c86d693..22231cfdf3 100644
--- a/doc/classes/MenuButton.xml
+++ b/doc/classes/MenuButton.xml
@@ -11,7 +11,7 @@
<demos>
</demos>
<methods>
- <method name="get_popup">
+ <method name="get_popup" qualifiers="const">
<return type="PopupMenu">
</return>
<description>
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index 76265e700a..ff3e513c79 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -91,6 +91,13 @@
Return the text of the item at index "idx".
</description>
</method>
+ <method name="get_popup" qualifiers="const">
+ <return type="PopupMenu">
+ </return>
+ <description>
+ Return the [PopupMenu] contained in this button.
+ </description>
+ </method>
<method name="get_selected_id" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/Physics2DDirectSpaceState.xml b/doc/classes/Physics2DDirectSpaceState.xml
index f63b8f17bc..2e2d8e95f9 100644
--- a/doc/classes/Physics2DDirectSpaceState.xml
+++ b/doc/classes/Physics2DDirectSpaceState.xml
@@ -17,8 +17,8 @@
<argument index="0" name="shape" type="Physics2DShapeQueryParameters">
</argument>
<description>
- Check whether the shape can travel to a point. If it can, the method will return an array with two floats: The first is the distance the shape can move in that direction without colliding, and the second is the distance at which it will collide.
- If the shape can not move, the array will be empty.
+ Checks how far the shape can travel toward a point. Note that both the shape and the motion are supplied through a [Physics2DShapeQueryParameters] object. The method will return an array with two floats between 0 and 1, both representing a fraction of [code]motion[/code]. The first is how far the shape can move without triggering a collision, and the second is the point at which a collision will occur. If no collision is detected, the returned array will be [1, 1].
+ If the shape can not move, the array will be empty ([code]dir.empty()==true[/code]).
</description>
</method>
<method name="collide_shape">
@@ -29,7 +29,7 @@
<argument index="1" name="max_results" type="int" default="32">
</argument>
<description>
- Check the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. The resulting array contains a list of points where the shape intersects another. Like with [method intersect_shape], the number of returned results can be limited to save processing time.
+ Checks the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. The resulting array contains a list of points where the shape intersects another. Like with [method intersect_shape], the number of returned results can be limited to save processing time.
</description>
</method>
<method name="get_rest_info">
@@ -38,16 +38,15 @@
<argument index="0" name="shape" type="Physics2DShapeQueryParameters">
</argument>
<description>
- Check the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. If it collides with more than a shape, the nearest one is selected. The returned object is a dictionary containing the following fields:
- pointo: Place where the shapes intersect.
- normal: Normal of the object at the point where the shapes intersect.
- shape: Shape index within the object against which the shape intersected.
- metadata: Metadata of the shape against which the shape intersected. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
- collider_id: Id of the object against which the shape intersected.
- collider: Object against which the shape intersected.
- rid: [RID] of the object against which the shape intersected.
- linear_velocity: The movement vector of the object the shape intersected, if it was a body. If it was an area, it is (0,0).
- If the shape did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead.
+ Checks the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. If it collides with more than one shape, the nearest one is selected. Note that this method does not take into account the [code]motion[/code] property of the object. The returned object is a dictionary containing the following fields:
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]linear_velocity[/code]: The colliding object's velocity [Vector2]. If the object is an [Area2D], the result is [code](0, 0)[/code].
+ [code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
+ [code]normal[/code]: The object's surface normal at the intersection point.
+ [code]point[/code]: The intersection point.
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
+ If the shape did not intersect anything, then an empty dictionary ([code]dir.empty()==true[/code]) is returned instead.
</description>
</method>
<method name="intersect_point">
@@ -62,12 +61,12 @@
<argument index="3" name="collision_layer" type="int" default="2147483647">
</argument>
<description>
- Check whether a point is inside any shape. The shapes the point is inside of are returned in an array containing dictionaries with the following fields:
- shape: Shape index within the object the point is in.
- metadata: Metadata of the shape the point is in. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
- collider_id: Id of the object the point is in.
- collider: Object the point is inside of.
- rid: [RID] of the object the point is in.
+ Checks whether a point is inside any shape. The shapes the point is inside of are returned in an array containing dictionaries with the following fields:
+ [code]collider[/code]: The colliding object.
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
Additionally, the method can take an array of objects or [RID]s that are to be excluded from collisions, or a bitmask representing the physics layers to check in.
</description>
</method>
@@ -83,15 +82,15 @@
<argument index="3" name="collision_layer" type="int" default="2147483647">
</argument>
<description>
- Intersect a ray in a given space. The returned object is a dictionary with the following fields:
- position: Place where ray is stopped.
- normal: Normal of the object at the point where the ray was stopped.
- shape: Shape index within the object against which the ray was stopped.
- metadata: Metadata of the shape against which the ray was stopped. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
- collider_id: Id of the object against which the ray was stopped.
- collider: Object against which the ray was stopped.
- rid: [RID] of the object against which the ray was stopped.
- If the ray did not intersect anything, then an empty dictionary (dir.empty()==true) is returned instead.
+ Intersects a ray in a given space. The returned object is a dictionary with the following fields:
+ [code]collider[/code]: The colliding object.
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
+ [code]normal[/code]: The object's surface normal at the intersection point.
+ [code]position[/code]: The intersection point.
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
+ If the ray did not intersect anything, then an empty dictionary ([code]dir.empty()==true[/code]) is returned instead.
Additionally, the method can take an array of objects or [RID]s that are to be excluded from collisions, or a bitmask representing the physics layers to check in.
</description>
</method>
@@ -103,12 +102,12 @@
<argument index="1" name="max_results" type="int" default="32">
</argument>
<description>
- Check the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. The intersected shapes are returned in an array containing dictionaries with the following fields:
- shape: Shape index within the object the shape intersected.
- metadata: Metadata of the shape intersected by the shape given through the [Physics2DShapeQueryParameters]. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
- collider_id: Id of the object the shape intersected.
- collider: Object the shape intersected.
- rid: [RID] of the object the shape intersected.
+ Checks the intersections of a shape, given through a [Physics2DShapeQueryParameters] object, against the space. Note that this method does not take into account the [code]motion[/code] property of the object. The intersected shapes are returned in an array containing dictionaries with the following fields:
+ [code]collider[/code]: The colliding object.
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]metadata[/code]: The intersecting shape's metadata. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
The number of intersections can be limited with the second parameter, to reduce the processing time.
</description>
</method>
diff --git a/doc/classes/PhysicsDirectSpaceState.xml b/doc/classes/PhysicsDirectSpaceState.xml
index 21576646f9..d93550eb47 100644
--- a/doc/classes/PhysicsDirectSpaceState.xml
+++ b/doc/classes/PhysicsDirectSpaceState.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicsDirectSpaceState" inherits="Object" category="Core" version="3.0-beta">
<brief_description>
+ Direct access object to a space in the [PhysicsServer].
</brief_description>
<description>
+ Direct access object to a space in the [PhysicsServer]. It's used mainly to do queries against objects and areas residing in a given space.
</description>
<tutorials>
</tutorials>
@@ -17,6 +19,8 @@
<argument index="1" name="motion" type="Vector3">
</argument>
<description>
+ Checks whether the shape can travel to a point. The method will return an array with two floats between 0 and 1, both representing a fraction of [code]motion[/code]. The first is how far the shape can move without triggering a collision, and the second is the point at which a collision will occur. If no collision is detected, the returned array will be [1, 1].
+ If the shape can not move, the array will be empty ([code]dir.empty()==true[/code]).
</description>
</method>
<method name="collide_shape">
@@ -27,6 +31,7 @@
<argument index="1" name="max_results" type="int" default="32">
</argument>
<description>
+ Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters] object, against the space. The resulting array contains a list of points where the shape intersects another. Like with [method intersect_shape], the number of returned results can be limited to save processing time.
</description>
</method>
<method name="get_rest_info">
@@ -35,6 +40,14 @@
<argument index="0" name="shape" type="PhysicsShapeQueryParameters">
</argument>
<description>
+ Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters] object, against the space. If it collides with more than a shape, the nearest one is selected. The returned object is a dictionary containing the following fields:
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]linear_velocity[/code]: The colliding object's velocity [Vector3]. If the object is an [Area], the result is [code](0, 0, 0)[/code].
+ [code]normal[/code]: The object's surface normal at the intersection point.
+ [code]point[/code]: The intersection point.
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
+ If the shape did not intersect anything, then an empty dictionary ([code]dir.empty()==true[/code]) is returned instead.
</description>
</method>
<method name="intersect_ray">
@@ -49,6 +62,15 @@
<argument index="3" name="collision_layer" type="int" default="2147483647">
</argument>
<description>
+ Intersects a ray in a given space. The returned object is a dictionary with the following fields:
+ [code]collider[/code]: The colliding object.
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]normal[/code]: The object's surface normal at the intersection point.
+ [code]position[/code]: The intersection point.
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
+ If the ray did not intersect anything, then an empty dictionary ([code]dir.empty()==true[/code]) is returned instead.
+ Additionally, the method can take an array of objects or [RID]s that are to be excluded from collisions, or a bitmask representing the physics layers to check in.
</description>
</method>
<method name="intersect_shape">
@@ -59,6 +81,12 @@
<argument index="1" name="max_results" type="int" default="32">
</argument>
<description>
+ Checks the intersections of a shape, given through a [PhysicsShapeQueryParameters] object, against the space. The intersected shapes are returned in an array containing dictionaries with the following fields:
+ [code]collider[/code]: The colliding object.
+ [code]collider_id[/code]: The colliding object's ID.
+ [code]rid[/code]: The intersecting object's [RID].
+ [code]shape[/code]: The shape index of the colliding shape.
+ The number of intersections can be limited with the second parameter, to reduce the processing time.
</description>
</method>
</methods>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 85cbeaaa03..ab722a24c3 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -345,18 +345,28 @@
</methods>
<members>
<member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled">
+ If [code]true[/code] the caret (visual cursor) blinks.
</member>
<member name="caret_blink_speed" type="float" setter="cursor_set_blink_speed" getter="cursor_get_blink_speed">
+ Duration (in seconds) of a caret's blinking cycle.
</member>
<member name="caret_block_mode" type="bool" setter="cursor_set_block_mode" getter="cursor_is_block_mode">
+ If [code]true[/code] the caret displays as a rectangle.
+ If [code]false[/code] the caret displays as a bar.
+ </member>
+ <member name="caret_moving_by_right_click" type="bool" setter="set_right_click_moves_caret" getter="is_right_click_moving_caret">
+ If [code]true[/code] a right click moves the cursor at the mouse position before displaying the context menu.
+ If [code]false[/code] the context menu disregards mouse location.
</member>
<member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled">
+ If [code]true[/code] a right click displays the context menu.
</member>
<member name="hiding_enabled" type="int" setter="set_hiding_enabled" getter="is_hiding_enabled">
</member>
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled">
</member>
<member name="highlight_current_line" type="bool" setter="set_highlight_current_line" getter="is_highlight_current_line_enabled">
+ If [code]true[/code] the line containing the cursor is highlighted.
</member>
<member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color">
</member>
@@ -364,6 +374,7 @@
If [code]true[/code] read-only mode is enabled. Existing text cannot be modified and new text cannot be added.
</member>
<member name="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled">
+ If [code]true[/code] line numbers are displayed to the left of the text.
</member>
<member name="smooth_scrolling" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled">
</member>
@@ -419,16 +430,22 @@
Search from end to beginning.
</constant>
<constant name="MENU_CUT" value="0" enum="MenuItems">
+ Cuts (Copies and clears) the selected text.
</constant>
<constant name="MENU_COPY" value="1" enum="MenuItems">
+ Copies the selected text.
</constant>
<constant name="MENU_PASTE" value="2" enum="MenuItems">
+ Pastes the clipboard text over the selected text (or at the cursor's position).
</constant>
<constant name="MENU_CLEAR" value="3" enum="MenuItems">
+ Erases the whole [TextEdit] text.
</constant>
<constant name="MENU_SELECT_ALL" value="4" enum="MenuItems">
+ Selects the whole [TextEdit] text.
</constant>
<constant name="MENU_UNDO" value="5" enum="MenuItems">
+ Undoes the previous action.
</constant>
<constant name="MENU_MAX" value="6" enum="MenuItems">
</constant>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index 17576f33ed..f4717aa995 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -4,7 +4,7 @@
2D Transformation. 3x2 matrix.
</brief_description>
<description>
- Represents one or many transformations in 3D space such as translation, rotation, or scaling. It consists of a two [Vector2] x, y and [Vector2] "origin". It is similar to a 3x2 matrix.
+ Represents one or many transformations in 2D space such as translation, rotation, or scaling. It consists of a two [Vector2] x, y and [Vector2] "origin". It is similar to a 3x2 matrix.
</description>
<tutorials>
</tutorials>
@@ -17,7 +17,7 @@
<argument index="0" name="from" type="Transform">
</argument>
<description>
- Constructs the [code]Transform2D[/code] from a 3D [Transform].
+ Constructs the transform from a 3D [Transform].
</description>
</method>
<method name="Transform2D">
@@ -30,7 +30,7 @@
<argument index="2" name="origin" type="Vector2">
</argument>
<description>
- Constructs the [code]Transform2D[/code] from 3 [Vector2] consisting of rows x, y and origin.
+ Constructs the transform from 3 [Vector2]s representing x, y, and origin.
</description>
</method>
<method name="Transform2D">
@@ -41,7 +41,7 @@
<argument index="1" name="position" type="Vector2">
</argument>
<description>
- Constructs the [code]Transform2D[/code] from rotation angle in radians and position [Vector2].
+ Constructs the transform from a given angle (in radians) and position.
</description>
</method>
<method name="affine_inverse">
@@ -57,7 +57,7 @@
<argument index="0" name="v" type="var">
</argument>
<description>
- Transforms the given vector "v" by this transform basis (no translation).
+ Transforms the given vector by this transform's basis (no translation).
</description>
</method>
<method name="basis_xform_inv">
@@ -66,21 +66,21 @@
<argument index="0" name="v" type="var">
</argument>
<description>
- Inverse-transforms the given vector "v" by this transform basis (no translation).
+ Inverse-transforms the given vector by this transform's basis (no translation).
</description>
</method>
<method name="get_origin">
<return type="Vector2">
</return>
<description>
- Returns the origin [Vector2] (translation).
+ Returns the transform's origin (translation).
</description>
</method>
<method name="get_rotation">
<return type="float">
</return>
<description>
- Returns the rotation (in radians).
+ Returns the transform's rotation (in radians).
</description>
</method>
<method name="get_scale">
@@ -98,7 +98,7 @@
<argument index="1" name="weight" type="float">
</argument>
<description>
- Interpolates the transform to other Transform2D by weight amount (0-1).
+ Returns a transform interpolated between this transform and another by a given weight (0-1).
</description>
</method>
<method name="inverse">
@@ -121,7 +121,7 @@
<argument index="0" name="phi" type="float">
</argument>
<description>
- Rotates the transform by phi.
+ Rotates the transform by the given angle (in radians).
</description>
</method>
<method name="scaled">
@@ -130,7 +130,7 @@
<argument index="0" name="scale" type="Vector2">
</argument>
<description>
- Scales the transform by the specified 2D scaling factors.
+ Scales the transform by the given factor.
</description>
</method>
<method name="translated">
@@ -139,7 +139,7 @@
<argument index="0" name="offset" type="Vector2">
</argument>
<description>
- Translates the transform by the specified offset.
+ Translates the transform by the given offset.
</description>
</method>
<method name="xform">
@@ -163,13 +163,13 @@
</methods>
<members>
<member name="origin" type="Vector2" setter="" getter="">
- The translation offset of the transform.
+ The transform's translation offset.
</member>
<member name="x" type="Vector2" setter="" getter="">
- The X axis of 2x2 basis matrix containing 2 [Vector2] as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
+ The X axis of 2x2 basis matrix containing 2 [Vector2]s as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
</member>
<member name="y" type="Vector2" setter="" getter="">
- The Y axis of 2x2 basis matrix containing 2 [Vector2] as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
+ The Y axis of 2x2 basis matrix containing 2 [Vector2]s as its columns: X axis and Y axis. These vectors can be interpreted as the basis vectors of local coordinate system traveling with the object.
</member>
</members>
<constants>
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index a4daa77b50..86415ea740 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -1086,19 +1086,22 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
}
}
- if (shader_ptr && shader_ptr != shader_cache) {
+ if (shader_ptr) {
if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) {
//copy if not copied before
_copy_texscreen(Rect2());
}
- if (shader_ptr->canvas_item.uses_time) {
- VisualServerRaster::redraw_request();
- }
+ if (shader_ptr != shader_cache) {
- state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
- state.canvas_shader.bind();
+ if (shader_ptr->canvas_item.uses_time) {
+ VisualServerRaster::redraw_request();
+ }
+
+ state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id);
+ state.canvas_shader.bind();
+ }
if (material_ptr->ubo_id) {
glBindBufferBase(GL_UNIFORM_BUFFER, 2, material_ptr->ubo_id);
@@ -1147,7 +1150,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
glBindTexture(t->target, t->tex_id);
}
- } else if (!shader_ptr) {
+ } else {
state.canvas_shader.set_custom_shader(0);
state.canvas_shader.bind();
}
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index b777f9343a..1c3361d2de 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1541,7 +1541,19 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
if (c.texture.is_valid() && storage->texture_owner.owns(c.texture)) {
- const RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture);
+ RasterizerStorageGLES3::Texture *t = storage->texture_owner.get(c.texture);
+
+ t = t->get_ptr(); //resolve for proxies
+#ifdef TOOLS_ENABLED
+ if (t->detect_3d) {
+ t->detect_3d(t->detect_3d_ud);
+ }
+#endif
+
+ if (t->render_target) {
+ t->render_target->used_in_frame = true;
+ }
+
glActiveTexture(GL_TEXTURE0);
glBindTexture(t->target, t->tex_id);
restore_tex = true;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 101978548d..ec00c057b2 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -806,7 +806,6 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv";
actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture";
actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer";
- actions[VS::SHADER_SPATIAL].renames["SIDE"] = "side";
actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor";
//for light
@@ -847,6 +846,8 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
+ actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index bb9ff29a8e..6427e3d967 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -174,7 +174,7 @@ void light_compute(vec3 N, vec3 L,vec3 V, vec3 light_color, float roughness, ino
vec3 H = normalize(V + L);
float dotNH = max(dot(N,H), 0.0 );
- float intensity = pow( dotNH, (1.0-roughness) * 256.0);
+ float intensity = (roughness >= 1.0 ? 1.0 : pow( dotNH, (1.0-roughness) * 256.0));
specular += light_color * intensity;
}
@@ -1615,7 +1615,7 @@ void main() {
float alpha = 1.0;
-#ifdef METERIAL_DOUBLESIDED
+#if defined(DO_SIDE_CHECK)
float side=float(gl_FrontFacing)*2.0-1.0;
#else
float side=1.0;
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 2584d26fc4..e904fd94be 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -267,7 +267,6 @@ void CreateDialog::_update_search() {
if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) {
//there are custom types based on this... cool.
- //print_line("there are custom types");
const Vector<EditorData::CustomType> &ct = EditorNode::get_editor_data().get_custom_types()[type];
for (int i = 0; i < ct.size(); i++) {
@@ -630,31 +629,40 @@ CreateDialog::CreateDialog() {
set_resizable(true);
- HSplitContainer *hbc = memnew(HSplitContainer);
+ HSplitContainer *hsc = memnew(HSplitContainer);
+ add_child(hsc);
- add_child(hbc);
+ VSplitContainer *vsc = memnew(VSplitContainer);
+ hsc->add_child(vsc);
- VBoxContainer *lvbc = memnew(VBoxContainer);
- hbc->add_child(lvbc);
- lvbc->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
+ VBoxContainer *fav_vb = memnew(VBoxContainer);
+ vsc->add_child(fav_vb);
+ fav_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE);
+ fav_vb->set_v_size_flags(SIZE_EXPAND_FILL);
favorites = memnew(Tree);
- lvbc->add_margin_child(TTR("Favorites:"), favorites, true);
+ fav_vb->add_margin_child(TTR("Favorites:"), favorites, true);
favorites->set_hide_root(true);
favorites->set_hide_folding(true);
favorites->connect("cell_selected", this, "_favorite_selected");
favorites->connect("item_activated", this, "_favorite_activated");
favorites->set_drag_forwarding(this);
+ VBoxContainer *rec_vb = memnew(VBoxContainer);
+ vsc->add_child(rec_vb);
+ rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE);
+ rec_vb->set_v_size_flags(SIZE_EXPAND_FILL);
+
recent = memnew(Tree);
- lvbc->add_margin_child(TTR("Recent:"), recent, true);
+ rec_vb->add_margin_child(TTR("Recent:"), recent, true);
recent->set_hide_root(true);
recent->set_hide_folding(true);
recent->connect("cell_selected", this, "_history_selected");
recent->connect("item_activated", this, "_history_activated");
VBoxContainer *vbc = memnew(VBoxContainer);
- hbc->add_child(vbc);
+ hsc->add_child(vbc);
+ vbc->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
vbc->set_h_size_flags(SIZE_EXPAND_FILL);
HBoxContainer *search_hb = memnew(HBoxContainer);
search_box = memnew(LineEdit);
@@ -676,7 +684,6 @@ CreateDialog::CreateDialog() {
set_hide_on_ok(false);
search_options->connect("item_activated", this, "_confirmed");
search_options->connect("cell_selected", this, "_item_selected");
- //search_options->set_hide_root(true);
base_type = "Object";
preferred_search_result_type = "";
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 5f026abb6d..6db3c09673 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -145,7 +145,7 @@ EditorAbout::EditorAbout() {
List<String> dev_sections;
dev_sections.push_back(TTR("Project Founders"));
dev_sections.push_back(TTR("Lead Developer"));
- dev_sections.push_back(TTR("Project Manager"));
+ dev_sections.push_back(TTR("Project Manager ")); // " " appended to distinguish between 'project supervisor' and 'project list'
dev_sections.push_back(TTR("Developers"));
const char **dev_src[] = { dev_founders, dev_lead, dev_manager, dev_names };
tc->add_child(_populate_list(TTR("Authors"), dev_sections, dev_src, 1));
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 49d55e6305..214b1cac89 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -701,6 +701,15 @@ String EditorData::get_scene_title(int p_idx) const {
return name;
}
+void EditorData::set_scene_path(int p_idx, const String &p_path) {
+
+ ERR_FAIL_INDEX(p_idx, edited_scene.size());
+
+ if (!edited_scene[p_idx].root)
+ return;
+ edited_scene[p_idx].root->set_filename(p_path);
+}
+
String EditorData::get_scene_path(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), String());
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 33a4091a65..f15b7e37f1 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -185,6 +185,7 @@ public:
String get_scene_title(int p_idx) const;
String get_scene_path(int p_idx) const;
String get_scene_type(int p_idx) const;
+ void set_scene_path(int p_idx, const String &p_path);
Ref<Script> get_scene_root_script(int p_idx) const;
void set_edited_scene_version(uint64_t version, int p_scene_idx = -1);
uint64_t get_edited_scene_version() const;
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index deba16a524..4bf138354d 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -54,7 +54,7 @@ void EditorFileDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
- //_update_icons
+ // update icons
mode_thumbnails->set_icon(get_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(get_icon("FileList", "EditorIcons"));
dir_prev->set_icon(get_icon("Back", "EditorIcons"));
@@ -65,7 +65,6 @@ void EditorFileDialog::_notification(int p_what) {
fav_up->set_icon(get_icon("MoveUp", "EditorIcons"));
fav_down->set_icon(get_icon("MoveDown", "EditorIcons"));
- fav_rm->set_icon(get_icon("Remove", "EditorIcons"));
} else if (p_what == NOTIFICATION_PROCESS) {
@@ -80,10 +79,6 @@ void EditorFileDialog::_notification(int p_what) {
preview_wheel_timeout = 0.1;
}
}
- } else if (p_what == NOTIFICATION_DRAW) {
-
- //RID ci = get_canvas_item();
- //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size()));
} else if (p_what == NOTIFICATION_POPUP_HIDE) {
set_process_unhandled_input(false);
@@ -95,7 +90,7 @@ void EditorFileDialog::_notification(int p_what) {
set_show_hidden_files(show_hidden);
set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int());
- //_update_icons
+ // update icons
mode_thumbnails->set_icon(get_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(get_icon("FileList", "EditorIcons"));
dir_prev->set_icon(get_icon("Back", "EditorIcons"));
@@ -106,7 +101,6 @@ void EditorFileDialog::_notification(int p_what) {
fav_up->set_icon(get_icon("MoveUp", "EditorIcons"));
fav_down->set_icon(get_icon("MoveDown", "EditorIcons"));
- fav_rm->set_icon(get_icon("Remove", "EditorIcons"));
// DO NOT CALL UPDATE FILE LIST HERE, ALL HUNDREDS OF HIDDEN DIALOGS WILL RESPOND, CALL INVALIDATE INSTEAD
invalidate();
}
@@ -260,7 +254,6 @@ void EditorFileDialog::_post_popup() {
name = name.get_file() + "/";
}
- //print_line("file: "+name);
recent->add_item(name, folder);
recent->set_item_metadata(recent->get_item_count() - 1, recentd[i]);
}
@@ -316,7 +309,7 @@ void EditorFileDialog::_request_single_thumbnail(const String &p_path) {
return;
EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_thumbnail_done", p_path);
- //print_line("want file "+p_path);
+
set_process(true);
preview_waiting = true;
preview_wheel_timeout = 0;
@@ -376,7 +369,7 @@ void EditorFileDialog::_action_pressed() {
bool valid = false;
if (filter->get_selected() == filter->get_item_count() - 1) {
- valid = true; //match none
+ valid = true; // match none
} else if (filters.size() > 1 && filter->get_selected() == 0) {
// match all filters
for (int i = 0; i < filters.size(); i++) {
@@ -777,14 +770,12 @@ void EditorFileDialog::update_file_list() {
}
if (match) {
- //TreeItem *ti=tree->create_item(root);
- //ti->set_text(0,files.front()->get());
+
item_list->add_item(files.front()->get());
if (get_icon_func) {
Ref<Texture> icon = get_icon_func(cdir.plus_file(files.front()->get()));
- //ti->set_icon(0,icon);
if (display_mode == DISPLAY_THUMBNAILS) {
item_list->set_item_icon(item_list->get_item_count() - 1, file_thumbnail);
@@ -794,11 +785,6 @@ void EditorFileDialog::update_file_list() {
}
}
- if (mode == MODE_OPEN_DIR) {
- //disabled mode?
- //ti->set_custom_color(0,get_color("files_disabled"));
- //ti->set_selectable(0,false);
- }
Dictionary d;
d["name"] = files.front()->get();
d["dir"] = false;
@@ -807,7 +793,6 @@ void EditorFileDialog::update_file_list() {
EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath, this, "_thumbnail_result", fullpath);
}
d["path"] = fullpath;
- //ti->set_metadata(0,d);
item_list->set_item_metadata(item_list->get_item_count() - 1, d);
if (file->get_text() == files.front()->get())
@@ -838,11 +823,6 @@ void EditorFileDialog::update_file_list() {
break;
}
}
- // ??
- /*
- if (tree->get_root() && tree->get_root()->get_children())
- tree->get_root()->get_children()->select(0);
- */
files.clear();
}
@@ -916,7 +896,6 @@ void EditorFileDialog::set_current_dir(const String &p_dir) {
dir_access->change_dir(p_dir);
update_dir();
invalidate();
- //_push_history();
}
void EditorFileDialog::set_current_file(const String &p_file) {
@@ -1191,7 +1170,6 @@ void EditorFileDialog::_update_favorites() {
name = name.get_file() + "/";
}
- //print_line("file: "+name);
favorites->add_item(name, star);
favorites->set_item_metadata(favorites->get_item_count() - 1, favorited[i]);
@@ -1442,6 +1420,8 @@ bool EditorFileDialog::is_overwrite_warning_disabled() const {
EditorFileDialog::EditorFileDialog() {
+ set_resizable(true);
+
show_hidden_files = default_show_hidden_files;
display_mode = default_display_mode;
local_history_pos = 0;
@@ -1499,6 +1479,8 @@ EditorFileDialog::EditorFileDialog() {
Ref<ButtonGroup> view_mode_group;
view_mode_group.instance();
+ pathhb->add_child(memnew(VSeparator));
+
mode_thumbnails = memnew(ToolButton);
mode_thumbnails->connect("pressed", this, "set_display_mode", varray(DISPLAY_THUMBNAILS));
mode_thumbnails->set_toggle_mode(true);
@@ -1528,8 +1510,13 @@ EditorFileDialog::EditorFileDialog() {
vbc->add_child(list_hb);
list_hb->set_v_size_flags(SIZE_EXPAND_FILL);
+ VSplitContainer *vsc = memnew(VSplitContainer);
+ list_hb->add_child(vsc);
+
VBoxContainer *fav_vb = memnew(VBoxContainer);
- list_hb->add_child(fav_vb);
+ vsc->add_child(fav_vb);
+ fav_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE);
+ fav_vb->set_v_size_flags(SIZE_EXPAND_FILL);
HBoxContainer *fav_hb = memnew(HBoxContainer);
fav_vb->add_child(fav_hb);
fav_hb->add_child(memnew(Label(TTR("Favorites:"))));
@@ -1540,23 +1527,23 @@ EditorFileDialog::EditorFileDialog() {
fav_down = memnew(ToolButton);
fav_hb->add_child(fav_down);
fav_down->connect("pressed", this, "_favorite_move_down");
- fav_rm = memnew(ToolButton);
- fav_hb->add_child(fav_rm);
- fav_rm->hide(); // redundant
- MarginContainer *fav_mv = memnew(MarginContainer);
- fav_vb->add_child(fav_mv);
- fav_mv->set_v_size_flags(SIZE_EXPAND_FILL);
favorites = memnew(ItemList);
- fav_mv->add_child(favorites);
+ fav_vb->add_child(favorites);
+ favorites->set_v_size_flags(SIZE_EXPAND_FILL);
favorites->connect("item_selected", this, "_favorite_selected");
+ VBoxContainer *rec_vb = memnew(VBoxContainer);
+ vsc->add_child(rec_vb);
+ rec_vb->set_custom_minimum_size(Size2(150, 100) * EDSCALE);
+ rec_vb->set_v_size_flags(SIZE_EXPAND_FILL);
recent = memnew(ItemList);
- fav_vb->add_margin_child(TTR("Recent:"), recent, true);
+ rec_vb->add_margin_child(TTR("Recent:"), recent, true);
recent->connect("item_selected", this, "_recent_selected");
VBoxContainer *item_vb = memnew(VBoxContainer);
list_hb->add_child(item_vb);
+ item_vb->set_custom_minimum_size(Size2(320, 0) * EDSCALE);
HBoxContainer *preview_hb = memnew(HBoxContainer);
preview_hb->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1599,7 +1586,7 @@ EditorFileDialog::EditorFileDialog() {
filter = memnew(OptionButton);
filter->set_stretch_ratio(3);
filter->set_h_size_flags(SIZE_EXPAND_FILL);
- filter->set_clip_text(true); //too many extensions overflow it
+ filter->set_clip_text(true); // too many extensions overflow it
filename_hbc->add_child(filter);
filename_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
item_vb->add_child(filename_hbc);
@@ -1609,7 +1596,6 @@ EditorFileDialog::EditorFileDialog() {
_update_drives();
connect("confirmed", this, "_action_pressed");
- //cancel->connect("pressed", this,"_cancel_pressed");
item_list->connect("item_selected", this, "_item_selected", varray(), CONNECT_DEFERRED);
item_list->connect("item_activated", this, "_item_db_selected", varray());
item_list->connect("nothing_selected", this, "_items_clear_selection");
@@ -1643,7 +1629,6 @@ EditorFileDialog::EditorFileDialog() {
exterr->set_text(TTR("Must use a valid extension."));
add_child(exterr);
- //update_file_list();
update_filters();
update_dir();
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index f4a9a174e7..281ded6889 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -36,6 +36,7 @@
#include "scene/gui/item_list.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
+#include "scene/gui/separator.h"
#include "scene/gui/split_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 8aca007e6b..a76c419152 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -173,11 +173,12 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font("output_source", "EditorFonts", df_output_code);
Ref<DynamicFont> df_text_editor_status_code;
- df_output_code.instance();
- df_output_code->set_size(14 * EDSCALE);
- df_output_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
- df_output_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
- df_output_code->set_font_data(dfmono);
- MAKE_FALLBACKS(df_output_code);
- p_theme->set_font("status_source", "EditorFonts", df_output_code);
+ df_text_editor_status_code.instance();
+ df_text_editor_status_code->set_size(14 * EDSCALE);
+ df_text_editor_status_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
+ df_text_editor_status_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
+ df_text_editor_status_code->set_font_data(dfmono);
+ MAKE_FALLBACKS(df_text_editor_status_code);
+
+ p_theme->set_font("status_source", "EditorFonts", df_text_editor_status_code);
}
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 46badc8c86..814da4b5f4 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -324,23 +324,14 @@ EditorHelpSearch::EditorHelpSearch() {
set_hide_on_ok(false);
search_options->connect("item_activated", this, "_confirmed");
set_title(TTR("Search Help"));
-
- //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 (!ClassDB::is_type(p_type,base) || p_type==base)
- return;
- */
String inherits = EditorHelp::get_doc_data()->class_list[p_type].inherits;
@@ -379,8 +370,6 @@ void EditorHelpIndex::_tree_item_selected() {
EditorNode::get_singleton()->set_visible_editor(EditorNode::EDITOR_SCRIPT);
emit_signal("open_class", s->get_text(0));
hide();
-
- //_goto_desc(s->get_text(0));
}
void EditorHelpIndex::select_class(const String &p_class) {
@@ -518,8 +507,6 @@ EditorHelpIndex::EditorHelpIndex() {
/////////////////////////////////
-////////////////////////////////////
-/// /////////////////////////////////
DocData *EditorHelp::doc = NULL;
void EditorHelp::_init_colors() {
@@ -572,9 +559,7 @@ 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("$")) { //enum
- //_goto_desc(p_select.substr(1,p_select.length()));
String select = p_select.substr(1, p_select.length());
String class_name;
if (select.find(".") != -1) {
@@ -585,7 +570,6 @@ void EditorHelp::_class_desc_select(const String &p_select) {
emit_signal("go_to_help", "class_enum:" + class_name + ":" + select);
return;
} else if (p_select.begins_with("#")) {
- //_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("@")) {
@@ -612,7 +596,6 @@ void EditorHelp::_class_desc_select(const String &p_select) {
}
if (link.find(".") != -1) {
- //must go somewhere else
emit_signal("go_to_help", topic + ":" + link.get_slice(".", 0) + ":" + link.get_slice(".", 1));
} else {
@@ -749,16 +732,13 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview
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)) {
select_locked = true;
- //}
class_desc->show();
- //tabs->set_current_tab(PAGE_CLASS_DESC);
+
description_line = 0;
if (p_class == edited_class)
@@ -770,7 +750,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
method_line.clear();
section_line.clear();
edited_class = p_class;
- //edited_class->show();
_init_colors();
@@ -866,7 +845,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop();
class_desc->pop();
- //class_desc->add_newline();
class_desc->add_newline();
class_desc->push_color(text_color);
class_desc->push_font(doc_font);
@@ -891,7 +869,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->add_text(TTR("Members:"));
class_desc->pop();
class_desc->pop();
- //class_desc->add_newline();
class_desc->push_indent(1);
class_desc->push_table(2);
@@ -970,9 +947,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop();
class_desc->pop();
- //class_desc->add_newline();
- //class_desc->add_newline();
-
class_desc->push_indent(1);
class_desc->push_table(2);
class_desc->set_table_column_expand(1, 1);
@@ -1098,7 +1072,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop();
class_desc->add_newline();
- //class_desc->add_newline();
class_desc->push_indent(1);
@@ -1106,8 +1079,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overridden if description
class_desc->push_font(doc_code_font); // monofont
- //_add_type("void");
- //class_desc->add_text(" ");
class_desc->push_color(headline_color);
_add_text(cd.signals[i].name);
class_desc->pop();
@@ -1141,7 +1112,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_font(doc_font);
class_desc->push_color(comment_color);
class_desc->push_indent(1);
- // class_desc->add_text(" ");
_add_text(cd.signals[i].description);
class_desc->pop(); // indent
class_desc->pop();
@@ -1185,7 +1155,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_indent(1);
class_desc->add_newline();
- //class_desc->add_newline();
for (Map<String, Vector<DocData::ConstantDoc> >::Element *E = enums.front(); E; E = E->next()) {
@@ -1260,7 +1229,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_indent(1);
class_desc->add_newline();
- //class_desc->add_newline();
for (int i = 0; i < constants.size(); i++) {
@@ -1279,7 +1247,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
if (constants[i].description != "") {
class_desc->push_font(doc_font);
class_desc->push_indent(1);
- //class_desc->add_text(" ");
class_desc->push_color(comment_color);
_add_text(constants[i].description);
class_desc->pop();
@@ -1353,8 +1320,6 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->pop(); // font
class_desc->pop(); // cell
- //class_desc->add_text(" ");
-
if (cd.properties[i].setter != "") {
class_desc->push_cell();
@@ -1538,7 +1503,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
}
if (brk_pos == bbcode.length())
- break; //nothing else o add
+ break; //nothing else to add
int brk_end = bbcode.find("]", brk_pos + 1);
@@ -1734,10 +1699,6 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
pos = brk_pos + 1;
}
}
-
- /*p_rt->pop();
- p_rt->pop();
- p_rt->pop();*/
}
void EditorHelp::_add_text(const String &p_bbcode) {
@@ -1762,8 +1723,7 @@ void EditorHelp::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- //forward->set_icon(get_icon("Forward","EditorIcons"));
- //back->set_icon(get_icon("Back","EditorIcons"));
+
_update_doc();
} break;
@@ -1836,7 +1796,6 @@ void EditorHelp::_bind_methods() {
ClassDB::bind_method("_class_list_select", &EditorHelp::_class_list_select);
ClassDB::bind_method("_class_desc_select", &EditorHelp::_class_desc_select);
ClassDB::bind_method("_class_desc_input", &EditorHelp::_class_desc_input);
- //ClassDB::bind_method("_button_pressed",&EditorHelp::_button_pressed);
ClassDB::bind_method("_request_help", &EditorHelp::_request_help);
ClassDB::bind_method("_unhandled_key_input", &EditorHelp::_unhandled_key_input);
ClassDB::bind_method("_search", &EditorHelp::_search);
@@ -1848,21 +1807,16 @@ void EditorHelp::_bind_methods() {
EditorHelp::EditorHelp() {
- VBoxContainer *vbc = this;
+ set_custom_minimum_size(Size2(150 * EDSCALE, 0));
EDITOR_DEF("text_editor/help/sort_functions_alphabetically", true);
- //class_list->connect("meta_clicked",this,"_class_list_select");
- //class_list->set_selection_enabled(true);
-
- {
- class_desc = memnew(RichTextLabel);
- vbc->add_child(class_desc);
- class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
- class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
- class_desc->connect("meta_clicked", this, "_class_desc_select");
- class_desc->connect("gui_input", this, "_class_desc_input");
- }
+ class_desc = memnew(RichTextLabel);
+ add_child(class_desc);
+ class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
+ class_desc->add_color_override("selection_color", get_color("text_editor/theme/selection_color", "Editor"));
+ class_desc->connect("meta_clicked", this, "_class_desc_select");
+ class_desc->connect("gui_input", this, "_class_desc_input");
class_desc->set_selection_enabled(true);
@@ -1882,12 +1836,6 @@ EditorHelp::EditorHelp() {
search_dialog->get_ok()->set_text(TTR("Find"));
search_dialog->connect("confirmed", this, "_search_cbk");
search_dialog->set_hide_on_ok(false);
-
- /*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() {
@@ -1905,9 +1853,9 @@ void EditorHelpBit::_go_to_help(String p_what) {
void EditorHelpBit::_meta_clicked(String p_select) {
print_line("got meta " + p_select);
- //print_line("LINK: "+p_select);
+
if (p_select.begins_with("$")) { //enum
- //_goto_desc(p_select.substr(1,p_select.length()));
+
String select = p_select.substr(1, p_select.length());
String class_name;
if (select.find(".") != -1) {
@@ -1918,24 +1866,15 @@ void EditorHelpBit::_meta_clicked(String p_select) {
_go_to_help("class_enum:" + class_name + ":" + select);
return;
} else if (p_select.begins_with("#")) {
- //_goto_desc(p_select.substr(1,p_select.length()));
+
_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 (m.find(".") != -1) {
- //must go somewhere else
-
- _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]);
- */
- }
+ if (m.find(".") != -1)
+ _go_to_help("class_method:" + m.get_slice(".", 0) + ":" + m.get_slice(".", 0)); //must go somewhere else
}
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index bd85927223..3bd592e934 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -351,6 +351,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/cursor/caret_blink", true);
_initial_set("text_editor/cursor/caret_blink_speed", 0.65);
hints["text_editor/cursor/caret_blink_speed"] = PropertyInfo(Variant::REAL, "text_editor/cursor/caret_blink_speed", PROPERTY_HINT_RANGE, "0.1, 10, 0.1");
+ _initial_set("text_editor/cursor/right_click_moves_caret", true);
_initial_set("text_editor/theme/font", "");
hints["text_editor/theme/font"] = PropertyInfo(Variant::STRING, "text_editor/theme/font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res");
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index cc0b292cc4..5610baa775 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -972,6 +972,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected);
theme->set_stylebox("breakpoint", "GraphNode", graphsbbreakpoint);
theme->set_stylebox("position", "GraphNode", graphsbposition);
+
+ Color default_node_color = Color(mv2, mv2, mv2);
+ theme->set_color("title_color", "GraphNode", default_node_color);
+ default_node_color.a = 0.7;
+ theme->set_color("close_color", "GraphNode", default_node_color);
+
theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE);
theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE);
theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 75e4f39e25..dce5a10d67 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -834,6 +834,58 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
memdelete(da);
}
+void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const {
+
+ //Rename all resources loaded, be it subresources or actual resources
+ List<Ref<Resource> > cached;
+ ResourceCache::get_cached_resources(&cached);
+
+ for (List<Ref<Resource> >::Element *E = cached.front(); E; E = E->next()) {
+
+ Ref<Resource> r = E->get();
+
+ String base_path = r->get_path();
+ String extra_path;
+ int sep_pos = r->get_path().find("::");
+ if (sep_pos >= 0) {
+ extra_path = base_path.substr(sep_pos, base_path.length());
+ base_path = base_path.substr(0, sep_pos);
+ }
+
+ if (p_renames.has(base_path)) {
+ base_path = p_renames[base_path];
+ }
+
+ r->set_path(base_path + extra_path);
+ }
+
+ for (int i = 0; i < EditorNode::get_editor_data().get_edited_scene_count(); i++) {
+
+ String path;
+ if (i == EditorNode::get_editor_data().get_edited_scene()) {
+ if (!get_tree()->get_edited_scene_root())
+ continue;
+
+ path = get_tree()->get_edited_scene_root()->get_filename();
+ } else {
+
+ path = EditorNode::get_editor_data().get_scene_path(i);
+ }
+
+ if (p_renames.has(path)) {
+ path = p_renames[path];
+ }
+
+ if (i == EditorNode::get_editor_data().get_edited_scene()) {
+
+ get_tree()->get_edited_scene_root()->set_filename(path);
+ } else {
+
+ EditorNode::get_editor_data().set_scene_path(i, path);
+ }
+ }
+}
+
void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
//The following code assumes that the following holds:
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
@@ -910,6 +962,7 @@ void FileSystemDock::_rename_operation_confirm() {
Map<String, String> renames;
_try_move_item(to_rename, new_path, renames);
_update_dependencies_after_move(renames);
+ _update_resource_paths_after_move(renames);
//Rescan everything
print_line("call rescan!");
@@ -959,6 +1012,8 @@ void FileSystemDock::_move_operation_confirm(const String &p_to_path) {
}
_update_dependencies_after_move(renames);
+ _update_resource_paths_after_move(renames);
+
print_line("call rescan!");
_rescan();
}
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index bc8d835ba1..65a71b86e0 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -178,6 +178,7 @@ private:
void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const;
void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
+ void _update_resource_paths_after_move(const Map<String, String> &p_renames) const;
void _make_dir_confirm();
void _rename_operation_confirm();
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 8fe6538653..0c6c608d3d 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -1435,7 +1435,7 @@ AnimationTreeEditorPlugin::AnimationTreeEditorPlugin(EditorNode *p_node) {
anim_tree_editor = memnew(AnimationTreeEditor);
anim_tree_editor->set_custom_minimum_size(Size2(0, 300));
- button = editor->add_bottom_panel_item("AnimationTree", anim_tree_editor);
+ button = editor->add_bottom_panel_item(TTR("AnimationTree"), anim_tree_editor);
button->hide();
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index ceb1ec09fc..1241441d43 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4344,7 +4344,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
additive_selection = false;
// Update the menus checkboxes
- call_deferred("set_state", get_state());
+ set_state(get_state());
}
CanvasItemEditor *CanvasItemEditor::singleton = NULL;
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index 3210af1433..88649ca267 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -444,7 +444,7 @@ ResourcePreloaderEditorPlugin::ResourcePreloaderEditorPlugin(EditorNode *p_node)
preloader_editor = memnew(ResourcePreloaderEditor);
preloader_editor->set_custom_minimum_size(Size2(0, 250));
- button = editor->add_bottom_panel_item("ResourcePreloader", preloader_editor);
+ button = editor->add_bottom_panel_item(TTR("ResourcePreloader"), preloader_editor);
button->hide();
//preloader_editor->set_anchor( MARGIN_TOP, Control::ANCHOR_END);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 591e6dac56..2f0f21cc0e 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -132,7 +132,7 @@ public:
I = I->next();
}
- if (O != E) { //should never heppane..
+ if (O != E) { //should never happen..
cached.erase(O);
}
}
@@ -234,7 +234,6 @@ ScriptEditorQuickOpen::ScriptEditorQuickOpen() {
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
- //set_child_rect(vbc);
search_box = memnew(LineEdit);
vbc->add_margin_child(TTR("Search:"), search_box);
search_box->connect("text_changed", this, "_text_changed");
@@ -257,8 +256,6 @@ ScriptEditor *ScriptEditor::script_editor = NULL;
String ScriptEditor::_get_debug_tooltip(const String &p_text, Node *_se) {
- //ScriptEditorBase *se=Object::cast_to<ScriptEditorBase>(_se);
-
String val = debugger->get_var_value(p_text);
if (val != String()) {
return p_text + ": " + val;
@@ -551,8 +548,6 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) {
idx = history[history_pos].control->get_index();
}
tab_container->set_current_tab(idx);
-
- //script_list->select(idx);
}
_update_history_arrows();
@@ -698,7 +693,6 @@ void ScriptEditor::_reload_scripts() {
uint64_t last_date = script->get_last_modified_time();
uint64_t date = FileAccess::get_modified_time(script->get_path());
- //printf("last date: %lli vs date: %lli\n",last_date,date);
if (last_date == date) {
continue;
}
@@ -776,7 +770,6 @@ bool ScriptEditor::_test_script_times_on_disk(Ref<Script> p_for_script) {
uint64_t last_date = script->get_last_modified_time();
uint64_t date = FileAccess::get_modified_time(script->get_path());
- //printf("last date: %lli vs date: %lli\n",last_date,date);
if (last_date != date) {
TreeItem *ti = disk_changed_list->create_item(r);
@@ -786,7 +779,6 @@ bool ScriptEditor::_test_script_times_on_disk(Ref<Script> p_for_script) {
need_ask = true;
}
need_reload = true;
- //r->set_metadata(0,);
}
}
}
@@ -1205,9 +1197,6 @@ void ScriptEditor::_notification(int p_what) {
_update_modified_scripts_for_external_editor();
} break;
- case NOTIFICATION_PROCESS: {
- } break;
-
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
help_search->set_icon(get_icon("HelpSearch", "EditorIcons"));
@@ -1367,18 +1356,9 @@ void ScriptEditor::ensure_select_current() {
if (!grab_focus_block && is_visible_in_tree())
se->ensure_focus();
-
- //edit_menu->show();
- //search_menu->show();
}
EditorHelp *eh = Object::cast_to<EditorHelp>(current);
-
- if (eh) {
- //edit_menu->hide();
- //search_menu->hide();
- //script_search_menu->show();
- }
}
_update_selected_editor_menu();
@@ -1823,12 +1803,8 @@ void ScriptEditor::save_all_scripts() {
if (script.is_valid())
se->apply_code();
- if (script->get_path() != "" && script->get_path().find("local://") == -1 && script->get_path().find("::") == -1) {
- //external script, save it
-
- editor->save_resource(script);
- //ResourceSaver::save(script->get_path(),script);
- }
+ if (script->get_path() != "" && script->get_path().find("local://") == -1 && script->get_path().find("::") == -1)
+ editor->save_resource(script); //external script, save it
}
_update_script_names();
@@ -1886,7 +1862,6 @@ void ScriptEditor::_editor_stop() {
void ScriptEditor::_add_callback(Object *p_obj, const String &p_function, const PoolStringArray &p_args) {
- //print_line("add callback! hohoho"); kinda sad to remove this
ERR_FAIL_COND(!p_obj);
Ref<Script> script = p_obj->get_script();
ERR_FAIL_COND(!script.is_valid());
@@ -1981,8 +1956,6 @@ void ScriptEditor::_script_split_dragged(float) {
Variant ScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- // return Variant(); // return this if drag disabled
-
Node *cur_node = tab_container->get_child(tab_container->get_current_tab());
HBoxContainer *drag_preview = memnew(HBoxContainer);
@@ -2202,9 +2175,6 @@ void ScriptEditor::_make_script_list_context_menu() {
}
EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(selected));
- if (eh) {
- // nothing
- }
context_menu->add_separator();
context_menu->add_shortcut(ED_GET_SHORTCUT("script_editor/window_move_up"), WINDOW_MOVE_UP);
@@ -2547,9 +2517,9 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_script_changed", &ScriptEditor::_script_changed);
ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts);
- ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &ScriptEditor::get_drag_data_fw);
- ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &ScriptEditor::can_drop_data_fw);
- ClassDB::bind_method(D_METHOD("drop_data_fw"), &ScriptEditor::drop_data_fw);
+ ClassDB::bind_method(D_METHOD("get_drag_data_fw", "point", "from"), &ScriptEditor::get_drag_data_fw);
+ ClassDB::bind_method(D_METHOD("can_drop_data_fw", "point", "data", "from"), &ScriptEditor::can_drop_data_fw);
+ ClassDB::bind_method(D_METHOD("drop_data_fw", "point", "data", "from"), &ScriptEditor::drop_data_fw);
ClassDB::bind_method(D_METHOD("get_current_script"), &ScriptEditor::_get_current_script);
ClassDB::bind_method(D_METHOD("get_open_scripts"), &ScriptEditor::_get_open_scripts);
@@ -2588,10 +2558,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
script_list = memnew(ItemList);
list_split->add_child(script_list);
- script_list->set_custom_minimum_size(Size2(150 * EDSCALE, 100)); //need to give a bit of limit to avoid it from disappearing
+ script_list->set_custom_minimum_size(Size2(150 * EDSCALE, 90)); //need to give a bit of limit to avoid it from disappearing
script_list->set_v_size_flags(SIZE_EXPAND_FILL);
script_split->set_split_offset(140);
- //list_split->set_split_offset(500);
_sort_list_on_update = true;
script_list->connect("gui_input", this, "_script_list_gui_input");
script_list->set_allow_rmb_select(true);
@@ -2603,18 +2572,18 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
members_overview = memnew(ItemList);
list_split->add_child(members_overview);
- members_overview->set_custom_minimum_size(Size2(0, 100)); //need to give a bit of limit to avoid it from disappearing
+ members_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing
members_overview->set_v_size_flags(SIZE_EXPAND_FILL);
help_overview = memnew(ItemList);
list_split->add_child(help_overview);
- help_overview->set_custom_minimum_size(Size2(0, 100)); //need to give a bit of limit to avoid it from disappearing
+ help_overview->set_custom_minimum_size(Size2(0, 90)); //need to give a bit of limit to avoid it from disappearing
help_overview->set_v_size_flags(SIZE_EXPAND_FILL);
tab_container = memnew(TabContainer);
tab_container->set_tabs_visible(false);
+ tab_container->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
script_split->add_child(tab_container);
-
tab_container->set_h_size_flags(SIZE_EXPAND_FILL);
ED_SHORTCUT("script_editor/window_sort", TTR("Sort"));
@@ -2762,7 +2731,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
{
VBoxContainer *vbc = memnew(VBoxContainer);
disk_changed->add_child(vbc);
- //disk_changed->set_child_rect(vbc);
Label *dl = memnew(Label);
dl->set_text(TTR("The following files are newer on disk.\nWhat action should be taken?:"));
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 0610f55b3f..3c9cd74aa1 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1396,48 +1396,70 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
+ if (mb->get_button_index() == BUTTON_RIGHT) {
int col, row;
TextEdit *tx = code_editor->get_text_edit();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
Vector2 mpos = mb->get_global_position() - tx->get_global_position();
- bool have_selection = (tx->get_selection_text().length() > 0);
- bool have_color = (tx->get_word_at_pos(mpos) == "Color");
+
+ tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+ bool has_color = (tx->get_word_at_pos(mpos) == "Color");
int fold_state = 0;
bool can_fold = tx->can_fold(row);
bool is_folded = tx->is_folded(row);
- if (have_color) {
-
- String line = tx->get_line(row);
- color_line = row;
- int begin = 0;
- int end = 0;
- bool valid = false;
- for (int i = col; i < line.length(); i++) {
- if (line[i] == '(') {
- begin = i;
- continue;
- } else if (line[i] == ')') {
- end = i + 1;
- valid = true;
- break;
+
+ if (tx->is_right_click_moving_caret()) {
+ if (tx->is_selection_active()) {
+
+ int from_line = tx->get_selection_from_line();
+ int to_line = tx->get_selection_to_line();
+ int from_column = tx->get_selection_from_column();
+ int to_column = tx->get_selection_to_column();
+
+ if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
+ // Right click is outside the seleted text
+ tx->deselect();
}
}
- if (valid) {
- color_args = line.substr(begin, end - begin);
- String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
- Vector<float> color = stripped.split_floats(",");
- if (color.size() > 2) {
- float alpha = color.size() > 3 ? color[3] : 1.0f;
- color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
+ if (!tx->is_selection_active()) {
+ tx->cursor_set_line(row, true, false);
+ tx->cursor_set_column(col);
+ }
+ }
+
+ if (!mb->is_pressed()) {
+ if (has_color) {
+ String line = tx->get_line(row);
+ color_line = row;
+ int begin = 0;
+ int end = 0;
+ bool valid = false;
+ for (int i = col; i < line.length(); i++) {
+ if (line[i] == '(') {
+ begin = i;
+ continue;
+ } else if (line[i] == ')') {
+ end = i + 1;
+ valid = true;
+ break;
+ }
+ }
+ if (valid) {
+ color_args = line.substr(begin, end - begin);
+ String stripped = color_args.replace(" ", "").replace("(", "").replace(")", "");
+ Vector<float> color = stripped.split_floats(",");
+ if (color.size() > 2) {
+ float alpha = color.size() > 3 ? color[3] : 1.0f;
+ color_picker->set_pick_color(Color(color[0], color[1], color[2], alpha));
+ }
+ color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
+ } else {
+ has_color = false;
}
- color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
- } else {
- have_color = false;
}
+ _make_context_menu(tx->is_selection_active(), has_color, can_fold, is_folded);
}
- _make_context_menu(have_selection, have_color, can_fold, is_folded);
}
}
}
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 3e00776dfd..d0b0d3690a 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -620,14 +620,36 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
if (mb.is_valid()) {
- if (mb->get_button_index() == BUTTON_RIGHT && !mb->is_pressed()) {
+ if (mb->get_button_index() == BUTTON_RIGHT) {
int col, row;
TextEdit *tx = shader_editor->get_text_edit();
tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col);
Vector2 mpos = mb->get_global_position() - tx->get_global_position();
- bool have_selection = (tx->get_selection_text().length() > 0);
- _make_context_menu(have_selection);
+ tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret"));
+
+ if (tx->is_right_click_moving_caret()) {
+ if (tx->is_selection_active()) {
+
+ int from_line = tx->get_selection_from_line();
+ int to_line = tx->get_selection_to_line();
+ int from_column = tx->get_selection_from_column();
+ int to_column = tx->get_selection_to_column();
+
+ if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
+ // Right click is outside the seleted text
+ tx->deselect();
+ }
+ }
+ if (!tx->is_selection_active()) {
+ tx->cursor_set_line(row, true, false);
+ tx->cursor_set_column(col);
+ }
+ }
+
+ if (!mb->is_pressed()) {
+ _make_context_menu(tx->is_selection_active());
+ }
}
}
}
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 59da5112ae..b26038fe09 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -51,7 +51,6 @@
#define GIZMO_ARROW_SIZE 0.35
#define GIZMO_RING_HALF_WIDTH 0.1
-//#define GIZMO_SCALE_DEFAULT 0.28
#define GIZMO_SCALE_DEFAULT 0.15
#define GIZMO_PLANE_SIZE 0.2
#define GIZMO_PLANE_DST 0.3
@@ -94,7 +93,6 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
// We interpolate a different point here, because in freelook mode the focus point (cursor.pos) orbits around eye_pos
camera_cursor.eye_pos = old_camera_cursor.eye_pos.linear_interpolate(cursor.eye_pos, CLAMP(factor, 0, 1));
- //camera_cursor.pos = camera_cursor.eye_pos + (cursor.pos - cursor.eye_pos);
float orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia");
orbit_inertia = MAX(0.0001, orbit_inertia);
@@ -153,13 +151,13 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
if (!equal || p_interp_delta == 0 || is_freelook_active() || is_orthogonal != orthogonal) {
camera->set_global_transform(to_camera_transform(camera_cursor));
- update_transform_gizmo_view();
- if (orthogonal) {
- //camera->set_orthogonal(size.width*cursor.distance,get_znear(),get_zfar());
+ if (orthogonal)
camera->set_orthogonal(2 * cursor.distance, 0.1, 8192);
- } else
+ else
camera->set_perspective(get_fov(), get_znear(), get_zfar());
+
+ update_transform_gizmo_view();
}
}
@@ -392,9 +390,6 @@ ObjectID SpatialEditorViewport::_select_ray(const Point2 &p_pos, bool p_append,
ERR_PRINT("Bug?");
}
}
-
- // if (editor_selection->is_selected(spat))
- // r_includes_current=true;
}
if (!item)
@@ -561,6 +556,8 @@ void SpatialEditorViewport::_update_name() {
view_menu->set_text("[ " + name + " " + ortho + " ]");
else
view_menu->set_text("[ " + ortho + " ]");
+
+ view_menu->set_size(Vector2(0, 0)); // resets the button size
}
void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
@@ -812,17 +809,27 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
return false;
}
-void SpatialEditorViewport::_smouseenter() {
+void SpatialEditorViewport::_surface_mouse_enter() {
if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
surface->grab_focus();
}
-void SpatialEditorViewport::_smouseexit() {
+void SpatialEditorViewport::_surface_mouse_exit() {
_remove_preview();
}
+void SpatialEditorViewport::_surface_focus_enter() {
+
+ view_menu->set_disable_shortcuts(false);
+}
+
+void SpatialEditorViewport::_surface_focus_exit() {
+
+ view_menu->set_disable_shortcuts(true);
+}
+
void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
_find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->get_shift());
@@ -949,7 +956,6 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (_edit.mode != TRANSFORM_NONE && b->is_pressed()) {
//cancel motion
_edit.mode = TRANSFORM_NONE;
- //_validate_selection();
List<Node *> &selection = editor_selection->get_selected_node_list();
@@ -966,7 +972,6 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
sp->set_global_transform(se->original);
}
surface->update();
- //VisualServer::get_singleton()->poly_clear(indicators);
set_message(TTR("Transform Aborted."), 3);
}
@@ -1059,7 +1064,6 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.gizmo = seg;
_edit.gizmo_handle = handle;
- //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
_edit.gizmo_initial_value = seg->get_handle_value(handle);
break;
}
@@ -1134,13 +1138,10 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.gizmo = seg;
_edit.gizmo_handle = gizmo_handle;
- //_edit.gizmo_initial_pos=seg->get_handle_pos(gizmo_handle);
_edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle);
- //print_line("GIZMO: "+itos(gizmo_handle)+" FROMPOS: "+_edit.orig_gizmo_pos);
break;
}
}
- //_compute_edit(Point2(b.x,b.y)); //in case a motion happens..
}
surface->update();
@@ -1186,7 +1187,6 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
undo_redo->commit_action();
_edit.mode = TRANSFORM_NONE;
- //VisualServer::get_singleton()->poly_clear(indicators);
set_message("");
}
@@ -1785,51 +1785,36 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
if (ED_IS_SHORTCUT("spatial_editor/bottom_view", p_event)) {
- cursor.y_rot = 0;
- cursor.x_rot = -Math_PI / 2.0;
- set_message(TTR("Bottom View."), 2);
- name = TTR("Bottom");
- _update_name();
+ _menu_option(VIEW_BOTTOM);
}
if (ED_IS_SHORTCUT("spatial_editor/top_view", p_event)) {
- cursor.y_rot = 0;
- cursor.x_rot = Math_PI / 2.0;
- set_message(TTR("Top View."), 2);
- name = TTR("Top");
- _update_name();
+ _menu_option(VIEW_TOP);
}
if (ED_IS_SHORTCUT("spatial_editor/rear_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot = Math_PI;
- set_message(TTR("Rear View."), 2);
- name = TTR("Rear");
- _update_name();
+ _menu_option(VIEW_REAR);
}
if (ED_IS_SHORTCUT("spatial_editor/front_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot = 0;
- set_message(TTR("Front View."), 2);
- name = TTR("Front");
- _update_name();
+ _menu_option(VIEW_FRONT);
}
if (ED_IS_SHORTCUT("spatial_editor/left_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot = Math_PI / 2.0;
- set_message(TTR("Left View."), 2);
- name = TTR("Left");
- _update_name();
+ _menu_option(VIEW_LEFT);
}
if (ED_IS_SHORTCUT("spatial_editor/right_view", p_event)) {
- cursor.x_rot = 0;
- cursor.y_rot = -Math_PI / 2.0;
- set_message(TTR("Right View."), 2);
- name = TTR("Right");
- _update_name();
+ _menu_option(VIEW_RIGHT);
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/focus_origin", p_event)) {
+ _menu_option(VIEW_CENTER_TO_ORIGIN);
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/focus_selection", p_event)) {
+ _menu_option(VIEW_CENTER_TO_SELECTION);
}
if (ED_IS_SHORTCUT("spatial_editor/switch_perspective_orthogonal", p_event)) {
_menu_option(orthogonal ? VIEW_PERSPECTIVE : VIEW_ORTHOGONAL);
_update_name();
}
+ if (ED_IS_SHORTCUT("spatial_editor/align_selection_with_view", p_event)) {
+ _menu_option(VIEW_ALIGN_SELECTION_WITH_VIEW);
+ }
if (ED_IS_SHORTCUT("spatial_editor/insert_anim_key", p_event)) {
if (!get_selected_count() || _edit.mode != TRANSFORM_NONE)
return;
@@ -2114,15 +2099,6 @@ void SpatialEditorViewport::_notification(int p_what) {
if (p_what == NOTIFICATION_PROCESS) {
- //force editr camera
- /*
- current_camera=get_root_node()->get_current_camera();
- if (current_camera!=camera) {
-
-
- }
- */
-
real_t delta = get_process_delta_time();
if (zoom_indicator_delay > 0) {
@@ -2248,8 +2224,10 @@ void SpatialEditorViewport::_notification(int p_what) {
surface->connect("draw", this, "_draw");
surface->connect("gui_input", this, "_sinput");
- surface->connect("mouse_entered", this, "_smouseenter");
- surface->connect("mouse_exited", this, "_smouseexit");
+ surface->connect("mouse_entered", this, "_surface_mouse_enter");
+ surface->connect("mouse_exited", this, "_surface_mouse_exit");
+ surface->connect("focus_entered", this, "_surface_focus_enter");
+ surface->connect("focus_exited", this, "_surface_focus_exit");
info_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles"));
fps_label->add_style_override("normal", editor->get_gui_base()->get_stylebox("Information3dViewport", "EditorStyles"));
preview_camera->set_icon(get_icon("Camera", "EditorIcons"));
@@ -2423,47 +2401,54 @@ void SpatialEditorViewport::_menu_option(int p_option) {
case VIEW_TOP: {
- cursor.x_rot = Math_PI / 2.0;
cursor.y_rot = 0;
+ cursor.x_rot = Math_PI / 2.0;
+ set_message(TTR("Top View."), 2);
name = TTR("Top");
_update_name();
+
} break;
case VIEW_BOTTOM: {
- cursor.x_rot = -Math_PI / 2.0;
cursor.y_rot = 0;
+ cursor.x_rot = -Math_PI / 2.0;
+ set_message(TTR("Bottom View."), 2);
name = TTR("Bottom");
_update_name();
} break;
case VIEW_LEFT: {
- cursor.y_rot = Math_PI / 2.0;
cursor.x_rot = 0;
+ cursor.y_rot = Math_PI / 2.0;
+ set_message(TTR("Left View."), 2);
name = TTR("Left");
_update_name();
} break;
case VIEW_RIGHT: {
- cursor.y_rot = -Math_PI / 2.0;
cursor.x_rot = 0;
+ cursor.y_rot = -Math_PI / 2.0;
+ set_message(TTR("Right View."), 2);
name = TTR("Right");
_update_name();
} break;
case VIEW_FRONT: {
- cursor.y_rot = 0;
cursor.x_rot = 0;
+ cursor.y_rot = 0;
+ set_message(TTR("Front View."), 2);
name = TTR("Front");
_update_name();
} break;
case VIEW_REAR: {
- cursor.y_rot = Math_PI;
cursor.x_rot = 0;
+ cursor.y_rot = Math_PI;
+ set_message(TTR("Rear View."), 2);
name = TTR("Rear");
_update_name();
@@ -2590,6 +2575,11 @@ void SpatialEditorViewport::_menu_option(int p_option) {
bool current = view_menu->get_popup()->is_item_checked(idx);
view_menu->get_popup()->set_item_checked(idx, !current);
+ if (current)
+ preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
+ else
+ preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 15 * EDSCALE + fps_label->get_size().height);
+
} break;
case VIEW_DISPLAY_NORMAL: {
@@ -2641,14 +2631,13 @@ void SpatialEditorViewport::_preview_exited_scene() {
void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
- uint32_t layer = 1 << (GIZMO_BASE_LAYER + p_idx); //|(1<<GIZMO_GRID_LAYER);
+ uint32_t layer = 1 << (GIZMO_BASE_LAYER + p_idx);
for (int i = 0; i < 3; i++) {
move_gizmo_instance[i] = VS::get_singleton()->instance_create();
VS::get_singleton()->instance_set_base(move_gizmo_instance[i], spatial_editor->get_move_gizmo(i)->get_rid());
VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_visible(move_gizmo_instance[i], false);
- //VS::get_singleton()->instance_geometry_set_flag(move_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i], layer);
@@ -2656,7 +2645,6 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
VS::get_singleton()->instance_set_base(move_plane_gizmo_instance[i], spatial_editor->get_move_plane_gizmo(i)->get_rid());
VS::get_singleton()->instance_set_scenario(move_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false);
- //VS::get_singleton()->instance_geometry_set_flag(move_plane_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_plane_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(move_plane_gizmo_instance[i], layer);
@@ -2664,7 +2652,6 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i], spatial_editor->get_rotate_gizmo(i)->get_rid());
VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], false);
- //VS::get_singleton()->instance_geometry_set_flag(rotate_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer);
@@ -2672,7 +2659,6 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid());
VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false);
- //VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer);
@@ -2680,7 +2666,6 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
VS::get_singleton()->instance_set_base(scale_plane_gizmo_instance[i], spatial_editor->get_scale_plane_gizmo(i)->get_rid());
VS::get_singleton()->instance_set_scenario(scale_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false);
- //VS::get_singleton()->instance_geometry_set_flag(scale_plane_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_plane_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_set_layer_mask(scale_plane_gizmo_instance[i], layer);
}
@@ -2745,16 +2730,8 @@ void SpatialEditorViewport::set_can_preview(Camera *p_preview) {
preview = p_preview;
- if (!preview_camera->is_pressed()) {
-
- if (p_preview) {
- fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 15 * EDSCALE + preview_camera->get_size().height);
- preview_camera->show();
- } else {
- fps_label->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
- preview_camera->hide();
- }
- }
+ if (!preview_camera->is_pressed())
+ preview_camera->set_visible(p_preview);
}
void SpatialEditorViewport::update_transform_gizmo_view() {
@@ -2781,8 +2758,6 @@ void SpatialEditorViewport::update_transform_gizmo_view() {
xform.basis.scale(scale);
- //xform.basis.scale(GIZMO_SCALE_DEFAULT*Vector3(1,1,1));
-
for (int i = 0; i < 3; i++) {
VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform);
VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_MOVE));
@@ -2799,18 +2774,36 @@ void SpatialEditorViewport::update_transform_gizmo_view() {
void SpatialEditorViewport::set_state(const Dictionary &p_state) {
- cursor.pos = p_state["position"];
- cursor.x_rot = p_state["x_rotation"];
- cursor.y_rot = p_state["y_rotation"];
- cursor.distance = p_state["distance"];
- bool env = p_state["use_environment"];
- bool orth = p_state["use_orthogonal"];
- if (orth)
- _menu_option(VIEW_ORTHOGONAL);
- else
- _menu_option(VIEW_PERSPECTIVE);
- if (env != camera->get_environment().is_valid())
- _menu_option(VIEW_ENVIRONMENT);
+ if (p_state.has("position"))
+ cursor.pos = p_state["position"];
+ if (p_state.has("x_rotation"))
+ cursor.x_rot = p_state["x_rotation"];
+ if (p_state.has("y_rotation"))
+ cursor.y_rot = p_state["y_rotation"];
+ if (p_state.has("distance"))
+ cursor.distance = p_state["distance"];
+
+ if (p_state.has("use_orthogonal")) {
+ bool orth = p_state["use_orthogonal"];
+
+ if (orth)
+ _menu_option(VIEW_ORTHOGONAL);
+ else
+ _menu_option(VIEW_PERSPECTIVE);
+ }
+ if (p_state.has("display_mode")) {
+ int display = p_state["display_mode"];
+
+ int idx = view_menu->get_popup()->get_item_index(display);
+ if (!view_menu->get_popup()->is_item_checked(idx))
+ _menu_option(display);
+ }
+ if (p_state.has("use_environment")) {
+ bool env = p_state["use_environment"];
+
+ if (env != camera->get_environment().is_valid())
+ _menu_option(VIEW_ENVIRONMENT);
+ }
if (p_state.has("listener")) {
bool listener = p_state["listener"];
@@ -2839,6 +2832,13 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) {
if (view_menu->get_popup()->is_item_checked(idx) != information)
_menu_option(VIEW_INFORMATION);
}
+ if (p_state.has("fps")) {
+ bool fps = p_state["fps"];
+
+ int idx = view_menu->get_popup()->get_item_index(VIEW_FPS);
+ if (view_menu->get_popup()->is_item_checked(idx) != fps)
+ _menu_option(VIEW_FPS);
+ }
if (p_state.has("half_res")) {
bool half_res = p_state["half_res"];
@@ -2869,14 +2869,22 @@ Dictionary SpatialEditorViewport::get_state() const {
d["distance"] = cursor.distance;
d["use_environment"] = camera->get_environment().is_valid();
d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
+ if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL)))
+ d["display_mode"] = VIEW_DISPLAY_NORMAL;
+ else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_WIREFRAME)))
+ d["display_mode"] = VIEW_DISPLAY_WIREFRAME;
+ else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_OVERDRAW)))
+ d["display_mode"] = VIEW_DISPLAY_OVERDRAW;
+ else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS)))
+ d["display_mode"] = VIEW_DISPLAY_SHADELESS;
d["listener"] = viewport->is_audio_listener();
d["doppler"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER));
d["gizmos"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS));
d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
+ d["fps"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_FPS));
d["half_res"] = viewport_container->get_stretch_shrink() > 1;
- if (previewing) {
+ if (previewing)
d["previewing"] = EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
- }
return d;
}
@@ -2884,8 +2892,11 @@ Dictionary SpatialEditorViewport::get_state() const {
void SpatialEditorViewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_draw"), &SpatialEditorViewport::_draw);
- ClassDB::bind_method(D_METHOD("_smouseenter"), &SpatialEditorViewport::_smouseenter);
- ClassDB::bind_method(D_METHOD("_smouseexit"), &SpatialEditorViewport::_smouseexit);
+
+ ClassDB::bind_method(D_METHOD("_surface_mouse_enter"), &SpatialEditorViewport::_surface_mouse_enter);
+ ClassDB::bind_method(D_METHOD("_surface_mouse_exit"), &SpatialEditorViewport::_surface_mouse_exit);
+ ClassDB::bind_method(D_METHOD("_surface_focus_enter"), &SpatialEditorViewport::_surface_focus_enter);
+ ClassDB::bind_method(D_METHOD("_surface_focus_exit"), &SpatialEditorViewport::_surface_focus_exit);
ClassDB::bind_method(D_METHOD("_sinput"), &SpatialEditorViewport::_sinput);
ClassDB::bind_method(D_METHOD("_menu_option"), &SpatialEditorViewport::_menu_option);
ClassDB::bind_method(D_METHOD("_toggle_camera_preview"), &SpatialEditorViewport::_toggle_camera_preview);
@@ -3309,7 +3320,6 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
camera = memnew(Camera);
camera->set_disable_gizmo(true);
camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER));
- //camera->set_environment(SpatialEditor::get_singleton()->get_viewport_environment());
viewport->add_child(camera);
camera->make_current();
surface->set_focus_mode(FOCUS_ALL);
@@ -3353,6 +3363,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW);
view_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+ view_menu->set_disable_shortcuts(true);
+
ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A);
ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D);
ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W);
@@ -3367,7 +3379,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
preview_camera->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 10 * EDSCALE);
preview_camera->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -10 * EDSCALE);
preview_camera->set_h_grow_direction(GROW_DIRECTION_BEGIN);
- preview_camera->set_text(TTR("preview"));
+ preview_camera->set_text(TTR("Preview"));
surface->add_child(preview_camera);
preview_camera->hide();
preview_camera->connect("toggled", this, "_toggle_camera_preview");
@@ -3771,7 +3783,6 @@ void SpatialEditor::update_transform_gizmo() {
center.expand_to(xf.origin);
gizmo_basis = Basis();
}
- //count++;
}
Vector3 pcenter = center.position + center.size * 0.5;
@@ -3994,17 +4005,6 @@ void SpatialEditor::edit(Spatial *p_spatial) {
}
}
}
-
- /*
- if (p_spatial) {
- _validate_selection();
- if (selected.has(p_spatial->get_instance_id()) && selected.size()==1)
- return;
- _select(p_spatial->get_instance_id(),false,true);
-
- // should become the selection
- }
- */
}
void SpatialEditor::_xform_dialog_action() {
@@ -4348,9 +4348,6 @@ void SpatialEditor::_init_indicators() {
VisualServer::get_singleton()->mesh_add_surface_from_arrays(origin, VisualServer::PRIMITIVE_LINES, d);
VisualServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid());
- //origin = VisualServer::get_singleton()->poly_create();
- //VisualServer::get_singleton()->poly_add_primitive(origin,origin_points,Vector<Vector3>(),origin_colors,Vector<Vector3>());
- //VisualServer::get_singleton()->poly_set_material(origin,indicator_mat,true);
origin_instance = VisualServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world()->get_scenario());
VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << SpatialEditorViewport::GIZMO_GRID_LAYER);
@@ -4635,9 +4632,6 @@ void SpatialEditor::_finish_indicators() {
VisualServer::get_singleton()->free(grid_instance[i]);
VisualServer::get_singleton()->free(grid[i]);
}
- //VisualServer::get_singleton()->free(poly);
- //VisualServer::get_singleton()->free(indicators_instance);
- //VisualServer::get_singleton()->free(indicators);
}
bool SpatialEditor::is_any_freelook_active() const {
@@ -4879,7 +4873,6 @@ void SpatialEditor::_node_removed(Node *p_node) {
void SpatialEditor::_bind_methods() {
- //ClassDB::bind_method("_gui_input",&SpatialEditor::_gui_input);
ClassDB::bind_method("_unhandled_key_input", &SpatialEditor::_unhandled_key_input);
ClassDB::bind_method("_node_removed", &SpatialEditor::_node_removed);
ClassDB::bind_method("_menu_item_pressed", &SpatialEditor::_menu_item_pressed);
@@ -4940,8 +4933,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
snap_enabled = false;
tool_mode = TOOL_MODE_SELECT;
- //set_focus_mode(FOCUS_ALL);
-
hbc_menu = memnew(HBoxContainer);
vbc->add_child(hbc_menu);
@@ -5116,7 +5107,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept);
viewport_base->add_child(viewports[i]);
}
- //vbc->add_child(viewport_base);
/* SNAP DIALOG */
@@ -5126,7 +5116,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
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_text("1");
@@ -5148,7 +5137,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
settings_vbc = memnew(VBoxContainer);
settings_vbc->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
settings_dialog->add_child(settings_vbc);
- //settings_dialog->set_child_rect(settings_vbc);
settings_fov = memnew(SpinBox);
settings_fov->set_max(MAX_FOV);
@@ -5171,7 +5159,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
settings_zfar->set_value(EDITOR_DEF("editors/3d/default_z_far", 1500));
settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar);
- //settings_dialog->get_cancel()->hide();
/* XFORM DIALOG */
xform_dialog = memnew(ConfirmationDialog);
@@ -5257,14 +5244,12 @@ void SpatialEditorPlugin::make_visible(bool p_visible) {
spatial_editor->show();
spatial_editor->set_process(true);
- //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),false);
spatial_editor->grab_focus();
} else {
spatial_editor->hide();
spatial_editor->set_process(false);
- //VisualServer::get_singleton()->viewport_set_hide_scenario(editor->get_scene_root()->get_viewport(),true);
}
}
void SpatialEditorPlugin::edit(Object *p_object) {
@@ -5317,11 +5302,8 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
spatial_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
editor->get_viewport()->add_child(spatial_editor);
- //spatial_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
spatial_editor->hide();
spatial_editor->connect("transform_key_request", editor, "_transform_keyed");
-
- //spatial_editor->set_process(true);
}
SpatialEditorPlugin::~SpatialEditorPlugin() {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 4aa1d9c0c1..d080745dc9 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -273,8 +273,11 @@ private:
Transform to_camera_transform(const Cursor &p_cursor) const;
void _draw();
- void _smouseenter();
- void _smouseexit();
+ void _surface_mouse_enter();
+ void _surface_mouse_exit();
+ void _surface_focus_enter();
+ void _surface_focus_exit();
+
void _sinput(const Ref<InputEvent> &p_event);
void _update_freelook(real_t delta);
SpatialEditor *spatial_editor;
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 175655119f..71c81f7111 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -840,7 +840,7 @@ SpriteFramesEditorPlugin::SpriteFramesEditorPlugin(EditorNode *p_node) {
editor = p_node;
frames_editor = memnew(SpriteFramesEditor);
frames_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
- button = editor->add_bottom_panel_item("SpriteFrames", frames_editor);
+ button = editor->add_bottom_panel_item(TTR("SpriteFrames"), frames_editor);
button->hide();
}
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 5c965e4a05..9840d9021c 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -103,6 +103,6 @@ StyleBoxEditorPlugin::StyleBoxEditorPlugin(EditorNode *p_node) {
stylebox_editor->set_custom_minimum_size(Size2(0, 250));
//p_node->get_viewport()->add_child(stylebox_editor);
- button = p_node->add_bottom_panel_item("StyleBox", stylebox_editor);
+ button = p_node->add_bottom_panel_item(TTR("StyleBox"), stylebox_editor);
button->hide();
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 7f956b01ff..38a4bfbfc6 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -934,6 +934,6 @@ ThemeEditorPlugin::ThemeEditorPlugin(EditorNode *p_node) {
theme_editor->set_custom_minimum_size(Size2(0, 200));
//p_node->get_viewport()->add_child(theme_editor);
- button = editor->add_bottom_panel_item("Theme", theme_editor);
+ button = editor->add_bottom_panel_item(TTR("Theme"), theme_editor);
button->hide();
}
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 5eb3435e24..b56585f62c 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -314,7 +314,7 @@ TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) {
autotile_editor->side_panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
autotile_editor->side_panel->set_custom_minimum_size(Size2(200, 0));
autotile_editor->side_panel->hide();
- autotile_button = p_node->add_bottom_panel_item("Autotiles", autotile_editor);
+ autotile_button = p_node->add_bottom_panel_item(TTR("Autotiles"), autotile_editor);
autotile_button->hide();
}
@@ -387,7 +387,7 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) {
tools[TOOL_SELECT] = memnew(ToolButton);
tool_containers[TOOLBAR_DUMMY]->add_child(tools[TOOL_SELECT]);
- tools[TOOL_SELECT]->set_tooltip("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.");
+ tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings."));
tools[TOOL_SELECT]->set_toggle_mode(true);
tools[TOOL_SELECT]->set_button_group(tg);
tools[TOOL_SELECT]->set_pressed(true);
@@ -533,7 +533,7 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) {
tool_containers[TOOLBAR_BITMASK]->show();
tool_containers[TOOLBAR_SHAPE]->hide();
tools[TOOL_SELECT]->set_pressed(true);
- tools[TOOL_SELECT]->set_tooltip("LMB: set bit on.\nRMB: set bit off.");
+ tools[TOOL_SELECT]->set_tooltip(TTR("LMB: set bit on.\nRMB: set bit off."));
spin_priority->hide();
} break;
case EDITMODE_COLLISION:
@@ -542,7 +542,7 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) {
tool_containers[TOOLBAR_DUMMY]->show();
tool_containers[TOOLBAR_BITMASK]->hide();
tool_containers[TOOLBAR_SHAPE]->show();
- tools[TOOL_SELECT]->set_tooltip("Select current edited sub-tile.");
+ tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile."));
spin_priority->hide();
} break;
default: {
@@ -550,10 +550,10 @@ void AutotileEditor::_on_edit_mode_changed(int p_edit_mode) {
tool_containers[TOOLBAR_BITMASK]->hide();
tool_containers[TOOLBAR_SHAPE]->hide();
if (edit_mode == EDITMODE_ICON) {
- tools[TOOL_SELECT]->set_tooltip("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.");
+ tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings."));
spin_priority->hide();
} else {
- tools[TOOL_SELECT]->set_tooltip("Select sub-tile to change it's priority.");
+ tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change it's priority."));
spin_priority->show();
}
} break;
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 00488a2a88..04e9f0adc1 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -536,21 +536,21 @@ public:
if (mode == MODE_IMPORT) {
set_title(TTR("Import Existing Project"));
- get_ok()->set_text(TTR("Import"));
+ get_ok()->set_text(TTR("Import & Edit"));
name_container->hide();
project_path->grab_focus();
} else if (mode == MODE_NEW) {
set_title(TTR("Create New Project"));
- get_ok()->set_text(TTR("Create"));
+ get_ok()->set_text(TTR("Create & Edit"));
name_container->show();
project_name->grab_focus();
} else if (mode == MODE_INSTALL) {
set_title(TTR("Install Project:") + " " + zip_title);
- get_ok()->set_text(TTR("Install"));
+ get_ok()->set_text(TTR("Install & Edit"));
name_container->hide();
project_path->grab_focus();
}
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 6f8573cd70..e69577489e 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -1460,7 +1460,6 @@ void ProjectSettingsEditor::_update_translations() {
t2->set_editable(1, true);
t2->set_metadata(1, path);
int idx = langs.find(locale);
- //print_line("find " + locale + " at " + itos(idx));
if (idx < 0)
idx = 0;
@@ -1709,7 +1708,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
add = memnew(Button);
hbc->add_child(add);
- add->set_custom_minimum_size(Size2(150, 0) * EDSCALE);
add->set_text(TTR("Add"));
add->set_disabled(true);
add->connect("pressed", this, "_action_add");
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 47feac9a12..16cf325bc2 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -335,6 +335,8 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
easing_draw->hide();
spinbox->hide();
slider->hide();
+ menu->clear();
+ menu->set_size(Size2(1, 1) * EDSCALE);
for (int i = 0; i < MAX_VALUE_EDITORS; i++) {
@@ -413,7 +415,6 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
} else if (hint == PROPERTY_HINT_ENUM) {
- menu->clear();
Vector<String> options = hint_text.split(",");
for (int i = 0; i < options.size(); i++) {
if (options[i].find(":") != -1) {
@@ -494,7 +495,6 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
easing_draw->show();
set_size(Size2(200, 150) * EDSCALE);
} else if (hint == PROPERTY_HINT_FLAGS) {
- menu->clear();
Vector<String> flags = hint_text.split(",");
for (int i = 0; i < flags.size(); i++) {
String flag = flags[i];
@@ -536,7 +536,6 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
config_action_buttons(names);
} else if (hint == PROPERTY_HINT_ENUM) {
- menu->clear();
Vector<String> options = hint_text.split(",");
for (int i = 0; i < options.size(); i++) {
menu->add_item(options[i], i);
@@ -869,9 +868,6 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
if (hint != PROPERTY_HINT_RESOURCE_TYPE)
break;
- menu->clear();
- menu->set_size(Size2(1, 1) * EDSCALE);
-
if (p_name == "script" && hint_text == "Script" && Object::cast_to<Node>(owner)) {
menu->add_icon_item(get_icon("Script", "EditorIcons"), TTR("New Script"), OBJ_MENU_NEW_SCRIPT);
menu->add_separator();
@@ -1764,24 +1760,40 @@ void CustomPropertyEditor::_focus_exit() {
void CustomPropertyEditor::config_action_buttons(const List<String> &p_strings) {
- int cell_width = 60;
- int cell_height = 25;
- int cell_margin = 5;
+ Ref<StyleBox> sb = get_stylebox("panel");
+ int margin_top = sb->get_margin(MARGIN_TOP);
+ int margin_left = sb->get_margin(MARGIN_LEFT);
+ int margin_bottom = sb->get_margin(MARGIN_BOTTOM);
+ int margin_right = sb->get_margin(MARGIN_RIGHT);
- set_size(Size2(cell_margin + (cell_width + cell_margin) * p_strings.size(), (cell_margin * 2) + cell_height) * EDSCALE);
+ int max_width = 0;
+ int height = 0;
for (int i = 0; i < MAX_ACTION_BUTTONS; i++) {
if (i < p_strings.size()) {
+
action_buttons[i]->show();
action_buttons[i]->set_text(p_strings[i]);
- action_buttons[i]->set_position(Point2(cell_margin + (cell_width + cell_margin) * i, cell_margin) * EDSCALE);
- action_buttons[i]->set_size(Size2(cell_width, cell_height - cell_margin * 2) * EDSCALE);
- action_buttons[i]->set_flat(true);
+
+ Size2 btn_m_size = action_buttons[i]->get_minimum_size();
+ if (btn_m_size.width > max_width)
+ max_width = btn_m_size.width;
+
} else {
action_buttons[i]->hide();
}
}
+
+ for (int i = 0; i < p_strings.size(); i++) {
+
+ Size2 btn_m_size = action_buttons[i]->get_size();
+ action_buttons[i]->set_position(Point2(0, height) + Point2(margin_left, margin_top));
+ action_buttons[i]->set_size(Size2(max_width, btn_m_size.height));
+
+ height += btn_m_size.height;
+ }
+ set_size(Size2(max_width, height) + Size2(margin_left + margin_right, margin_top + margin_bottom));
}
void CustomPropertyEditor::config_value_editors(int p_amount, int p_columns, int p_label_w, const List<String> &p_strings) {
@@ -1902,6 +1914,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
Vector<Variant> binds;
binds.push_back(i);
action_buttons[i]->connect("pressed", this, "_action_pressed", binds);
+ action_buttons[i]->set_flat(true);
}
color_picker = NULL;
@@ -3956,11 +3969,13 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
if (t == Variant::NODE_PATH) {
Variant v = obj->get(n);
- custom_editor->edit(obj, n, (Variant::Type)t, v, h, ht);
Rect2 where = tree->get_item_rect(ti, 1);
where.position -= tree->get_scroll();
- where.position += tree->get_global_position();
+ where.position += tree->get_global_position() + Point2(where.size.width, 0);
+ for (int i = ti->get_button_count(p_column) - 1; i >= p_button; i--)
+ where.position.x -= ti->get_button(p_column, i)->get_width();
custom_editor->set_position(where.position);
+ custom_editor->edit(obj, n, (Variant::Type)t, v, h, ht);
custom_editor->popup();
} else if (t == Variant::STRING) {
@@ -3971,7 +3986,9 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
Rect2 where = tree->get_item_rect(ti, 1);
where.position -= tree->get_scroll();
- where.position += tree->get_global_position();
+ where.position += tree->get_global_position() + Point2(where.size.width, 0);
+ for (int i = ti->get_button_count(p_column) - 1; i >= p_button; i--)
+ where.position.x -= ti->get_button(p_column, i)->get_width();
custom_editor->set_position(where.position);
custom_editor->popup();
} else {
@@ -4591,6 +4608,8 @@ SectionedPropertyEditor::SectionedPropertyEditor() {
search_box = NULL;
+ add_constant_override("autohide", 1); // Fixes the dragger always showing up
+
VBoxContainer *left_vb = memnew(VBoxContainer);
left_vb->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
add_child(left_vb);
@@ -4602,6 +4621,7 @@ SectionedPropertyEditor::SectionedPropertyEditor() {
left_vb->add_child(sections, true);
VBoxContainer *right_vb = memnew(VBoxContainer);
+ right_vb->set_custom_minimum_size(Size2(300, 0) * EDSCALE);
right_vb->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(right_vb);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 6fbca5c904..06dd6bd375 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1360,6 +1360,7 @@ void SceneTreeDock::_create() {
editor_data->get_undo_redo().commit_action();
editor->push_item(c);
editor_selection->clear();
+ editor_selection->add_node(child);
if (Object::cast_to<Control>(c)) {
//make editor more comfortable, so some controls don't appear super shrunk
Control *ct = Object::cast_to<Control>(c);
@@ -1699,7 +1700,7 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
icon = get_icon("Object", "EditorIcons");
if (menu->get_item_count() == 0) {
- menu->add_submenu_item(TTR("Sub-Resources:"), "Sub-Resources");
+ menu->add_submenu_item(TTR("Sub-Resources"), "Sub-Resources");
}
int index = menu_subresources->get_item_count();
menu_subresources->add_icon_item(icon, E->get().name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size());
@@ -1733,6 +1734,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
if (selection.size() == 1) {
subresources.clear();
+ menu_subresources->clear();
_add_children_to_popup(selection.front()->get(), 0);
if (menu->get_item_count() > 0)
menu->add_separator();
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 7342dd5b5d..1a3ab309f7 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -2964,227 +2964,220 @@ NavigationMeshSpatialGizmo::NavigationMeshSpatialGizmo(NavigationMeshInstance *p
navmesh = p_navmesh;
}
-//////
-///
-///
+ //////
+ ///
+ ///
+ ///
-void PinJointSpatialGizmo::redraw() {
+#define BODY_A_RADIUS 0.25
+#define BODY_B_RADIUS 0.27
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- cursor_points.push_back(Vector3(+cs, 0, 0));
- cursor_points.push_back(Vector3(-cs, 0, 0));
- cursor_points.push_back(Vector3(0, +cs, 0));
- cursor_points.push_back(Vector3(0, -cs, 0));
- cursor_points.push_back(Vector3(0, 0, +cs));
- cursor_points.push_back(Vector3(0, 0, -cs));
- add_collision_segments(cursor_points);
+Basis JointGizmosDrawer::look_body(const Transform &p_joint_transform, const Transform &p_body_transform) {
+ const Vector3 &p_eye(p_joint_transform.origin);
+ const Vector3 &p_target(p_body_transform.origin);
- Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ Vector3 v_x, v_y, v_z;
- add_lines(cursor_points, material);
+ // Look the body with X
+ v_x = p_target - p_eye;
+ v_x.normalize();
+
+ v_z = v_x.cross(Vector3(0, 1, 0));
+ v_z.normalize();
+
+ v_y = v_z.cross(v_x);
+ v_y.normalize();
+
+ Basis base;
+ base.set(v_x, v_y, v_z);
+
+ // Absorb current joint transform
+ base = p_joint_transform.basis.inverse() * base;
+
+ return base;
}
-PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint *p_p3d) {
+Basis JointGizmosDrawer::look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform) {
- p3d = p_p3d;
- set_spatial_node(p3d);
+ switch (p_axis) {
+ case Vector3::AXIS_X:
+ return look_body_toward_x(joint_transform, body_transform);
+ case Vector3::AXIS_Y:
+ return look_body_toward_y(joint_transform, body_transform);
+ case Vector3::AXIS_Z:
+ return look_body_toward_z(joint_transform, body_transform);
+ default:
+ return Basis();
+ }
}
-////
+Basis JointGizmosDrawer::look_body_toward_x(const Transform &p_joint_transform, const Transform &p_body_transform) {
-void HingeJointSpatialGizmo::redraw() {
+ const Vector3 &p_eye(p_joint_transform.origin);
+ const Vector3 &p_target(p_body_transform.origin);
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0, 0, +cs * 2));
- cursor_points.push_back(Vector3(0, 0, -cs * 2));
+ const Vector3 p_front(p_joint_transform.basis.get_axis(0));
- float ll = p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER);
- float ul = p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER);
+ Vector3 v_x, v_y, v_z;
- if (p3d->get_flag(HingeJoint::FLAG_USE_LIMIT) && ll < ul) {
+ // Look the body with X
+ v_x = p_target - p_eye;
+ v_x.normalize();
- const int points = 32;
+ v_y = p_front.cross(v_x);
+ v_y.normalize();
- for (int i = 0; i < points; i++) {
+ v_z = v_y.cross(p_front);
+ v_z.normalize();
- float s = ll + i * (ul - ll) / points;
- float n = ll + (i + 1) * (ul - ll) / points;
+ // Clamp X to FRONT axis
+ v_x = p_front;
+ v_x.normalize();
- Vector3 from = Vector3(-Math::sin(s), Math::cos(s), 0) * cs;
- Vector3 to = Vector3(-Math::sin(n), Math::cos(n), 0) * cs;
+ Basis base;
+ base.set(v_x, v_y, v_z);
- if (i == points - 1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i == 0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
+ // Absorb current joint transform
+ base = p_joint_transform.basis.inverse() * base;
- cursor_points.push_back(from);
- cursor_points.push_back(to);
- }
+ return base;
+}
- cursor_points.push_back(Vector3(0, cs * 1.5, 0));
- cursor_points.push_back(Vector3());
+Basis JointGizmosDrawer::look_body_toward_y(const Transform &p_joint_transform, const Transform &p_body_transform) {
- } else {
+ const Vector3 &p_eye(p_joint_transform.origin);
+ const Vector3 &p_target(p_body_transform.origin);
- const int points = 32;
+ const Vector3 p_up(p_joint_transform.basis.get_axis(1));
- for (int i = 0; i < points; i++) {
+ Vector3 v_x, v_y, v_z;
- float s = ll + i * (Math_PI * 2.0) / points;
- float n = ll + (i + 1) * (Math_PI * 2.0) / points;
+ // Look the body with X
+ v_x = p_target - p_eye;
+ v_x.normalize();
- Vector3 from = Vector3(-Math::sin(s), Math::cos(s), 0) * cs;
- Vector3 to = Vector3(-Math::sin(n), Math::cos(n), 0) * cs;
+ v_z = v_x.cross(p_up);
+ v_z.normalize();
- cursor_points.push_back(from);
- cursor_points.push_back(to);
- }
- }
+ v_x = p_up.cross(v_z);
+ v_x.normalize();
- Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ // Clamp Y to UP axis
+ v_y = p_up;
+ v_y.normalize();
- add_collision_segments(cursor_points);
- add_lines(cursor_points, material);
-}
+ Basis base;
+ base.set(v_x, v_y, v_z);
-HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint *p_p3d) {
+ // Absorb current joint transform
+ base = p_joint_transform.basis.inverse() * base;
- p3d = p_p3d;
- set_spatial_node(p3d);
+ return base;
}
-///////
-///
-////
+Basis JointGizmosDrawer::look_body_toward_z(const Transform &p_joint_transform, const Transform &p_body_transform) {
-void SliderJointSpatialGizmo::redraw() {
+ const Vector3 &p_eye(p_joint_transform.origin);
+ const Vector3 &p_target(p_body_transform.origin);
- clear();
- Vector<Vector3> cursor_points;
- float cs = 0.25;
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));*/
- cursor_points.push_back(Vector3(0, 0, +cs * 2));
- cursor_points.push_back(Vector3(0, 0, -cs * 2));
-
- float ll = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER);
- float ul = p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER);
- float lll = p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER);
- float lul = p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER);
-
- if (lll <= lul) {
-
- cursor_points.push_back(Vector3(lul, 0, 0));
- cursor_points.push_back(Vector3(lll, 0, 0));
-
- cursor_points.push_back(Vector3(lul, -cs, -cs));
- cursor_points.push_back(Vector3(lul, -cs, cs));
- cursor_points.push_back(Vector3(lul, -cs, cs));
- cursor_points.push_back(Vector3(lul, cs, cs));
- cursor_points.push_back(Vector3(lul, cs, cs));
- cursor_points.push_back(Vector3(lul, cs, -cs));
- cursor_points.push_back(Vector3(lul, cs, -cs));
- cursor_points.push_back(Vector3(lul, -cs, -cs));
-
- cursor_points.push_back(Vector3(lll, -cs, -cs));
- cursor_points.push_back(Vector3(lll, -cs, cs));
- cursor_points.push_back(Vector3(lll, -cs, cs));
- cursor_points.push_back(Vector3(lll, cs, cs));
- cursor_points.push_back(Vector3(lll, cs, cs));
- cursor_points.push_back(Vector3(lll, cs, -cs));
- cursor_points.push_back(Vector3(lll, cs, -cs));
- cursor_points.push_back(Vector3(lll, -cs, -cs));
+ const Vector3 p_lateral(p_joint_transform.basis.get_axis(2));
- } else {
+ Vector3 v_x, v_y, v_z;
- cursor_points.push_back(Vector3(+cs * 2, 0, 0));
- cursor_points.push_back(Vector3(-cs * 2, 0, 0));
- }
+ // Look the body with X
+ v_x = p_target - p_eye;
+ v_x.normalize();
- if (ll < ul) {
+ v_z = p_lateral;
+ v_z.normalize();
- const int points = 32;
+ v_y = v_z.cross(v_x);
+ v_y.normalize();
- for (int i = 0; i < points; i++) {
+ // Clamp X to Z axis
+ v_x = v_y.cross(v_z);
+ v_x.normalize();
- float s = ll + i * (ul - ll) / points;
- float n = ll + (i + 1) * (ul - ll) / points;
+ Basis base;
+ base.set(v_x, v_y, v_z);
- Vector3 from = Vector3(0, Math::cos(s), -Math::sin(s)) * cs;
- Vector3 to = Vector3(0, Math::cos(n), -Math::sin(n)) * cs;
+ // Absorb current joint transform
+ base = p_joint_transform.basis.inverse() * base;
- if (i == points - 1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i == 0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
+ return base;
+}
- cursor_points.push_back(from);
- cursor_points.push_back(to);
- }
+void JointGizmosDrawer::draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse) {
+
+ if (p_limit_lower == p_limit_upper) {
- cursor_points.push_back(Vector3(0, cs * 1.5, 0));
- cursor_points.push_back(Vector3());
+ r_points.push_back(p_offset.translated(Vector3()).origin);
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(0.5, 0, 0))).origin);
} else {
+ if (p_limit_lower > p_limit_upper) {
+ p_limit_lower = -Math_PI;
+ p_limit_upper = Math_PI;
+ }
+
const int points = 32;
for (int i = 0; i < points; i++) {
- float s = ll + i * (Math_PI * 2.0) / points;
- float n = ll + (i + 1) * (Math_PI * 2.0) / points;
+ real_t s = p_limit_lower + i * (p_limit_upper - p_limit_lower) / points;
+ real_t n = p_limit_lower + (i + 1) * (p_limit_upper - p_limit_lower) / points;
+
+ Vector3 from;
+ Vector3 to;
+ switch (p_axis) {
+ case Vector3::AXIS_X:
+ if (p_inverse) {
+ from = p_base.xform(Vector3(0, Math::sin(s), Math::cos(s))) * p_radius;
+ to = p_base.xform(Vector3(0, Math::sin(n), Math::cos(n))) * p_radius;
+ } else {
+ from = p_base.xform(Vector3(0, -Math::sin(s), Math::cos(s))) * p_radius;
+ to = p_base.xform(Vector3(0, -Math::sin(n), Math::cos(n))) * p_radius;
+ }
+ break;
+ case Vector3::AXIS_Y:
+ if (p_inverse) {
+ from = p_base.xform(Vector3(Math::cos(s), 0, -Math::sin(s))) * p_radius;
+ to = p_base.xform(Vector3(Math::cos(n), 0, -Math::sin(n))) * p_radius;
+ } else {
+ from = p_base.xform(Vector3(Math::cos(s), 0, Math::sin(s))) * p_radius;
+ to = p_base.xform(Vector3(Math::cos(n), 0, Math::sin(n))) * p_radius;
+ }
+ break;
+ case Vector3::AXIS_Z:
+ from = p_base.xform(Vector3(Math::cos(s), Math::sin(s), 0)) * p_radius;
+ to = p_base.xform(Vector3(Math::cos(n), Math::sin(n), 0)) * p_radius;
+ break;
+ }
- Vector3 from = Vector3(0, Math::cos(s), -Math::sin(s)) * cs;
- Vector3 to = Vector3(0, Math::cos(n), -Math::sin(n)) * cs;
+ if (i == points - 1) {
+ r_points.push_back(p_offset.translated(to).origin);
+ r_points.push_back(p_offset.translated(Vector3()).origin);
+ }
+ if (i == 0) {
+ r_points.push_back(p_offset.translated(from).origin);
+ r_points.push_back(p_offset.translated(Vector3()).origin);
+ }
- cursor_points.push_back(from);
- cursor_points.push_back(to);
+ r_points.push_back(p_offset.translated(from).origin);
+ r_points.push_back(p_offset.translated(to).origin);
}
- }
-
- Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
-
- add_collision_segments(cursor_points);
- add_lines(cursor_points, material);
-}
-
-SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint *p_p3d) {
- p3d = p_p3d;
- set_spatial_node(p3d);
+ r_points.push_back(p_offset.translated(Vector3(0, p_radius * 1.5, 0)).origin);
+ r_points.push_back(p_offset.translated(Vector3()).origin);
+ }
}
-///////
-///
-////
-
-void ConeTwistJointSpatialGizmo::redraw() {
-
- clear();
- Vector<Vector3> points;
+void JointGizmosDrawer::draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points) {
float r = 1.0;
- float w = r * Math::sin(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
- float d = r * Math::cos(p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN));
+ float w = r * Math::sin(p_swing);
+ float d = r * Math::cos(p_swing);
//swing
for (int i = 0; i < 360; i += 10) {
@@ -3194,27 +3187,21 @@ void ConeTwistJointSpatialGizmo::redraw() {
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w;
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
- points.push_back(Vector3(d, a.x, a.y));
- points.push_back(Vector3(d, b.x, b.y));
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, b.x, b.y))).origin);
if (i % 90 == 0) {
- points.push_back(Vector3(d, a.x, a.y));
- points.push_back(Vector3());
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(d, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
}
}
- points.push_back(Vector3());
- points.push_back(Vector3(1, 0, 0));
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3())).origin);
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(1, 0, 0))).origin);
- //twist
- /*
- */
- float ts = Math::rad2deg(p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN));
+ /// Twist
+ float ts = Math::rad2deg(p_twist);
ts = MIN(ts, 720);
for (int i = 0; i < int(ts); i += 5) {
@@ -3226,18 +3213,276 @@ void ConeTwistJointSpatialGizmo::redraw() {
Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c;
Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w * cn;
- /*points.push_back(Vector3(a.x,0,a.y));
- points.push_back(Vector3(b.x,0,b.y));
- points.push_back(Vector3(0,a.x,a.y));
- points.push_back(Vector3(0,b.x,b.y));*/
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(c, a.x, a.y))).origin);
+ r_points.push_back(p_offset.translated(p_base.xform(Vector3(cn, b.x, b.y))).origin);
+ }
+}
+
+void PinJointSpatialGizmo::CreateGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points) {
+ float cs = 0.25;
+
+ r_cursor_points.push_back(p_offset.translated(Vector3(+cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated(Vector3(-cs, 0, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated(Vector3(0, +cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated(Vector3(0, -cs, 0)).origin);
+ r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, +cs)).origin);
+ r_cursor_points.push_back(p_offset.translated(Vector3(0, 0, -cs)).origin);
+}
+
+void PinJointSpatialGizmo::redraw() {
+
+ clear();
+ Vector<Vector3> cursor_points;
+ CreateGizmo(Transform(), cursor_points);
+ add_collision_segments(cursor_points);
+
+ Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+
+ add_lines(cursor_points, material);
+}
+
+PinJointSpatialGizmo::PinJointSpatialGizmo(PinJoint *p_p3d) {
+
+ p3d = p_p3d;
+ set_spatial_node(p3d);
+}
+
+////
+
+void HingeJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+
+ r_common_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
+ r_common_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+
+ if (!p_use_limit) {
+ p_limit_upper = -1;
+ p_limit_lower = 0;
+ }
+
+ if (r_body_a_points) {
+
+ JointGizmosDrawer::draw_circle(Vector3::AXIS_Z,
+ BODY_A_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward_z(p_trs_joint, p_trs_body_a),
+ p_limit_lower,
+ p_limit_upper,
+ *r_body_a_points);
+ }
- points.push_back(Vector3(c, a.x, a.y));
- points.push_back(Vector3(cn, b.x, b.y));
+ if (r_body_b_points) {
+ JointGizmosDrawer::draw_circle(Vector3::AXIS_Z,
+ BODY_B_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward_z(p_trs_joint, p_trs_body_b),
+ p_limit_lower,
+ p_limit_upper,
+ *r_body_b_points);
}
+}
+
+void HingeJointSpatialGizmo::redraw() {
+
+ const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a()));
+ const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b()));
+
+ Vector<Vector3> points;
+ Vector<Vector3> body_a_points;
+ Vector<Vector3> body_b_points;
+ CreateGizmo(
+ Transform(),
+ p3d->get_global_transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform(),
+ node_body_b ? node_body_b->get_global_transform() : Transform(),
+ p3d->get_param(HingeJoint::PARAM_LIMIT_LOWER),
+ p3d->get_param(HingeJoint::PARAM_LIMIT_UPPER),
+ p3d->get_flag(HingeJoint::FLAG_USE_LIMIT),
+ points,
+ node_body_a ? &body_a_points : NULL,
+ node_body_b ? &body_b_points : NULL);
+
+ clear();
+
+ Ref<Material> common_material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a"));
+ Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b"));
+
+ add_collision_segments(points);
+ add_collision_segments(body_a_points);
+ add_collision_segments(body_b_points);
+
+ add_lines(points, common_material);
+ add_lines(body_a_points, body_a_material);
+ add_lines(body_b_points, body_b_material);
+}
+
+HingeJointSpatialGizmo::HingeJointSpatialGizmo(HingeJoint *p_p3d) {
+
+ p3d = p_p3d;
+ set_spatial_node(p3d);
+}
+
+///////
+///
+////
+
+void SliderJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+
+ p_linear_limit_lower = -p_linear_limit_lower;
+ p_linear_limit_upper = -p_linear_limit_upper;
+
+ float cs = 0.25;
+ r_points.push_back(p_offset.translated(Vector3(0, 0, 0.5)).origin);
+ r_points.push_back(p_offset.translated(Vector3(0, 0, -0.5)).origin);
+
+ if (p_linear_limit_lower >= p_linear_limit_upper) {
+
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, 0, 0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, 0, 0)).origin);
+
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_upper, -cs, -cs)).origin);
+
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, cs, -cs)).origin);
+ r_points.push_back(p_offset.translated(Vector3(p_linear_limit_lower, -cs, -cs)).origin);
+
+ } else {
+
+ r_points.push_back(p_offset.translated(Vector3(+cs * 2, 0, 0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(-cs * 2, 0, 0)).origin);
+ }
+
+ if (r_body_a_points)
+ JointGizmosDrawer::draw_circle(
+ Vector3::AXIS_X,
+ BODY_A_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward(Vector3::AXIS_X, p_trs_joint, p_trs_body_a),
+ p_angular_limit_lower,
+ p_angular_limit_upper,
+ *r_body_a_points);
+
+ if (r_body_b_points)
+ JointGizmosDrawer::draw_circle(
+ Vector3::AXIS_X,
+ BODY_B_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward(Vector3::AXIS_X, p_trs_joint, p_trs_body_b),
+ p_angular_limit_lower,
+ p_angular_limit_upper,
+ *r_body_b_points,
+ true);
+}
+
+void SliderJointSpatialGizmo::redraw() {
+
+ const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a()));
+ const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b()));
+
+ clear();
+ Vector<Vector3> cursor_points;
+ Vector<Vector3> body_a_points;
+ Vector<Vector3> body_b_points;
+
+ CreateGizmo(
+ Transform(),
+ p3d->get_global_transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform(),
+ node_body_b ? node_body_b->get_global_transform() : Transform(),
+ p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_LOWER),
+ p3d->get_param(SliderJoint::PARAM_ANGULAR_LIMIT_UPPER),
+ p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_LOWER),
+ p3d->get_param(SliderJoint::PARAM_LINEAR_LIMIT_UPPER),
+ cursor_points,
+ node_body_a ? &body_a_points : NULL,
+ node_body_b ? &body_b_points : NULL);
+
+ Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a"));
+ Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b"));
+
+ add_collision_segments(cursor_points);
+ add_collision_segments(body_a_points);
+ add_collision_segments(body_b_points);
+
+ add_lines(cursor_points, material);
+ add_lines(body_a_points, body_a_material);
+ add_lines(body_b_points, body_b_material);
+}
+
+SliderJointSpatialGizmo::SliderJointSpatialGizmo(SliderJoint *p_p3d) {
+
+ p3d = p_p3d;
+ set_spatial_node(p3d);
+}
+
+///////
+///
+////
+
+void ConeTwistJointSpatialGizmo::CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points) {
+
+ if (r_body_a_points)
+ JointGizmosDrawer::draw_cone(
+ p_offset,
+ JointGizmosDrawer::look_body(p_trs_joint, p_trs_body_a),
+ p_swing,
+ p_twist,
+ *r_body_a_points);
+
+ if (r_body_b_points)
+ JointGizmosDrawer::draw_cone(
+ p_offset,
+ JointGizmosDrawer::look_body(p_trs_joint, p_trs_body_b),
+ p_swing,
+ p_twist,
+ *r_body_b_points);
+}
+
+void ConeTwistJointSpatialGizmo::redraw() {
+
+ const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a()));
+ const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b()));
+
+ clear();
+ Vector<Vector3> points;
+ Vector<Vector3> body_a_points;
+ Vector<Vector3> body_b_points;
+
+ CreateGizmo(
+ Transform(),
+ p3d->get_global_transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform(),
+ node_body_b ? node_body_b->get_global_transform() : Transform(),
+ p3d->get_param(ConeTwistJoint::PARAM_SWING_SPAN),
+ p3d->get_param(ConeTwistJoint::PARAM_TWIST_SPAN),
+ points,
+ node_body_a ? &body_a_points : NULL,
+ node_body_b ? &body_b_points : NULL);
Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a"));
+ Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b"));
+
add_collision_segments(points);
+ add_collision_segments(body_a_points);
+ add_collision_segments(body_b_points);
+
add_lines(points, material);
+ add_lines(body_a_points, body_a_material);
+ add_lines(body_b_points, body_b_material);
}
ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d) {
@@ -3246,26 +3491,46 @@ ConeTwistJointSpatialGizmo::ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d) {
set_spatial_node(p3d);
}
-////////
-/// \brief SpatialEditorGizmos::singleton
-///
///////
///
////
-void Generic6DOFJointSpatialGizmo::redraw() {
+void Generic6DOFJointSpatialGizmo::CreateGizmo(
+ const Transform &p_offset,
+ const Transform &p_trs_joint,
+ const Transform &p_trs_body_a,
+ const Transform &p_trs_body_b,
+ real_t p_angular_limit_lower_x,
+ real_t p_angular_limit_upper_x,
+ real_t p_linear_limit_lower_x,
+ real_t p_linear_limit_upper_x,
+ bool p_enable_angular_limit_x,
+ bool p_enable_linear_limit_x,
+ real_t p_angular_limit_lower_y,
+ real_t p_angular_limit_upper_y,
+ real_t p_linear_limit_lower_y,
+ real_t p_linear_limit_upper_y,
+ bool p_enable_angular_limit_y,
+ bool p_enable_linear_limit_y,
+ real_t p_angular_limit_lower_z,
+ real_t p_angular_limit_upper_z,
+ real_t p_linear_limit_lower_z,
+ real_t p_linear_limit_upper_z,
+ bool p_enable_angular_limit_z,
+ bool p_enable_linear_limit_z,
+ Vector<Vector3> &r_points,
+ Vector<Vector3> *r_body_a_points,
+ Vector<Vector3> *r_body_b_points) {
- clear();
- Vector<Vector3> cursor_points;
float cs = 0.25;
for (int ax = 0; ax < 3; ax++) {
- /*cursor_points.push_back(Vector3(+cs,0,0));
- cursor_points.push_back(Vector3(-cs,0,0));
- cursor_points.push_back(Vector3(0,+cs,0));
- cursor_points.push_back(Vector3(0,-cs,0));
- cursor_points.push_back(Vector3(0,0,+cs*2));
- cursor_points.push_back(Vector3(0,0,-cs*2)); */
+ /*r_points.push_back(p_offset.translated(Vector3(+cs,0,0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(-cs,0,0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(0,+cs,0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(0,-cs,0)).origin);
+ r_points.push_back(p_offset.translated(Vector3(0,0,+cs*2)).origin);
+ r_points.push_back(p_offset.translated(Vector3(0,0,-cs*2)).origin); */
float ll;
float ul;
@@ -3278,61 +3543,50 @@ void Generic6DOFJointSpatialGizmo::redraw() {
switch (ax) {
case 0:
- ll = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
+ ll = p_angular_limit_lower_x;
+ ul = p_angular_limit_upper_x;
+ lll = -p_linear_limit_lower_x;
+ lul = -p_linear_limit_upper_x;
+ enable_ang = p_enable_angular_limit_x;
+ enable_lin = p_enable_linear_limit_x;
a1 = 0;
a2 = 1;
a3 = 2;
break;
case 1:
- ll = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
-
+ ll = p_angular_limit_lower_y;
+ ul = p_angular_limit_upper_y;
+ lll = -p_linear_limit_lower_y;
+ lul = -p_linear_limit_upper_y;
+ enable_ang = p_enable_angular_limit_y;
+ enable_lin = p_enable_linear_limit_y;
a1 = 1;
a2 = 2;
a3 = 0;
break;
case 2:
- ll = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT);
- ul = p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT);
- lll = p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT);
- lul = p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT);
- enable_ang = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT);
- enable_lin = p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT);
-
+ ll = p_angular_limit_lower_z;
+ ul = p_angular_limit_upper_z;
+ lll = -p_linear_limit_lower_z;
+ lul = -p_linear_limit_upper_z;
+ enable_ang = p_enable_angular_limit_z;
+ enable_lin = p_enable_linear_limit_z;
a1 = 2;
a2 = 0;
a3 = 1;
break;
}
-#define ADD_VTX(x, y, z) \
- { \
- Vector3 v; \
- v[a1] = (x); \
- v[a2] = (y); \
- v[a3] = (z); \
- cursor_points.push_back(v); \
- }
-
-#define SET_VTX(what, x, y, z) \
- { \
- Vector3 v; \
- v[a1] = (x); \
- v[a2] = (y); \
- v[a3] = (z); \
- what = v; \
+#define ADD_VTX(x, y, z) \
+ { \
+ Vector3 v; \
+ v[a1] = (x); \
+ v[a2] = (y); \
+ v[a3] = (z); \
+ r_points.push_back(p_offset.translated(v).origin); \
}
- if (enable_lin && lll <= lul) {
+ if (enable_lin && lll >= lul) {
ADD_VTX(lul, 0, 0);
ADD_VTX(lll, 0, 0);
@@ -3361,69 +3615,88 @@ void Generic6DOFJointSpatialGizmo::redraw() {
ADD_VTX(-cs * 2, 0, 0);
}
- if (enable_ang && ll <= ul) {
-
- const int points = 32;
-
- for (int i = 0; i < points; i++) {
-
- float s = ll + i * (ul - ll) / points;
- float n = ll + (i + 1) * (ul - ll) / points;
-
- Vector3 from;
- SET_VTX(from, 0, Math::cos(s), -Math::sin(s));
- from *= cs;
- Vector3 to;
- SET_VTX(to, 0, Math::cos(n), -Math::sin(n));
- to *= cs;
-
- if (i == points - 1) {
- cursor_points.push_back(to);
- cursor_points.push_back(Vector3());
- }
- if (i == 0) {
- cursor_points.push_back(from);
- cursor_points.push_back(Vector3());
- }
-
- cursor_points.push_back(from);
- cursor_points.push_back(to);
- }
-
- ADD_VTX(0, cs * 1.5, 0);
- cursor_points.push_back(Vector3());
-
- } else {
-
- const int points = 32;
-
- for (int i = 0; i < points; i++) {
+ if (!enable_ang) {
+ ll = 0;
+ ul = -1;
+ }
- float s = ll + i * (Math_PI * 2.0) / points;
- float n = ll + (i + 1) * (Math_PI * 2.0) / points;
+ if (r_body_a_points)
+ JointGizmosDrawer::draw_circle(
+ static_cast<Vector3::Axis>(ax),
+ BODY_A_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward(static_cast<Vector3::Axis>(ax), p_trs_joint, p_trs_body_a),
+ ll,
+ ul,
+ *r_body_a_points,
+ true);
+
+ if (r_body_b_points)
+ JointGizmosDrawer::draw_circle(
+ static_cast<Vector3::Axis>(ax),
+ BODY_B_RADIUS,
+ p_offset,
+ JointGizmosDrawer::look_body_toward(static_cast<Vector3::Axis>(ax), p_trs_joint, p_trs_body_b),
+ ll,
+ ul,
+ *r_body_b_points);
+ }
- //Vector3 from=Vector3(0,Math::cos(s),-Math::sin(s) )*cs;
- //Vector3 to=Vector3( 0,Math::cos(n),-Math::sin(n) )*cs;
+#undef ADD_VTX
+}
- Vector3 from;
- SET_VTX(from, 0, Math::cos(s), -Math::sin(s));
- from *= cs;
- Vector3 to;
- SET_VTX(to, 0, Math::cos(n), -Math::sin(n));
- to *= cs;
+void Generic6DOFJointSpatialGizmo::redraw() {
- cursor_points.push_back(from);
- cursor_points.push_back(to);
- }
- }
- }
+ const Spatial *node_body_a = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_a()));
+ const Spatial *node_body_b = Object::cast_to<Spatial>(p3d->get_node(p3d->get_node_b()));
-#undef ADD_VTX
-#undef SET_VTX
+ clear();
+ Vector<Vector3> cursor_points;
+ Vector<Vector3> body_a_points;
+ Vector<Vector3> body_b_points;
+
+ CreateGizmo(
+ Transform(),
+ p3d->get_global_transform(),
+ node_body_a ? node_body_a->get_global_transform() : Transform(),
+ node_body_b ? node_body_b->get_global_transform() : Transform(),
+
+ p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT),
+ p3d->get_param_x(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT),
+ p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT),
+ p3d->get_param_x(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT),
+ p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT),
+ p3d->get_flag_x(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT),
+
+ p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT),
+ p3d->get_param_y(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT),
+ p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT),
+ p3d->get_param_y(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT),
+ p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT),
+ p3d->get_flag_y(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT),
+
+ p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_LOWER_LIMIT),
+ p3d->get_param_z(Generic6DOFJoint::PARAM_ANGULAR_UPPER_LIMIT),
+ p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_LOWER_LIMIT),
+ p3d->get_param_z(Generic6DOFJoint::PARAM_LINEAR_UPPER_LIMIT),
+ p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_ANGULAR_LIMIT),
+ p3d->get_flag_z(Generic6DOFJoint::FLAG_ENABLE_LINEAR_LIMIT),
+
+ cursor_points,
+ node_body_a ? &body_a_points : NULL,
+ node_body_a ? &body_b_points : NULL);
Ref<Material> material = create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
+ Ref<Material> body_a_material = create_material("joint_body_a_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_a"));
+ Ref<Material> body_b_material = create_material("joint_body_b_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint_body_b"));
+
add_collision_segments(cursor_points);
+ add_collision_segments(body_a_points);
+ add_collision_segments(body_b_points);
+
add_lines(cursor_points, material);
+ add_lines(body_a_points, body_a_material);
+ add_lines(body_b_points, body_b_material);
}
Generic6DOFJointSpatialGizmo::Generic6DOFJointSpatialGizmo(Generic6DOFJoint *p_p3d) {
@@ -3616,6 +3889,8 @@ SpatialEditorGizmos::SpatialEditorGizmos() {
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/baked_indirect_light", Color(0.5, 0.6, 1));
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1));
+ EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1));
+ EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1));
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge", Color(0.5, 1, 1));
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_edge_disabled", Color(0.7, 0.7, 0.7));
EDITOR_DEF("editors/3d_gizmos/gizmo_colors/navigation_solid", Color(0.5, 1, 1, 0.4));
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
index ea8a33d2c6..7bf632d371 100644
--- a/editor/spatial_editor_gizmos.h
+++ b/editor/spatial_editor_gizmos.h
@@ -107,6 +107,7 @@ protected:
void add_solid_box(Ref<Material> &p_material, Vector3 size);
void set_spatial_node(Spatial *p_node);
+ const Spatial *get_spatial_node() const { return spatial_node; }
static void _bind_methods();
@@ -372,6 +373,21 @@ public:
NavigationMeshSpatialGizmo(NavigationMeshInstance *p_navmesh = NULL);
};
+class JointGizmosDrawer {
+public:
+ static Basis look_body(const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body_toward(Vector3::Axis p_axis, const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body_toward_x(const Transform &joint_transform, const Transform &body_transform);
+ static Basis look_body_toward_y(const Transform &joint_transform, const Transform &body_transform);
+ /// Special function just used for physics joints, it that returns a basis constrained toward Joint Z axis
+ /// with axis X and Y that are looking toward the body and oriented toward up
+ static Basis look_body_toward_z(const Transform &joint_transform, const Transform &body_transform);
+
+ // Draw circle around p_axis
+ static void draw_circle(Vector3::Axis p_axis, real_t p_radius, const Transform &p_offset, const Basis &p_base, real_t p_limit_lower, real_t p_limit_upper, Vector<Vector3> &r_points, bool p_inverse = false);
+ static void draw_cone(const Transform &p_offset, const Basis &p_base, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points);
+};
+
class PinJointSpatialGizmo : public EditorSpatialGizmo {
GDCLASS(PinJointSpatialGizmo, EditorSpatialGizmo);
@@ -379,6 +395,8 @@ class PinJointSpatialGizmo : public EditorSpatialGizmo {
PinJoint *p3d;
public:
+ static void CreateGizmo(const Transform &p_offset, Vector<Vector3> &r_cursor_points);
+
void redraw();
PinJointSpatialGizmo(PinJoint *p_p3d = NULL);
};
@@ -390,6 +408,8 @@ class HingeJointSpatialGizmo : public EditorSpatialGizmo {
HingeJoint *p3d;
public:
+ static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_limit_lower, real_t p_limit_upper, bool p_use_limit, Vector<Vector3> &r_common_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+
void redraw();
HingeJointSpatialGizmo(HingeJoint *p_p3d = NULL);
};
@@ -401,6 +421,8 @@ class SliderJointSpatialGizmo : public EditorSpatialGizmo {
SliderJoint *p3d;
public:
+ static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_angular_limit_lower, real_t p_angular_limit_upper, real_t p_linear_limit_lower, real_t p_linear_limit_upper, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+
void redraw();
SliderJointSpatialGizmo(SliderJoint *p_p3d = NULL);
};
@@ -412,6 +434,8 @@ class ConeTwistJointSpatialGizmo : public EditorSpatialGizmo {
ConeTwistJoint *p3d;
public:
+ static void CreateGizmo(const Transform &p_offset, const Transform &p_trs_joint, const Transform &p_trs_body_a, const Transform &p_trs_body_b, real_t p_swing, real_t p_twist, Vector<Vector3> &r_points, Vector<Vector3> *r_body_a_points, Vector<Vector3> *r_body_b_points);
+
void redraw();
ConeTwistJointSpatialGizmo(ConeTwistJoint *p_p3d = NULL);
};
@@ -423,6 +447,33 @@ class Generic6DOFJointSpatialGizmo : public EditorSpatialGizmo {
Generic6DOFJoint *p3d;
public:
+ static void CreateGizmo(
+ const Transform &p_offset,
+ const Transform &p_trs_joint,
+ const Transform &p_trs_body_a,
+ const Transform &p_trs_body_b,
+ real_t p_angular_limit_lower_x,
+ real_t p_angular_limit_upper_x,
+ real_t p_linear_limit_lower_x,
+ real_t p_linear_limit_upper_x,
+ bool p_enable_angular_limit_x,
+ bool p_enable_linear_limit_x,
+ real_t p_angular_limit_lower_y,
+ real_t p_angular_limit_upper_y,
+ real_t p_linear_limit_lower_y,
+ real_t p_linear_limit_upper_y,
+ bool p_enable_angular_limit_y,
+ bool p_enable_linear_limit_y,
+ real_t p_angular_limit_lower_z,
+ real_t p_angular_limit_upper_z,
+ real_t p_linear_limit_lower_z,
+ real_t p_linear_limit_upper_z,
+ bool p_enable_angular_limit_z,
+ bool p_enable_linear_limit_z,
+ Vector<Vector3> &r_points,
+ Vector<Vector3> *r_body_a_points,
+ Vector<Vector3> *r_body_b_points);
+
void redraw();
Generic6DOFJointSpatialGizmo(Generic6DOFJoint *p_p3d = NULL);
};
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index cbf30c8a2e..37e45cfff8 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -142,6 +142,9 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1) {
+ if (m_count >= m_resultMax)
+ return cp.getDistance();
+
if (cp.getDistance() <= 0) {
PhysicsDirectSpaceState::ShapeResult &result = m_results[m_count];
@@ -165,7 +168,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con
++m_count;
}
- return m_count < m_resultMax;
+ return cp.getDistance();
}
bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 669b2c3f0c..5e736c1856 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -264,6 +264,7 @@ RigidBodyBullet::RigidBodyBullet() :
can_sleep(true),
force_integration_callback(NULL),
isTransformChanged(false),
+ previousActiveState(true),
maxCollisionsDetection(0),
collisionsCount(0),
maxAreasWhereIam(10),
@@ -287,6 +288,7 @@ RigidBodyBullet::RigidBodyBullet() :
for (int i = areasWhereIam.size() - 1; 0 <= i; --i) {
areasWhereIam[i] = NULL;
}
+ btBody->setSleepingThresholds(0.2, 0.2);
}
RigidBodyBullet::~RigidBodyBullet() {
@@ -337,7 +339,7 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) {
void RigidBodyBullet::dispatch_callbacks() {
/// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent
- if (btBody->isActive() && force_integration_callback && isTransformChanged) {
+ if ((btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) {
BulletPhysicsDirectBodyState *bodyDirect = BulletPhysicsDirectBodyState::get_singleton(this);
@@ -364,6 +366,8 @@ void RigidBodyBullet::dispatch_callbacks() {
/// Lock axis
btBody->setLinearVelocity(btBody->getLinearVelocity() * btBody->getLinearFactor());
btBody->setAngularVelocity(btBody->getAngularVelocity() * btBody->getAngularFactor());
+
+ previousActiveState = btBody->isActive();
}
void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) {
@@ -580,7 +584,8 @@ Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const {
void RigidBodyBullet::apply_central_impulse(const Vector3 &p_impulse) {
btVector3 btImpu;
G_TO_B(p_impulse, btImpu);
- btBody->activate();
+ if (Vector3() != p_impulse)
+ btBody->activate();
btBody->applyCentralImpulse(btImpu);
}
@@ -589,14 +594,16 @@ void RigidBodyBullet::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impul
btVector3 btPos;
G_TO_B(p_impulse, btImpu);
G_TO_B(p_pos, btPos);
- btBody->activate();
+ if (Vector3() != p_impulse)
+ btBody->activate();
btBody->applyImpulse(btImpu, btPos);
}
void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) {
btVector3 btImp;
G_TO_B(p_impulse, btImp);
- btBody->activate();
+ if (Vector3() != p_impulse)
+ btBody->activate();
btBody->applyTorqueImpulse(btImp);
}
@@ -605,28 +612,32 @@ void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_pos)
btVector3 btPos;
G_TO_B(p_force, btForce);
G_TO_B(p_pos, btPos);
- btBody->activate();
+ if (Vector3() != p_force)
+ btBody->activate();
btBody->applyForce(btForce, btPos);
}
void RigidBodyBullet::apply_central_force(const Vector3 &p_force) {
btVector3 btForce;
G_TO_B(p_force, btForce);
- btBody->activate();
+ if (Vector3() != p_force)
+ btBody->activate();
btBody->applyCentralForce(btForce);
}
void RigidBodyBullet::apply_torque(const Vector3 &p_torque) {
btVector3 btTorq;
G_TO_B(p_torque, btTorq);
- btBody->activate();
+ if (Vector3() != p_torque)
+ btBody->activate();
btBody->applyTorque(btTorq);
}
void RigidBodyBullet::set_applied_force(const Vector3 &p_force) {
btVector3 btVec = btBody->getTotalTorque();
- btBody->activate();
+ if (Vector3() != p_force)
+ btBody->activate();
btBody->clearForces();
btBody->applyTorque(btVec);
@@ -644,7 +655,8 @@ Vector3 RigidBodyBullet::get_applied_force() const {
void RigidBodyBullet::set_applied_torque(const Vector3 &p_torque) {
btVector3 btVec = btBody->getTotalForce();
- btBody->activate();
+ if (Vector3() != p_torque)
+ btBody->activate();
btBody->clearForces();
btBody->applyCentralForce(btVec);
@@ -711,7 +723,8 @@ bool RigidBodyBullet::is_continuous_collision_detection_enabled() const {
void RigidBodyBullet::set_linear_velocity(const Vector3 &p_velocity) {
btVector3 btVec;
G_TO_B(p_velocity, btVec);
- btBody->activate();
+ if (Vector3() != p_velocity)
+ btBody->activate();
btBody->setLinearVelocity(btVec);
}
@@ -724,7 +737,8 @@ Vector3 RigidBodyBullet::get_linear_velocity() const {
void RigidBodyBullet::set_angular_velocity(const Vector3 &p_velocity) {
btVector3 btVec;
G_TO_B(p_velocity, btVec);
- btBody->activate();
+ if (Vector3() != p_velocity)
+ btBody->activate();
btBody->setAngularVelocity(btVec);
}
@@ -833,6 +847,9 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) {
void RigidBodyBullet::reload_space_override_modificator() {
+ if (!is_active())
+ return;
+
Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude());
real_t newLinearDamp(linearDamp);
real_t newAngularDamp(angularDamp);
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index c0eb148e24..c3b72172d9 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -207,6 +207,7 @@ private:
bool isScratchedSpaceOverrideModificator;
bool isTransformChanged;
+ bool previousActiveState; // Last check state
ForceIntegrationCallback *force_integration_callback;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index af5a0334c3..44dd776e9a 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1376,7 +1376,7 @@ bool CSharpScript::_update_exports() {
hint_string = NATIVE_GDMONOCLASS_NAME(field_type.type_class);
} else {
hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
- hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
+ hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr);
}
PropertyInfo prop_info = PropertyInfo(type, name, hint, hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE);
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index fbb9b2ed14..d7885ade61 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -108,7 +108,7 @@ const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in
bool BindingsGenerator::verbose_output = false;
-static String snake_to_pascal_case(const String &p_identifier) {
+static String snake_to_pascal_case(const String &p_identifier, bool p_input_is_upper = false) {
String ret;
Vector<String> parts = p_identifier.split("_", true);
@@ -118,6 +118,10 @@ static String snake_to_pascal_case(const String &p_identifier) {
if (part.length()) {
part[0] = _find_upper(part[0]);
+ if (p_input_is_upper) {
+ for (int j = 1; j < part.length(); j++)
+ part[j] = _find_lower(part[j]);
+ }
ret += part;
} else {
if (i == 0 || i == (parts.size() - 1)) {
@@ -137,7 +141,7 @@ static String snake_to_pascal_case(const String &p_identifier) {
return ret;
}
-static String snake_to_camel_case(const String &p_identifier) {
+static String snake_to_camel_case(const String &p_identifier, bool p_input_is_upper = false) {
String ret;
Vector<String> parts = p_identifier.split("_", true);
@@ -146,8 +150,13 @@ static String snake_to_camel_case(const String &p_identifier) {
String part = parts[i];
if (part.length()) {
- if (i != 0)
+ if (i != 0) {
part[0] = _find_upper(part[0]);
+ }
+ if (p_input_is_upper) {
+ for (int j = i != 0 ? 1 : 0; j < part.length(); j++)
+ part[j] = _find_lower(part[j]);
+ }
ret += part;
} else {
if (i == 0 || i == (parts.size() - 1)) {
@@ -167,6 +176,25 @@ static String snake_to_camel_case(const String &p_identifier) {
return ret;
}
+String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
+
+ CRASH_COND(p_ienum.constants.empty());
+
+ const List<ConstantInterface>::Element *front = p_ienum.constants.front();
+ int candidate_len = front->get().name.length();
+
+ for (const List<ConstantInterface>::Element *E = front->next(); E; E = E->next()) {
+ int j = 0;
+ for (j = 0; j < candidate_len && j < E->get().name.length(); j++) {
+ if (front->get().name[j] != E->get().name[j])
+ break;
+ }
+ candidate_len = j;
+ }
+
+ return front->get().name.substr(0, candidate_len);
+}
+
void BindingsGenerator::_generate_header_icalls() {
core_custom_icalls.clear();
@@ -220,7 +248,7 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE;
- String im_unique_sig = imethod.return_type + ",IntPtr,IntPtr";
+ String im_unique_sig = imethod.return_type.operator String() + ",IntPtr,IntPtr";
// Get arguments information
int i = 0;
@@ -256,6 +284,129 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
}
}
+void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
+
+ // Constants (in partial GD class)
+
+ p_output.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ p_output.push_back(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
+
+ for (const List<ConstantInterface>::Element *E = global_constants.front(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
+
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
+ p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+
+ Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
+ p_output.push_back(INDENT2 "/// ");
+ p_output.push_back(description_line.xml_escape());
+ p_output.push_back("\n");
+ }
+ }
+
+ p_output.push_back(INDENT2 "/// </summary>");
+ }
+
+ p_output.push_back(MEMBER_BEGIN "public const int ");
+ p_output.push_back(iconstant.name);
+ p_output.push_back(" = ");
+ p_output.push_back(itos(iconstant.value));
+ p_output.push_back(";");
+ }
+
+ if (!global_constants.empty())
+ p_output.push_back("\n");
+
+ p_output.push_back(INDENT1 CLOSE_BLOCK); // end of GD class
+
+ // Enums
+
+ for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
+ const EnumInterface &ienum = E->get();
+
+ CRASH_COND(ienum.constants.empty());
+
+ String enum_proxy_name = ienum.cname.operator String();
+
+ bool enum_in_static_class = false;
+
+ if (enum_proxy_name.find(".") > 0) {
+ enum_in_static_class = true;
+ String enum_class_name = enum_proxy_name.get_slicec('.', 0);
+ enum_proxy_name = enum_proxy_name.get_slicec('.', 1);
+
+ CRASH_COND(enum_class_name != "Variant"); // Hard-coded...
+
+ if (verbose_output) {
+ WARN_PRINTS("Declaring global enum `" + enum_proxy_name + "` inside static class `" + enum_class_name + "`");
+ }
+
+ p_output.push_back("\n" INDENT1 "public static partial class ");
+ p_output.push_back(enum_class_name);
+ p_output.push_back("\n" INDENT1 OPEN_BLOCK);
+ }
+
+ p_output.push_back("\n" INDENT1 "public enum ");
+ p_output.push_back(enum_proxy_name);
+ p_output.push_back("\n" INDENT1 OPEN_BLOCK);
+
+ for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
+
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
+ p_output.push_back(INDENT2 "/// <summary>\n");
+
+ Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
+ p_output.push_back(INDENT2 "/// ");
+ p_output.push_back(description_line.xml_escape());
+ p_output.push_back("\n");
+ }
+ }
+
+ p_output.push_back(INDENT2 "/// </summary>\n");
+ }
+
+ String constant_name = iconstant.name;
+
+ if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
+ constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
+ }
+
+ if (constant_name[0] >= '0' && constant_name[0] <= '9') {
+ // The name of enum constants may begin with a numeric digit when strip from the enum prefix,
+ // so we make the prefix one word shorter in those cases.
+ int i = 0;
+ for (i = ienum.prefix.length() - 1; i >= 0; i--) {
+ if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
+ break;
+ }
+ constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
+ }
+
+ p_output.push_back(INDENT2);
+ p_output.push_back(constant_name);
+ p_output.push_back(" = ");
+ p_output.push_back(itos(iconstant.value));
+ p_output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
+ }
+
+ p_output.push_back(INDENT1 CLOSE_BLOCK);
+
+ if (enum_in_static_class)
+ p_output.push_back(INDENT1 CLOSE_BLOCK);
+ }
+
+ p_output.push_back(CLOSE_BLOCK); // end of namespace
+}
+
Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bool p_verbose_output) {
verbose_output = p_verbose_output;
@@ -282,7 +433,19 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
if (!solution.set_path(p_output_dir))
return ERR_FILE_NOT_FOUND;
- for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
+ // Generate source file for global scope constants and enums
+ {
+ List<String> constants_source;
+ _generate_global_constants(constants_source);
+ String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
+ Error save_err = _save_file(output_file, constants_source);
+ if (save_err != OK)
+ return save_err;
+
+ compile_items.push_back(output_file);
+ }
+
+ for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
const TypeInterface &itype = E->get();
if (itype.api_type == ClassDB::API_EDITOR)
@@ -314,49 +477,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
#undef GENERATE_BUILTIN_TYPE
- // Generate source for GlobalConstants
-
- String constants_source;
- int global_constants_count = GlobalConstants::get_global_constant_count();
-
- if (global_constants_count > 0) {
- Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope");
-
- ERR_EXPLAIN("Could not find `@GlobalScope` in DocData");
- ERR_FAIL_COND_V(!match, ERR_BUG);
-
- const DocData::ClassDoc &global_scope_doc = match->value();
-
- for (int i = 0; i < global_constants_count; i++) {
- const DocData::ConstantDoc &const_doc = global_scope_doc.constants[i];
-
- if (i > 0)
- constants_source += MEMBER_BEGIN;
-
- if (const_doc.description.size()) {
- constants_source += "/// <summary>\n";
-
- Vector<String> description_lines = const_doc.description.split("\n");
-
- for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
- constants_source += INDENT2 "/// ";
- constants_source += description_lines[i].strip_edges().xml_escape();
- constants_source += "\n";
- }
- }
-
- constants_source += INDENT2 "/// </summary>" MEMBER_BEGIN;
- }
-
- constants_source += "public const int ";
- constants_source += GlobalConstants::get_global_constant_name(i);
- constants_source += " = ";
- constants_source += itos(GlobalConstants::get_global_constant_value(i));
- constants_source += ";";
- }
- }
-
// Generate sources from compressed files
Map<String, CompressedFile> compressed_files;
@@ -372,19 +492,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
data.resize(file_data.uncompressed_size);
Compression::decompress(data.ptrw(), file_data.uncompressed_size, file_data.data, file_data.compressed_size, Compression::MODE_DEFLATE);
- if (file_name.get_basename() == BINDINGS_GLOBAL_SCOPE_CLASS) {
- // GD.cs must be formatted to include the generated global constants
- String data_str = String::utf8(reinterpret_cast<const char *>(data.ptr()), data.size());
-
- Dictionary format_keys;
- format_keys["GodotGlobalConstants"] = constants_source;
- data_str = data_str.format(format_keys, "/*{_}*/");
-
- CharString data_utf8 = data_str.utf8();
- data.resize(data_utf8.length());
- copymem(data.ptrw(), reinterpret_cast<const uint8_t *>(data_utf8.get_data()), data_utf8.length());
- }
-
FileAccessRef file = FileAccess::open(output_file, FileAccess::WRITE);
ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
file->store_buffer(data.ptr(), data.size());
@@ -470,7 +577,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
if (!solution.set_path(p_output_dir))
return ERR_FILE_NOT_FOUND;
- for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
+ for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
const TypeInterface &itype = E->get();
if (itype.api_type != ClassDB::API_EDITOR)
@@ -543,7 +650,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended.
Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) {
- bool is_derived_type = itype.base_name.length();
+ bool is_derived_type = itype.base_name != StringName();
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
@@ -569,9 +676,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
Vector<String> description_lines = class_doc->description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
output.push_back(INDENT1 "/// ");
- output.push_back(description_lines[i].strip_edges().xml_escape());
+ output.push_back(description_line.xml_escape());
output.push_back("\n");
}
}
@@ -592,7 +700,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back(obj_types[itype.base_name].proxy_name);
output.push_back("\n");
} else {
- ERR_PRINTS("Base type '" + itype.base_name + "' does not exist, for class " + itype.name);
+ ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
return ERR_INVALID_DATA;
}
@@ -602,18 +710,19 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add constants
- for (int i = 0; i < class_doc->constants.size(); i++) {
- const DocData::ConstantDoc &const_doc = class_doc->constants[i];
+ for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
- if (const_doc.description.size()) {
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
output.push_back(MEMBER_BEGIN "/// <summary>\n");
- Vector<String> description_lines = const_doc.description.split("\n");
+ Vector<String> description_lines = iconstant.const_doc->description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
output.push_back(INDENT2 "/// ");
- output.push_back(description_lines[i].strip_edges().xml_escape());
+ output.push_back(description_line.xml_escape());
output.push_back("\n");
}
}
@@ -622,24 +731,84 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output.push_back(MEMBER_BEGIN "public const int ");
- output.push_back(const_doc.name);
+ output.push_back(iconstant.name);
output.push_back(" = ");
- output.push_back(const_doc.value);
+ output.push_back(itos(iconstant.value));
output.push_back(";");
}
- if (class_doc->constants.size())
+ if (itype.constants.size())
output.push_back("\n");
- // Add properties
+ // Add enums
+
+ for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) {
+ const EnumInterface &ienum = E->get();
+
+ ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG);
+
+ output.push_back(MEMBER_BEGIN "public enum ");
+ output.push_back(ienum.cname.operator String());
+ output.push_back(MEMBER_BEGIN OPEN_BLOCK);
+
+ for (const List<ConstantInterface>::Element *E = ienum.constants.front(); E; E = E->next()) {
+ const ConstantInterface &iconstant = E->get();
+
+ if (iconstant.const_doc && iconstant.const_doc->description.size()) {
+ output.push_back(INDENT3 "/// <summary>\n");
+
+ Vector<String> description_lines = iconstant.const_doc->description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
+ output.push_back(INDENT3 "/// ");
+ output.push_back(description_line.xml_escape());
+ output.push_back("\n");
+ }
+ }
+
+ output.push_back(INDENT3 "/// </summary>\n");
+ }
+
+ String constant_name = iconstant.name;
+
+ if (!ienum.prefix.empty() && constant_name.begins_with(ienum.prefix)) {
+ constant_name = constant_name.substr(ienum.prefix.length(), constant_name.length());
+ }
+
+ if (constant_name[0] >= '0' && constant_name[0] <= '9') {
+ // The name of enum constants may begin with a numeric digit when strip from the enum prefix,
+ // so we make the prefix one word shorter in those cases.
+ int i = 0;
+ for (i = ienum.prefix.length() - 1; i >= 0; i--) {
+ if (ienum.prefix[i] >= 'A' && ienum.prefix[i] <= 'Z')
+ break;
+ }
+ constant_name = ienum.prefix.substr(i, ienum.prefix.length()) + constant_name;
+ }
+
+ output.push_back(INDENT3);
+ output.push_back(constant_name);
+ output.push_back(" = ");
+ output.push_back(itos(iconstant.value));
+ output.push_back(E != ienum.constants.back() ? ",\n" : "\n");
+ }
+
+ output.push_back(INDENT2 CLOSE_BLOCK);
+ }
+
+ if (itype.enums.size())
+ output.push_back("\n");
- const Vector<DocData::PropertyDoc> &properties = class_doc->properties;
+ // Add properties
- for (int i = 0; i < properties.size(); i++) {
- const DocData::PropertyDoc &prop_doc = properties[i];
- Error prop_err = _generate_cs_property(itype, prop_doc, output);
+ for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
+ const PropertyInterface &iprop = E->get();
+ Error prop_err = _generate_cs_property(itype, iprop, output);
if (prop_err != OK) {
- ERR_EXPLAIN("Failed to generate property '" + prop_doc.name + "' for class '" + itype.name + "'");
+ ERR_EXPLAIN("Failed to generate property '" + iprop.cname.operator String() +
+ "' for class '" + itype.name + "'");
ERR_FAIL_V(prop_err);
}
}
@@ -766,14 +935,14 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
" = IntPtr.Zero;\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
"GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
- Map<String, TypeInterface>::Element *array_itype = builtin_types.find("Array");
+ Map<StringName, TypeInterface>::Element *array_itype = builtin_types.find(name_cache.type_Array);
if (!array_itype) {
ERR_PRINT("BUG: Array type interface not found!");
return ERR_BUG;
}
- Map<String, TypeInterface>::Element *object_itype = obj_types.find("Object");
+ Map<StringName, TypeInterface>::Element *object_itype = obj_types.find("Object");
if (!object_itype) {
ERR_PRINT("BUG: Object type interface not found!");
@@ -787,7 +956,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
}
- Map<String, String>::Element *extra_member = extra_members.find(itype.name);
+ Map<StringName, String>::Element *extra_member = extra_members.find(itype.cname);
if (extra_member)
output.push_back(extra_member->get());
@@ -820,43 +989,39 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
return _save_file(p_output_file, output);
}
-Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output) {
+Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output) {
- const MethodInterface *setter = p_itype.find_method_by_name(p_prop_doc.setter);
+ const MethodInterface *setter = p_itype.find_method_by_name(p_iprop.setter);
// Search it in base types too
const TypeInterface *current_type = &p_itype;
- while (!setter && current_type->base_name.length()) {
- Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ while (!setter && current_type->base_name != StringName()) {
+ Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
ERR_FAIL_NULL_V(base_match, ERR_BUG);
current_type = &base_match->get();
- setter = current_type->find_method_by_name(p_prop_doc.setter);
+ setter = current_type->find_method_by_name(p_iprop.setter);
}
- const MethodInterface *getter = p_itype.find_method_by_name(p_prop_doc.getter);
+ const MethodInterface *getter = p_itype.find_method_by_name(p_iprop.getter);
// Search it in base types too
current_type = &p_itype;
- while (!getter && current_type->base_name.length()) {
- Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ while (!getter && current_type->base_name != StringName()) {
+ Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
ERR_FAIL_NULL_V(base_match, ERR_BUG);
current_type = &base_match->get();
- getter = current_type->find_method_by_name(p_prop_doc.getter);
+ getter = current_type->find_method_by_name(p_iprop.getter);
}
ERR_FAIL_COND_V(!setter && !getter, ERR_BUG);
- bool is_valid = false;
- int prop_index = ClassDB::get_property_index(p_itype.name, p_prop_doc.name, &is_valid);
- ERR_FAIL_COND_V(!is_valid, ERR_BUG);
-
if (setter) {
- int setter_argc = prop_index != -1 ? 2 : 1;
+ int setter_argc = p_iprop.index != -1 ? 2 : 1;
ERR_FAIL_COND_V(setter->arguments.size() != setter_argc, ERR_BUG);
}
if (getter) {
- int getter_argc = prop_index != -1 ? 1 : 0;
+ int getter_argc = p_iprop.index != -1 ? 1 : 0;
ERR_FAIL_COND_V(getter->arguments.size() != getter_argc, ERR_BUG);
}
@@ -864,18 +1029,12 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
ERR_FAIL_COND_V(getter->return_type != setter->arguments.back()->get().type, ERR_BUG);
}
- // Let's not trust PropertyDoc::type
- String proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type;
+ StringName proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type;
const TypeInterface *prop_itype = _get_type_by_name_or_null(proptype_name);
- if (!prop_itype) {
- // Try with underscore prefix
- prop_itype = _get_type_by_name_or_null("_" + proptype_name);
- }
+ ERR_FAIL_NULL_V(prop_itype, ERR_BUG); // Property type not found
- ERR_FAIL_NULL_V(prop_itype, ERR_BUG);
-
- String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_prop_doc.name));
+ String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(p_iprop.cname));
// Prevent property and enclosing type from sharing the same name
if (prop_proxy_name == p_itype.proxy_name) {
@@ -887,15 +1046,16 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
prop_proxy_name += "_";
}
- if (p_prop_doc.description.size()) {
+ if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) {
p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
- Vector<String> description_lines = p_prop_doc.description.split("\n");
+ Vector<String> description_lines = p_iprop.prop_doc->description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_lines[i].strip_edges().xml_escape());
+ p_output.push_back(description_line.xml_escape());
p_output.push_back("\n");
}
}
@@ -917,16 +1077,34 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
p_output.push_back(INDENT3 "get\n" OPEN_BLOCK_L3);
p_output.push_back("return ");
p_output.push_back(getter->proxy_name + "(");
- if (prop_index != -1)
- p_output.push_back(itos(prop_index));
+ if (p_iprop.index != -1) {
+ const ArgumentInterface &idx_arg = getter->arguments.front()->get();
+ if (idx_arg.type != name_cache.type_int) {
+ // Assume the index parameter is an enum
+ const TypeInterface *idx_arg_type = _get_type_by_name_or_null(idx_arg.type);
+ CRASH_COND(idx_arg_type == NULL);
+ p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index));
+ } else {
+ p_output.push_back(itos(p_iprop.index));
+ }
+ }
p_output.push_back(");\n" CLOSE_BLOCK_L3);
}
if (setter) {
p_output.push_back(INDENT3 "set\n" OPEN_BLOCK_L3);
p_output.push_back(setter->proxy_name + "(");
- if (prop_index != -1)
- p_output.push_back(itos(prop_index) + ", ");
+ if (p_iprop.index != -1) {
+ const ArgumentInterface &idx_arg = setter->arguments.front()->get();
+ if (idx_arg.type != name_cache.type_int) {
+ // Assume the index parameter is an enum
+ const TypeInterface *idx_arg_type = _get_type_by_name_or_null(idx_arg.type);
+ CRASH_COND(idx_arg_type == NULL);
+ p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index) + ", ");
+ } else {
+ p_output.push_back(itos(p_iprop.index) + ", ");
+ }
+ }
p_output.push_back("value);\n" CLOSE_BLOCK_L3);
}
@@ -1033,9 +1211,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
Vector<String> description_lines = p_imethod.method_doc->description.split("\n");
for (int i = 0; i < description_lines.size(); i++) {
- if (description_lines[i].size()) {
+ String description_line = description_lines[i].strip_edges();
+ if (description_line.size()) {
p_output.push_back(INDENT2 "/// ");
- p_output.push_back(description_lines[i].strip_edges().xml_escape());
+ p_output.push_back(description_line.xml_escape());
p_output.push_back("\n");
}
}
@@ -1069,7 +1248,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
if (p_imethod.is_virtual) {
// Godot virtual method must be overridden, therefore we return a default value by default.
- if (return_type->name == "void") {
+ if (return_type->cname == name_cache.type_void) {
p_output.push_back("return;\n" CLOSE_BLOCK_L2);
} else {
p_output.push_back("return default(");
@@ -1108,7 +1287,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
if (p_imethod.arguments.size())
p_output.push_back(cs_in_statements);
- if (return_type->name == "void") {
+ if (return_type->cname == name_cache.type_void) {
p_output.push_back(im_call);
} else if (return_type->cs_out.empty()) {
p_output.push_back("return " + im_call);
@@ -1142,7 +1321,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
generated_icall_funcs.clear();
- for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
+ for (Map<StringName, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
const TypeInterface &itype = type_elem->get();
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
@@ -1295,7 +1474,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
if (p_imethod.is_virtual)
return OK; // Ignore
- bool ret_void = p_imethod.return_type == "void";
+ bool ret_void = p_imethod.return_type == name_cache.type_void;
const TypeInterface *return_type = _get_type_by_name_or_placeholder(p_imethod.return_type);
@@ -1447,14 +1626,19 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
return OK;
}
-const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const String &p_name) {
+const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const StringName &p_cname) {
+
+ const Map<StringName, TypeInterface>::Element *match = builtin_types.find(p_cname);
- const Map<String, TypeInterface>::Element *match = builtin_types.find(p_name);
+ if (match)
+ return &match->get();
+
+ match = obj_types.find(p_cname);
if (match)
return &match->get();
- match = obj_types.find(p_name);
+ match = enum_types.find(p_cname);
if (match)
return &match->get();
@@ -1462,24 +1646,27 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_
return NULL;
}
-const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_placeholder(const String &p_name) {
+const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_placeholder(const StringName &p_cname) {
- const TypeInterface *found = _get_type_by_name_or_null(p_name);
+ const TypeInterface *found = _get_type_by_name_or_null(p_cname);
if (found)
return found;
- ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_name);
+ ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_cname.operator String());
- const Map<String, TypeInterface>::Element *match = placeholder_types.find(p_name);
+ const Map<StringName, TypeInterface>::Element *match = placeholder_types.find(p_cname);
if (match)
return &match->get();
TypeInterface placeholder;
- TypeInterface::create_placeholder_type(placeholder, p_name);
+ TypeInterface::create_placeholder_type(placeholder, p_cname);
- return &placeholder_types.insert(placeholder.name, placeholder)->get();
+ return &placeholder_types.insert(placeholder.cname, placeholder)->get();
+}
+
+static void _create_constant_interface_from(const StringName &p_constant, const DocData::ClassDoc &p_classdoc) {
}
void BindingsGenerator::_populate_object_type_interfaces() {
@@ -1490,8 +1677,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
ClassDB::get_class_list(&class_list);
class_list.sort_custom<StringName::AlphCompare>();
- StringName refclass_name = String("Reference");
-
while (class_list.size()) {
StringName type_cname = class_list.front()->get();
@@ -1502,21 +1687,23 @@ void BindingsGenerator::_populate_object_type_interfaces() {
continue;
}
+ if (!ClassDB::is_class_exposed(type_cname)) {
+ if (verbose_output)
+ WARN_PRINTS("Ignoring type " + type_cname.operator String() + " because it's not exposed");
+ class_list.pop_front();
+ continue;
+ }
+
+ ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(type_cname);
+
TypeInterface itype = TypeInterface::create_object_type(type_cname, api_type);
itype.base_name = ClassDB::get_parent_class(type_cname);
itype.is_singleton = Engine::get_singleton()->has_singleton(itype.proxy_name);
itype.is_instantiable = ClassDB::can_instance(type_cname) && !itype.is_singleton;
- itype.is_reference = ClassDB::is_parent_class(type_cname, refclass_name);
+ itype.is_reference = ClassDB::is_parent_class(type_cname, name_cache.type_Reference);
itype.memory_own = itype.is_reference;
- if (!ClassDB::is_class_exposed(type_cname)) {
- if (verbose_output)
- WARN_PRINTS("Ignoring type " + String(type_cname) + " because it's not exposed");
- class_list.pop_front();
- continue;
- }
-
itype.c_out = "\treturn ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
@@ -1530,6 +1717,8 @@ void BindingsGenerator::_populate_object_type_interfaces() {
itype.im_type_in = "IntPtr";
itype.im_type_out = itype.proxy_name;
+ // Populate methods
+
List<MethodInfo> virtual_method_list;
ClassDB::get_virtual_methods(type_cname, &virtual_method_list, true);
@@ -1547,6 +1736,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
MethodInterface imethod;
imethod.name = method_info.name;
+ imethod.cname = imethod.name;
if (method_info.flags & METHOD_FLAG_VIRTUAL)
imethod.is_virtual = true;
@@ -1570,12 +1760,12 @@ void BindingsGenerator::_populate_object_type_interfaces() {
// The method Object.free is registered as a virtual method, but without the virtual flag.
// This is because this method is not supposed to be overridden, but called.
// We assume the return type is void.
- imethod.return_type = "void";
+ imethod.return_type = name_cache.type_void;
// Actually, more methods like this may be added in the future,
// which could actually will return something differnet.
// Let's put this to notify us if that ever happens.
- if (itype.name != "Object" || imethod.name != "free") {
+ if (itype.cname != name_cache.type_Object || imethod.name != "free") {
if (verbose_output) {
WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
"We only expected Object.free, but found " +
@@ -1585,22 +1775,21 @@ void BindingsGenerator::_populate_object_type_interfaces() {
} else {
ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name);
}
- } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
- //imethod.return_type = return_info.class_name;
- imethod.return_type = "int";
+ } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { // TODO redundant?
+ imethod.return_type = return_info.class_name;
} else if (return_info.class_name != StringName()) {
imethod.return_type = return_info.class_name;
} else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
imethod.return_type = return_info.hint_string;
} else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
- imethod.return_type = "Variant";
+ imethod.return_type = name_cache.type_Variant;
} else if (return_info.type == Variant::NIL) {
- imethod.return_type = "void";
+ imethod.return_type = name_cache.type_void;
} else {
imethod.return_type = Variant::get_type_name(return_info.type);
}
- if (!itype.requires_collections && imethod.return_type == "Dictionary")
+ if (!itype.requires_collections && imethod.return_type == name_cache.type_Dictionary)
itype.requires_collections = true;
for (int i = 0; i < argc; i++) {
@@ -1609,22 +1798,21 @@ void BindingsGenerator::_populate_object_type_interfaces() {
ArgumentInterface iarg;
iarg.name = arginfo.name;
- if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
- //iarg.type = arginfo.class_name;
- iarg.type = "int";
+ if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { // TODO redundant?
+ iarg.type = arginfo.class_name;
} else if (arginfo.class_name != StringName()) {
iarg.type = arginfo.class_name;
} else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
iarg.type = arginfo.hint_string;
} else if (arginfo.type == Variant::NIL) {
- iarg.type = "Variant";
+ iarg.type = name_cache.type_Variant;
} else {
iarg.type = Variant::get_type_name(arginfo.type);
}
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
- if (!itype.requires_collections && iarg.type == "Dictionary")
+ if (!itype.requires_collections && iarg.type == name_cache.type_Dictionary)
itype.requires_collections = true;
if (m && m->has_default_argument(i)) {
@@ -1636,7 +1824,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
if (imethod.is_vararg) {
ArgumentInterface ivararg;
- ivararg.type = "VarArg";
+ ivararg.type = name_cache.type_VarArg;
ivararg.name = "@args";
imethod.add_argument(ivararg);
}
@@ -1679,7 +1867,128 @@ void BindingsGenerator::_populate_object_type_interfaces() {
}
}
- obj_types.insert(itype.name, itype);
+ // Populate properties
+
+ List<PropertyInfo> property_list;
+ ClassDB::get_property_list(type_cname, &property_list, true);
+ for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ const PropertyInfo &property = E->get();
+
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_CATEGORY)
+ continue;
+
+ PropertyInterface iprop;
+ iprop.cname = property.name;
+ iprop.proxy_name = escape_csharp_keyword(snake_to_pascal_case(iprop.cname));
+ iprop.setter = ClassDB::get_property_setter(type_cname, iprop.cname);
+ iprop.getter = ClassDB::get_property_getter(type_cname, iprop.cname);
+
+ bool valid = false;
+ iprop.index = ClassDB::get_property_index(type_cname, iprop.cname, &valid);
+ ERR_FAIL_COND(!valid);
+
+ // Prevent property and enclosing type from sharing the same name
+ if (iprop.proxy_name == itype.proxy_name) {
+ if (verbose_output) {
+ WARN_PRINTS("Name of property `" + iprop.proxy_name + "` is ambiguous with the name of its class `" +
+ itype.proxy_name + "`. Renaming property to `" + iprop.proxy_name + "_`");
+ }
+
+ iprop.proxy_name += "_";
+ }
+
+ iprop.prop_doc = NULL;
+
+ for (int i = 0; i < itype.class_doc->properties.size(); i++) {
+ const DocData::PropertyDoc &prop_doc = itype.class_doc->properties[i];
+
+ if (prop_doc.name == iprop.cname) {
+ iprop.prop_doc = &prop_doc;
+ break;
+ }
+ }
+
+ itype.properties.push_back(iprop);
+ }
+
+ // Populate enums and constants
+
+ List<String> constant_list;
+ ClassDB::get_integer_constant_list(type_cname, &constant_list, true);
+
+ const HashMap<StringName, List<StringName> > &enum_map = class_info->enum_map;
+ const StringName *k = NULL;
+
+ while ((k = enum_map.next(k))) {
+ StringName enum_proxy_cname = *k;
+ String enum_proxy_name = enum_proxy_cname.operator String();
+ if (itype.find_property_by_proxy_name(enum_proxy_cname)) {
+ // We have several conflicts between enums and PascalCase properties,
+ // so we append 'Enum' to the enum name in those cases.
+ enum_proxy_name += "Enum";
+ enum_proxy_cname = StringName(enum_proxy_name);
+ }
+ EnumInterface ienum(enum_proxy_cname);
+ const List<StringName> &constants = enum_map.get(*k);
+ for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+ int *value = class_info->constant_map.getptr(E->get());
+ ERR_FAIL_NULL(value);
+ constant_list.erase(E->get().operator String());
+
+ ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
+
+ iconstant.const_doc = NULL;
+ for (int i = 0; i < itype.class_doc->constants.size(); i++) {
+ const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i];
+
+ if (const_doc.name == iconstant.name) {
+ iconstant.const_doc = &const_doc;
+ break;
+ }
+ }
+
+ ienum.constants.push_back(iconstant);
+ }
+
+ ienum.prefix = _determine_enum_prefix(ienum);
+
+ itype.enums.push_back(ienum);
+
+ TypeInterface enum_itype;
+ enum_itype.name = itype.name + "." + String(*k);
+ enum_itype.cname = StringName(enum_itype.name);
+ enum_itype.proxy_name = itype.proxy_name + "." + enum_proxy_name;
+ enum_itype.c_arg_in = "&%s";
+ enum_itype.c_type = "int";
+ enum_itype.c_type_in = "int";
+ enum_itype.c_type_out = "int";
+ enum_itype.cs_type = enum_itype.proxy_name;
+ enum_itype.im_type_in = enum_itype.proxy_name;
+ enum_itype.im_type_out = enum_itype.proxy_name;
+ enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[enum_itype.proxy_name];
+ enum_types.insert(enum_itype.cname, enum_itype);
+ }
+
+ for (const List<String>::Element *E = constant_list.front(); E; E = E->next()) {
+ int *value = class_info->constant_map.getptr(E->get());
+ ERR_FAIL_NULL(value);
+
+ ConstantInterface iconstant(snake_to_pascal_case(E->get(), true), *value);
+
+ iconstant.const_doc = NULL;
+ for (int i = 0; i < itype.class_doc->constants.size(); i++) {
+ const DocData::ConstantDoc &const_doc = itype.class_doc->constants[i];
+
+ if (const_doc.name == iconstant.name) {
+ iconstant.const_doc = &const_doc;
+ break;
+ }
+ }
+
+ itype.constants.push_back(iconstant);
+ }
+
+ obj_types.insert(itype.cname, itype);
class_list.pop_front();
}
@@ -1704,7 +2013,10 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
r_iarg.default_argument = bool(p_val) ? "true" : "false";
break;
case Variant::INT:
- break; // Keep it
+ if (r_iarg.type != name_cache.type_int) {
+ r_iarg.default_argument = "(%s)" + r_iarg.default_argument;
+ }
+ break;
case Variant::REAL:
#ifndef REAL_T_IS_DOUBLE
r_iarg.default_argument += "f";
@@ -1762,7 +2074,7 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
default: {}
}
- if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type == "Variant" && r_iarg.default_argument != "null")
+ if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type == name_cache.type_Variant && r_iarg.default_argument != "null")
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
}
@@ -1774,7 +2086,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
#define INSERT_STRUCT_TYPE(m_type, m_type_in) \
{ \
- itype = TypeInterface::create_value_type(#m_type); \
+ itype = TypeInterface::create_value_type(String(#m_type)); \
itype.c_in = "\tMARSHALLED_IN(" #m_type ", %1, %1_in);\n"; \
itype.c_out = "\tMARSHALLED_OUT(" #m_type ", %1, ret_out)\n" \
"\treturn mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(%2), ret_out);\n"; \
@@ -1783,7 +2095,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_in = "ref %s"; \
itype.cs_out = "return (" #m_type ")%0;"; \
itype.im_type_out = "object"; \
- builtin_types.insert(#m_type, itype); \
+ builtin_types.insert(itype.cname, itype); \
}
INSERT_STRUCT_TYPE(Vector2, "real_t*")
@@ -1799,22 +2111,22 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
#undef INSERT_STRUCT_TYPE
-#define INSERT_PRIMITIVE_TYPE(m_type) \
- { \
- itype = TypeInterface::create_value_type(#m_type); \
- itype.c_arg_in = "&%s"; \
- itype.c_type_in = #m_type; \
- itype.c_type_out = #m_type; \
- itype.im_type_in = #m_type; \
- itype.im_type_out = #m_type; \
- builtin_types.insert(#m_type, itype); \
+#define INSERT_PRIMITIVE_TYPE(m_type) \
+ { \
+ itype = TypeInterface::create_value_type(String(#m_type)); \
+ itype.c_arg_in = "&%s"; \
+ itype.c_type_in = #m_type; \
+ itype.c_type_out = #m_type; \
+ itype.im_type_in = #m_type; \
+ itype.im_type_out = #m_type; \
+ builtin_types.insert(itype.cname, itype); \
}
INSERT_PRIMITIVE_TYPE(bool)
//INSERT_PRIMITIVE_TYPE(int)
// int
- itype = TypeInterface::create_value_type("int");
+ itype = TypeInterface::create_value_type(String("int"));
itype.c_arg_in = "&%s_in";
//* ptrcall only supports int64_t and uint64_t
itype.c_in = "\t%0 %1_in = (%0)%1;\n";
@@ -1825,7 +2137,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_out = itype.name;
itype.im_type_in = itype.name;
itype.im_type_out = itype.name;
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
#undef INSERT_PRIMITIVE_TYPE
@@ -1836,6 +2148,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
#else
itype.name = "float";
#endif
+ itype.cname = itype.name;
itype.proxy_name = itype.name;
itype.c_arg_in = "&%s_in";
//* ptrcall only supports double
@@ -1848,11 +2161,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_type = itype.proxy_name;
itype.im_type_in = itype.proxy_name;
itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
// String
itype = TypeInterface();
itype.name = "String";
+ itype.cname = itype.name;
itype.proxy_name = "string";
itype.c_in = "\t%0 %1_in = " C_METHOD_MONOSTR_TO_GODOT "(%1);\n";
itype.c_out = "\treturn " C_METHOD_MONOSTR_FROM_GODOT "(%1);\n";
@@ -1863,11 +2177,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_type = itype.proxy_name;
itype.im_type_in = itype.proxy_name;
itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
// NodePath
itype = TypeInterface();
itype.name = "NodePath";
+ itype.cname = itype.name;
itype.proxy_name = "NodePath";
itype.c_out = "\treturn memnew(NodePath(%1));\n";
itype.c_type = itype.name;
@@ -1879,16 +2194,17 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
_populate_builtin_type(itype, Variant::NODE_PATH);
- extra_members.insert(itype.name, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2
- "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2
- MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2
- MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2
- "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2);
- builtin_types.insert(itype.name, itype);
+ extra_members.insert(itype.cname, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2
+ "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2
+ MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2
+ MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2
+ "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2);
+ builtin_types.insert(itype.cname, itype);
// RID
itype = TypeInterface();
itype.name = "RID";
+ itype.cname = itype.name;
itype.proxy_name = "RID";
itype.c_out = "\treturn memnew(RID(%1));\n";
itype.c_type = itype.name;
@@ -1900,13 +2216,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
_populate_builtin_type(itype, Variant::_RID);
- extra_members.insert(itype.name, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2
- "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2);
- builtin_types.insert(itype.name, itype);
+ extra_members.insert(itype.cname, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2
+ "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+ builtin_types.insert(itype.cname, itype);
// Variant
itype = TypeInterface();
itype.name = "Variant";
+ itype.cname = itype.name;
itype.proxy_name = "object";
itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n";
itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_VARIANT "(%1);\n";
@@ -1917,11 +2234,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_type = itype.proxy_name;
itype.im_type_in = "object";
itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
// VarArg (fictitious type to represent variable arguments)
itype = TypeInterface();
itype.name = "VarArg";
+ itype.cname = itype.name;
itype.proxy_name = "object[]";
itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(Array) "(%1);\n";
itype.c_arg_in = "&%s_in";
@@ -1929,12 +2247,13 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.c_type_in = "MonoArray*";
itype.cs_type = "params object[]";
itype.im_type_in = "object[]";
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
#define INSERT_ARRAY_FULL(m_name, m_type, m_proxy_t) \
{ \
itype = TypeInterface(); \
itype.name = #m_name; \
+ itype.cname = itype.name; \
itype.proxy_name = #m_proxy_t "[]"; \
itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \
itype.c_out = "\treturn " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \
@@ -1971,6 +2290,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
// Dictionary
itype = TypeInterface();
itype.name = "Dictionary";
+ itype.cname = itype.name;
itype.proxy_name = "Dictionary<object, object>";
itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_DICT "(%1);\n";
itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_DICT "(%1);\n";
@@ -1981,11 +2301,12 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_type = itype.proxy_name;
itype.im_type_in = itype.proxy_name;
itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
// void (fictitious type to represent the return type of methods that do not return anything)
itype = TypeInterface();
itype.name = "void";
+ itype.cname = itype.name;
itype.proxy_name = itype.name;
itype.c_type = itype.name;
itype.c_type_in = itype.c_type;
@@ -1993,21 +2314,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_type = itype.proxy_name;
itype.im_type_in = itype.proxy_name;
itype.im_type_out = itype.proxy_name;
- builtin_types.insert(itype.name, itype);
-
- // Error
- itype = TypeInterface();
- itype.name = "Error";
- itype.proxy_name = "Error";
- itype.c_type = itype.name;
- itype.c_type_in = itype.c_type;
- itype.c_type_out = itype.c_type;
- itype.cs_type = itype.proxy_name;
- itype.cs_in = "(int)%0";
- itype.cs_out = "return (Error)%s;";
- itype.im_type_in = "int";
- itype.im_type_out = "int";
- builtin_types.insert(itype.name, itype);
+ builtin_types.insert(itype.cname, itype);
}
void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) {
@@ -2024,6 +2331,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
MethodInterface imethod;
imethod.name = mi.name;
+ imethod.cname = imethod.name;
imethod.proxy_name = mi.name;
for (int i = 0; i < mi.arguments.size(); i++) {
@@ -2033,11 +2341,11 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
iarg.name = pi.name;
if (pi.type == Variant::NIL)
- iarg.type = "Variant";
+ iarg.type = name_cache.type_Variant;
else
iarg.type = Variant::get_type_name(pi.type);
- if (!r_itype.requires_collections && iarg.type == "Dictionary")
+ if (!r_itype.requires_collections && iarg.type == name_cache.type_Dictionary)
r_itype.requires_collections = true;
if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0)
@@ -2048,12 +2356,12 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
if (mi.return_val.type == Variant::NIL) {
if (mi.return_val.name != "")
- imethod.return_type = "Variant";
+ imethod.return_type = name_cache.type_Variant;
} else {
imethod.return_type = Variant::get_type_name(mi.return_val.type);
}
- if (!r_itype.requires_collections && imethod.return_type == "Dictionary")
+ if (!r_itype.requires_collections && imethod.return_type == name_cache.type_Dictionary)
r_itype.requires_collections = true;
if (r_itype.class_doc) {
@@ -2069,15 +2377,113 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
}
}
-BindingsGenerator::BindingsGenerator() {
+void BindingsGenerator::_populate_global_constants() {
+
+ int global_constants_count = GlobalConstants::get_global_constant_count();
+
+ if (global_constants_count > 0) {
+ Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@GlobalScope");
+
+ ERR_EXPLAIN("Could not find `@GlobalScope` in DocData");
+ CRASH_COND(!match);
+
+ const DocData::ClassDoc &global_scope_doc = match->value();
+
+ for (int i = 0; i < global_constants_count; i++) {
+
+ String constant_name = GlobalConstants::get_global_constant_name(i);
+
+ const DocData::ConstantDoc *const_doc = NULL;
+ for (int i = 0; i < global_scope_doc.constants.size(); i++) {
+ const DocData::ConstantDoc &curr_const_doc = global_scope_doc.constants[i];
+
+ if (curr_const_doc.name == constant_name) {
+ const_doc = &curr_const_doc;
+ break;
+ }
+ }
+
+ int constant_value = GlobalConstants::get_global_constant_value(i);
+ StringName enum_name = GlobalConstants::get_global_constant_enum(i);
+
+ ConstantInterface iconstant(snake_to_pascal_case(constant_name, true), constant_value);
+ iconstant.const_doc = const_doc;
+
+ if (enum_name != StringName()) {
+ EnumInterface ienum(enum_name);
+ List<EnumInterface>::Element *match = global_enums.find(ienum);
+ if (match) {
+ match->get().constants.push_back(iconstant);
+ } else {
+ ienum.constants.push_back(iconstant);
+ global_enums.push_back(ienum);
+ }
+ } else {
+ global_constants.push_back(iconstant);
+ }
+ }
+
+ for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
+ EnumInterface &ienum = E->get();
+
+ TypeInterface enum_itype;
+ enum_itype = TypeInterface::create_value_type(ienum.cname);
+ enum_itype.c_arg_in = "&%s";
+ enum_itype.c_type = "int";
+ enum_itype.c_type_in = "int";
+ enum_itype.c_type_out = "int";
+ enum_itype.im_type_in = enum_itype.name;
+ enum_itype.im_type_out = enum_itype.name;
+ enum_types.insert(enum_itype.cname, enum_itype);
+
+ ienum.prefix = _determine_enum_prefix(ienum);
+
+ // HARDCODED
+ if (ienum.cname == name_cache.enum_Error) {
+ if (!ienum.prefix.empty()) { // Just in case it ever changes
+ ERR_PRINTS("Prefix for enum 'Error' is not empty");
+ }
+
+ ienum.prefix = "Err";
+ }
+ }
+ }
+
+ // HARDCODED
+ List<StringName> hardcoded_enums;
+ hardcoded_enums.push_back("Vector3.Axis");
+ for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) {
+ // These enums are not generated and must be written manually (e.g.: Vector3.Axis)
+ // Here, we are assuming core types do not begin with underscore
+ TypeInterface enum_itype;
+ enum_itype = TypeInterface::create_value_type(E->get());
+ enum_itype.c_arg_in = "&%s";
+ enum_itype.c_type = "int";
+ enum_itype.c_type_in = "int";
+ enum_itype.c_type_out = "int";
+ enum_itype.im_type_in = enum_itype.name;
+ enum_itype.im_type_out = enum_itype.name;
+ enum_types.insert(enum_itype.cname, enum_itype);
+ }
+}
+
+BindingsGenerator::BindingsGenerator() :
+ name_cache(NameCache::get_singleton()) {
EditorHelp::generate_doc();
+ enum_types.clear();
+
_populate_object_type_interfaces();
_populate_builtin_type_interfaces();
+
+ _populate_global_constants();
+
+ // Populate internal calls (after populating type interfaces and global constants)
+
_generate_header_icalls();
- for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next())
+ for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next())
_generate_method_icalls(E->get());
_generate_method_icalls(builtin_types["NodePath"]);
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index dfa3aa9911..eac00690ff 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -39,6 +39,47 @@
#include "ustring.h"
class BindingsGenerator {
+
+ struct ConstantInterface {
+ String name;
+ int value;
+ const DocData::ConstantDoc *const_doc;
+
+ ConstantInterface() {}
+
+ ConstantInterface(const String &p_name, int p_value) {
+ name = p_name;
+ value = p_value;
+ }
+ };
+
+ struct EnumInterface {
+ StringName cname;
+ String prefix;
+ List<ConstantInterface> constants;
+
+ _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const {
+ return p_ienum.cname == cname;
+ }
+
+ EnumInterface() {}
+
+ EnumInterface(const StringName &p_cname) {
+ cname = p_cname;
+ }
+ };
+
+ struct PropertyInterface {
+ StringName cname;
+ String proxy_name;
+ int index;
+
+ StringName setter;
+ StringName getter;
+
+ const DocData::PropertyDoc *prop_doc;
+ };
+
struct ArgumentInterface {
enum DefaultParamMode {
CONSTANT,
@@ -46,7 +87,7 @@ class BindingsGenerator {
NULLABLE_REF
};
- String type;
+ StringName type;
String name;
String default_argument;
DefaultParamMode def_param_mode;
@@ -58,6 +99,7 @@ class BindingsGenerator {
struct MethodInterface {
String name;
+ StringName cname;
/**
* Name of the C# method
@@ -67,7 +109,7 @@ class BindingsGenerator {
/**
* [TypeInterface::name] of the return type
*/
- String return_type;
+ StringName return_type;
/**
* Determines if the method has a variable number of arguments (VarArg)
@@ -103,7 +145,7 @@ class BindingsGenerator {
}
MethodInterface() {
- return_type = "void";
+ return_type = NameCache::get_singleton().type_void;
is_vararg = false;
is_virtual = false;
requires_object_call = false;
@@ -118,11 +160,12 @@ class BindingsGenerator {
* Also used to format [c_out].
*/
String name;
+ StringName cname;
/**
* Identifier name of the base class.
*/
- String base_name;
+ StringName base_name;
/**
* Name of the C# class
@@ -256,23 +299,32 @@ class BindingsGenerator {
const DocData::ClassDoc *class_doc;
+ List<ConstantInterface> constants;
+ List<EnumInterface> enums;
+ List<PropertyInterface> properties;
List<MethodInterface> methods;
- const MethodInterface *find_method_by_name(const String &p_name) const {
-
+ const MethodInterface *find_method_by_name(const StringName &p_cname) const {
for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name == p_name)
+ if (E->get().cname == p_cname)
return &E->get();
}
return NULL;
}
- static TypeInterface create_value_type(const String &p_name) {
- TypeInterface itype;
+ const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
+ for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
+ if (E->get().proxy_name == p_proxy_name)
+ return &E->get();
+ }
- itype.name = p_name;
- itype.proxy_name = p_name;
+ return NULL;
+ }
+
+ private:
+ static void _init_value_type(TypeInterface &itype) {
+ itype.proxy_name = itype.name;
itype.c_type = itype.name;
itype.c_type_in = "void*";
@@ -281,15 +333,31 @@ class BindingsGenerator {
itype.im_type_in = "ref " + itype.proxy_name;
itype.im_type_out = itype.proxy_name;
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
+ }
+ public:
+ static TypeInterface create_value_type(const String &p_name) {
+ TypeInterface itype;
+ itype.name = p_name;
+ itype.cname = StringName(p_name);
+ _init_value_type(itype);
+ return itype;
+ }
+
+ static TypeInterface create_value_type(const StringName &p_name) {
+ TypeInterface itype;
+ itype.name = p_name.operator String();
+ itype.cname = p_name;
+ _init_value_type(itype);
return itype;
}
- static TypeInterface create_object_type(const String &p_name, ClassDB::APIType p_api_type) {
+ static TypeInterface create_object_type(const StringName &p_cname, ClassDB::APIType p_api_type) {
TypeInterface itype;
- itype.name = p_name;
- itype.proxy_name = p_name.begins_with("_") ? p_name.substr(1, p_name.length()) : p_name;
+ itype.name = p_cname;
+ itype.cname = p_cname;
+ itype.proxy_name = itype.name.begins_with("_") ? itype.name.substr(1, itype.name.length()) : itype.name;
itype.api_type = p_api_type;
itype.is_object_type = true;
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
@@ -297,9 +365,10 @@ class BindingsGenerator {
return itype;
}
- static void create_placeholder_type(TypeInterface &r_itype, const String &p_name) {
- r_itype.name = p_name;
- r_itype.proxy_name = p_name;
+ static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
+ r_itype.name = p_cname;
+ r_itype.cname = p_cname;
+ r_itype.proxy_name = r_itype.name;
r_itype.c_type = r_itype.name;
r_itype.c_type_in = "MonoObject*";
@@ -359,11 +428,15 @@ class BindingsGenerator {
static bool verbose_output;
- Map<String, TypeInterface> placeholder_types;
- Map<String, TypeInterface> builtin_types;
- Map<String, TypeInterface> obj_types;
+ Map<StringName, TypeInterface> placeholder_types;
+ Map<StringName, TypeInterface> builtin_types;
+ Map<StringName, TypeInterface> enum_types;
+ Map<StringName, TypeInterface> obj_types;
- Map<String, String> extra_members;
+ List<EnumInterface> global_enums;
+ List<ConstantInterface> global_constants;
+
+ Map<StringName, String> extra_members;
List<InternalCall> method_icalls;
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
@@ -373,8 +446,41 @@ class BindingsGenerator {
List<InternalCall> core_custom_icalls;
List<InternalCall> editor_custom_icalls;
- const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
+ struct NameCache {
+ StringName type_void;
+ StringName type_int;
+ StringName type_Array;
+ StringName type_Dictionary;
+ StringName type_Variant;
+ StringName type_VarArg;
+ StringName type_Object;
+ StringName type_Reference;
+ StringName enum_Error;
+
+ NameCache() {
+ type_void = StaticCString::create("void");
+ type_int = StaticCString::create("int");
+ type_Array = StaticCString::create("Array");
+ type_Dictionary = StaticCString::create("Dictionary");
+ type_Variant = StaticCString::create("Variant");
+ type_VarArg = StaticCString::create("VarArg");
+ type_Object = StaticCString::create("Object");
+ type_Reference = StaticCString::create("Reference");
+ enum_Error = StaticCString::create("Error");
+ }
+
+ static NameCache &get_singleton() {
+ static NameCache singleton;
+ return singleton;
+ }
+
+ NameCache(const NameCache &);
+ NameCache &operator=(const NameCache &);
+ };
+
+ const NameCache &name_cache;
+ const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
const List<InternalCall>::Element *it = p_list.front();
while (it) {
if (it->get().name == p_name) return it;
@@ -392,11 +498,13 @@ class BindingsGenerator {
return p_type.name;
}
+ String _determine_enum_prefix(const EnumInterface &p_ienum);
+
void _generate_header_icalls();
void _generate_method_icalls(const TypeInterface &p_itype);
- const TypeInterface *_get_type_by_name_or_null(const String &p_name);
- const TypeInterface *_get_type_by_name_or_placeholder(const String &p_name);
+ const TypeInterface *_get_type_by_name_or_null(const StringName &p_cname);
+ const TypeInterface *_get_type_by_name_or_placeholder(const StringName &p_cname);
void _default_argument_from_variant(const Variant &p_var, ArgumentInterface &r_iarg);
void _populate_builtin_type(TypeInterface &r_type, Variant::Type vtype);
@@ -404,11 +512,15 @@ class BindingsGenerator {
void _populate_object_type_interfaces();
void _populate_builtin_type_interfaces();
+ void _populate_global_constants();
+
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
- Error _generate_cs_property(const TypeInterface &p_itype, const DocData::PropertyDoc &p_prop_doc, List<String> &p_output);
+ Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_prop_doc, List<String> &p_output);
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
+ void _generate_global_constants(List<String> &p_output);
+
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
Error _save_file(const String &path, const List<String> &content);
diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp
index 9a1efb4423..d5819a4ca3 100644
--- a/modules/mono/editor/csharp_project.cpp
+++ b/modules/mono/editor/csharp_project.cpp
@@ -54,7 +54,7 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi
ERR_FAIL_V(String());
}
- return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
}
String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) {
@@ -75,7 +75,7 @@ String generate_editor_api_project(const String &p_dir, const String &p_core_dll
ERR_FAIL_V(String());
}
- return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
}
String generate_game_project(const String &p_dir, const String &p_name, const Vector<String> &p_files) {
@@ -96,7 +96,7 @@ String generate_game_project(const String &p_dir, const String &p_name, const Ve
ERR_FAIL_V(String());
}
- return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
}
void add_item(const String &p_project_path, const String &p_item_type, const String &p_include) {
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index b88d34fc33..3750a2b02a 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -313,7 +313,7 @@ GodotSharpBuilds *GodotSharpBuilds::singleton = NULL;
void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) {
BuildProcess *match = builds.getptr(p_build_info);
- ERR_FAIL_COND(!match);
+ ERR_FAIL_NULL(match);
BuildProcess &bp = *match;
bp.on_exit(p_exit_code);
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 1bc1e8a515..1e61646769 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -50,9 +50,9 @@ GodotSharpEditor *GodotSharpEditor::singleton = NULL;
bool GodotSharpEditor::_create_project_solution() {
- EditorProgress pr("create_csharp_solution", "Generating solution...", 2);
+ EditorProgress pr("create_csharp_solution", TTR("Generating solution..."), 2);
- pr.step("Generating C# project...");
+ pr.step(TTR("Generating C# project..."));
String path = OS::get_singleton()->get_resource_dir();
String name = ProjectSettings::get_singleton()->get("application/config/name");
@@ -67,7 +67,7 @@ bool GodotSharpEditor::_create_project_solution() {
NETSolution solution(name);
if (!solution.set_path(path)) {
- show_error_dialog("Failed to create solution.");
+ show_error_dialog(TTR("Failed to create solution."));
return false;
}
@@ -79,7 +79,7 @@ bool GodotSharpEditor::_create_project_solution() {
Error sln_error = solution.save();
if (sln_error != OK) {
- show_error_dialog("Failed to save solution.");
+ show_error_dialog(TTR("Failed to save solution."));
return false;
}
@@ -89,13 +89,13 @@ bool GodotSharpEditor::_create_project_solution() {
if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR))
return false;
- pr.step("Done");
+ pr.step(TTR("Done"));
// Here, after all calls to progress_task_step
call_deferred("_remove_create_sln_menu_option");
} else {
- show_error_dialog("Failed to create C# project.");
+ show_error_dialog(TTR("Failed to create C# project."));
}
return true;
@@ -194,14 +194,14 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
error_dialog = memnew(AcceptDialog);
editor->get_gui_base()->add_child(error_dialog);
- bottom_panel_btn = editor->add_bottom_panel_item("Mono", memnew(MonoBottomPanel(editor)));
+ bottom_panel_btn = editor->add_bottom_panel_item(TTR("Mono"), memnew(MonoBottomPanel(editor)));
godotsharp_builds = memnew(GodotSharpBuilds);
editor->add_child(memnew(MonoReloadNode));
menu_button = memnew(MenuButton);
- menu_button->set_text("Mono");
+ menu_button->set_text(TTR("Mono"));
menu_popup = menu_button->get_popup();
String sln_path = GodotSharpDirs::get_project_sln_path();
@@ -209,7 +209,7 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
bottom_panel_btn->hide();
- menu_popup->add_item("Create C# solution", MENU_CREATE_SLN);
+ menu_popup->add_item(TTR("Create C# solution"), MENU_CREATE_SLN);
}
menu_popup->connect("id_pressed", this, "_menu_option_pressed");
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
index 31dc09856a..be714026ad 100644
--- a/modules/mono/editor/mono_bottom_panel.cpp
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -197,7 +197,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
panel_builds_tab->add_child(toolbar_hbc);
ToolButton *build_project_btn = memnew(ToolButton);
- build_project_btn->set_text("Build Project");
+ build_project_btn->set_text(TTR("Build Project"));
build_project_btn->set_focus_mode(FOCUS_NONE);
build_project_btn->connect("pressed", this, "_build_project_pressed");
toolbar_hbc->add_child(build_project_btn);
@@ -205,7 +205,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
toolbar_hbc->add_spacer();
warnings_btn = memnew(ToolButton);
- warnings_btn->set_text("Warnings");
+ warnings_btn->set_text(TTR("Warnings"));
warnings_btn->set_toggle_mode(true);
warnings_btn->set_pressed(true);
warnings_btn->set_visible(false);
@@ -214,7 +214,7 @@ MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
toolbar_hbc->add_child(warnings_btn);
errors_btn = memnew(ToolButton);
- errors_btn->set_text("Errors");
+ errors_btn->set_text(TTR("Errors"));
errors_btn->set_toggle_mode(true);
errors_btn->set_pressed(true);
errors_btn->set_visible(false);
diff --git a/modules/mono/glue/cs_files/Error.cs b/modules/mono/glue/cs_files/Error.cs
deleted file mode 100644
index dee4b88f74..0000000000
--- a/modules/mono/glue/cs_files/Error.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-namespace Godot
-{
- public enum Error : int
- {
- OK = 0,
- FAILED = 1,
- ERR_UNAVAILABLE = 2,
- ERR_UNCONFIGURED = 3,
- ERR_UNAUTHORIZED = 4,
- ERR_PARAMETER_RANGE_ERROR = 5,
- ERR_OUT_OF_MEMORY = 6,
- ERR_FILE_NOT_FOUND = 7,
- ERR_FILE_BAD_DRIVE = 8,
- ERR_FILE_BAD_PATH = 9,
- ERR_FILE_NO_PERMISSION = 10,
- ERR_FILE_ALREADY_IN_USE = 11,
- ERR_FILE_CANT_OPEN = 12,
- ERR_FILE_CANT_WRITE = 13,
- ERR_FILE_CANT_READ = 14,
- ERR_FILE_UNRECOGNIZED = 15,
- ERR_FILE_CORRUPT = 16,
- ERR_FILE_MISSING_DEPENDENCIES = 17,
- ERR_FILE_EOF = 18,
- ERR_CANT_OPEN = 19,
- ERR_CANT_CREATE = 20,
- ERR_PARSE_ERROR = 43,
- ERROR_QUERY_FAILED = 21,
- ERR_ALREADY_IN_USE = 22,
- ERR_LOCKED = 23,
- ERR_TIMEOUT = 24,
- ERR_CANT_AQUIRE_RESOURCE = 28,
- ERR_INVALID_DATA = 30,
- ERR_INVALID_PARAMETER = 31,
- ERR_ALREADY_EXISTS = 32,
- ERR_DOES_NOT_EXIST = 33,
- ERR_DATABASE_CANT_READ = 34,
- ERR_DATABASE_CANT_WRITE = 35,
- ERR_COMPILATION_FAILED = 36,
- ERR_METHOD_NOT_FOUND = 37,
- ERR_LINK_FAILED = 38,
- ERR_SCRIPT_FAILED = 39,
- ERR_CYCLIC_LINK = 40,
- ERR_BUSY = 44,
- ERR_HELP = 46,
- ERR_BUG = 47
- }
-}
diff --git a/modules/mono/glue/cs_files/ExportAttribute.cs b/modules/mono/glue/cs_files/ExportAttribute.cs
index dce9cc59a0..e6f569e1bb 100644
--- a/modules/mono/glue/cs_files/ExportAttribute.cs
+++ b/modules/mono/glue/cs_files/ExportAttribute.cs
@@ -5,13 +5,13 @@ namespace Godot
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ExportAttribute : Attribute
{
- private int hint;
- private string hint_string;
+ private PropertyHint hint;
+ private string hintString;
- public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "")
+ public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "")
{
this.hint = hint;
- this.hint_string = hint_string;
+ this.hintString = hintString;
}
}
}
diff --git a/modules/mono/glue/cs_files/GD.cs b/modules/mono/glue/cs_files/GD.cs
index 99fc289161..b335ef55e4 100644
--- a/modules/mono/glue/cs_files/GD.cs
+++ b/modules/mono/glue/cs_files/GD.cs
@@ -2,10 +2,8 @@ using System;
namespace Godot
{
- public static class GD
+ public static partial class GD
{
- /*{GodotGlobalConstants}*/
-
public static object Bytes2Var(byte[] bytes)
{
return NativeCalls.godot_icall_Godot_bytes2var(bytes);
diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/cs_files/Rect2.cs
index f2718d7b7a..e1fbb65da5 100644
--- a/modules/mono/glue/cs_files/Rect2.cs
+++ b/modules/mono/glue/cs_files/Rect2.cs
@@ -109,14 +109,14 @@ namespace Godot
return g;
}
- public Rect2 GrowMargin(int margin, float by)
+ public Rect2 GrowMargin(Margin margin, float by)
{
Rect2 g = this;
- g.GrowIndividual((GD.MARGIN_LEFT == margin) ? by : 0,
- (GD.MARGIN_TOP == margin) ? by : 0,
- (GD.MARGIN_RIGHT == margin) ? by : 0,
- (GD.MARGIN_BOTTOM == margin) ? by : 0);
+ g.GrowIndividual((Margin.Left == margin) ? by : 0,
+ (Margin.Top == margin) ? by : 0,
+ (Margin.Right == margin) ? by : 0,
+ (Margin.Bottom == margin) ? by : 0);
return g;
}
@@ -230,4 +230,4 @@ namespace Godot
});
}
}
-} \ No newline at end of file
+}
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index eb34f9dd3f..63b24f3ee6 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -290,7 +290,7 @@ int GDMonoField::get_int_value(MonoObject *p_object) {
String GDMonoField::get_string_value(MonoObject *p_object) {
MonoObject *val = get_value(p_object);
- return val ? GDMonoMarshal::mono_string_to_godot((MonoString *)val) : String();
+ return GDMonoMarshal::mono_string_to_godot((MonoString *)val);
}
bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 8bc2bb5096..d744d24f24 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -490,8 +490,9 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
return unbox<double>(p_obj);
case MONO_TYPE_STRING: {
- String str = mono_string_to_godot((MonoString *)p_obj);
- return str;
+ if (p_obj == NULL)
+ return Variant(); // NIL
+ return mono_string_to_godot_not_null((MonoString *)p_obj);
} break;
case MONO_TYPE_VALUETYPE: {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 443e947fb5..1be4be1a1c 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -62,13 +62,20 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type);
String mono_to_utf8_string(MonoString *p_mono_string);
String mono_to_utf16_string(MonoString *p_mono_string);
-_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) {
+_FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) {
if (sizeof(CharType) == 2)
return mono_to_utf16_string(p_mono_string);
return mono_to_utf8_string(p_mono_string);
}
+_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) {
+ if (p_mono_string == NULL)
+ return String();
+
+ return mono_string_to_godot_not_null(p_mono_string);
+}
+
_FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) {
return mono_string_new(mono_domain_get(), p_string.utf8().get_data());
}
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 1cccd0ad9d..638636e985 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -95,7 +95,7 @@ void MonoCache::clear_members() {
class_ExportAttribute = NULL;
field_ExportAttribute_hint = NULL;
- field_ExportAttribute_hint_string = NULL;
+ field_ExportAttribute_hintString = NULL;
class_ToolAttribute = NULL;
class_RemoteAttribute = NULL;
class_SyncAttribute = NULL;
@@ -163,7 +163,7 @@ void update_godot_api_cache() {
// Attributes
CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
- CACHE_FIELD_AND_CHECK(ExportAttribute, hint_string, CACHED_CLASS(ExportAttribute)->get_field("hint_string"));
+ CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString"));
CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index c38f8c5af5..4308b357ba 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -97,7 +97,7 @@ struct MonoCache {
GDMonoClass *class_ExportAttribute;
GDMonoField *field_ExportAttribute_hint;
- GDMonoField *field_ExportAttribute_hint_string;
+ GDMonoField *field_ExportAttribute_hintString;
GDMonoClass *class_ToolAttribute;
GDMonoClass *class_RemoteAttribute;
GDMonoClass *class_SyncAttribute;
diff --git a/modules/opus/register_types.cpp b/modules/opus/register_types.cpp
index a69c8bf9f3..6d7a3575ed 100644
--- a/modules/opus/register_types.cpp
+++ b/modules/opus/register_types.cpp
@@ -34,13 +34,18 @@
static ResourceFormatLoaderAudioStreamOpus *opus_stream_loader = NULL;
void register_opus_types() {
-
- opus_stream_loader = memnew(ResourceFormatLoaderAudioStreamOpus);
- ResourceLoader::add_resource_format_loader(opus_stream_loader);
- ClassDB::register_class<AudioStreamOpus>();
+ // Sorry guys, do not enable this unless you can figure out a way
+ // to get Opus to not do any memory allocation or system calls
+ // in the audio thread.
+ // Currently the implementation even reads files from the audio thread,
+ // and this is not how audio programming works.
+
+ //opus_stream_loader = memnew(ResourceFormatLoaderAudioStreamOpus);
+ //ResourceLoader::add_resource_format_loader(opus_stream_loader);
+ //ClassDB::register_class<AudioStreamOpus>();
}
void unregister_opus_types() {
- memdelete(opus_stream_loader);
+ //memdelete(opus_stream_loader);
}
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 5b04ab8826..2e686fbee4 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -82,9 +82,6 @@ def configure(env):
env['RANLIB'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ranlib"
env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
- if env['tools'] and env['openmp']:
- env.Append(CPPFLAGS=['-fopenmp'])
- env.Append(LINKFLAGS=['-fopenmp'])
else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index e216868bd8..3b8de2caf4 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -191,8 +191,6 @@ def configure(env):
if (env["use_lto"]):
env.Append(CCFLAGS=['/GL'])
env.Append(LINKFLAGS=['/LTCG'])
- if env['tools'] and env['openmp']:
- env.Append(CPPFLAGS=['/openmp'])
env.Append(CCFLAGS=["/I" + p for p in os.getenv("INCLUDE").split(";")])
env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
@@ -270,9 +268,6 @@ def configure(env):
env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
- if env['tools'] and env['openmp']:
- env.Append(CPPFLAGS=['-fopenmp'])
- env.Append(LINKFLAGS=['-fopenmp'])
## Compile flags
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 98ae9a8658..cb45fed1be 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -265,9 +265,5 @@ def configure(env):
env.Append(LINKFLAGS=['-m64', '-L/usr/lib/i686-linux-gnu'])
- if env['tools'] and env['openmp']:
- env.Append(CPPFLAGS=['-fopenmp'])
- env.Append(LINKFLAGS=['-fopenmp'])
-
if env['use_static_cpp']:
env.Append(LINKFLAGS=['-static-libstdc++'])
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 6616e47317..f3f4b1f217 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -1050,6 +1050,10 @@ void OS_X11::set_window_maximized(bool p_enabled) {
XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+ while (p_enabled && !is_window_maximized()) {
+ // Wait for effective resizing (so the GLX context is too).
+ }
+
maximized = p_enabled;
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 7b30ddaa56..a83c1c1cad 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1527,7 +1527,7 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("_recreate_quadrants"), &TileMap::_recreate_quadrants);
ClassDB::bind_method(D_METHOD("_update_dirty_quadrants"), &TileMap::_update_dirty_quadrants);
- ClassDB::bind_method(D_METHOD("update_bitmask_area"), &TileMap::update_bitmask_area);
+ ClassDB::bind_method(D_METHOD("update_bitmask_area", "position"), &TileMap::update_bitmask_area);
ClassDB::bind_method(D_METHOD("update_bitmask_region", "start", "end"), &TileMap::update_bitmask_region, DEFVAL(Vector2()), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("_set_tile_data"), &TileMap::_set_tile_data);
diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp
index 9a77626296..8c282a31b8 100644
--- a/scene/3d/baked_lightmap.cpp
+++ b/scene/3d/baked_lightmap.cpp
@@ -772,8 +772,8 @@ void BakedLightmap::_bind_methods() {
BakedLightmap::BakedLightmap() {
extents = Vector3(10, 10, 10);
- bake_cell_size = 0.1;
- capture_cell_size = 0.25;
+ bake_cell_size = 0.25;
+ capture_cell_size = 0.5;
bake_quality = BAKE_QUALITY_MEDIUM;
bake_mode = BAKE_MODE_CONE_TRACE;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index c74abb7e2d..7143310036 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -70,6 +70,9 @@ void Camera::_validate_property(PropertyInfo &p_property) const {
void Camera::_update_camera() {
+ if (!is_inside_tree())
+ return;
+
Transform tr = get_camera_transform();
tr.origin += tr.basis.get_axis(1) * v_offset;
tr.origin += tr.basis.get_axis(0) * h_offset;
@@ -81,7 +84,7 @@ void Camera::_update_camera() {
get_viewport()->_camera_transform_changed_notify();
*/
- if (!is_inside_tree() || get_tree()->is_node_being_edited(this) || !is_current())
+ if (get_tree()->is_node_being_edited(this) || !is_current())
return;
get_viewport()->_camera_transform_changed_notify();
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index d9f88ac693..e890533ab7 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -558,27 +558,27 @@ bool Spatial::is_visible() const {
void Spatial::rotate(const Vector3 &p_normal, float p_radians) {
Transform t = get_transform();
- t.basis.rotate(p_normal, p_radians);
+ t.basis.rotate_local(p_normal, p_radians); //use local rotation here, as it makes more sense here in tree hierarchy
set_transform(t);
}
void Spatial::rotate_x(float p_radians) {
Transform t = get_transform();
- t.basis.rotate(Vector3(1, 0, 0), p_radians);
+ t.basis.rotate_local(Vector3(1, 0, 0), p_radians);
set_transform(t);
}
void Spatial::rotate_y(float p_radians) {
Transform t = get_transform();
- t.basis.rotate(Vector3(0, 1, 0), p_radians);
+ t.basis.rotate_local(Vector3(0, 1, 0), p_radians);
set_transform(t);
}
void Spatial::rotate_z(float p_radians) {
Transform t = get_transform();
- t.basis.rotate(Vector3(0, 0, 1), p_radians);
+ t.basis.rotate_local(Vector3(0, 0, 1), p_radians);
set_transform(t);
}
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
index bf0f801e32..bd7e52d947 100644
--- a/scene/3d/voxel_light_baker.cpp
+++ b/scene/3d/voxel_light_baker.cpp
@@ -30,11 +30,9 @@
#include "voxel_light_baker.h"
#include "os/os.h"
+#include "os/threaded_array_processor.h"
#include <stdlib.h>
-#ifdef _OPENMP
-#include <omp.h>
-#endif
#define FINDMINMAX(x0, x1, x2, min, max) \
min = max = x0; \
@@ -1689,7 +1687,7 @@ _ALWAYS_INLINE_ uint32_t xorshift32(uint32_t *state) {
return x;
}
-Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state) {
+Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal) {
int samples_per_quality[3] = { 48, 128, 512 };
@@ -1711,8 +1709,7 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
const Light *light = bake_light.ptr();
const Cell *cells = bake_cells.ptr();
- // Prevent false sharing when running on OpenMP
- uint32_t local_rng_state = *rng_state;
+ uint32_t local_rng_state = rand(); //needs to be fixed again
for (int i = 0; i < samples; i++) {
@@ -1796,10 +1793,28 @@ Vector3 VoxelLightBaker::_compute_ray_trace_at_pos(const Vector3 &p_pos, const V
}
// Make sure we don't reset this thread's RNG state
- *rng_state = local_rng_state;
+
return accum / samples;
}
+void VoxelLightBaker::_lightmap_bake_point(uint32_t p_x, LightMap *p_line) {
+
+ LightMap *pixel = &p_line[p_x];
+ if (pixel->pos == Vector3())
+ return;
+ //print_line("pos: " + pixel->pos + " normal " + pixel->normal);
+ switch (bake_mode) {
+ case BAKE_MODE_CONE_TRACE: {
+ pixel->light = _compute_pixel_light_at_pos(pixel->pos, pixel->normal) * energy;
+ } break;
+ case BAKE_MODE_RAY_TRACE: {
+ pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal) * energy;
+ } break;
+ // pixel->light = Vector3(1, 1, 1);
+ //}
+ }
+}
+
Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh, LightMapData &r_lightmap, bool (*p_bake_time_func)(void *, float, float), void *p_bake_time_ud) {
//transfer light information to a lightmap
@@ -1862,53 +1877,10 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
volatile int lines = 0;
// make sure our OS-level rng is seeded
- srand(OS::get_singleton()->get_ticks_usec());
-
- // setup an RNG state for each OpenMP thread
- uint32_t threadcount = 1;
- uint32_t threadnum = 0;
-#ifdef _OPENMP
- threadcount = omp_get_max_threads();
-#endif
- Vector<uint32_t> rng_states;
- rng_states.resize(threadcount);
- for (uint32_t i = 0; i < threadcount; i++) {
- do {
- rng_states[i] = rand();
- } while (rng_states[i] == 0);
- }
- uint32_t *rng_states_p = rng_states.ptrw();
for (int i = 0; i < height; i++) {
- //print_line("bake line " + itos(i) + " / " + itos(height));
-#ifdef _OPENMP
-#pragma omp parallel for schedule(dynamic, 1) private(threadnum)
-#endif
- for (int j = 0; j < width; j++) {
-
-#ifdef _OPENMP
- threadnum = omp_get_thread_num();
-#endif
-
- //if (i == 125 && j == 280) {
-
- LightMap *pixel = &lightmap_ptr[i * width + j];
- if (pixel->pos == Vector3())
- continue; //unused, skipe
-
- //print_line("pos: " + pixel->pos + " normal " + pixel->normal);
- switch (bake_mode) {
- case BAKE_MODE_CONE_TRACE: {
- pixel->light = _compute_pixel_light_at_pos(pixel->pos, pixel->normal) * energy;
- } break;
- case BAKE_MODE_RAY_TRACE: {
- pixel->light = _compute_ray_trace_at_pos(pixel->pos, pixel->normal, &rng_states_p[threadnum]) * energy;
- } break;
- // pixel->light = Vector3(1, 1, 1);
- //}
- }
- }
+ thread_process_array(width, this, &VoxelLightBaker::_lightmap_bake_point, &lightmap_ptr[i * width]);
lines = MAX(lines, i); //for multithread
if (p_bake_time_func) {
diff --git a/scene/3d/voxel_light_baker.h b/scene/3d/voxel_light_baker.h
index 7db31f8a67..68e11c356b 100644
--- a/scene/3d/voxel_light_baker.h
+++ b/scene/3d/voxel_light_baker.h
@@ -148,9 +148,12 @@ private:
_FORCE_INLINE_ void _sample_baked_octree_filtered_and_anisotropic(const Vector3 &p_posf, const Vector3 &p_direction, float p_level, Vector3 &r_color, float &r_alpha);
_FORCE_INLINE_ Vector3 _voxel_cone_trace(const Vector3 &p_pos, const Vector3 &p_normal, float p_aperture);
_FORCE_INLINE_ Vector3 _compute_pixel_light_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
- _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal, uint32_t *rng_state);
+ _FORCE_INLINE_ Vector3 _compute_ray_trace_at_pos(const Vector3 &p_pos, const Vector3 &p_normal);
+
+ void _lightmap_bake_point(uint32_t p_x, LightMap *p_line);
public:
+
void begin_bake(int p_subdiv, const AABB &p_bounds);
void plot_mesh(const Transform &p_xform, Ref<Mesh> &p_mesh, const Vector<Ref<Material> > &p_materials, const Ref<Material> &p_override_material);
void begin_bake_light(BakeQuality p_quality = BAKE_QUALITY_MEDIUM, BakeMode p_bake_mode = BAKE_MODE_CONE_TRACE, float p_propagation = 0.85, float p_energy = 1);
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 32f82fe6b8..a50047e426 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -386,8 +386,6 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const {
void AnimationTreePlayer::_get_property_list(List<PropertyInfo> *p_list) const {
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, "base_path"));
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, "master_player"));
p_list->push_back(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_NETWORK));
}
@@ -1140,6 +1138,9 @@ void AnimationTreePlayer::transition_node_set_input_count(const StringName &p_no
n->inputs.resize(p_inputs);
n->input_data.resize(p_inputs);
+
+ _clear_cycle_test();
+
last_error = _cycle_test(out_name);
}
void AnimationTreePlayer::transition_node_set_input_auto_advance(const StringName &p_node, int p_input, bool p_auto_advance) {
@@ -1360,6 +1361,8 @@ void AnimationTreePlayer::remove_node(const StringName &p_node) {
node_map.erase(p_node);
+ _clear_cycle_test();
+
// compute last error again, just in case
last_error = _cycle_test(out_name);
dirty_caches = true;
@@ -1387,6 +1390,14 @@ AnimationTreePlayer::ConnectError AnimationTreePlayer::_cycle_test(const StringN
return CONNECT_OK;
}
+// Use this function to not alter next complete _cycle_test().
+void AnimationTreePlayer::_clear_cycle_test() {
+ for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) {
+ NodeBase *nb = E->get();
+ nb->cycletest = false;
+ }
+}
+
Error AnimationTreePlayer::connect_nodes(const StringName &p_src_node, const StringName &p_dst_node, int p_dst_input) {
ERR_FAIL_COND_V(!node_map.has(p_src_node), ERR_INVALID_PARAMETER);
@@ -1411,11 +1422,7 @@ Error AnimationTreePlayer::connect_nodes(const StringName &p_src_node, const Str
dst->inputs[p_dst_input].node = p_src_node;
- for (Map<StringName, NodeBase *>::Element *E = node_map.front(); E; E = E->next()) {
-
- NodeBase *nb = E->get();
- nb->cycletest = false;
- }
+ _clear_cycle_test();
last_error = _cycle_test(out_name);
if (last_error) {
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index c49b0c4d1b..7213441d6e 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -317,6 +317,7 @@ private:
bool reset_request;
ConnectError _cycle_test(const StringName &p_at_node);
+ void _clear_cycle_test();
Track *_find_track(const NodePath &p_path);
void _recompute_caches();
diff --git a/scene/gui/button.h b/scene/gui/button.h
index 35488582de..5c5a73bae3 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -56,7 +56,6 @@ private:
float _internal_margin[4];
protected:
- virtual Size2 get_minimum_size() const;
void _set_internal_margin(Margin p_margin, float p_value);
void _notification(int p_what);
static void _bind_methods();
@@ -64,6 +63,8 @@ protected:
public:
//
+ virtual Size2 get_minimum_size() const;
+
void set_text(const String &p_text);
String get_text() const;
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index cb6283507e..446676e80d 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -39,33 +39,32 @@ void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- //sample->set_texture(get_icon("color_sample"));
+
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
bt_add_preset->set_icon(get_icon("add_preset"));
_update_controls();
} break;
-
case NOTIFICATION_ENTER_TREE: {
+
btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
bt_add_preset->set_icon(get_icon("add_preset"));
_update_color();
} break;
-
case NOTIFICATION_PARENTED: {
+
for (int i = 0; i < 4; i++)
set_margin((Margin)i, get_constant("margin"));
} break;
-
case NOTIFICATION_VISIBILITY_CHANGED: {
Popup *p = Object::cast_to<Popup>(get_parent());
if (p)
p->set_size(Size2(get_combined_minimum_size().width + get_constant("margin") * 2, get_combined_minimum_size().height + get_constant("margin") * 2));
} break;
-
case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: {
+
if (screen != NULL) {
if (screen->is_visible()) {
screen->hide();
@@ -523,7 +522,6 @@ ColorPicker::ColorPicker() :
add_child(hb_edit);
w_edit = memnew(Control);
- //w_edit->set_ignore_mouse(false);
w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0));
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -589,7 +587,6 @@ ColorPicker::ColorPicker() :
c_text->set_h_size_flags(SIZE_EXPAND_FILL);
_update_controls();
- //_update_color();
updating = false;
set_pick_color(Color(1, 1, 1));
@@ -599,7 +596,6 @@ ColorPicker::ColorPicker() :
preset = memnew(TextureRect);
bbc->add_child(preset);
- //preset->set_ignore_mouse(false);
preset->connect("gui_input", this, "_preset_input");
preset->connect("draw", this, "_update_presets");
@@ -660,11 +656,13 @@ bool ColorPickerButton::is_editing_alpha() const {
return picker->is_editing_alpha();
}
-ColorPicker *ColorPickerButton::get_picker() {
+ColorPicker *ColorPickerButton::get_picker() const {
+
return picker;
}
-PopupPanel *ColorPickerButton::get_popup() {
+PopupPanel *ColorPickerButton::get_popup() const {
+
return popup;
}
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index c02cdc8608..2bae279ed5 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -129,8 +129,8 @@ public:
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
- ColorPicker *get_picker();
- PopupPanel *get_popup();
+ ColorPicker *get_picker() const;
+ PopupPanel *get_popup() const;
ColorPickerButton();
};
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index d850553957..c235797bef 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -33,6 +33,9 @@
void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
+ if (disable_shortcuts)
+ return;
+
if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
if (!get_parent() || !is_visible_in_tree() || is_disabled())
@@ -60,25 +63,10 @@ void MenuButton::pressed() {
void MenuButton::_gui_input(Ref<InputEvent> p_event) {
- /*if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==BUTTON_LEFT) {
- clicked=p_event->is_pressed();
- }
- if (clicked && p_event.type==InputEvent::MOUSE_MOTION && popup->is_visible_in_tree()) {
-
- Point2 gt = Point2(p_event.mouse_motion.x,p_event.mouse_motion.y);
- gt = get_global_transform().xform(gt);
- Point2 lt = popup->get_transform().affine_inverse().xform(gt);
- if (popup->has_point(lt)) {
- //print_line("HAS POINT!!!");
- popup->call_deferred("grab_click_focus");
- }
-
- }*/
-
BaseButton::_gui_input(p_event);
}
-PopupMenu *MenuButton::get_popup() {
+PopupMenu *MenuButton::get_popup() const {
return popup;
}
@@ -98,14 +86,22 @@ void MenuButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items);
ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items);
+ ClassDB::bind_method(D_METHOD("set_disable_shortcuts", "disabled"), &MenuButton::set_disable_shortcuts);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items");
ADD_SIGNAL(MethodInfo("about_to_show"));
}
+
+void MenuButton::set_disable_shortcuts(bool p_disabled) {
+
+ disable_shortcuts = p_disabled;
+}
+
MenuButton::MenuButton() {
set_flat(true);
+ set_disable_shortcuts(false);
set_enabled_focus_mode(FOCUS_NONE);
popup = memnew(PopupMenu);
popup->hide();
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index c7f1d976ff..1bd9b155b2 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -40,6 +40,7 @@ class MenuButton : public Button {
GDCLASS(MenuButton, Button);
bool clicked;
+ bool disable_shortcuts;
PopupMenu *popup;
virtual void pressed();
@@ -53,7 +54,9 @@ protected:
static void _bind_methods();
public:
- PopupMenu *get_popup();
+ PopupMenu *get_popup() const;
+ void set_disable_shortcuts(bool p_disabled);
+
MenuButton();
~MenuButton();
};
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 70f3d9ca83..6f784b56de 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -42,38 +42,35 @@ Size2 OptionButton::get_minimum_size() const {
void OptionButton::_notification(int p_what) {
- switch (p_what) {
-
- case NOTIFICATION_DRAW: {
-
- if (!has_icon("arrow"))
- return;
-
- RID ci = get_canvas_item();
- Ref<Texture> arrow = Control::get_icon("arrow");
- Ref<StyleBox> normal = get_stylebox("normal");
- Color clr = Color(1, 1, 1);
- if (get_constant("modulate_arrow"))
- switch (get_draw_mode()) {
- case DRAW_PRESSED:
- clr = get_color("font_color_pressed");
- break;
- case DRAW_HOVER:
- clr = get_color("font_color_hover");
- break;
- case DRAW_DISABLED:
- clr = get_color("font_color_disabled");
- break;
- default:
- clr = get_color("font_color");
- }
-
- Size2 size = get_size();
-
- Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
- arrow->draw(ci, ofs, clr);
-
- } break;
+ if (p_what == NOTIFICATION_DRAW) {
+
+ if (!has_icon("arrow"))
+ return;
+
+ RID ci = get_canvas_item();
+ Ref<Texture> arrow = Control::get_icon("arrow");
+ Ref<StyleBox> normal = get_stylebox("normal");
+ Color clr = Color(1, 1, 1);
+ if (get_constant("modulate_arrow")) {
+ switch (get_draw_mode()) {
+ case DRAW_PRESSED:
+ clr = get_color("font_color_pressed");
+ break;
+ case DRAW_HOVER:
+ clr = get_color("font_color_hover");
+ break;
+ case DRAW_DISABLED:
+ clr = get_color("font_color_disabled");
+ break;
+ default:
+ clr = get_color("font_color");
+ }
+ }
+
+ Size2 size = get_size();
+
+ Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ arrow->draw(ci, ofs, clr);
}
}
@@ -244,6 +241,11 @@ void OptionButton::remove_item(int p_idx) {
popup->remove_item(p_idx);
}
+PopupMenu *OptionButton::get_popup() const {
+
+ return popup;
+}
+
Array OptionButton::_get_items() const {
Array items;
@@ -310,6 +312,8 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_item", "idx"), &OptionButton::remove_item);
ClassDB::bind_method(D_METHOD("_select_int"), &OptionButton::_select_int);
+ ClassDB::bind_method(D_METHOD("get_popup"), &OptionButton::get_popup);
+
ClassDB::bind_method(D_METHOD("_set_items"), &OptionButton::_set_items);
ClassDB::bind_method(D_METHOD("_get_items"), &OptionButton::_get_items);
@@ -320,15 +324,16 @@ void OptionButton::_bind_methods() {
OptionButton::OptionButton() {
+ current = -1;
+ set_text_align(ALIGN_LEFT);
+ set_action_mode(ACTION_MODE_BUTTON_PRESS);
+
popup = memnew(PopupMenu);
popup->hide();
+ add_child(popup);
popup->set_as_toplevel(true);
popup->set_pass_on_modal_close_click(false);
- add_child(popup);
popup->connect("id_pressed", this, "_selected");
-
- current = -1;
- set_text_align(ALIGN_LEFT);
}
OptionButton::~OptionButton() {
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index a06c540678..b09942b072 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -85,6 +85,8 @@ public:
void remove_item(int p_idx);
+ PopupMenu *get_popup() const;
+
virtual void get_translatable_strings(List<String> *p_strings) const;
OptionButton();
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 4420a936d2..1c15953517 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -61,7 +61,7 @@ Control *SplitContainer::_getch(int p_idx) const {
void SplitContainer::_resort() {
- /** First pass, determine minimum size AND amount of stretchable elements */
+ /* First pass, determine minimum size AND amount of stretchable elements */
int axis = vertical ? 1 : 0;
@@ -114,10 +114,8 @@ void SplitContainer::_resort() {
Size2 ms_second = second->get_combined_minimum_size();
if (vertical) {
-
minimum = ms_first.height + ms_second.height;
} else {
-
minimum = ms_first.width + ms_second.width;
}
@@ -141,12 +139,10 @@ void SplitContainer::_resort() {
} else if (expand_first_mode) {
middle_sep = get_size()[axis] - ms_second[axis] - sep;
-
} else {
middle_sep = ms_first[axis];
}
-
} else if (ratiomode) {
int first_ratio = first->get_stretch_ratio();
@@ -160,23 +156,19 @@ void SplitContainer::_resort() {
expand_ofs = (available * (1.0 - ratio));
middle_sep = ms_first[axis] + available * ratio + expand_ofs;
-
} else if (expand_first_mode) {
if (expand_ofs > 0)
expand_ofs = 0;
-
- if (expand_ofs < -available)
+ else if (expand_ofs < -available)
expand_ofs = -available;
middle_sep = get_size()[axis] - ms_second[axis] - sep + expand_ofs;
-
} else {
if (expand_ofs < 0)
expand_ofs = 0;
-
- if (expand_ofs > available)
+ else if (expand_ofs > available)
expand_ofs = available;
middle_sep = ms_first[axis] + expand_ofs;
@@ -187,7 +179,6 @@ void SplitContainer::_resort() {
fit_child_in_rect(first, Rect2(Point2(0, 0), Size2(get_size().width, middle_sep)));
int sofs = middle_sep + sep;
fit_child_in_rect(second, Rect2(Point2(0, sofs), Size2(get_size().width, get_size().height - sofs)));
-
} else {
fit_child_in_rect(first, Rect2(Point2(0, 0), Size2(middle_sep, get_size().height)));
@@ -246,10 +237,12 @@ void SplitContainer::_notification(int p_what) {
_resort();
} break;
case NOTIFICATION_MOUSE_ENTER: {
+
mouse_inside = true;
update();
} break;
case NOTIFICATION_MOUSE_EXIT: {
+
mouse_inside = false;
update();
} break;
@@ -260,22 +253,17 @@ void SplitContainer::_notification(int p_what) {
if (collapsed || (!mouse_inside && get_constant("autohide")))
return;
+
int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_constant("separation") : 0;
Ref<Texture> tex = get_icon("grabber");
Size2 size = get_size();
- if (vertical) {
+ if (dragger_visibility == DRAGGER_VISIBLE) {
- //draw_style_box( get_stylebox("bg"), Rect2(0,middle_sep,get_size().width,sep));
- if (dragger_visibility == DRAGGER_VISIBLE)
+ if (vertical)
draw_texture(tex, Point2i((size.x - tex->get_width()) / 2, middle_sep + (sep - tex->get_height()) / 2));
-
- } else {
-
- //draw_style_box( get_stylebox("bg"), Rect2(middle_sep,0,sep,get_size().height));
- if (dragger_visibility == DRAGGER_VISIBLE)
+ else
draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2));
}
-
} break;
}
}
@@ -292,11 +280,13 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_LEFT) {
if (mb->is_pressed()) {
+
int sep = get_constant("separation");
if (vertical) {
if (mb->get_position().y > middle_sep && mb->get_position().y < middle_sep + sep) {
+
dragging = true;
drag_from = mb->get_position().y;
drag_ofs = expand_ofs;
@@ -304,6 +294,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
} else {
if (mb->get_position().x > middle_sep && mb->get_position().x < middle_sep + sep) {
+
dragging = true;
drag_from = mb->get_position().x;
drag_ofs = expand_ofs;
@@ -318,36 +309,31 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid()) {
-
- if (dragging) {
+ if (mm.is_valid() && dragging) {
- expand_ofs = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from);
- queue_sort();
- emit_signal("dragged", get_split_offset());
- }
+ expand_ofs = drag_ofs + ((vertical ? mm->get_position().y : mm->get_position().x) - drag_from);
+ queue_sort();
+ emit_signal("dragged", get_split_offset());
}
}
Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const {
- if (collapsed)
- return Control::get_cursor_shape(p_pos);
-
if (dragging)
return (vertical ? CURSOR_VSIZE : CURSOR_HSIZE);
- int sep = get_constant("separation");
+ if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
- if (vertical) {
+ int sep = get_constant("separation");
- if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep) {
- return CURSOR_VSIZE;
- }
- } else {
+ if (vertical) {
- if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep) {
- return CURSOR_HSIZE;
+ if (p_pos.y > middle_sep && p_pos.y < middle_sep + sep)
+ return CURSOR_VSIZE;
+ } else {
+
+ if (p_pos.x > middle_sep && p_pos.x < middle_sep + sep)
+ return CURSOR_HSIZE;
}
}
@@ -358,6 +344,7 @@ void SplitContainer::set_split_offset(int p_offset) {
if (expand_ofs == p_offset)
return;
+
expand_ofs = p_offset;
queue_sort();
}
@@ -371,6 +358,7 @@ void SplitContainer::set_collapsed(bool p_collapsed) {
if (collapsed == p_collapsed)
return;
+
collapsed = p_collapsed;
queue_sort();
}
diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h
index c7a484c4c5..40a58d4b32 100644
--- a/scene/gui/split_container.h
+++ b/scene/gui/split_container.h
@@ -88,7 +88,7 @@ class HSplitContainer : public SplitContainer {
public:
HSplitContainer() :
- SplitContainer(false) { set_default_cursor_shape(CURSOR_HSPLIT); }
+ SplitContainer(false) {}
};
class VSplitContainer : public SplitContainer {
@@ -97,7 +97,7 @@ class VSplitContainer : public SplitContainer {
public:
VSplitContainer() :
- SplitContainer(true) { set_default_cursor_shape(CURSOR_VSPLIT); }
+ SplitContainer(true) {}
};
#endif // SPLIT_CONTAINER_H
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 07f1bdf8e5..0fba4a6f94 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1695,10 +1695,9 @@ void TextEdit::indent_right() {
// fix selection and cursor being off by one on the last line
if (is_selection_active()) {
- selection.to_column++;
- selection.from_column++;
+ select(selection.from_line, selection.from_column + 1, selection.to_line, selection.to_column + 1);
}
- cursor.column++;
+ cursor_set_column(cursor.column + 1, false);
end_complex_operation();
update();
}
@@ -1737,14 +1736,9 @@ void TextEdit::indent_left() {
// fix selection and cursor being off by one on the last line
if (is_selection_active() && last_line_text != get_line(end_line)) {
- if (selection.to_column > 0)
- selection.to_column--;
- if (selection.from_column > 0)
- selection.from_column--;
- }
- if (cursor.column > 0) {
- cursor.column--;
+ select(selection.from_line, selection.from_column - 1, selection.to_line, selection.to_column - 1);
}
+ cursor_set_column(cursor.column - 1, false);
end_complex_operation();
update();
}
@@ -1973,6 +1967,31 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
+ _reset_caret_blink_timer();
+
+ int row, col;
+ update_line_scroll_pos();
+ _get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col);
+
+ if (is_right_click_moving_caret()) {
+ if (is_selection_active()) {
+
+ int from_line = get_selection_from_line();
+ int to_line = get_selection_to_line();
+ int from_column = get_selection_from_column();
+ int to_column = get_selection_to_column();
+
+ if (row < from_line || row > to_line || (row == from_line && col < from_column) || (row == to_line && col > to_column)) {
+ // Right click is outside the seleted text
+ deselect();
+ }
+ }
+ if (!is_selection_active()) {
+ cursor_set_line(row, true, false);
+ cursor_set_column(col);
+ }
+ }
+
menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
@@ -3708,6 +3727,14 @@ bool TextEdit::cursor_is_block_mode() const {
return block_caret;
}
+void TextEdit::set_right_click_moves_caret(bool p_enable) {
+ right_click_moves_caret = p_enable;
+}
+
+bool TextEdit::is_right_click_moving_caret() const {
+ return right_click_moves_caret;
+}
+
void TextEdit::_v_scroll_input() {
scrolling = false;
}
@@ -4168,11 +4195,15 @@ void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_t
p_from_line = text.size() - 1;
if (p_from_column >= text[p_from_line].length())
p_from_column = text[p_from_line].length();
+ if (p_from_column < 0)
+ p_from_column = 0;
if (p_to_line >= text.size())
p_to_line = text.size() - 1;
if (p_to_column >= text[p_to_line].length())
p_to_column = text[p_to_line].length();
+ if (p_to_column < 0)
+ p_to_column = 0;
selection.from_line = p_from_line;
selection.from_column = p_from_column;
@@ -5457,6 +5488,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode);
ClassDB::bind_method(D_METHOD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode);
+ ClassDB::bind_method(D_METHOD("set_right_click_moves_caret", "enable"), &TextEdit::set_right_click_moves_caret);
+ ClassDB::bind_method(D_METHOD("is_right_click_moving_caret"), &TextEdit::is_right_click_moving_caret);
+
ClassDB::bind_method(D_METHOD("set_readonly", "enable"), &TextEdit::set_readonly);
ClassDB::bind_method(D_METHOD("is_readonly"), &TextEdit::is_readonly);
@@ -5492,7 +5526,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hiding_enabled", "enable"), &TextEdit::set_hiding_enabled);
ClassDB::bind_method(D_METHOD("is_hiding_enabled"), &TextEdit::is_hiding_enabled);
ClassDB::bind_method(D_METHOD("set_line_as_hidden", "line", "enable"), &TextEdit::set_line_as_hidden);
- ClassDB::bind_method(D_METHOD("is_line_hidden"), &TextEdit::is_line_hidden);
+ ClassDB::bind_method(D_METHOD("is_line_hidden", "line"), &TextEdit::is_line_hidden);
ClassDB::bind_method(D_METHOD("fold_all_lines"), &TextEdit::fold_all_lines);
ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines);
ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line);
@@ -5540,6 +5574,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), "cursor_set_block_mode", "cursor_is_block_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), "cursor_set_blink_enabled", "cursor_get_blink_enabled");
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed", PROPERTY_HINT_RANGE, "0.1,10,0.1"), "cursor_set_blink_speed", "cursor_get_blink_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_moving_by_right_click"), "set_right_click_moves_caret", "is_right_click_moving_caret");
ADD_SIGNAL(MethodInfo("cursor_changed"));
ADD_SIGNAL(MethodInfo("text_changed"));
@@ -5617,6 +5652,7 @@ TextEdit::TextEdit() {
caret_blink_timer->set_wait_time(0.65);
caret_blink_timer->connect("timeout", this, "_toggle_draw_caret");
cursor_set_blink_enabled(false);
+ right_click_moves_caret = true;
idle_detect = memnew(Timer);
add_child(idle_detect);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 836d5c7388..f18eaa85cb 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -246,6 +246,7 @@ class TextEdit : public Control {
bool draw_caret;
bool window_has_focus;
bool block_caret;
+ bool right_click_moves_caret;
bool setting_row;
bool wrap;
@@ -481,6 +482,9 @@ public:
void cursor_set_block_mode(const bool p_enable);
bool cursor_is_block_mode() const;
+ void set_right_click_moves_caret(bool p_enable);
+ bool is_right_click_moving_caret() const;
+
void set_readonly(bool p_readonly);
bool is_readonly() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index b5b42e8f29..51ad22e271 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1775,7 +1775,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
case TreeItem::CELL_MODE_STRING: {
//nothing in particular
- if (select_mode == SELECT_MULTI && (get_tree()->get_last_event_id() == focus_in_id || !already_cursor)) {
+ if (select_mode == SELECT_MULTI && (get_tree()->get_event_count() == focus_in_id || !already_cursor)) {
bring_up_editor = false;
}
@@ -1863,7 +1863,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
} else {
editor_text = String::num(p_item->cells[col].val, Math::step_decimals(p_item->cells[col].step));
- if (select_mode == SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id)
+ if (select_mode == SELECT_MULTI && get_tree()->get_event_count() == focus_in_id)
bring_up_editor = false;
}
}
@@ -2786,7 +2786,7 @@ void Tree::_notification(int p_what) {
if (p_what == NOTIFICATION_FOCUS_ENTER) {
- focus_in_id = get_tree()->get_last_event_id();
+ focus_in_id = get_tree()->get_event_count();
}
if (p_what == NOTIFICATION_MOUSE_EXIT) {
@@ -2950,43 +2950,51 @@ Size2 Tree::get_minimum_size() const {
return Size2(1, 1);
}
-TreeItem *Tree::create_item(TreeItem *p_parent) {
+TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
ERR_FAIL_COND_V(blocked > 0, NULL);
- TreeItem *ti = memnew(TreeItem(this));
-
- ERR_FAIL_COND_V(!ti, NULL);
- ti->cells.resize(columns.size());
+ TreeItem *ti = NULL;
if (p_parent) {
- /* Always append at the end */
+ // Append or insert a new item to the given parent.
+ ti = memnew(TreeItem(this));
+ ERR_FAIL_COND_V(!ti, NULL);
+ ti->cells.resize(columns.size());
- TreeItem *last = 0;
+ TreeItem *prev = NULL;
TreeItem *c = p_parent->childs;
+ int idx = 0;
while (c) {
-
- last = c;
+ if (idx++ == p_idx) {
+ ti->next = c;
+ break;
+ }
+ prev = c;
c = c->next;
}
- if (last) {
-
- last->next = ti;
- } else {
-
+ if (prev)
+ prev->next = ti;
+ else
p_parent->childs = ti;
- }
ti->parent = p_parent;
} else {
- if (root)
- ti->childs = root;
+ if (!root) {
+ // No root exists, make the given item the new root.
+ ti = memnew(TreeItem(this));
+ ERR_FAIL_COND_V(!ti, NULL);
+ ti->cells.resize(columns.size());
- root = ti;
+ root = ti;
+ } else {
+ // Root exists, append or insert to root.
+ ti = create_item(root, p_idx);
+ }
}
return ti;
@@ -3723,7 +3731,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("_scroll_moved"), &Tree::_scroll_moved);
ClassDB::bind_method(D_METHOD("clear"), &Tree::clear);
- ClassDB::bind_method(D_METHOD("create_item", "parent"), &Tree::_create_item, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::_create_item, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
ClassDB::bind_method(D_METHOD("set_column_min_width", "column", "min_width"), &Tree::set_column_min_width);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 112de3165f..b8d94bcffb 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -359,7 +359,7 @@ private:
LineEdit *text_editor;
HSlider *value_editor;
bool updating_value_editor;
- uint32_t focus_in_id;
+ int64_t focus_in_id;
PopupMenu *popup_menu;
Vector<ColumnInfo> columns;
@@ -511,8 +511,8 @@ protected:
static void _bind_methods();
//bind helpers
- Object *_create_item(Object *p_parent) {
- return create_item(Object::cast_to<TreeItem>(p_parent));
+ Object *_create_item(Object *p_parent, int p_idx = -1) {
+ return create_item(Object::cast_to<TreeItem>(p_parent), p_idx);
}
TreeItem *_get_next_selected(Object *p_item) {
@@ -532,7 +532,7 @@ public:
void clear();
- TreeItem *create_item(TreeItem *p_parent = 0);
+ TreeItem *create_item(TreeItem *p_parent = 0, int p_idx = -1);
TreeItem *get_root();
TreeItem *get_last_item();
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index de1ab9959a..942a6d5428 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -340,7 +340,8 @@ void Node::move_child(Node *p_child, int p_pos) {
data.children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
}
for (const Map<StringName, GroupData>::Element *E = p_child->data.grouped.front(); E; E = E->next()) {
- E->get().group->changed = true;
+ if (E->get().group)
+ E->get().group->changed = true;
}
data.blocked--;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 7c31b72bb5..db39b37bd5 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -391,13 +391,12 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) {
if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_event)))
return; //avoid joy input on editor
+ current_event++;
root_lock++;
- //last_id=p_event.ID;
input_handled = false;
Ref<InputEvent> ev = p_event;
- ev->set_id(++last_id); //this should work better
MainLoop::input_event(ev);
@@ -941,11 +940,6 @@ void SceneMainLoop::_update_listener_2d() {
}
*/
-uint32_t SceneTree::get_last_event_id() const {
-
- return last_id;
-}
-
Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
r_error.error = Variant::CallError::CALL_OK;
@@ -994,6 +988,10 @@ int64_t SceneTree::get_frame() const {
return current_frame;
}
+int64_t SceneTree::get_event_count() const {
+
+ return current_event;
+}
Array SceneTree::_get_nodes_in_group(const StringName &p_group) {
@@ -2287,9 +2285,10 @@ SceneTree::SceneTree() {
tree_version = 1;
physics_process_time = 1;
idle_process_time = 1;
- last_id = 1;
+
root = NULL;
current_frame = 0;
+ current_event = 0;
tree_changed_name = "tree_changed";
node_added_name = "node_added";
node_removed_name = "node_removed";
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 9c5b0f69cb..3e2e74b553 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -109,7 +109,6 @@ private:
float idle_process_time;
bool accept_quit;
bool quit_on_go_back;
- uint32_t last_id;
#ifdef DEBUG_ENABLED
bool debug_collisions_hint;
@@ -130,6 +129,7 @@ private:
bool use_font_oversampling;
int64_t current_frame;
+ int64_t current_event;
int node_count;
#ifdef TOOLS_ENABLED
@@ -325,7 +325,7 @@ public:
NOTIFICATION_TRANSFORM_CHANGED = 29
};
- enum CallGroupFlags {
+ enum GroupCallFlags {
GROUP_CALL_DEFAULT = 0,
GROUP_CALL_REVERSE = 1,
GROUP_CALL_REALTIME = 2,
@@ -335,8 +335,6 @@ public:
_FORCE_INLINE_ Viewport *get_root() const { return root; }
- uint32_t get_last_event_id() const;
-
void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification);
void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value);
@@ -412,6 +410,7 @@ public:
int get_collision_debug_contact_count() { return collision_debug_contacts; }
int64_t get_frame() const;
+ int64_t get_event_count() const;
int get_node_count() const;
@@ -467,6 +466,6 @@ public:
VARIANT_ENUM_CAST(SceneTree::StretchMode);
VARIANT_ENUM_CAST(SceneTree::StretchAspect);
-VARIANT_ENUM_CAST(SceneTree::CallGroupFlags);
+VARIANT_ENUM_CAST(SceneTree::GroupCallFlags);
#endif
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 8f431389d8..fa6a7832f5 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -184,7 +184,6 @@ Viewport::GUI::GUI() {
key_focus = NULL;
mouse_over = NULL;
- cancelled_input_ID = 0;
tooltip = NULL;
tooltip_popup = NULL;
tooltip_label = NULL;
@@ -1620,9 +1619,6 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che
void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
- if (p_event->get_id() == gui.cancelled_input_ID) {
- return;
- }
//?
/*
if (!is_visible()) {
@@ -1640,7 +1636,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (mb->is_pressed()) {
Size2 pos = mpos;
- if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button) {
+ if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button && mb->get_button_index() == BUTTON_LEFT) {
//do not steal mouse focus and stuff
@@ -1752,7 +1748,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
_gui_call_input(gui.mouse_focus, mb);
}
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", mb->get_id());
get_tree()->set_input_as_handled();
if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
@@ -1825,7 +1820,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data=Variant(); //always clear
}*/
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "windows", "_cancel_input_ID", mb->get_id());
get_tree()->set_input_as_handled();
}
}
@@ -2904,7 +2898,7 @@ Viewport::Viewport() {
gui.canvas_sort_index = 0;
msaa = MSAA_DISABLED;
- hdr = false;
+ hdr = true;
usage = USAGE_3D;
debug_draw = DEBUG_DRAW_DISABLED;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 0835e3f69a..c084e348b5 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -269,7 +269,6 @@ private:
float tooltip_timer;
float tooltip_delay;
List<Control *> modal_stack;
- unsigned int cancelled_input_ID;
Transform2D focus_inv_xform;
bool subwindow_order_dirty;
List<Control *> subwindows;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 39e6698725..0c8837ee1a 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -200,6 +200,9 @@ static ResourceFormatLoaderDynamicFont *resource_loader_dynamic_font = NULL;
static ResourceFormatLoaderStreamTexture *resource_loader_stream_texture = NULL;
+static ResourceFormatSaverShader *resource_saver_shader = NULL;
+static ResourceFormatLoaderShader *resource_loader_shader = NULL;
+
void register_scene_types() {
SceneStringNames::create();
@@ -607,6 +610,12 @@ void register_scene_types() {
resource_loader_text = memnew(ResourceFormatLoaderText);
ResourceLoader::add_resource_format_loader(resource_loader_text, true);
+ resource_saver_shader = memnew(ResourceFormatSaverShader);
+ ResourceSaver::add_resource_format_saver(resource_saver_shader, true);
+
+ resource_loader_shader = memnew(ResourceFormatLoaderShader);
+ ResourceLoader::add_resource_format_loader(resource_loader_shader, true);
+
for (int i = 0; i < 20; i++) {
GLOBAL_DEF("layer_names/2d_render/layer_" + itos(i + 1), "");
GLOBAL_DEF("layer_names/2d_physics/layer_" + itos(i + 1), "");
@@ -632,6 +641,13 @@ void unregister_scene_types() {
memdelete(resource_loader_text);
}
+ if (resource_saver_shader) {
+ memdelete(resource_saver_shader);
+ }
+ if (resource_loader_shader) {
+ memdelete(resource_loader_shader);
+ }
+
SpatialMaterial::finish_shaders();
ParticlesMaterial::finish_shaders();
CanvasItemMaterial::finish_shaders();
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 326320c60f..cc9fde58e2 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -753,7 +753,7 @@ void SpatialMaterial::_update_shader() {
if (features[FEATURE_REFRACTION] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //refraction not supported with triplanar
if (features[FEATURE_NORMAL_MAPPING]) {
- code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) ) * SIDE;\n";
+ code += "\tvec3 ref_normal = normalize( mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH) );\n";
} else {
code += "\tvec3 ref_normal = NORMAL;\n";
}
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index 66df7dfda8..207c50f673 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -151,3 +151,80 @@ Shader::~Shader() {
VisualServer::get_singleton()->free(shader);
}
+////////////
+
+RES ResourceFormatLoaderShader::load(const String &p_path, const String &p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error = ERR_FILE_CANT_OPEN;
+
+ Ref<Shader> shader;
+ shader.instance();
+
+ Vector<uint8_t> buffer = FileAccess::get_file_as_array(p_path);
+
+ String str;
+ str.parse_utf8((const char *)buffer.ptr(), buffer.size());
+
+ shader->set_code(str);
+
+ if (r_error)
+ *r_error = OK;
+
+ return shader;
+}
+
+void ResourceFormatLoaderShader::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("shader");
+}
+
+bool ResourceFormatLoaderShader::handles_type(const String &p_type) const {
+
+ return (p_type == "Shader");
+}
+
+String ResourceFormatLoaderShader::get_resource_type(const String &p_path) const {
+
+ String el = p_path.get_extension().to_lower();
+ if (el == "shader")
+ return "Shader";
+ return "";
+}
+
+Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+
+ Ref<Shader> shader = p_resource;
+ ERR_FAIL_COND_V(shader.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = shader->get_code();
+
+ Error err;
+ FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+
+ if (err) {
+
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ memdelete(file);
+ return ERR_CANT_CREATE;
+ }
+ file->close();
+ memdelete(file);
+
+ return OK;
+}
+
+void ResourceFormatSaverShader::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+
+ if (Object::cast_to<Shader>(*p_resource)) {
+ p_extensions->push_back("shader");
+ }
+}
+bool ResourceFormatSaverShader::recognize(const RES &p_resource) const {
+
+ return Object::cast_to<Shader>(*p_resource) != NULL;
+}
diff --git a/scene/resources/shader.h b/scene/resources/shader.h
index 5cc70629c7..78d73a33e2 100644
--- a/scene/resources/shader.h
+++ b/scene/resources/shader.h
@@ -31,6 +31,7 @@
#define SHADER_H
#include "io/resource_loader.h"
+#include "io/resource_saver.h"
#include "resource.h"
#include "scene/resources/texture.h"
@@ -38,7 +39,6 @@ class Shader : public Resource {
GDCLASS(Shader, Resource);
OBJ_SAVE_TYPE(Shader);
- RES_BASE_EXTENSION("shd");
public:
enum Mode {
@@ -95,4 +95,19 @@ public:
VARIANT_ENUM_CAST(Shader::Mode);
+class ResourceFormatLoaderShader : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverShader : public ResourceFormatSaver {
+public:
+ virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const RES &p_resource) const;
+};
+
#endif // SHADER_H
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 987d6c5f6a..35d0d55d85 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -707,6 +707,8 @@ Ref<Image> StreamTexture::get_data() const {
}
void StreamTexture::set_flags(uint32_t p_flags) {
+ flags = p_flags;
+ VS::get_singleton()->texture_set_flags(texture, flags);
}
void StreamTexture::reload_from_file() {
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index bd6b917d4e..144c208c07 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -893,8 +893,8 @@ void TileSet::clear() {
void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_tile", "id"), &TileSet::create_tile);
- ClassDB::bind_method(D_METHOD("autotile_set_bitmask_mode", "mode"), &TileSet::autotile_set_bitmask_mode);
- ClassDB::bind_method(D_METHOD("autotile_get_bitmask_mode"), &TileSet::autotile_get_bitmask_mode);
+ ClassDB::bind_method(D_METHOD("autotile_set_bitmask_mode", "id", "mode"), &TileSet::autotile_set_bitmask_mode);
+ ClassDB::bind_method(D_METHOD("autotile_get_bitmask_mode", "id"), &TileSet::autotile_get_bitmask_mode);
ClassDB::bind_method(D_METHOD("tile_set_name", "id", "name"), &TileSet::tile_set_name);
ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name);
ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture"), &TileSet::tile_set_texture);
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index dc58cd36dd..dad4711c07 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -654,6 +654,10 @@ void Physics2DServer::_bind_methods() {
BIND_ENUM_CONSTANT(JOINT_GROOVE);
BIND_ENUM_CONSTANT(JOINT_DAMPED_SPRING);
+ BIND_ENUM_CONSTANT(JOINT_PARAM_BIAS);
+ BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS);
+ BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE);
+
BIND_ENUM_CONSTANT(DAMPED_STRING_REST_LENGTH);
BIND_ENUM_CONSTANT(DAMPED_STRING_STIFFNESS);
BIND_ENUM_CONSTANT(DAMPED_STRING_DAMPING);
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index a25c5ca65e..96f981ab5e 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -109,7 +109,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SIDE"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);