summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/list.h6
-rw-r--r--core/math/expression.cpp7
-rw-r--r--core/math/expression.h1
-rw-r--r--core/math/rect2.h2
-rw-r--r--doc/classes/@GDScript.xml23
-rw-r--r--doc/classes/BaseButton.xml3
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp12
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp12
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp160
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h7
-rw-r--r--editor/project_manager.cpp4
-rw-r--r--editor/script_create_dialog.cpp169
-rw-r--r--editor/script_create_dialog.h1
-rw-r--r--modules/gdscript/gdscript.h5
-rw-r--r--modules/gdscript/gdscript_editor.cpp11
-rw-r--r--modules/gdscript/gdscript_functions.cpp16
-rw-r--r--modules/gdscript/gdscript_functions.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp13
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp387
-rw-r--r--modules/gridmap/grid_map_editor_plugin.h43
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs29
-rw-r--r--modules/mono/glue/Managed/Files/MathfEx.cs10
-rw-r--r--modules/mono/utils/string_utils.cpp3
-rw-r--r--modules/pvr/texture_loader_pvr.cpp7
-rw-r--r--platform/android/export/export.cpp2
-rw-r--r--platform/iphone/export/export.cpp2
-rw-r--r--platform/osx/export/export.cpp1
-rw-r--r--platform/x11/crash_handler_x11.cpp10
-rw-r--r--platform/x11/os_x11.cpp72
-rw-r--r--platform/x11/power_x11.cpp2
-rw-r--r--scene/gui/base_button.cpp16
-rw-r--r--scene/gui/base_button.h4
-rw-r--r--scene/gui/popup_menu.cpp8
-rw-r--r--scene/gui/text_edit.cpp56
-rw-r--r--scene/resources/animation.h1
35 files changed, 714 insertions, 392 deletions
diff --git a/core/list.h b/core/list.h
index c21c20ba34..103a82a31d 100644
--- a/core/list.h
+++ b/core/list.h
@@ -503,8 +503,7 @@ public:
if (p_I->prev_ptr)
p_I->prev_ptr->next_ptr = p_I->next_ptr;
- if (p_I->next_ptr)
- p_I->next_ptr->prev_ptr = p_I->prev_ptr;
+ p_I->next_ptr->prev_ptr = p_I->prev_ptr;
_data->last->next_ptr = p_I;
p_I->prev_ptr = _data->last;
@@ -538,8 +537,7 @@ public:
if (_data->last == p_I)
_data->last = p_I->prev_ptr;
- if (p_I->prev_ptr)
- p_I->prev_ptr->next_ptr = p_I->next_ptr;
+ p_I->prev_ptr->next_ptr = p_I->next_ptr;
if (p_I->next_ptr)
p_I->next_ptr->prev_ptr = p_I->prev_ptr;
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 133dcc7ab9..079c9b524f 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -64,6 +64,7 @@ const char *Expression::func_name[Expression::FUNC_MAX] = {
"is_inf",
"ease",
"decimals",
+ "step_decimals",
"stepify",
"lerp",
"inverse_lerp",
@@ -149,6 +150,7 @@ int Expression::get_func_argument_count(BuiltinFunc p_func) {
case MATH_ISNAN:
case MATH_ISINF:
case MATH_DECIMALS:
+ case MATH_STEP_DECIMALS:
case MATH_SEED:
case MATH_RANDSEED:
case MATH_DEG2RAD:
@@ -365,6 +367,11 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant
VALIDATE_ARG_NUM(0);
*r_return = Math::step_decimals((double)*p_inputs[0]);
} break;
+ case MATH_STEP_DECIMALS: {
+
+ VALIDATE_ARG_NUM(0);
+ *r_return = Math::step_decimals((double)*p_inputs[0]);
+ } break;
case MATH_STEPIFY: {
VALIDATE_ARG_NUM(0);
diff --git a/core/math/expression.h b/core/math/expression.h
index f9075cb689..f20619f0b6 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -62,6 +62,7 @@ public:
MATH_ISINF,
MATH_EASE,
MATH_DECIMALS,
+ MATH_STEP_DECIMALS,
MATH_STEPIFY,
MATH_LERP,
MATH_INVERSE_LERP,
diff --git a/core/math/rect2.h b/core/math/rect2.h
index 3b66617c83..d636aa223f 100644
--- a/core/math/rect2.h
+++ b/core/math/rect2.h
@@ -67,7 +67,7 @@ struct Rect2 {
if (p_point.x < position.x) {
real_t d = position.x - p_point.x;
- dist = inside ? d : MIN(dist, d);
+ dist = d;
inside = false;
}
if (p_point.y < position.y) {
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index 22834a4c81..2f7f05b2e4 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -264,11 +264,7 @@
<argument index="0" name="step" type="float">
</argument>
<description>
- Returns the position of the first non-zero digit, after the decimal point.
- [codeblock]
- # n is 2
- n = decimals(0.035)
- [/codeblock]
+ Deprecated alias for "[method step_decimals]".
</description>
</method>
<method name="dectime">
@@ -1023,6 +1019,23 @@
[/codeblock]
</description>
</method>
+ <method name="step_decimals">
+ <return type="float">
+ </return>
+ <argument index="0" name="step" type="float">
+ </argument>
+ <description>
+ Returns the position of the first non-zero digit, after the decimal point.
+ [codeblock]
+ # n is 0
+ n = step_decimals(5)
+ # n is 4
+ n = step_decimals(1.0005)
+ # n is 9
+ n = step_decimals(0.000000005)
+ [/codeblock]
+ </description>
+ </method>
<method name="stepify">
<return type="float">
</return>
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 08be3ed0f4..c65d545f3e 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -69,6 +69,9 @@
<member name="toggle_mode" type="bool" setter="set_toggle_mode" getter="is_toggle_mode">
If [code]true[/code], the button is in toggle mode. Makes the button flip state between pressed and unpressed each time its area is clicked.
</member>
+ <member name="keep_pressed_outside" type="bool" setter="set_keep_pressed_outside" getter="is_keep_pressed_outside">
+ If [code]true[/code], the button stays pressed when moving the cursor outside the button while pressing it. Default value: [code]false[/code].
+ </member>
</members>
<signals>
<signal name="button_down">
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 41f35c3bed..7c075b5635 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -846,6 +846,12 @@ void AnimationPlayerEditor::_update_player() {
onion_skinning->set_disabled(player == NULL);
pin->set_disabled(player == NULL);
+ if (!player) {
+ AnimationPlayerEditor::singleton->get_track_editor()->update_keying();
+ EditorNode::get_singleton()->update_keying();
+ return;
+ }
+
int active_idx = -1;
for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
@@ -858,12 +864,6 @@ void AnimationPlayerEditor::_update_player() {
active_idx = animation->get_item_count() - 1;
}
- if (!player) {
- AnimationPlayerEditor::singleton->get_track_editor()->update_keying();
- EditorNode::get_singleton()->update_keying();
- return;
- }
-
updating = false;
if (active_idx != -1) {
animation->select(active_idx);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 88bb8e38fe..c0f2410636 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1471,10 +1471,14 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, false);
break;
case DRAG_ANCHOR_ALL:
- if (!use_single_axis || !use_y) control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
- if (!use_single_axis || !use_y) control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
- if (!use_single_axis || use_y) control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
- if (!use_single_axis || use_y) control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ if (!use_single_axis || !use_y) {
+ control->set_anchor(MARGIN_LEFT, new_anchor.x, false, true);
+ control->set_anchor(MARGIN_RIGHT, new_anchor.x, false, true);
+ }
+ if (!use_single_axis || use_y) {
+ control->set_anchor(MARGIN_TOP, new_anchor.y, false, true);
+ control->set_anchor(MARGIN_BOTTOM, new_anchor.y, false, true);
+ }
break;
default:
break;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 964303ba22..f8261fe949 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -58,7 +58,11 @@ void VisualShaderNodePlugin::_bind_methods() {
void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
+ bool was_null = false;
if (p_visual_shader) {
+ if (visual_shader.is_null()) {
+ was_null = true;
+ }
visual_shader = Ref<VisualShader>(p_visual_shader);
} else {
visual_shader.unref();
@@ -67,6 +71,9 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
if (visual_shader.is_null()) {
hide();
} else {
+ if (was_null) { // to avoid tree collapse
+ _update_options_menu();
+ }
_update_graph();
}
}
@@ -174,6 +181,12 @@ void VisualShaderEditor::_update_options_menu() {
int item_count2 = 0;
bool is_first_item = true;
+ int current_func = -1;
+
+ if (!visual_shader.is_null()) {
+ current_func = visual_shader->get_mode();
+ }
+
for (int i = 0; i < add_options.size() + 1; i++) {
if (i == add_options.size()) {
@@ -220,7 +233,7 @@ void VisualShaderEditor::_update_options_menu() {
}
}
if (sub_category != NULL) {
- if (_is_available(add_options[i].mode)) {
+ if ((add_options[i].func == current_func || add_options[i].func == -1) && _is_available(add_options[i].mode)) {
++item_count2;
TreeItem *item = members->create_item(sub_category);
item->set_text(0, add_options[i].name);
@@ -252,7 +265,7 @@ void VisualShaderEditor::_update_options_menu() {
}
} else {
if (category != NULL) {
- if (_is_available(add_options[i].mode)) {
+ if ((add_options[i].func == current_func || add_options[i].func == -1) && _is_available(add_options[i].mode)) {
++item_count;
TreeItem *item = members->create_item(category);
item->set_text(0, add_options[i].name);
@@ -1250,8 +1263,8 @@ void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
void VisualShaderEditor::_bind_methods() {
-
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
+ ClassDB::bind_method("_update_options_menu", &VisualShaderEditor::_update_options_menu);
ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node);
ClassDB::bind_method("_node_dragged", &VisualShaderEditor::_node_dragged);
ClassDB::bind_method("_connection_request", &VisualShaderEditor::_connection_request);
@@ -1441,50 +1454,106 @@ VisualShaderEditor::VisualShaderEditor() {
// INPUT
- add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", TTR("'camera' input parameter for all shader modes."), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM));
- add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", TTR("'inv_camera' input parameter for all shader modes."), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM));
- add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", TTR("'inv_projection' input parameter for all shader modes."), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM));
- add_options.push_back(AddOption("Normal", "Input", "All", "VisualShaderNodeInput", TTR("'normal' input parameter for all shader modes."), "normal", VisualShaderNode::PORT_TYPE_VECTOR));
- add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", TTR("'projection' input parameter for all shader modes."), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM));
- add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", TTR("'time' input parameter for all shader modes."), "time", VisualShaderNode::PORT_TYPE_SCALAR));
- add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", TTR("'viewport_size' input parameter for all shader modes."), "viewport_size", VisualShaderNode::PORT_TYPE_VECTOR));
- add_options.push_back(AddOption("World", "Input", "All", "VisualShaderNodeInput", TTR("'world' input parameter for all shader modes."), "world", VisualShaderNode::PORT_TYPE_TRANSFORM));
+ // SPATIAL-FOR-ALL
+
+ add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", TTR("'camera' input parameter for all shader modes."), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", TTR("'inv_camera' input parameter for all shader modes."), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", TTR("'inv_projection' input parameter for all shader modes."), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Normal", "Input", "All", "VisualShaderNodeInput", TTR("'normal' input parameter for all shader modes."), "normal", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", TTR("'projection' input parameter for all shader modes."), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", TTR("'time' input parameter for all shader modes."), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", TTR("'viewport_size' input parameter for all shader modes."), "viewport_size", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("World", "Input", "All", "VisualShaderNodeInput", TTR("'world' input parameter for all shader modes."), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::Mode::MODE_SPATIAL));
+
+ // CANVASITEM-FOR-ALL
+
+ add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", TTR("'alpha' input parameter for all shader modes."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", TTR("'color' input parameter for all shader modes."), "color", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", TTR("'texture_pixel_size' input parameter for all shader modes."), "texture_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", TTR("'time' input parameter for all shader modes."), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", TTR("'uv' input parameter for all shader modes."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::Mode::MODE_CANVAS_ITEM));
+
+ /////////////////
add_options.push_back(AddOption("Input", "Input", "Common", "VisualShaderNodeInput", TTR("Input parameter.")));
- add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", TTR("'alpha' input parameter for fragment shader mode."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", TTR("'binormal' input parameter for fragment shader mode."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", TTR("'color' input parameter for fragment shader mode."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment shader mode."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'point_coord' input parameter for fragment shader mode."), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'screen_uv' input parameter for fragment shader mode."), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", TTR("'side' input parameter for fragment shader mode."), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", TTR("'tangent' input parameter for fragment shader mode."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv' input parameter for fragment shader mode."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv2' input parameter for fragment shader mode."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", TTR("'vertex' input parameter for fragment shader mode."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
- add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", TTR("'view' input parameter for fragment shader mode."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT));
-
- add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", TTR("'albedo' input parameter for light shader mode."), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", TTR("'attenuation' input parameter for light shader mode."), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", TTR("'diffuse' input parameter for light shader mode."), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for light shader mode."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", TTR("'light' input parameter for light shader mode."), "light", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", TTR("'light_color' input parameter for light shader mode."), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", TTR("'roughness' input parameter for light shader mode."), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", TTR("'specular' input parameter for light shader mode."), "specular", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", TTR("'transmission' input parameter for light shader mode."), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
- add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", TTR("'view' input parameter for light shader mode."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT));
-
- add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", TTR("'alpha' input parameter for vertex shader mode."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", TTR("'binormal' input parameter for vertex shader mode."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", TTR("'color' input parameter for vertex shader mode."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", TTR("'modelview' input parameter for vertex shader mode."), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", TTR("'point_size' input parameter for vertex shader mode."), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", TTR("'tangent' input parameter for vertex shader mode."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv' input parameter for vertex shader mode."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv2' input parameter for vertex shader mode."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
- add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", TTR("'vertex' input parameter for vertex shader mode."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX));
+ // SPATIAL INPUTS
+
+ add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", TTR("'alpha' input parameter for vertex and fragment shader modes."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", TTR("'binormal' input parameter for vertex and fragment shader modes."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", TTR("'color' input parameter for vertex and fragment shader modes."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment and light shader modes."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'point_coord' input parameter for fragment shader mode."), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'screen_uv' input parameter for fragment shader mode."), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", TTR("'side' input parameter for fragment shader mode."), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", TTR("'tangent' input parameter for vertex and fragment shader modes."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv' input parameter for vertex and fragment shader modes."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", TTR("'uv2' input parameter for vertex and fragment shader modes."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", TTR("'vertex' input parameter for vertex and fragment shader modes."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", TTR("'view' input parameter for fragment and light shader modes."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_SPATIAL));
+
+ add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", TTR("'albedo' input parameter for light shader mode."), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", TTR("'attenuation' input parameter for light shader mode."), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", TTR("'diffuse' input parameter for light shader mode."), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment and light shader modes."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", TTR("'light' input parameter for light shader mode."), "light", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", TTR("'light_color' input parameter for light shader mode."), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", TTR("'roughness' input parameter for light shader mode."), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", TTR("'specular' input parameter for light shader mode."), "specular", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", TTR("'transmission' input parameter for light shader mode."), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", TTR("'view' input parameter for fragment and light shader modes."), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_SPATIAL));
+
+ add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", TTR("'alpha' input parameter for vertex and fragment shader modes."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", TTR("'binormal' input parameter for vertex and fragment shader modes."), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", TTR("'color' input parameter for vertex and fragment shader modes."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", TTR("'modelview' input parameter for vertex shader mode."), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", TTR("'point_size' input parameter for vertex shader mode."), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", TTR("'tangent' input parameter for vertex and fragment shader mode."), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv' input parameter for vertex and fragment shader modes."), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", TTR("'uv2' input parameter for vertex and fragment shader modes."), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+ add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", TTR("'vertex' input parameter for vertex and fragment shader modes."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_SPATIAL));
+
+ // CANVASITEM INPUTS
+
+ add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment and light shader modes."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightPass", "Input", "Fragment", "VisualShaderNodeInput", TTR("'light_pass' input parameter for vertex and fragment shader modes."), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", TTR("'point_coord' input parameter for fragment and light shader modes."), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", TTR("'screen_pixel_size' input parameter for fragment shader mode."), "screen_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", TTR("'screen_uv' input parameter for fragment and light shader modes."), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::Mode::MODE_CANVAS_ITEM));
+
+ add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", TTR("'fragcoord' input parameter for fragment and light shader modes."), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", TTR("'light_alpha' input parameter for light shader mode."), "light_alpha", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", TTR("'light_color' input parameter for light shader mode."), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightHeight", "Input", "Light", "VisualShaderNodeInput", TTR("'light_height' input parameter for light shader mode."), "light_height", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightUV", "Input", "Light", "VisualShaderNodeInput", TTR("'light_uv' input parameter for light shader mode."), "light_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightVector", "Input", "Light", "VisualShaderNodeInput", TTR("'light_vec' input parameter for light shader mode."), "light_vec", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", TTR("'normal' input parameter for light shader mode."), "normal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", TTR("'point_coord' input parameter for fragment and light shader modes."), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", TTR("'screen_uv' input parameter for fragment and light shader modes."), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("ShadowColor", "Input", "Light", "VisualShaderNodeInput", TTR("'shadow_color' input parameter for light shader mode."), "shadow_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::Mode::MODE_CANVAS_ITEM));
+
+ add_options.push_back(AddOption("Extra", "Input", "Vertex", "VisualShaderNodeInput", TTR("'extra' input parameter for vertex shader mode."), "extra", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightPass", "Input", "Vertex", "VisualShaderNodeInput", TTR("'light_pass' input parameter for vertex and fragment shader modes."), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", TTR("'point_size' input parameter for vertex shader mode."), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Projection", "Input", "Vertex", "VisualShaderNodeInput", TTR("'projection' input parameter for vertex shader mode."), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", TTR("'vertex' input parameter for vertex shader mode."), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", TTR("'world' input parameter for vertex shader mode."), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_CANVAS_ITEM));
+
+ // PARTICLES INPUTS
+
+ add_options.push_back(AddOption("Active", "Input", "Vertex", "VisualShaderNodeInput", TTR("'active' input parameter for vertex shader mode."), "active", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", TTR("'alpha' input parameter for vertex shader mode."), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", TTR("'color' input parameter for vertex shader mode."), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Custom", "Input", "Vertex", "VisualShaderNodeInput", TTR("'custom' input parameter for vertex shader mode."), "custom", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("CustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", TTR("'custom_alpha' input parameter for vertex shader mode."), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Delta", "Input", "Vertex", "VisualShaderNodeInput", TTR("'delta' input parameter for vertex shader mode."), "delta", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("EmissionTransform", "Input", "Vertex", "VisualShaderNodeInput", TTR("'emission_transform' input parameter for vertex shader mode."), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Index", "Input", "Vertex", "VisualShaderNodeInput", TTR("'index' input parameter for vertex shader mode."), "index", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("LifeTime", "Input", "Vertex", "VisualShaderNodeInput", TTR("'lifetime' input parameter for vertex shader mode."), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Restart", "Input", "Vertex", "VisualShaderNodeInput", TTR("'restart' input parameter for vertex shader mode."), "restart", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Time", "Input", "Vertex", "VisualShaderNodeInput", TTR("'time' input parameter for vertex shader mode."), "time", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Transform", "Input", "Vertex", "VisualShaderNodeInput", TTR("'transform' input parameter for vertex shader mode."), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
+ add_options.push_back(AddOption("Velocity", "Input", "Vertex", "VisualShaderNodeInput", TTR("'velocity' input parameter for vertex shader mode."), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::Mode::MODE_PARTICLES));
// SCALAR
@@ -1933,6 +2002,9 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
}
}
+ undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_options_menu");
+ undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_options_menu");
+
//update graph
undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_graph");
undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_graph");
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 35041da2bd..eb0dee7594 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -100,8 +100,9 @@ class VisualShaderEditor : public VBoxContainer {
Ref<Script> script;
int mode;
int return_type;
+ int func;
- AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_sub_category = String(), const String &p_type = String(), const String &p_description = String(), int p_sub_func = -1, int p_return_type = -1, int p_mode = -1) {
+ AddOption(const String &p_name = String(), const String &p_category = String(), const String &p_sub_category = String(), const String &p_type = String(), const String &p_description = String(), int p_sub_func = -1, int p_return_type = -1, int p_mode = -1, int p_func = -1) {
name = p_name;
type = p_type;
category = p_category;
@@ -110,9 +111,10 @@ class VisualShaderEditor : public VBoxContainer {
sub_func = p_sub_func;
return_type = p_return_type;
mode = p_mode;
+ func = p_func;
}
- AddOption(const String &p_name, const String &p_category, const String &p_sub_category, const String &p_type, const String &p_description, const String &p_sub_func, int p_return_type = -1, int p_mode = -1) {
+ AddOption(const String &p_name, const String &p_category, const String &p_sub_category, const String &p_type, const String &p_description, const String &p_sub_func, int p_return_type = -1, int p_mode = -1, int p_func = -1) {
name = p_name;
type = p_type;
category = p_category;
@@ -121,6 +123,7 @@ class VisualShaderEditor : public VBoxContainer {
sub_func_str = p_sub_func;
return_type = p_return_type;
mode = p_mode;
+ func = p_func;
}
};
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 709c2caa96..6de4330493 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -997,7 +997,7 @@ void ProjectManager::_update_project_buttons() {
}
}
for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) {
- String project_name = E->key().replace("::", "/") + "/project.godot";
+ String project_name = E->key().replace(":::", ":/").replace("::", "/") + "/project.godot";
if (!FileAccess::exists(project_name)) {
missing_projects = true;
break;
@@ -1735,7 +1735,7 @@ void ProjectManager::_erase_missing_projects_confirm() {
int deleted_projects = 0;
int remaining_projects = 0;
for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) {
- String project_name = E->key().replace("::", "/") + "/project.godot";
+ String project_name = E->key().replace(":::", ":/").replace("::", "/") + "/project.godot";
if (!FileAccess::exists(project_name)) {
deleted_projects++;
EditorSettings::get_singleton()->erase("projects/" + E->key());
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 292cb8ddc3..0f851c526d 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -105,8 +105,12 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
if (p_string.length() == 0)
return false;
- String path_chars = "\"res://";
- bool is_val_path = ScriptServer::get_language(language_menu->get_selected())->can_inherit_from_file();
+ if (ScriptServer::get_language(language_menu->get_selected())->can_inherit_from_file() && p_string.is_quoted()) {
+ String p = p_string.substr(1, p_string.length() - 2);
+ if (_validate_path(p, true) == "")
+ return true;
+ }
+
for (int i = 0; i < p_string.length(); i++) {
if (i == 0) {
@@ -114,17 +118,7 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
return false; // no start with number plz
}
- if (i == p_string.length() - 1 && is_val_path)
- return p_string[i] == '\"';
-
- if (is_val_path && i < path_chars.length()) {
- if (p_string[i] != path_chars[i])
- is_val_path = false;
- else
- continue;
- }
-
- bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || p_string[i] == '-' || (is_val_path && (p_string[i] == '/' || p_string[i] == '.'));
+ bool valid_char = (p_string[i] >= '0' && p_string[i] <= '9') || (p_string[i] >= 'a' && p_string[i] <= 'z') || (p_string[i] >= 'A' && p_string[i] <= 'Z') || p_string[i] == '_' || p_string[i] == '-';
if (!valid_char)
return false;
@@ -133,6 +127,70 @@ bool ScriptCreateDialog::_validate(const String &p_string) {
return true;
}
+String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must_exist) {
+
+ String p = p_path.strip_edges();
+
+ if (p == "") return TTR("Path is empty.");
+ if (p.get_file().get_basename() == "") return TTR("Filename is empty.");
+
+ p = ProjectSettings::get_singleton()->localize_path(p);
+ if (!p.begins_with("res://")) return TTR("Path is not local.");
+
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (d->change_dir(p.get_base_dir()) != OK) {
+ memdelete(d);
+ return TTR("Invalid base path.");
+ }
+ memdelete(d);
+
+ /* Does file already exist */
+ DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (f->dir_exists(p)) {
+ memdelete(f);
+ return TTR("A directory with the same name exists.");
+ } else if (p_file_must_exist && !f->file_exists(p)) {
+ memdelete(f);
+ return TTR("File does not exist.");
+ }
+ memdelete(f);
+
+ /* Check file extension */
+ String extension = p.get_extension();
+ List<String> extensions;
+
+ // get all possible extensions for script
+ for (int l = 0; l < language_menu->get_item_count(); l++) {
+ ScriptServer::get_language(l)->get_recognized_extensions(&extensions);
+ }
+
+ bool found = false;
+ bool match = false;
+ int index = 0;
+ for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
+ if (E->get().nocasecmp_to(extension) == 0) {
+ //FIXME (?) - changing language this way doesn't update controls, needs rework
+ //language_menu->select(index); // change Language option by extension
+ found = true;
+ if (E->get() == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
+ match = true;
+ }
+ break;
+ }
+ index++;
+ }
+
+ if (!found) return TTR("Invalid extension.");
+ if (!match) return TTR("Wrong extension chosen.");
+
+ /* Let ScriptLanguage do custom validation */
+ String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
+ if (path_error != "") return path_error;
+
+ /* All checks passed */
+ return "";
+}
+
void ScriptCreateDialog::_class_name_changed(const String &p_name) {
if (_validate(class_name->get_text())) {
@@ -400,97 +458,22 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
is_path_valid = false;
is_new_script_created = true;
- String p = p_path.strip_edges();
- if (p == "") {
- _msg_path_valid(false, TTR("Path is empty."));
- _update_dialog();
- return;
- }
-
- if (p.get_file().get_basename() == "") {
- _msg_path_valid(false, TTR("Filename is empty."));
- _update_dialog();
- return;
- }
-
- p = ProjectSettings::get_singleton()->localize_path(p);
- if (!p.begins_with("res://")) {
- _msg_path_valid(false, TTR("Path is not local."));
- _update_dialog();
- return;
- }
-
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (d->change_dir(p.get_base_dir()) != OK) {
- _msg_path_valid(false, TTR("Invalid base path."));
- memdelete(d);
+ String path_error = _validate_path(p_path, false);
+ if (path_error != "") {
+ _msg_path_valid(false, path_error);
_update_dialog();
return;
}
- memdelete(d);
/* Does file already exist */
-
DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (f->dir_exists(p)) {
+ String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
+ if (f->file_exists(p)) {
is_new_script_created = false;
- is_path_valid = false;
- _msg_path_valid(false, TTR("A directory with the same name exists."));
- } else if (f->file_exists(p)) {
- is_new_script_created = false;
- is_path_valid = true;
_msg_path_valid(true, TTR("File exists, it will be reused."));
}
memdelete(f);
- _update_dialog();
-
- /* Check file extension */
-
- String extension = p.get_extension();
- List<String> extensions;
-
- // get all possible extensions for script
- for (int l = 0; l < language_menu->get_item_count(); l++) {
- ScriptServer::get_language(l)->get_recognized_extensions(&extensions);
- }
-
- bool found = false;
- bool match = false;
- int index = 0;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
- //FIXME (?) - changing language this way doesn't update controls, needs rework
- //language_menu->select(index); // change Language option by extension
- found = true;
- if (E->get() == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
- match = true;
- }
- break;
- }
- index++;
- }
-
- if (!found) {
- _msg_path_valid(false, TTR("Invalid extension."));
- _update_dialog();
- return;
- }
-
- if (!match) {
- _msg_path_valid(false, TTR("Wrong extension chosen."));
- _update_dialog();
- return;
- }
-
- String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
- if (path_error != "") {
- _msg_path_valid(false, path_error);
- _update_dialog();
- return;
- }
-
- /* All checks passed */
is_path_valid = true;
_update_dialog();
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index f5c335c00a..1a3ba3d371 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -87,6 +87,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
void _lang_changed(int l = 0);
void _built_in_pressed();
bool _validate(const String &p_string);
+ String _validate_path(const String &p_path, bool p_file_must_exist);
void _class_name_changed(const String &p_name);
void _parent_name_changed(const String &p_parent);
void _template_changed(int p_template = 0);
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 1d75d9e2fe..38009b878d 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -407,9 +407,10 @@ public:
csi.resize(_debug_call_stack_pos);
for (int i = 0; i < _debug_call_stack_pos; i++) {
csi.write[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0;
- if (_call_stack[i].function)
+ if (_call_stack[i].function) {
csi.write[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name();
- csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path();
+ csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path();
+ }
}
return csi;
}
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 69bf114c8e..bcf3140fa6 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -2178,7 +2178,6 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Set<String> &r_result, String &r_arghint) {
Variant base = p_base.value;
GDScriptParser::DataType base_type = p_base.type;
- bool _static = false;
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@@ -2191,12 +2190,10 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
return;
}
}
- if (!_static) {
- for (int i = 0; i < base_type.class_type->functions.size(); i++) {
- if (base_type.class_type->functions[i]->name == p_method) {
- r_arghint = _make_arguments_hint(base_type.class_type->functions[i], p_argidx);
- return;
- }
+ for (int i = 0; i < base_type.class_type->functions.size(); i++) {
+ if (base_type.class_type->functions[i]->name == p_method) {
+ r_arghint = _make_arguments_hint(base_type.class_type->functions[i], p_argidx);
+ return;
}
}
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 7552bc6bff..5ebcddfd7c 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -72,6 +72,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"is_zero_approx",
"ease",
"decimals",
+ "step_decimals",
"stepify",
"lerp",
"inverse_lerp",
@@ -339,6 +340,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
r_ret = Math::step_decimals((double)*p_args[0]);
+ ERR_EXPLAIN("GDScript method 'decimals' is deprecated and has been renamed to 'step_decimals', please update your code accordingly.");
+ WARN_DEPRECATED
+ } break;
+ case MATH_STEP_DECIMALS: {
+ VALIDATE_ARG_COUNT(1);
+ VALIDATE_ARG_NUM(0);
+ r_ret = Math::step_decimals((double)*p_args[0]);
} break;
case MATH_STEPIFY: {
VALIDATE_ARG_COUNT(2);
@@ -1452,6 +1460,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_ISINF:
case MATH_EASE:
case MATH_DECIMALS:
+ case MATH_STEP_DECIMALS:
case MATH_STEPIFY:
case MATH_LERP:
case MATH_INVERSE_LERP:
@@ -1626,7 +1635,12 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case MATH_DECIMALS: {
MethodInfo mi("decimals", PropertyInfo(Variant::REAL, "step"));
- mi.return_val.type = Variant::REAL;
+ mi.return_val.type = Variant::INT;
+ return mi;
+ } break;
+ case MATH_STEP_DECIMALS: {
+ MethodInfo mi("step_decimals", PropertyInfo(Variant::REAL, "step"));
+ mi.return_val.type = Variant::INT;
return mi;
} break;
case MATH_STEPIFY: {
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index 0dbd172acf..c594480ff8 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -63,6 +63,7 @@ public:
MATH_ISZEROAPPROX,
MATH_EASE,
MATH_DECIMALS,
+ MATH_STEP_DECIMALS,
MATH_STEPIFY,
MATH_LERP,
MATH_INVERSE_LERP,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 80af094c2c..51ec0c1442 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -282,7 +282,6 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
switch (tokenizer->get_token()) {
case GDScriptTokenizer::TK_CURSOR: {
- completion_cursor = StringName();
completion_type = COMPLETION_GET_NODE;
completion_class = current_class;
completion_function = current_function;
@@ -2870,8 +2869,6 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
lv->assign_op = op;
lv->assign = assigned;
- lv->assign_op = op;
-
if (!_end_statement()) {
_set_error("Expected end of statement (var)");
return;
@@ -6226,8 +6223,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
return DataType();
}
#ifdef DEBUG_ENABLED
- if (var_op == Variant::OP_DIVIDE && argument_a_type.has_type && argument_a_type.kind == DataType::BUILTIN && argument_a_type.builtin_type == Variant::INT &&
- argument_b_type.has_type && argument_b_type.kind == DataType::BUILTIN && argument_b_type.builtin_type == Variant::INT) {
+ if (var_op == Variant::OP_DIVIDE && argument_a_type.kind == DataType::BUILTIN && argument_a_type.builtin_type == Variant::INT &&
+ argument_b_type.kind == DataType::BUILTIN && argument_b_type.builtin_type == Variant::INT) {
_add_warning(GDScriptWarning::INTEGER_DIVISION, op->line);
}
#endif // DEBUG_ENABLED
@@ -6938,10 +6935,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
#ifdef DEBUG_ENABLED
if (current_function && !for_completion && !is_static && p_call->arguments[0]->type == Node::TYPE_SELF && current_function->_static) {
- if (current_function && current_function->_static && p_call->arguments[0]->type == Node::TYPE_SELF) {
- _set_error("Can't call non-static function from a static function.", p_call->line);
- return DataType();
- }
+ _set_error("Can't call non-static function from a static function.", p_call->line);
+ return DataType();
}
if (check_types && !is_static && !is_initializer && base_type.is_meta_type) {
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 17eb6f674c..657aa1f9ce 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -67,9 +67,6 @@ void GridMapEditor::_menu_option(int p_option) {
floor->set_value(floor->get_value() + 1);
} break;
- case MENU_OPTION_CONFIGURE: {
-
- } break;
case MENU_OPTION_LOCK_VIEW: {
int index = options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW);
@@ -121,14 +118,15 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_ROTATE_Y: {
Basis r;
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
- r.set_orthogonal_index(selection.duplicate_rot);
+ r.set_orthogonal_index(paste_indicator.orientation);
r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0);
- selection.duplicate_rot = r.get_orthogonal_index();
- _update_duplicate_indicator();
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
break;
}
+
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(0, 1, 0), -Math_PI / 2.0);
cursor_rot = r.get_orthogonal_index();
@@ -137,12 +135,12 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_ROTATE_X: {
Basis r;
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
- r.set_orthogonal_index(selection.duplicate_rot);
+ r.set_orthogonal_index(paste_indicator.orientation);
r.rotate(Vector3(1, 0, 0), -Math_PI / 2.0);
- selection.duplicate_rot = r.get_orthogonal_index();
- _update_duplicate_indicator();
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
break;
}
@@ -154,12 +152,12 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_ROTATE_Z: {
Basis r;
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
- r.set_orthogonal_index(selection.duplicate_rot);
+ r.set_orthogonal_index(paste_indicator.orientation);
r.rotate(Vector3(0, 0, 1), -Math_PI / 2.0);
- selection.duplicate_rot = r.get_orthogonal_index();
- _update_duplicate_indicator();
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
break;
}
@@ -171,6 +169,15 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_BACK_ROTATE_Y: {
Basis r;
+ if (input_action == INPUT_PASTE) {
+
+ r.set_orthogonal_index(paste_indicator.orientation);
+ r.rotate(Vector3(0, 1, 0), Math_PI / 2.0);
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
+ break;
+ }
+
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(0, 1, 0), Math_PI / 2.0);
cursor_rot = r.get_orthogonal_index();
@@ -179,6 +186,15 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_BACK_ROTATE_X: {
Basis r;
+ if (input_action == INPUT_PASTE) {
+
+ r.set_orthogonal_index(paste_indicator.orientation);
+ r.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
+ break;
+ }
+
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
cursor_rot = r.get_orthogonal_index();
@@ -187,6 +203,15 @@ void GridMapEditor::_menu_option(int p_option) {
case MENU_OPTION_CURSOR_BACK_ROTATE_Z: {
Basis r;
+ if (input_action == INPUT_PASTE) {
+
+ r.set_orthogonal_index(paste_indicator.orientation);
+ r.rotate(Vector3(0, 0, 1), Math_PI / 2.0);
+ paste_indicator.orientation = r.get_orthogonal_index();
+ _update_paste_indicator();
+ break;
+ }
+
r.set_orthogonal_index(cursor_rot);
r.rotate(Vector3(0, 0, 1), Math_PI / 2.0);
cursor_rot = r.get_orthogonal_index();
@@ -194,10 +219,10 @@ void GridMapEditor::_menu_option(int p_option) {
} break;
case MENU_OPTION_CURSOR_CLEAR_ROTATION: {
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
- selection.duplicate_rot = 0;
- _update_duplicate_indicator();
+ paste_indicator.orientation = 0;
+ _update_paste_indicator();
break;
}
@@ -205,28 +230,33 @@ void GridMapEditor::_menu_option(int p_option) {
_update_cursor_transform();
} break;
- case MENU_OPTION_DUPLICATE_SELECTS: {
- int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS);
+ case MENU_OPTION_PASTE_SELECTS: {
+ int idx = options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS);
options->get_popup()->set_item_checked(idx, !options->get_popup()->is_item_checked(idx));
} break;
- case MENU_OPTION_SELECTION_DUPLICATE:
+
+ case MENU_OPTION_SELECTION_DUPLICATE: // fallthrough
+ case MENU_OPTION_SELECTION_CUT: {
if (!(selection.active && input_action == INPUT_NONE))
- return;
- if (last_mouseover == Vector3(-1, -1, -1)) //nono mouseovering anythin
break;
- last_mouseover = selection.begin;
- VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], Transform(Basis(), grid_ofs));
+ _set_clipboard_data();
- input_action = INPUT_DUPLICATE;
- selection.click = last_mouseover;
- selection.current = last_mouseover;
- selection.duplicate_rot = 0;
- _update_duplicate_indicator();
- break;
+ if (p_option == MENU_OPTION_SELECTION_CUT) {
+ _delete_selection();
+ }
+
+ input_action = INPUT_PASTE;
+ paste_indicator.click = selection.begin;
+ paste_indicator.current = selection.begin;
+ paste_indicator.begin = selection.begin;
+ paste_indicator.end = selection.end;
+ paste_indicator.orientation = 0;
+ _update_paste_indicator();
+ } break;
case MENU_OPTION_SELECTION_CLEAR: {
if (!selection.active)
- return;
+ break;
_delete_selection();
@@ -315,17 +345,28 @@ void GridMapEditor::_validate_selection() {
_update_selection_transform();
}
+void GridMapEditor::_set_selection(bool p_active, const Vector3 p_begin, const Vector3 p_end) {
+
+ selection.active = p_active;
+ selection.begin = p_begin;
+ selection.end = p_end;
+ selection.click = p_begin;
+ selection.current = p_end;
+
+ _update_selection_transform();
+}
+
bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, bool p_click) {
if (!spatial_editor)
return false;
- if (selected_palette < 0 && input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE)
+ if (selected_palette < 0 && input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE)
return false;
Ref<MeshLibrary> mesh_library = node->get_mesh_library();
if (mesh_library.is_null())
return false;
- if (input_action != INPUT_COPY && input_action != INPUT_SELECT && input_action != INPUT_DUPLICATE && !mesh_library->has_item(selected_palette))
+ if (input_action != INPUT_PICK && input_action != INPUT_SELECT && input_action != INPUT_PASTE && !mesh_library->has_item(selected_palette))
return false;
Camera *camera = p_camera;
@@ -386,13 +427,17 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo
cursor_origin = (Vector3(cell[0], cell[1], cell[2]) + Vector3(0.5 * node->get_center_x(), 0.5 * node->get_center_y(), 0.5 * node->get_center_z())) * node->get_cell_size();
cursor_visible = true;
+ if (input_action == INPUT_SELECT || input_action == INPUT_PASTE) {
+ cursor_visible = false;
+ }
+
_update_cursor_transform();
}
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
- selection.current = Vector3(cell[0], cell[1], cell[2]);
- _update_duplicate_indicator();
+ paste_indicator.current = Vector3(cell[0], cell[1], cell[2]);
+ _update_paste_indicator();
} else if (input_action == INPUT_SELECT) {
@@ -403,7 +448,7 @@ bool GridMapEditor::do_input_action(Camera *p_camera, const Point2 &p_point, boo
_validate_selection();
return true;
- } else if (input_action == INPUT_COPY) {
+ } else if (input_action == INPUT_PICK) {
int item = node->get_cell_item(cell[0], cell[1], cell[2]);
if (item >= 0) {
@@ -456,10 +501,9 @@ void GridMapEditor::_delete_selection() {
}
}
}
+ undo_redo->add_do_method(this, "_set_selection", !selection.active, selection.begin, selection.end);
+ undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end);
undo_redo->commit_action();
-
- selection.active = false;
- _validate_selection();
}
void GridMapEditor::_fill_selection() {
@@ -479,97 +523,124 @@ void GridMapEditor::_fill_selection() {
}
}
}
+ undo_redo->add_do_method(this, "_set_selection", !selection.active, selection.begin, selection.end);
+ undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end);
undo_redo->commit_action();
+}
- selection.active = false;
- _validate_selection();
+void GridMapEditor::_clear_clipboard_data() {
+
+ for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
+
+ VisualServer::get_singleton()->free(E->get().instance);
+ }
+
+ clipboard_items.clear();
}
-void GridMapEditor::_update_duplicate_indicator() {
+void GridMapEditor::_set_clipboard_data() {
- if (!selection.active || input_action != INPUT_DUPLICATE) {
+ _clear_clipboard_data();
+
+ Ref<MeshLibrary> meshLibrary = node->get_mesh_library();
+
+ for (int i = selection.begin.x; i <= selection.end.x; i++) {
+
+ for (int j = selection.begin.y; j <= selection.end.y; j++) {
+
+ for (int k = selection.begin.z; k <= selection.end.z; k++) {
+
+ int itm = node->get_cell_item(i, j, k);
+ if (itm == GridMap::INVALID_CELL_ITEM)
+ continue;
+
+ Ref<Mesh> mesh = meshLibrary->get_item_mesh(itm);
+
+ ClipboardItem item;
+ item.cell_item = itm;
+ item.grid_offset = Vector3(i, j, k) - selection.begin;
+ item.orientation = node->get_cell_item_orientation(i, j, k);
+ item.instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario());
+
+ clipboard_items.push_back(item);
+ }
+ }
+ }
+}
+
+void GridMapEditor::_update_paste_indicator() {
+
+ if (input_action != INPUT_PASTE) {
Transform xf;
xf.basis.set_zero();
- VisualServer::get_singleton()->instance_set_transform(duplicate_instance, xf);
+ VisualServer::get_singleton()->instance_set_transform(paste_instance, xf);
return;
}
+ Vector3 center = 0.5 * Vector3(node->get_center_x(), node->get_center_y(), node->get_center_z());
+ Vector3 scale = (Vector3(1, 1, 1) + (paste_indicator.end - paste_indicator.begin)) * node->get_cell_size();
Transform xf;
- xf.scale(Vector3(1, 1, 1) * (Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size());
- xf.origin = (selection.begin + (selection.current - selection.click)) * node->get_cell_size();
+ xf.scale(scale);
+ xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
Basis rot;
- rot.set_orthogonal_index(selection.duplicate_rot);
+ rot.set_orthogonal_index(paste_indicator.orientation);
xf.basis = rot * xf.basis;
+ xf.translate((-center * node->get_cell_size()) / scale);
- VisualServer::get_singleton()->instance_set_transform(duplicate_instance, node->get_global_transform() * xf);
-}
+ VisualServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf);
-struct __Item {
- Vector3 pos;
- int rot;
- int item;
-};
-void GridMapEditor::_duplicate_paste() {
+ for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
- if (!selection.active)
- return;
+ ClipboardItem &item = E->get();
- int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS);
- bool reselect = options->get_popup()->is_item_checked(idx);
+ xf = Transform();
+ xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
+ xf.basis = rot * xf.basis;
+ xf.translate(item.grid_offset * node->get_cell_size());
+
+ Basis item_rot;
+ item_rot.set_orthogonal_index(item.orientation);
+ xf.basis = item_rot * xf.basis;
+
+ VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf);
+ }
+}
- List<__Item> items;
+void GridMapEditor::_do_paste() {
+
+ int idx = options->get_popup()->get_item_index(MENU_OPTION_PASTE_SELECTS);
+ bool reselect = options->get_popup()->is_item_checked(idx);
Basis rot;
- rot.set_orthogonal_index(selection.duplicate_rot);
+ rot.set_orthogonal_index(paste_indicator.orientation);
- for (int i = selection.begin.x; i <= selection.end.x; i++) {
+ Vector3 ofs = paste_indicator.current - paste_indicator.click;
+ undo_redo->create_action(TTR("GridMap Paste Selection"));
- for (int j = selection.begin.y; j <= selection.end.y; j++) {
+ for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
- for (int k = selection.begin.z; k <= selection.end.z; k++) {
+ ClipboardItem &item = E->get();
- int itm = node->get_cell_item(i, j, k);
- if (itm == GridMap::INVALID_CELL_ITEM)
- continue;
- int orientation = node->get_cell_item_orientation(i, j, k);
- __Item item;
- Vector3 rel = Vector3(i, j, k) - selection.begin;
- rel = rot.xform(rel);
-
- Basis orm;
- orm.set_orthogonal_index(orientation);
- orm = rot * orm;
-
- item.pos = selection.begin + rel;
- item.item = itm;
- item.rot = orm.get_orthogonal_index();
- items.push_back(item);
- }
- }
- }
+ Vector3 pos = rot.xform(item.grid_offset) + paste_indicator.begin + ofs;
- Vector3 ofs = selection.current - selection.click;
- if (items.size()) {
- undo_redo->create_action(TTR("GridMap Duplicate Selection"));
- for (List<__Item>::Element *E = items.front(); E; E = E->next()) {
- __Item &it = E->get();
- Vector3 pos = it.pos + ofs;
+ Basis orm;
+ orm.set_orthogonal_index(item.orientation);
+ orm = rot * orm;
- undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, it.item, it.rot);
- undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z));
- }
- undo_redo->commit_action();
+ undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, item.cell_item, orm.get_orthogonal_index());
+ undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z));
}
if (reselect) {
- selection.begin += ofs;
- selection.end += ofs;
- selection.click = selection.begin;
- selection.current = selection.end;
- _validate_selection();
+ undo_redo->add_do_method(this, "_set_selection", true, paste_indicator.begin + ofs, paste_indicator.end + ofs);
+ undo_redo->add_undo_method(this, "_set_selection", selection.active, selection.begin, selection.end);
}
+
+ undo_redo->commit_action();
+
+ _clear_clipboard_data();
}
bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<InputEvent> &p_event) {
@@ -596,28 +667,31 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
if (mb->get_button_index() == BUTTON_LEFT) {
- if (input_action == INPUT_DUPLICATE) {
- //paste
- _duplicate_paste();
+ if (input_action == INPUT_PASTE) {
+ _do_paste();
input_action = INPUT_NONE;
- _update_duplicate_indicator();
+ _update_paste_indicator();
} else if (mb->get_shift()) {
input_action = INPUT_SELECT;
+ last_selection = selection;
} else if (mb->get_command()) {
- input_action = INPUT_COPY;
+ input_action = INPUT_PICK;
} else {
input_action = INPUT_PAINT;
set_items.clear();
}
} else if (mb->get_button_index() == BUTTON_RIGHT) {
- if (input_action == INPUT_DUPLICATE) {
+ if (input_action == INPUT_PASTE) {
+ _clear_clipboard_data();
input_action = INPUT_NONE;
- _update_duplicate_indicator();
- } else if (mb->get_shift()) {
+ _update_paste_indicator();
+ return true;
+ } else if (selection.active) {
+ _set_selection(false);
+ return true;
+ } else {
input_action = INPUT_ERASE;
set_items.clear();
- } else {
- return false;
}
} else {
return false;
@@ -650,13 +724,21 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
return set_items.size() > 0;
}
+ if (mb->get_button_index() == BUTTON_LEFT && input_action == INPUT_SELECT) {
+
+ undo_redo->create_action("GridMap Selection");
+ undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end);
+ undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end);
+ undo_redo->commit_action();
+ }
+
if (mb->get_button_index() == BUTTON_LEFT && input_action != INPUT_NONE) {
set_items.clear();
input_action = INPUT_NONE;
return true;
}
- if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_DUPLICATE)) {
+ if (mb->get_button_index() == BUTTON_RIGHT && (input_action == INPUT_ERASE || input_action == INPUT_PASTE)) {
input_action = INPUT_NONE;
return true;
}
@@ -670,6 +752,45 @@ bool GridMapEditor::forward_spatial_input_event(Camera *p_camera, const Ref<Inpu
return do_input_action(p_camera, mm->get_position(), false);
}
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid()) {
+ if (k->is_pressed()) {
+ if (k->get_scancode() == KEY_ESCAPE) {
+
+ if (input_action == INPUT_PASTE) {
+ _clear_clipboard_data();
+ input_action = INPUT_NONE;
+ _update_paste_indicator();
+ return true;
+ } else if (selection.active) {
+ _set_selection(false);
+ return true;
+ } else {
+ selected_palette = -1;
+ mesh_library_palette->unselect_all();
+ update_palette();
+ _update_cursor_instance();
+ return true;
+ }
+ }
+
+ if (k->get_shift() && selection.active && input_action != INPUT_PASTE) {
+
+ if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_PREV_LEVEL))) {
+ selection.click[edit_axis]--;
+ _validate_selection();
+ return true;
+ }
+ if (k->get_scancode() == options->get_popup()->get_item_accelerator(options->get_popup()->get_item_index(MENU_OPTION_NEXT_LEVEL))) {
+ selection.click[edit_axis]++;
+ _validate_selection();
+ return true;
+ }
+ }
+ }
+ }
+
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
@@ -818,7 +939,7 @@ void GridMapEditor::edit(GridMap *p_gridmap) {
input_action = INPUT_NONE;
selection.active = false;
_update_selection_transform();
- _update_duplicate_indicator();
+ _update_paste_indicator();
spatial_editor = Object::cast_to<SpatialEditorPlugin>(editor->get_editor_plugin_screen());
@@ -953,13 +1074,15 @@ void GridMapEditor::_notification(int p_what) {
}
selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario());
- duplicate_instance = VisualServer::get_singleton()->instance_create2(duplicate_mesh, get_tree()->get_root()->get_world()->get_scenario());
+ paste_instance = VisualServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario());
_update_selection_transform();
- _update_duplicate_indicator();
+ _update_paste_indicator();
} break;
case NOTIFICATION_EXIT_TREE: {
+ _clear_clipboard_data();
+
for (int i = 0; i < 3; i++) {
VS::get_singleton()->free(grid_instance[i]);
@@ -970,9 +1093,9 @@ void GridMapEditor::_notification(int p_what) {
}
VisualServer::get_singleton()->free(selection_instance);
- VisualServer::get_singleton()->free(duplicate_instance);
+ VisualServer::get_singleton()->free(paste_instance);
selection_instance = RID();
- duplicate_instance = RID();
+ paste_instance = RID();
} break;
case NOTIFICATION_PROCESS: {
@@ -1065,6 +1188,7 @@ void GridMapEditor::_bind_methods() {
ClassDB::bind_method("_configure", &GridMapEditor::_configure);
ClassDB::bind_method("_item_selected_cbk", &GridMapEditor::_item_selected_cbk);
ClassDB::bind_method("_floor_changed", &GridMapEditor::_floor_changed);
+ ClassDB::bind_method("_set_selection", &GridMapEditor::_set_selection);
ClassDB::bind_method(D_METHOD("_set_display_mode", "mode"), &GridMapEditor::_set_display_mode);
}
@@ -1128,15 +1252,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
options->get_popup()->add_item(TTR("Cursor Back Rotate Z"), MENU_OPTION_CURSOR_BACK_ROTATE_Z, KEY_MASK_SHIFT + KEY_D);
options->get_popup()->add_item(TTR("Cursor Clear Rotation"), MENU_OPTION_CURSOR_CLEAR_ROTATION, KEY_W);
options->get_popup()->add_separator();
- options->get_popup()->add_check_item("Duplicate Selects", MENU_OPTION_DUPLICATE_SELECTS);
- options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Create Area"), MENU_OPTION_SELECTION_MAKE_AREA, KEY_CONTROL + KEY_C);
- options->get_popup()->add_item(TTR("Create Exterior Connector"), MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR);
- options->get_popup()->add_item(TTR("Erase Area"), MENU_OPTION_REMOVE_AREA);
+ options->get_popup()->add_check_item("Paste Selects", MENU_OPTION_PASTE_SELECTS);
options->get_popup()->add_separator();
- options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_SHIFT + KEY_C);
- options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_MASK_SHIFT + KEY_X);
- options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KEY_MASK_SHIFT + KEY_F);
+ options->get_popup()->add_item(TTR("Duplicate Selection"), MENU_OPTION_SELECTION_DUPLICATE, KEY_MASK_CTRL + KEY_C);
+ options->get_popup()->add_item(TTR("Cut Selection"), MENU_OPTION_SELECTION_CUT, KEY_MASK_CTRL + KEY_X);
+ options->get_popup()->add_item(TTR("Clear Selection"), MENU_OPTION_SELECTION_CLEAR, KEY_DELETE);
+ options->get_popup()->add_item(TTR("Fill Selection"), MENU_OPTION_SELECTION_FILL, KEY_MASK_CTRL + KEY_F);
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Settings"), MENU_OPTION_GRIDMAP_SETTINGS);
@@ -1211,7 +1332,7 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
last_mouseover = Vector3(-1, -1, -1);
selection_mesh = VisualServer::get_singleton()->mesh_create();
- duplicate_mesh = VisualServer::get_singleton()->mesh_create();
+ paste_mesh = VisualServer::get_singleton()->mesh_create();
{
//selection mesh create
@@ -1319,12 +1440,12 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid());
d[VS::ARRAY_VERTEX] = triangles;
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh, VS::PRIMITIVE_TRIANGLES, d);
- VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 0, inner_mat->get_rid());
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d);
+ VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid());
d[VS::ARRAY_VERTEX] = lines;
- VisualServer::get_singleton()->mesh_add_surface_from_arrays(duplicate_mesh, VS::PRIMITIVE_LINES, d);
- VisualServer::get_singleton()->mesh_surface_set_material(duplicate_mesh, 1, outer_mat->get_rid());
+ VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d);
+ VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid());
for (int i = 0; i < 3; i++) {
d[VS::ARRAY_VERTEX] = square[i];
@@ -1341,6 +1462,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) {
GridMapEditor::~GridMapEditor() {
+ _clear_clipboard_data();
+
for (int i = 0; i < 3; i++) {
if (grid[i].is_valid())
@@ -1359,9 +1482,9 @@ GridMapEditor::~GridMapEditor() {
if (selection_instance.is_valid())
VisualServer::get_singleton()->free(selection_instance);
- VisualServer::get_singleton()->free(duplicate_mesh);
- if (duplicate_instance.is_valid())
- VisualServer::get_singleton()->free(duplicate_instance);
+ VisualServer::get_singleton()->free(paste_mesh);
+ if (paste_instance.is_valid())
+ VisualServer::get_singleton()->free(paste_instance);
}
void GridMapEditorPlugin::_notification(int p_what) {
diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h
index 59b8ac13da..8e1948ea7d 100644
--- a/modules/gridmap/grid_map_editor_plugin.h
+++ b/modules/gridmap/grid_map_editor_plugin.h
@@ -54,9 +54,9 @@ class GridMapEditor : public VBoxContainer {
INPUT_NONE,
INPUT_PAINT,
INPUT_ERASE,
- INPUT_COPY,
+ INPUT_PICK,
INPUT_SELECT,
- INPUT_DUPLICATE,
+ INPUT_PASTE,
};
enum ClipMode {
@@ -116,8 +116,17 @@ class GridMapEditor : public VBoxContainer {
RID selection_instance;
RID selection_level_mesh[3];
RID selection_level_instance[3];
- RID duplicate_mesh;
- RID duplicate_instance;
+ RID paste_mesh;
+ RID paste_instance;
+
+ struct ClipboardItem {
+ int cell_item;
+ Vector3 grid_offset;
+ int orientation;
+ RID instance;
+ };
+
+ List<ClipboardItem> clipboard_items;
Ref<SpatialMaterial> indicator_mat;
Ref<SpatialMaterial> inner_mat;
@@ -132,9 +141,19 @@ class GridMapEditor : public VBoxContainer {
Vector3 current;
Vector3 begin;
Vector3 end;
- int duplicate_rot;
bool active;
} selection;
+ Selection last_selection;
+
+ struct PasteIndicator {
+
+ Vector3 click;
+ Vector3 current;
+ Vector3 begin;
+ Vector3 end;
+ int orientation;
+ };
+ PasteIndicator paste_indicator;
bool cursor_visible;
Transform cursor_transform;
@@ -148,7 +167,6 @@ class GridMapEditor : public VBoxContainer {
enum Menu {
- MENU_OPTION_CONFIGURE,
MENU_OPTION_NEXT_LEVEL,
MENU_OPTION_PREV_LEVEL,
MENU_OPTION_LOCK_VIEW,
@@ -165,13 +183,11 @@ class GridMapEditor : public VBoxContainer {
MENU_OPTION_CURSOR_BACK_ROTATE_X,
MENU_OPTION_CURSOR_BACK_ROTATE_Z,
MENU_OPTION_CURSOR_CLEAR_ROTATION,
- MENU_OPTION_DUPLICATE_SELECTS,
- MENU_OPTION_SELECTION_MAKE_AREA,
- MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR,
+ MENU_OPTION_PASTE_SELECTS,
MENU_OPTION_SELECTION_DUPLICATE,
+ MENU_OPTION_SELECTION_CUT,
MENU_OPTION_SELECTION_CLEAR,
MENU_OPTION_SELECTION_FILL,
- MENU_OPTION_REMOVE_AREA,
MENU_OPTION_GRIDMAP_SETTINGS
};
@@ -200,10 +216,13 @@ class GridMapEditor : public VBoxContainer {
void _icon_size_changed(float p_value);
- void _update_duplicate_indicator();
- void _duplicate_paste();
+ void _clear_clipboard_data();
+ void _set_clipboard_data();
+ void _update_paste_indicator();
+ void _do_paste();
void _update_selection_transform();
void _validate_selection();
+ void _set_selection(bool p_active, const Vector3 p_begin = Vector3(), const Vector3 p_end = Vector3());
void _floor_changed(float p_value);
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index 947fbb6665..ff26c7fddf 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -79,14 +79,27 @@ namespace Godot
return (real_t)Math.Cosh(s);
}
- public static int Decimals(real_t step)
- {
- return Decimals((decimal)step);
- }
-
- public static int Decimals(decimal step)
- {
- return BitConverter.GetBytes(decimal.GetBits(step)[3])[2];
+ public static int StepDecimals(real_t step)
+ {
+ double[] sd = new double[] {
+ 0.9999,
+ 0.09999,
+ 0.009999,
+ 0.0009999,
+ 0.00009999,
+ 0.000009999,
+ 0.0000009999,
+ 0.00000009999,
+ 0.000000009999,
+ };
+ double abs = Mathf.Abs(step);
+ double decs = abs - (int)abs; // Strip away integer part
+ for (int i = 0; i < sd.Length; i++) {
+ if (decs >= sd[i]) {
+ return i;
+ }
+ }
+ return 0;
}
public static real_t Deg2Rad(real_t deg)
diff --git a/modules/mono/glue/Managed/Files/MathfEx.cs b/modules/mono/glue/Managed/Files/MathfEx.cs
index d6eb65b097..b96f01bc2e 100644
--- a/modules/mono/glue/Managed/Files/MathfEx.cs
+++ b/modules/mono/glue/Managed/Files/MathfEx.cs
@@ -21,6 +21,16 @@ namespace Godot
public const real_t Epsilon = 1e-06f;
#endif
+ public static int DecimalCount(real_t s)
+ {
+ return DecimalCount((decimal)s);
+ }
+
+ public static int DecimalCount(decimal s)
+ {
+ return BitConverter.GetBytes(decimal.GetBits(s)[3])[2];
+ }
+
public static int CeilToInt(real_t s)
{
return (int)Math.Ceiling(s);
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 0ef66577fe..1fdddd3925 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -33,6 +33,7 @@
#include "core/os/file_access.h"
#include <stdio.h>
+#include <stdlib.h>
namespace {
@@ -210,7 +211,7 @@ String str_format(const char *p_format, ...) {
#endif
#if defined(MINGW_ENABLED) || defined(_MSC_VER)
-#define vsnprintf vsnprintf_s
+#define vsnprintf(m_buffer, m_count, m_format, m_argptr) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_argptr)
#endif
String str_format(const char *p_format, va_list p_list) {
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 82f323e8cf..8f6ffcc83f 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -192,9 +192,9 @@ static void _compress_pvrtc4(Image *p_img) {
Ref<Image> img = p_img->duplicate();
bool make_mipmaps = false;
- if (img->get_width() % 8 || img->get_height() % 8) {
+ if (!img->is_size_po2() || img->get_width() != img->get_height()) {
make_mipmaps = img->has_mipmaps();
- img->resize(img->get_width() + (8 - (img->get_width() % 8)), img->get_height() + (8 - (img->get_height() % 8)));
+ img->resize_to_po2(true);
}
img->convert(Image::FORMAT_RGBA8);
if (!img->has_mipmaps() && make_mipmaps)
@@ -204,7 +204,7 @@ static void _compress_pvrtc4(Image *p_img) {
Ref<Image> new_img;
new_img.instance();
- new_img->create(img->get_width(), img->get_height(), true, use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4);
+ new_img->create(img->get_width(), img->get_height(), img->has_mipmaps(), use_alpha ? Image::FORMAT_PVRTC4A : Image::FORMAT_PVRTC4);
PoolVector<uint8_t> data = new_img->get_data();
{
@@ -221,7 +221,6 @@ static void _compress_pvrtc4(Image *p_img) {
/* red and Green colors are swapped. */
new (dp) Javelin::ColorRgba<unsigned char>(r[ofs + 4 * j + 2], r[ofs + 4 * j + 1], r[ofs + 4 * j], r[ofs + 4 * j + 3]);
}
-
new_img->get_mipmap_offset_size_and_dimensions(i, ofs, size, w, h);
Javelin::PvrTcEncoder::EncodeRgba4Bpp(&wr[ofs], bm);
}
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 2a3d0843a8..f45644f1eb 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1864,7 +1864,6 @@ public:
return ERR_FILE_NOT_FOUND;
}
- ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
int ret = unzGoToFirstFile(pkg);
zlib_filefunc_def io2 = io;
@@ -2204,7 +2203,6 @@ public:
return ERR_FILE_NOT_FOUND;
}
- ERR_FAIL_COND_V(!tmp_unaligned, ERR_CANT_OPEN);
ret = unzGoToFirstFile(tmp_unaligned);
io2 = io;
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 85d4b9e847..e1083aeefc 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -920,7 +920,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name);
return ERR_CANT_OPEN;
}
- ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
+
int ret = unzGoToFirstFile(src_pkg_zip);
Vector<uint8_t> project_file_data;
while (ret == UNZ_OK) {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 1a63d6ff75..89212b0e5e 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -441,7 +441,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_NOT_FOUND;
}
- ERR_FAIL_COND_V(!src_pkg_zip, ERR_CANT_OPEN);
int ret = unzGoToFirstFile(src_pkg_zip);
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp
index 1e7f393bdd..44d3cf1910 100644
--- a/platform/x11/crash_handler_x11.cpp
+++ b/platform/x11/crash_handler_x11.cpp
@@ -96,12 +96,10 @@ static void handle_crash(int sig) {
String output = "";
// Try to get the file/line number using addr2line
- if (OS::get_singleton()) {
- int ret;
- Error err = OS::get_singleton()->execute(String("addr2line"), args, true, NULL, &output, &ret);
- if (err == OK) {
- output.erase(output.length() - 1, 1);
- }
+ int ret;
+ Error err = OS::get_singleton()->execute(String("addr2line"), args, true, NULL, &output, &ret);
+ if (err == OK) {
+ output.erase(output.length() - 1, 1);
}
fprintf(stderr, "[%ld] %s (%ls)\n", i, fname, output.c_str());
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 267ac08a72..d5ca3742db 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -503,35 +503,33 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
current_cursor = CURSOR_ARROW;
- if (cursor_theme) {
- for (int i = 0; i < CURSOR_MAX; i++) {
-
- static const char *cursor_file[] = {
- "left_ptr",
- "xterm",
- "hand2",
- "cross",
- "watch",
- "left_ptr_watch",
- "fleur",
- "hand1",
- "X_cursor",
- "sb_v_double_arrow",
- "sb_h_double_arrow",
- "size_bdiag",
- "size_fdiag",
- "hand1",
- "sb_v_double_arrow",
- "sb_h_double_arrow",
- "question_arrow"
- };
+ for (int i = 0; i < CURSOR_MAX; i++) {
- img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
- if (img[i]) {
- cursors[i] = XcursorImageLoadCursor(x11_display, img[i]);
- } else {
- print_verbose("Failed loading custom cursor: " + String(cursor_file[i]));
- }
+ static const char *cursor_file[] = {
+ "left_ptr",
+ "xterm",
+ "hand2",
+ "cross",
+ "watch",
+ "left_ptr_watch",
+ "fleur",
+ "hand1",
+ "X_cursor",
+ "sb_v_double_arrow",
+ "sb_h_double_arrow",
+ "size_bdiag",
+ "size_fdiag",
+ "hand1",
+ "sb_v_double_arrow",
+ "sb_h_double_arrow",
+ "question_arrow"
+ };
+
+ img[i] = XcursorLibraryLoadImage(cursor_file[i], cursor_theme, cursor_size);
+ if (img[i]) {
+ cursors[i] = XcursorImageLoadCursor(x11_display, img[i]);
+ } else {
+ print_verbose("Failed loading custom cursor: " + String(cursor_file[i]));
}
}
@@ -1192,9 +1190,12 @@ void OS_X11::set_window_position(const Point2 &p_position) {
unsigned long remaining;
unsigned char *data = NULL;
if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
- long *extents = (long *)data;
- x = extents[0];
- y = extents[2];
+ if (format == 32 && len == 4) {
+ long *extents = (long *)data;
+ x = extents[0];
+ y = extents[2];
+ }
+ XFree(data);
}
}
XMoveWindow(x11_display, x11_window, p_position.x - x, p_position.y - y);
@@ -1220,9 +1221,12 @@ Size2 OS_X11::get_real_window_size() const {
unsigned long remaining;
unsigned char *data = NULL;
if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) {
- long *extents = (long *)data;
- w += extents[0] + extents[1]; // left, right
- h += extents[2] + extents[3]; // top, bottom
+ if (format == 32 && len == 4) {
+ long *extents = (long *)data;
+ w += extents[0] + extents[1]; // left, right
+ h += extents[2] + extents[3]; // top, bottom
+ }
+ XFree(data);
}
return Size2(w, h);
}
diff --git a/platform/x11/power_x11.cpp b/platform/x11/power_x11.cpp
index 943c2b1383..50da6a4967 100644
--- a/platform/x11/power_x11.cpp
+++ b/platform/x11/power_x11.cpp
@@ -115,7 +115,7 @@ bool PowerX11::make_proc_acpi_key_val(char **_ptr, char **_key, char **_val) {
*(ptr++) = '\0'; /* terminate the key. */
- while ((*ptr == ' ') && (*ptr != '\0')) {
+ while (*ptr == ' ') {
ptr++; /* skip whitespace. */
}
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index f808d6c234..e95781c181 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -376,7 +376,7 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const {
bool pressing;
if (status.press_attempt) {
- pressing = status.pressing_inside;
+ pressing = (status.pressing_inside || keep_pressed_outside);
if (status.pressed)
pressing = !pressing;
} else {
@@ -446,6 +446,16 @@ Control::FocusMode BaseButton::get_enabled_focus_mode() const {
return enabled_focus_mode;
}
+void BaseButton::set_keep_pressed_outside(bool p_on) {
+
+ keep_pressed_outside = p_on;
+}
+
+bool BaseButton::is_keep_pressed_outside() const {
+
+ return keep_pressed_outside;
+}
+
void BaseButton::set_shortcut(const Ref<ShortCut> &p_shortcut) {
if (shortcut.is_null() == p_shortcut.is_null())
@@ -528,6 +538,8 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_draw_mode"), &BaseButton::get_draw_mode);
ClassDB::bind_method(D_METHOD("set_enabled_focus_mode", "mode"), &BaseButton::set_enabled_focus_mode);
ClassDB::bind_method(D_METHOD("get_enabled_focus_mode"), &BaseButton::get_enabled_focus_mode);
+ ClassDB::bind_method(D_METHOD("set_keep_pressed_outside", "enabled"), &BaseButton::set_keep_pressed_outside);
+ ClassDB::bind_method(D_METHOD("is_keep_pressed_outside"), &BaseButton::is_keep_pressed_outside);
ClassDB::bind_method(D_METHOD("set_shortcut", "shortcut"), &BaseButton::set_shortcut);
ClassDB::bind_method(D_METHOD("get_shortcut"), &BaseButton::get_shortcut);
@@ -549,6 +561,7 @@ void BaseButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask");
ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group");
@@ -566,6 +579,7 @@ BaseButton::BaseButton() {
toggle_mode = false;
shortcut_in_tooltip = true;
+ keep_pressed_outside = false;
status.pressed = false;
status.press_attempt = false;
status.hovering = false;
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 9a00cc79f2..22a8f6d8fe 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -52,6 +52,7 @@ private:
int button_mask;
bool toggle_mode;
bool shortcut_in_tooltip;
+ bool keep_pressed_outside;
FocusMode enabled_focus_mode;
Ref<ShortCut> shortcut;
@@ -110,6 +111,9 @@ public:
void set_action_mode(ActionMode p_mode);
ActionMode get_action_mode() const;
+ void set_keep_pressed_outside(bool p_on);
+ bool is_keep_pressed_outside() const;
+
void set_button_mask(int p_mask);
int get_button_mask() const;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 8825891807..e77ee8c744 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -93,14 +93,14 @@ Size2 PopupMenu::get_minimum_size() const {
if (items[i].submenu != "")
size.width += get_icon("submenu")->get_width();
- if (has_check)
- size.width += check_w;
- max_w = MAX(max_w, size.width + icon_w);
+ max_w = MAX(max_w, size.width);
minsize.height += size.height;
}
- minsize.width += max_w + accel_max_w;
+ minsize.width += max_w + icon_w + accel_max_w;
+ if (has_check)
+ minsize.width += check_w;
return minsize;
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 3eb4e6d75a..9ab30b1976 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1560,8 +1560,7 @@ void TextEdit::_consume_pair_symbol(CharType ch) {
}
if ((ch == '\'' || ch == '"') &&
- cursor_get_column() > 0 &&
- _is_text_char(text[cursor.line][cursor_get_column() - 1])) {
+ cursor_get_column() > 0 && _is_text_char(text[cursor.line][cursor_get_column() - 1]) && !_is_pair_right_symbol(text[cursor.line][cursor_get_column()])) {
insert_text_at_cursor(ch_single);
cursor_set_column(cursor_position_to_move);
return;
@@ -2597,6 +2596,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
FALLTHROUGH;
}
+#ifdef APPLE_STYLE_KEYS
+ case KEY_B: {
+ if (!k->get_control()) {
+ scancode_handled = false;
+ break;
+ }
+ FALLTHROUGH;
+ }
+#endif
case KEY_LEFT: {
if (k->get_shift())
@@ -2610,9 +2618,22 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
#ifdef APPLE_STYLE_KEYS
if (k->get_command()) {
- cursor_set_column(0);
+ // Start at first column (it's slightly faster that way) and look for the first non-whitespace character.
+ int new_cursor_pos = 0;
+ for (int i = 0; i < text[cursor.line].length(); ++i) {
+ if (!_is_whitespace(text[cursor.line][i])) {
+ new_cursor_pos = i;
+ break;
+ }
+ }
+ if (new_cursor_pos == cursor.column) {
+ // We're already at the first text character, so move to the very beginning of the line.
+ cursor_set_column(0);
+ } else {
+ // We're somewhere to the right of the first text character; move to the first one.
+ cursor_set_column(new_cursor_pos);
+ }
} else if (k->get_alt()) {
-
#else
if (k->get_alt()) {
scancode_handled = false;
@@ -2660,6 +2681,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
FALLTHROUGH;
}
+#ifdef APPLE_STYLE_KEYS
+ case KEY_F: {
+ if (!k->get_control()) {
+ scancode_handled = false;
+ break;
+ }
+ FALLTHROUGH;
+ }
+#endif
case KEY_RIGHT: {
if (k->get_shift())
@@ -2721,6 +2751,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
FALLTHROUGH;
}
+#ifdef APPLE_STYLE_KEYS
+ case KEY_P: {
+ if (!k->get_control()) {
+ scancode_handled = false;
+ break;
+ }
+ FALLTHROUGH;
+ }
+#endif
case KEY_UP: {
if (k->get_alt()) {
@@ -2774,6 +2813,15 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
FALLTHROUGH;
}
+#ifdef APPLE_STYLE_KEYS
+ case KEY_N: {
+ if (!k->get_control()) {
+ scancode_handled = false;
+ break;
+ }
+ FALLTHROUGH;
+ }
+#endif
case KEY_DOWN: {
if (k->get_alt()) {
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index b66ae184e9..3d38a8902f 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -93,7 +93,6 @@ private:
template <class T>
struct TKey : public Key {
- float time;
T value;
};