summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/os/os.h1
-rw-r--r--core/script_debugger_local.cpp207
-rw-r--r--core/script_debugger_local.h6
-rw-r--r--core/script_language.h1
-rw-r--r--core/ustring.cpp4
-rw-r--r--doc/classes/Generic6DOFJoint.xml57
-rw-r--r--doc/classes/PhysicsServer.xml27
-rw-r--r--drivers/unix/os_unix.cpp17
-rw-r--r--drivers/unix/os_unix.h1
-rw-r--r--editor/editor_data.cpp4
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/rename_dialog.cpp691
-rw-r--r--editor/rename_dialog.h119
-rw-r--r--editor/scene_tree_dock.cpp15
-rw-r--r--editor/scene_tree_dock.h3
-rw-r--r--main/main.cpp1
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp13
-rw-r--r--modules/gdscript/gdscript_functions.cpp22
-rw-r--r--platform/android/export/export.cpp4
-rw-r--r--platform/windows/detect.py10
-rw-r--r--platform/windows/os_windows.cpp19
-rw-r--r--platform/windows/os_windows.h1
-rw-r--r--scene/2d/animated_sprite.cpp19
-rw-r--r--scene/2d/animated_sprite.h4
-rw-r--r--scene/2d/sprite.cpp34
-rw-r--r--scene/2d/tile_map.cpp8
-rw-r--r--scene/3d/physics_joint.cpp21
-rw-r--r--scene/3d/physics_joint.h3
-rw-r--r--scene/gui/line_edit.h2
-rw-r--r--scene/gui/option_button.cpp2
-rw-r--r--scene/main/instance_placeholder.cpp24
-rw-r--r--scene/main/instance_placeholder.h1
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--servers/physics_server.cpp3
-rw-r--r--servers/physics_server.h3
35 files changed, 1240 insertions, 113 deletions
diff --git a/core/os/os.h b/core/os/os.h
index 943c0498f1..f6404468b1 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -320,6 +320,7 @@ public:
virtual void disable_crash_handler() {}
virtual bool is_disable_crash_handler() const { return false; }
+ virtual void initialize_debugging() {}
enum CursorShape {
CURSOR_ARROW,
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index c0e115e300..55d7270473 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -29,12 +29,23 @@
/*************************************************************************/
#include "script_debugger_local.h"
+#include "scene/main/scene_tree.h"
#include "os/os.h"
void ScriptDebuggerLocal::debug(ScriptLanguage *p_script, bool p_can_continue) {
- print_line("Debugger Break, Reason: '" + p_script->debug_get_error() + "'");
+ if (!target_function.empty()) {
+ String current_function = p_script->debug_get_stack_level_function(0);
+ if (current_function != target_function) {
+ set_depth(0);
+ set_lines_left(1);
+ return;
+ }
+ target_function = "";
+ }
+
+ print_line("\nDebugger Break, Reason: '" + p_script->debug_get_error() + "'");
print_line("*Frame " + itos(0) + " - " + p_script->debug_get_stack_level_source(0) + ":" + itos(p_script->debug_get_stack_level_line(0)) + " in function '" + p_script->debug_get_stack_level_function(0) + "'");
print_line("Enter \"help\" for assistance.");
int current_frame = 0;
@@ -44,8 +55,11 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script, bool p_can_continue) {
OS::get_singleton()->print("debug> ");
String line = OS::get_singleton()->get_stdin_string().strip_edges();
+ // Cache options
+ String variable_prefix = options["variable_prefix"];
+
if (line == "") {
- print_line("Debugger Break, Reason: '" + p_script->debug_get_error() + "'");
+ print_line("\nDebugger Break, Reason: '" + p_script->debug_get_error() + "'");
print_line("*Frame " + itos(current_frame) + " - " + p_script->debug_get_stack_level_source(current_frame) + ":" + itos(p_script->debug_get_stack_level_line(current_frame)) + " in function '" + p_script->debug_get_stack_level_function(current_frame) + "'");
print_line("Enter \"help\" for assistance.");
} else if (line == "c" || line == "continue")
@@ -72,38 +86,56 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script, bool p_can_continue) {
}
}
+ } else if (line.begins_with("set")) {
+
+ if (line.get_slice_count(" ") == 1) {
+
+ for (Map<String, String>::Element *E = options.front(); E; E = E->next()) {
+ print_line("\t" + E->key() + "=" + E->value());
+ }
+
+ } else {
+ String key_value = line.get_slicec(' ', 1);
+ int value_pos = key_value.find("=");
+
+ if (value_pos < 0) {
+ print_line("Error: Invalid set format. Use: set key=value");
+ } else {
+
+ String key = key_value.left(value_pos);
+
+ if (!options.has(key)) {
+ print_line("Error: Unknown option " + key);
+ } else {
+
+ // Allow explicit tab character
+ String value = key_value.right(value_pos + 1).replace("\\t", "\t");
+
+ options[key] = value;
+ }
+ }
+ }
+
} else if (line == "lv" || line == "locals") {
List<String> locals;
List<Variant> values;
p_script->debug_get_stack_level_locals(current_frame, &locals, &values);
- List<Variant>::Element *V = values.front();
- for (List<String>::Element *E = locals.front(); E; E = E->next()) {
- print_line(E->get() + ": " + String(V->get()));
- V = V->next();
- }
+ print_variables(locals, values, variable_prefix);
} else if (line == "gv" || line == "globals") {
- List<String> locals;
+ List<String> globals;
List<Variant> values;
- p_script->debug_get_globals(&locals, &values);
- List<Variant>::Element *V = values.front();
- for (List<String>::Element *E = locals.front(); E; E = E->next()) {
- print_line(E->get() + ": " + String(V->get()));
- V = V->next();
- }
+ p_script->debug_get_globals(&globals, &values);
+ print_variables(globals, values, variable_prefix);
} else if (line == "mv" || line == "members") {
- List<String> locals;
+ List<String> members;
List<Variant> values;
- p_script->debug_get_stack_level_members(current_frame, &locals, &values);
- List<Variant>::Element *V = values.front();
- for (List<String>::Element *E = locals.front(); E; E = E->next()) {
- print_line(E->get() + ": " + String(V->get()));
- V = V->next();
- }
+ p_script->debug_get_stack_level_members(current_frame, &members, &values);
+ print_variables(members, values, variable_prefix);
} else if (line.begins_with("p") || line.begins_with("print")) {
@@ -121,65 +153,149 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script, bool p_can_continue) {
set_depth(-1);
set_lines_left(1);
break;
- } else if (line.begins_with("n") || line.begins_with("next")) {
+ } else if (line == "n" || line == "next") {
set_depth(0);
set_lines_left(1);
break;
+ } else if (line == "fin" || line == "finish") {
+
+ String current_function = p_script->debug_get_stack_level_function(0);
+
+ for (int i = 0; i < total_frames; i++) {
+ target_function = p_script->debug_get_stack_level_function(i);
+ if (target_function != current_function) {
+ set_depth(0);
+ set_lines_left(1);
+ return;
+ }
+ }
+
+ print_line("Error: Reached last frame.");
+ target_function = "";
+
} else if (line.begins_with("br") || line.begins_with("break")) {
if (line.get_slice_count(" ") <= 1) {
- //show breakpoints
+
+ const Map<int, Set<StringName> > &breakpoints = get_breakpoints();
+ if (breakpoints.size() == 0) {
+ print_line("No Breakpoints.");
+ continue;
+ }
+
+ print_line("Breakpoint(s): " + itos(breakpoints.size()));
+ for (Map<int, Set<StringName> >::Element *E = breakpoints.front(); E; E = E->next()) {
+ print_line("\t" + String(E->value().front()->get()) + ":" + itos(E->key()));
+ }
+
} else {
- String bppos = line.get_slicec(' ', 1);
- String source = bppos.get_slicec(':', 0).strip_edges();
- int line = bppos.get_slicec(':', 1).strip_edges().to_int();
+ Pair<String, int> breakpoint = to_breakpoint(line);
+
+ String source = breakpoint.first;
+ int linenr = breakpoint.second;
- source = breakpoint_find_source(source);
+ if (source.empty())
+ continue;
- insert_breakpoint(line, source);
+ insert_breakpoint(linenr, source);
- print_line("BreakPoint at " + source + ":" + itos(line));
+ print_line("Added breakpoint at " + source + ":" + itos(linenr));
}
+ } else if (line == "q" || line == "quit") {
+
+ // Do not stop again on quit
+ clear_breakpoints();
+ ScriptDebugger::get_singleton()->set_depth(-1);
+ ScriptDebugger::get_singleton()->set_lines_left(-1);
+
+ SceneTree::get_singleton()->quit();
+ break;
} else if (line.begins_with("delete")) {
if (line.get_slice_count(" ") <= 1) {
clear_breakpoints();
} else {
- String bppos = line.get_slicec(' ', 1);
- String source = bppos.get_slicec(':', 0).strip_edges();
- int line = bppos.get_slicec(':', 1).strip_edges().to_int();
+ Pair<String, int> breakpoint = to_breakpoint(line);
+
+ String source = breakpoint.first;
+ int linenr = breakpoint.second;
- source = breakpoint_find_source(source);
+ if (source.empty())
+ continue;
- remove_breakpoint(line, source);
+ remove_breakpoint(linenr, source);
- print_line("Removed BreakPoint at " + source + ":" + itos(line));
+ print_line("Removed breakpoint at " + source + ":" + itos(linenr));
}
} else if (line == "h" || line == "help") {
print_line("Built-In Debugger command list:\n");
- print_line("\tc,continue :\t\t Continue execution.");
- print_line("\tbt,backtrace :\t\t Show stack trace (frames).");
+ print_line("\tc,continue\t\t Continue execution.");
+ print_line("\tbt,backtrace\t\t Show stack trace (frames).");
print_line("\tfr,frame <frame>:\t Change current frame.");
- print_line("\tlv,locals :\t\t Show local variables for current frame.");
- print_line("\tmv,members :\t\t Show member variables for \"this\" in frame.");
- print_line("\tgv,globals :\t\t Show global variables.");
- print_line("\tp,print <expr> :\t Execute and print variable in expression.");
- print_line("\ts,step :\t\t Step to next line.");
- print_line("\tn,next :\t\t Next line.");
- print_line("\tbr,break source:line :\t Place a breakpoint.");
- print_line("\tdelete [source:line]:\t\t Delete one/all breakpoints.");
+ print_line("\tlv,locals\t\t Show local variables for current frame.");
+ print_line("\tmv,members\t\t Show member variables for \"this\" in frame.");
+ print_line("\tgv,globals\t\t Show global variables.");
+ print_line("\tp,print <expr>\t\t Execute and print variable in expression.");
+ print_line("\ts,step\t\t\t Step to next line.");
+ print_line("\tn,next\t\t\t Next line.");
+ print_line("\tfin,finish\t\t Step out of current frame.");
+ print_line("\tbr,break [source:line]\t List all breakpoints or place a breakpoint.");
+ print_line("\tdelete [source:line]:\t Delete one/all breakpoints.");
+ print_line("\tset [key=value]:\t List all options, or set one.");
+ print_line("\tq,quit\t\t\t Quit application.");
} else {
print_line("Error: Invalid command, enter \"help\" for assistance.");
}
}
}
+void ScriptDebuggerLocal::print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix) {
+
+ String value;
+ Vector<String> value_lines;
+ const List<Variant>::Element *V = values.front();
+ for (const List<String>::Element *E = names.front(); E; E = E->next()) {
+
+ value = String(V->get());
+
+ if (variable_prefix.empty()) {
+ print_line(E->get() + ": " + String(V->get()));
+ } else {
+
+ print_line(E->get() + ":");
+ value_lines = value.split("\n");
+ for (int i = 0; i < value_lines.size(); ++i) {
+ print_line(variable_prefix + value_lines[i]);
+ }
+ }
+
+ V = V->next();
+ }
+}
+
+Pair<String, int> ScriptDebuggerLocal::to_breakpoint(const String &p_line) {
+
+ String breakpoint_part = p_line.get_slicec(' ', 1);
+ Pair<String, int> breakpoint;
+
+ int last_colon = breakpoint_part.rfind(":");
+ if (last_colon < 0) {
+ print_line("Error: Invalid breakpoint format. Expected [source:line]");
+ return breakpoint;
+ }
+
+ breakpoint.first = breakpoint_find_source(breakpoint_part.left(last_colon).strip_edges());
+ breakpoint.second = breakpoint_part.right(last_colon).strip_edges().to_int();
+
+ return breakpoint;
+}
+
struct _ScriptDebuggerLocalProfileInfoSort {
bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const {
@@ -304,4 +420,5 @@ ScriptDebuggerLocal::ScriptDebuggerLocal() {
profiling = false;
idle_accum = OS::get_singleton()->get_ticks_usec();
+ options["variable_prefix"] = "";
}
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index c87bc90bb4..7eea6ef215 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -31,6 +31,7 @@
#ifndef SCRIPT_DEBUGGER_LOCAL_H
#define SCRIPT_DEBUGGER_LOCAL_H
+#include "list.h"
#include "script_language.h"
class ScriptDebuggerLocal : public ScriptDebugger {
@@ -38,9 +39,14 @@ class ScriptDebuggerLocal : public ScriptDebugger {
bool profiling;
float frame_time, idle_time, physics_time, physics_frame_time;
uint64_t idle_accum;
+ String target_function;
+ Map<String, String> options;
Vector<ScriptLanguage::ProfilingInfo> pinfo;
+ Pair<String, int> to_breakpoint(const String &p_line);
+ void print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix);
+
public:
void debug(ScriptLanguage *p_script, bool p_can_continue);
virtual void send_message(const String &p_message, const Array &p_args);
diff --git a/core/script_language.h b/core/script_language.h
index 0c1f99cea6..55a20c7478 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -386,6 +386,7 @@ public:
bool is_breakpoint(int p_line, const StringName &p_source) const;
bool is_breakpoint_line(int p_line) const;
void clear_breakpoints();
+ const Map<int, Set<StringName> > &get_breakpoints() const { return breakpoints; }
virtual void debug(ScriptLanguage *p_script, bool p_can_continue = true) = 0;
virtual void idle_poll();
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 921d20a6fd..85b7a16e6a 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -945,8 +945,8 @@ String String::num(double p_num, int p_decimals) {
#ifndef NO_USE_STDLIB
- if (p_decimals > 12)
- p_decimals = 12;
+ if (p_decimals > 16)
+ p_decimals = 16;
char fmt[7];
fmt[0] = '%';
diff --git a/doc/classes/Generic6DOFJoint.xml b/doc/classes/Generic6DOFJoint.xml
index 2aec6d7f4e..0863ead4ec 100644
--- a/doc/classes/Generic6DOFJoint.xml
+++ b/doc/classes/Generic6DOFJoint.xml
@@ -167,6 +167,33 @@
<member name="linear_limit_z/upper_distance" type="float" setter="set_param_z" getter="get_param_z">
The maximum difference between the pivot points' z-axis.
</member>
+ <member name="linear_motor_x/enabled" type="bool" setter="set_flag_x" getter="get_flag_x">
+ If [code]true[/code] then there is a linear motor on the x-axis. It will attempt to reach the target velocity while staying within the force limits.
+ </member>
+ <member name="linear_motor_x/force_limit" type="float" setter="set_param_x" getter="get_param_x">
+ The maximum force the linear motor can apply on the x-axis while trying to reach the target velocity.
+ </member>
+ <member name="linear_motor_x/target_velocity" type="float" setter="set_param_x" getter="get_param_x">
+ The speed that the linear motor will attempt to reach on the x-axis.
+ </member>
+ <member name="linear_motor_y/enabled" type="bool" setter="set_flag_y" getter="get_flag_y">
+ If [code]true[/code] then there is a linear motor on the y-axis. It will attempt to reach the target velocity while staying within the force limits.
+ </member>
+ <member name="linear_motor_y/force_limit" type="float" setter="set_param_y" getter="get_param_y">
+ The maximum force the linear motor can apply on the y-axis while trying to reach the target velocity.
+ </member>
+ <member name="linear_motor_y/target_velocity" type="float" setter="set_param_y" getter="get_param_y">
+ The speed that the linear motor will attempt to reach on the y-axis.
+ </member>
+ <member name="linear_motor_z/enabled" type="bool" setter="set_flag_z" getter="get_flag_z">
+ If [code]true[/code] then there is a linear motor on the z-axis. It will attempt to reach the target velocity while staying within the force limits.
+ </member>
+ <member name="linear_motor_z/force_limit" type="float" setter="set_param_z" getter="get_param_z">
+ The maximum force the linear motor can apply on the z-axis while trying to reach the target velocity.
+ </member>
+ <member name="linear_motor_z/target_velocity" type="float" setter="set_param_z" getter="get_param_z">
+ The speed that the linear motor will attempt to reach on the z-axis.
+ </member>
</members>
<constants>
<constant name="PARAM_LINEAR_LOWER_LIMIT" value="0" enum="Param">
@@ -184,34 +211,40 @@
<constant name="PARAM_LINEAR_DAMPING" value="4" enum="Param">
The amount of damping that happens at the linear motion across the axes.
</constant>
- <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="5" enum="Param">
+ <constant name="PARAM_LINEAR_MOTOR_TARGET_VELOCITY" value="5" enum="Param">
+ The velocity the linear motor will try to reach.
+ </constant>
+ <constant name="PARAM_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="Param">
+ The maximum force the linear motor will apply while trying to reach the velocity target.
+ </constant>
+ <constant name="PARAM_ANGULAR_LOWER_LIMIT" value="7" enum="Param">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="6" enum="Param">
+ <constant name="PARAM_ANGULAR_UPPER_LIMIT" value="8" enum="Param">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="7" enum="Param">
+ <constant name="PARAM_ANGULAR_LIMIT_SOFTNESS" value="9" enum="Param">
The speed of all rotations across the axes.
</constant>
- <constant name="PARAM_ANGULAR_DAMPING" value="8" enum="Param">
+ <constant name="PARAM_ANGULAR_DAMPING" value="10" enum="Param">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="PARAM_ANGULAR_RESTITUTION" value="9" enum="Param">
+ <constant name="PARAM_ANGULAR_RESTITUTION" value="11" enum="Param">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="10" enum="Param">
+ <constant name="PARAM_ANGULAR_FORCE_LIMIT" value="12" enum="Param">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="PARAM_ANGULAR_ERP" value="11" enum="Param">
+ <constant name="PARAM_ANGULAR_ERP" value="13" enum="Param">
When rotating across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="12" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="Param">
Target speed for the motor at the axes.
</constant>
- <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="13" enum="Param">
+ <constant name="PARAM_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="Param">
Maximum acceleration for the motor at the axes.
</constant>
- <constant name="PARAM_MAX" value="14" enum="Param">
+ <constant name="PARAM_MAX" value="16" enum="Param">
End flag of PARAM_* constants, used internally.
</constant>
<constant name="FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="Flag">
@@ -223,7 +256,9 @@
<constant name="FLAG_ENABLE_MOTOR" value="2" enum="Flag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
- <constant name="FLAG_MAX" value="3" enum="Flag">
+ <constant name="FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="Flag">
+ </constant>
+ <constant name="FLAG_MAX" value="4" enum="Flag">
End flag of FLAG_* constants, used internally.
</constant>
</constants>
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index 6c3a435360..dd2c322ee3 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -1331,31 +1331,37 @@
<constant name="G6DOF_JOINT_LINEAR_DAMPING" value="4" enum="G6DOFJointAxisParam">
The amount of damping that happens at the linear motion across the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="5" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY" value="5" enum="G6DOFJointAxisParam">
+ The velocity that the joint's linear motor will attempt to reach.
+ </constant>
+ <constant name="G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT" value="6" enum="G6DOFJointAxisParam">
+ The maximum force that the linear motor can apply while trying to reach the target velocity.
+ </constant>
+ <constant name="G6DOF_JOINT_ANGULAR_LOWER_LIMIT" value="7" enum="G6DOFJointAxisParam">
The minimum rotation in negative direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="6" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_UPPER_LIMIT" value="8" enum="G6DOFJointAxisParam">
The minimum rotation in positive direction to break loose and rotate around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="7" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS" value="9" enum="G6DOFJointAxisParam">
A factor that gets multiplied onto all rotations across the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="8" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_DAMPING" value="10" enum="G6DOFJointAxisParam">
The amount of rotational damping across the axes. The lower, the more dampening occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="9" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_RESTITUTION" value="11" enum="G6DOFJointAxisParam">
The amount of rotational restitution across the axes. The lower, the more restitution occurs.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="10" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_FORCE_LIMIT" value="12" enum="G6DOFJointAxisParam">
The maximum amount of force that can occur, when rotating around the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_ERP" value="11" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_ERP" value="13" enum="G6DOFJointAxisParam">
When correcting the crossing of limits in rotation across the axes, this error tolerance factor defines how much the correction gets slowed down. The lower, the slower.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="12" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY" value="14" enum="G6DOFJointAxisParam">
Target speed for the motor at the axes.
</constant>
- <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="13" enum="G6DOFJointAxisParam">
+ <constant name="G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT" value="15" enum="G6DOFJointAxisParam">
Maximum acceleration for the motor at the axes.
</constant>
<constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT" value="0" enum="G6DOFJointAxisFlag">
@@ -1367,6 +1373,9 @@
<constant name="G6DOF_JOINT_FLAG_ENABLE_MOTOR" value="2" enum="G6DOFJointAxisFlag">
If [code]set[/code] there is a rotational motor across these axes.
</constant>
+ <constant name="G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR" value="3" enum="G6DOFJointAxisFlag">
+ If [code]set[/code] there is a linear motor on this axis that targets a specific velocity.
+ </constant>
<constant name="SHAPE_PLANE" value="0" enum="ShapeType">
The [Shape] is a [PlaneShape].
</constant>
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index eeb3b31fc2..1e34d63b13 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -73,6 +73,23 @@ void OS_Unix::debug_break() {
assert(false);
};
+static void handle_interrupt(int sig) {
+ if (ScriptDebugger::get_singleton() == NULL)
+ return;
+
+ ScriptDebugger::get_singleton()->set_depth(-1);
+ ScriptDebugger::get_singleton()->set_lines_left(1);
+}
+
+void OS_Unix::initialize_debugging() {
+
+ if (ScriptDebugger::get_singleton() != NULL) {
+ struct sigaction action;
+ action.sa_handler = handle_interrupt;
+ sigaction(SIGINT, &action, NULL);
+ }
+}
+
int OS_Unix::unix_initialize_audio(int p_audio_driver) {
return 0;
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index db0fe1e00b..95b74d23ff 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -101,6 +101,7 @@ public:
virtual int get_processor_count() const;
virtual void debug_break();
+ virtual void initialize_debugging();
virtual String get_executable_path() const;
virtual String get_user_data_dir() const;
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index b584107bcb..4ac3e33cb9 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -898,7 +898,7 @@ Array EditorSelection::_get_transformable_selected_nodes() {
return ret;
}
-Array EditorSelection::_get_selected_nodes() {
+Array EditorSelection::get_selected_nodes() {
Array ret;
@@ -916,7 +916,7 @@ void EditorSelection::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &EditorSelection::clear);
ClassDB::bind_method(D_METHOD("add_node", "node"), &EditorSelection::add_node);
ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node);
- ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::_get_selected_nodes);
+ ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::get_selected_nodes);
ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::_get_transformable_selected_nodes);
ClassDB::bind_method(D_METHOD("_emit_change"), &EditorSelection::_emit_change);
ADD_SIGNAL(MethodInfo("selection_changed"));
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 5a0b58464a..f020d07ea7 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -226,7 +226,6 @@ private:
List<Node *> selected_node_list;
void _update_nl();
- Array _get_selected_nodes();
Array _get_transformable_selected_nodes();
void _emit_change();
@@ -234,6 +233,7 @@ protected:
static void _bind_methods();
public:
+ Array get_selected_nodes();
void add_node(Node *p_node);
void remove_node(Node *p_node);
bool is_selected(Node *) const;
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
new file mode 100644
index 0000000000..d617089142
--- /dev/null
+++ b/editor/rename_dialog.cpp
@@ -0,0 +1,691 @@
+/*************************************************************************/
+/* rename_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "rename_dialog.h"
+
+#include "editor_node.h"
+#include "editor_settings.h"
+#include "editor_themes.h"
+#include "modules/regex/regex.h"
+#include "plugins/script_editor_plugin.h"
+#include "print_string.h"
+#include "scene/gui/control.h"
+#include "scene/gui/label.h"
+#include "scene/gui/tab_container.h"
+
+RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo) {
+
+ scene_tree_editor = p_scene_tree_editor;
+ undo_redo = p_undo_redo;
+ preview_node = NULL;
+
+ set_title(TTR("Batch Rename"));
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ add_child(vbc);
+
+ // -- Search/Replace Area
+
+ GridContainer *grd_main = memnew(GridContainer);
+ grd_main->set_columns(2);
+ grd_main->set_v_size_flags(SIZE_EXPAND_FILL);
+ vbc->add_child(grd_main);
+
+ // ---- 1st & 2nd row
+
+ Label *lbl_search = memnew(Label);
+ lbl_search->set_text(TTR("Search"));
+
+ lne_search = memnew(LineEdit);
+ lne_search->set_placeholder(TTR("Search"));
+ lne_search->set_name("lne_search");
+ lne_search->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ Label *lbl_replace = memnew(Label);
+ lbl_replace->set_text(TTR("Replace"));
+
+ lne_replace = memnew(LineEdit);
+ lne_replace->set_placeholder(TTR("Replace"));
+ lne_replace->set_name("lne_replace");
+ lne_replace->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grd_main->add_child(lbl_search);
+ grd_main->add_child(lbl_replace);
+ grd_main->add_child(lne_search);
+ grd_main->add_child(lne_replace);
+
+ // ---- 3rd & 4th row
+
+ Label *lbl_prefix = memnew(Label);
+ lbl_prefix->set_text(TTR("Prefix"));
+
+ lne_prefix = memnew(LineEdit);
+ lne_prefix->set_placeholder(TTR("Prefix"));
+ lne_prefix->set_name("lne_prefix");
+ lne_prefix->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ Label *lbl_suffix = memnew(Label);
+ lbl_suffix->set_text(TTR("Suffix"));
+
+ lne_suffix = memnew(LineEdit);
+ lne_suffix->set_placeholder(TTR("Suffix"));
+ lne_suffix->set_name("lne_suffix");
+ lne_suffix->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ grd_main->add_child(lbl_prefix);
+ grd_main->add_child(lbl_suffix);
+ grd_main->add_child(lne_prefix);
+ grd_main->add_child(lne_suffix);
+
+ // -- Feature Tabs
+
+ const int feature_min_height = 160;
+
+ Ref<Theme> collapse_theme = create_editor_theme();
+ collapse_theme->set_icon("checked", "CheckBox", collapse_theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
+ collapse_theme->set_icon("unchecked", "CheckBox", collapse_theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
+
+ CheckBox *chk_collapse_features = memnew(CheckBox);
+ chk_collapse_features->set_text(TTR("Advanced options"));
+ chk_collapse_features->set_theme(collapse_theme);
+ chk_collapse_features->set_focus_mode(FOCUS_NONE);
+ vbc->add_child(chk_collapse_features);
+
+ tabc_features = memnew(TabContainer);
+ tabc_features->set_tab_align(TabContainer::ALIGN_LEFT);
+ vbc->add_child(tabc_features);
+
+ // ---- Tab Substitute
+
+ VBoxContainer *vbc_substitute = memnew(VBoxContainer);
+ vbc_substitute->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc_substitute->set_custom_minimum_size(Size2(0, feature_min_height));
+
+ vbc_substitute->set_name(TTR("Substitute"));
+ tabc_features->add_child(vbc_substitute);
+
+ cbut_substitute = memnew(CheckButton);
+ cbut_substitute->set_text(TTR("Substitute"));
+ vbc_substitute->add_child(cbut_substitute);
+
+ GridContainer *grd_substitute = memnew(GridContainer);
+ grd_substitute->set_columns(3);
+ vbc_substitute->add_child(grd_substitute);
+
+ // Name
+
+ but_insert_name = memnew(Button);
+ but_insert_name->set_text("NAME");
+ but_insert_name->set_tooltip(String("${NAME}\n") + TTR("Node name"));
+ but_insert_name->set_focus_mode(FOCUS_NONE);
+ but_insert_name->connect("pressed", this, "_insert_text", make_binds("${NAME}"));
+ but_insert_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_name);
+
+ // Parent
+
+ but_insert_parent = memnew(Button);
+ but_insert_parent->set_text("PARENT");
+ but_insert_parent->set_tooltip(String("${PARENT}\n") + TTR("Node's parent name, if available"));
+ but_insert_parent->set_focus_mode(FOCUS_NONE);
+ but_insert_parent->connect("pressed", this, "_insert_text", make_binds("${PARENT}"));
+ but_insert_parent->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_parent);
+
+ // Type
+
+ but_insert_type = memnew(Button);
+ but_insert_type->set_text("TYPE");
+ but_insert_type->set_tooltip(String("${TYPE}\n") + TTR("Node type"));
+ but_insert_type->set_focus_mode(FOCUS_NONE);
+ but_insert_type->connect("pressed", this, "_insert_text", make_binds("${TYPE}"));
+ but_insert_type->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_type);
+
+ // Scene
+
+ but_insert_scene = memnew(Button);
+ but_insert_scene->set_text("SCENE");
+ but_insert_scene->set_tooltip(String("${SCENE}\n") + TTR("Current scene name"));
+ but_insert_scene->set_focus_mode(FOCUS_NONE);
+ but_insert_scene->connect("pressed", this, "_insert_text", make_binds("${SCENE}"));
+ but_insert_scene->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_scene);
+
+ // Root
+
+ but_insert_root = memnew(Button);
+ but_insert_root->set_text("ROOT");
+ but_insert_root->set_tooltip(String("${ROOT}\n") + TTR("Root node name"));
+ but_insert_root->set_focus_mode(FOCUS_NONE);
+ but_insert_root->connect("pressed", this, "_insert_text", make_binds("${ROOT}"));
+ but_insert_root->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_root);
+
+ // Count
+
+ but_insert_count = memnew(Button);
+ but_insert_count->set_text("COUNTER");
+ but_insert_count->set_tooltip(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options."));
+ but_insert_count->set_focus_mode(FOCUS_NONE);
+ but_insert_count->connect("pressed", this, "_insert_text", make_binds("${COUNTER}"));
+ but_insert_count->set_h_size_flags(SIZE_EXPAND_FILL);
+ grd_substitute->add_child(but_insert_count);
+
+ chk_per_level_counter = memnew(CheckBox);
+ chk_per_level_counter->set_text(TTR("Per Level counter"));
+ chk_per_level_counter->set_tooltip(TTR("If set the counter restarts for each group of child nodes"));
+ vbc_substitute->add_child(chk_per_level_counter);
+
+ HBoxContainer *hbc_count_options = memnew(HBoxContainer);
+ vbc_substitute->add_child(hbc_count_options);
+
+ Label *lbl_count_start = memnew(Label);
+ lbl_count_start->set_text(TTR("Start"));
+ lbl_count_start->set_tooltip(TTR("Initial value for the counter"));
+ hbc_count_options->add_child(lbl_count_start);
+
+ spn_count_start = memnew(SpinBox);
+ spn_count_start->set_tooltip(TTR("Initial value for the counter"));
+ spn_count_start->set_step(1);
+ spn_count_start->set_min(0);
+ hbc_count_options->add_child(spn_count_start);
+
+ Label *lbl_count_step = memnew(Label);
+ lbl_count_step->set_text(TTR("Step"));
+ lbl_count_step->set_tooltip(TTR("Ammount by which counter is incremented for each node"));
+ hbc_count_options->add_child(lbl_count_step);
+
+ spn_count_step = memnew(SpinBox);
+ spn_count_step->set_tooltip(TTR("Ammount by which counter is incremented for each node"));
+ spn_count_step->set_step(1);
+ hbc_count_options->add_child(spn_count_step);
+
+ Label *lbl_count_padding = memnew(Label);
+ lbl_count_padding->set_text(TTR("Padding"));
+ lbl_count_padding->set_tooltip(TTR("Minium number of digits for the counter.\nMissing digits are padded with leading zeros."));
+ hbc_count_options->add_child(lbl_count_padding);
+
+ spn_count_padding = memnew(SpinBox);
+ spn_count_padding->set_tooltip(TTR("Minium number of digits for the counter.\nMissing digits are padded with leading zeros."));
+ spn_count_padding->set_step(1);
+ hbc_count_options->add_child(spn_count_padding);
+
+ // ---- Tab RegEx
+
+ VBoxContainer *vbc_regex = memnew(VBoxContainer);
+ vbc_regex->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc_regex->set_name(TTR("Regular Expressions"));
+ vbc_regex->set_custom_minimum_size(Size2(0, feature_min_height));
+ tabc_features->add_child(vbc_regex);
+
+ cbut_regex = memnew(CheckButton);
+ cbut_regex->set_text(TTR("Regular Expressions"));
+ vbc_regex->add_child(cbut_regex);
+
+ // ---- Tab Process
+
+ VBoxContainer *vbc_process = memnew(VBoxContainer);
+ vbc_process->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbc_process->set_name(TTR("Post-Process"));
+ vbc_process->set_custom_minimum_size(Size2(0, feature_min_height));
+ tabc_features->add_child(vbc_process);
+
+ cbut_process = memnew(CheckButton);
+ cbut_process->set_text(TTR("Post-Process"));
+ vbc_process->add_child(cbut_process);
+
+ // ------ Style
+
+ HBoxContainer *hbc_style = memnew(HBoxContainer);
+ vbc_process->add_child(hbc_style);
+
+ Label *lbl_style = memnew(Label);
+ lbl_style->set_text(TTR("Style"));
+ hbc_style->add_child(lbl_style);
+
+ opt_style = memnew(OptionButton);
+ opt_style->add_item(TTR("Keep"));
+ opt_style->add_item(TTR("CamelCase to under_scored"));
+ opt_style->add_item(TTR("under_scored to CamelCase"));
+ hbc_style->add_child(opt_style);
+
+ // ------ Case
+
+ HBoxContainer *hbc_case = memnew(HBoxContainer);
+ vbc_process->add_child(hbc_case);
+
+ Label *lbl_case = memnew(Label);
+ lbl_case->set_text(TTR("Case"));
+ hbc_case->add_child(lbl_case);
+
+ opt_case = memnew(OptionButton);
+ opt_case->add_item(TTR("Keep"));
+ opt_case->add_item(TTR("To Lowercase"));
+ opt_case->add_item(TTR("To Uppercase"));
+ hbc_case->add_child(opt_case);
+
+ // -- Preview
+
+ HSeparator *sep_preview = memnew(HSeparator);
+ sep_preview->set_custom_minimum_size(Size2(10, 20));
+ vbc->add_child(sep_preview);
+
+ lbl_preview_title = memnew(Label);
+ lbl_preview_title->set_text(TTR("Preview"));
+ vbc->add_child(lbl_preview_title);
+
+ lbl_preview = memnew(Label);
+ lbl_preview->set_text("");
+ lbl_preview->add_color_override("font_color", Color(1, 0.5f, 0, 1));
+ vbc->add_child(lbl_preview);
+
+ // ---- Dialog related
+
+ set_custom_minimum_size(Size2(383, 0));
+ set_as_toplevel(true);
+ get_ok()->set_text(TTR("Rename"));
+ Button *but_reset = add_button(TTR("Reset"));
+
+ eh.errfunc = _error_handler;
+ eh.userdata = this;
+
+ // ---- Connections
+
+ chk_collapse_features->connect("toggled", this, "_features_toggled");
+
+ // Substitite Buttons
+
+ lne_search->connect("focus_entered", this, "_update_substitute");
+ lne_search->connect("focus_exited", this, "_update_substitute");
+ lne_replace->connect("focus_entered", this, "_update_substitute");
+ lne_replace->connect("focus_exited", this, "_update_substitute");
+ lne_prefix->connect("focus_entered", this, "_update_substitute");
+ lne_prefix->connect("focus_exited", this, "_update_substitute");
+ lne_suffix->connect("focus_entered", this, "_update_substitute");
+ lne_suffix->connect("focus_exited", this, "_update_substitute");
+
+ // Preview
+
+ lne_prefix->connect("text_changed", this, "_update_preview");
+ lne_suffix->connect("text_changed", this, "_update_preview");
+ lne_search->connect("text_changed", this, "_update_preview");
+ lne_replace->connect("text_changed", this, "_update_preview");
+ spn_count_start->connect("value_changed", this, "_update_preview_int");
+ spn_count_step->connect("value_changed", this, "_update_preview_int");
+ spn_count_padding->connect("value_changed", this, "_update_preview_int");
+ opt_style->connect("item_selected", this, "_update_preview_int");
+ opt_case->connect("item_selected", this, "_update_preview_int");
+ cbut_substitute->connect("pressed", this, "_update_preview", varray(""));
+ cbut_regex->connect("pressed", this, "_update_preview", varray(""));
+ cbut_process->connect("pressed", this, "_update_preview", varray(""));
+
+ but_reset->connect("pressed", this, "reset");
+
+ reset();
+ _features_toggled(false);
+}
+
+void RenameDialog::_bind_methods() {
+
+ ClassDB::bind_method("_features_toggled", &RenameDialog::_features_toggled);
+ ClassDB::bind_method("_update_preview", &RenameDialog::_update_preview);
+ ClassDB::bind_method("_update_preview_int", &RenameDialog::_update_preview_int);
+ ClassDB::bind_method("_insert_text", &RenameDialog::_insert_text);
+ ClassDB::bind_method("_update_substitute", &RenameDialog::_update_substitute);
+ ClassDB::bind_method("reset", &RenameDialog::reset);
+ ClassDB::bind_method("rename", &RenameDialog::rename);
+}
+
+void RenameDialog::_update_substitute() {
+
+ LineEdit *focus_owner_line_edit = Object::cast_to<LineEdit>(get_focus_owner());
+ bool is_main_field = _is_main_field(focus_owner_line_edit);
+
+ but_insert_name->set_disabled(!is_main_field);
+ but_insert_parent->set_disabled(!is_main_field);
+ but_insert_type->set_disabled(!is_main_field);
+ but_insert_scene->set_disabled(!is_main_field);
+ but_insert_root->set_disabled(!is_main_field);
+ but_insert_count->set_disabled(!is_main_field);
+
+ // The focus mode seems to be reset when disabling/re-enabling
+ but_insert_name->set_focus_mode(FOCUS_NONE);
+ but_insert_parent->set_focus_mode(FOCUS_NONE);
+ but_insert_type->set_focus_mode(FOCUS_NONE);
+ but_insert_scene->set_focus_mode(FOCUS_NONE);
+ but_insert_root->set_focus_mode(FOCUS_NONE);
+ but_insert_count->set_focus_mode(FOCUS_NONE);
+}
+
+void RenameDialog::_post_popup() {
+
+ EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
+ preview_node = NULL;
+
+ Array selected_node_list = editor_selection->get_selected_nodes();
+ ERR_FAIL_COND(selected_node_list.size() == 0);
+
+ preview_node = selected_node_list[0];
+
+ _update_preview();
+ _update_substitute();
+}
+
+void RenameDialog::_update_preview_int(int new_value) {
+ _update_preview();
+}
+
+void RenameDialog::_update_preview(String new_text) {
+
+ if (lock_preview_update || preview_node == NULL)
+ return;
+
+ has_errors = false;
+ add_error_handler(&eh);
+
+ String new_name = _apply_rename(preview_node, spn_count_start->get_value());
+
+ if (!has_errors) {
+
+ lbl_preview_title->set_text(TTR("Preview"));
+ lbl_preview->set_text(new_name);
+
+ if (new_name == preview_node->get_name()) {
+ lbl_preview->add_color_override("font_color", Color(0, 0.5f, 0.25f, 1));
+ } else {
+ lbl_preview->add_color_override("font_color", Color(0, 1, 0.5f, 1));
+ }
+ }
+
+ remove_error_handler(&eh);
+}
+
+String RenameDialog::_apply_rename(const Node *node, int count) {
+
+ String search = lne_search->get_text();
+ String replace = lne_replace->get_text();
+ String prefix = lne_prefix->get_text();
+ String suffix = lne_suffix->get_text();
+ String new_name = node->get_name();
+
+ if (cbut_substitute->is_pressed()) {
+ search = _substitute(search, node, count);
+ replace = _substitute(replace, node, count);
+ prefix = _substitute(prefix, node, count);
+ suffix = _substitute(suffix, node, count);
+ }
+
+ if (cbut_regex->is_pressed()) {
+
+ new_name = _regex(search, new_name, replace);
+ } else {
+ new_name = new_name.replace(search, replace);
+ }
+
+ new_name = prefix + new_name + suffix;
+
+ if (cbut_process->is_pressed()) {
+ new_name = _postprocess(new_name);
+ }
+
+ return new_name;
+}
+
+String RenameDialog::_substitute(const String &subject, const Node *node, int count) {
+
+ String result = subject.replace("${COUNTER}", vformat("%0" + itos(spn_count_padding->get_value()) + "d", count));
+
+ if (node) {
+ result = result.replace("${NAME}", node->get_name());
+ result = result.replace("${TYPE}", node->get_class());
+ }
+
+ int current = EditorNode::get_singleton()->get_editor_data().get_edited_scene();
+ result = result.replace("${SCENE}", EditorNode::get_singleton()->get_editor_data().get_scene_title(current));
+
+ Node *root_node = SceneTree::get_singleton()->get_edited_scene_root();
+ if (root_node) {
+ result = result.replace("${ROOT}", root_node->get_name());
+ }
+
+ Node *parent_node = node->get_parent();
+ if (parent_node) {
+ if (node == root_node) {
+ // Can not substitute parent of root.
+ result = result.replace("${PARENT}", "");
+ } else {
+ result = result.replace("${PARENT}", parent_node->get_name());
+ }
+ }
+
+ return result;
+}
+
+void RenameDialog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) {
+
+ RenameDialog *self = (RenameDialog *)p_self;
+ String source_file(p_file);
+
+ // Only show first error that is related to "regex"
+ if (self->has_errors || source_file.find("regex") < 0)
+ return;
+
+ String err_str;
+ if (p_errorexp && p_errorexp[0]) {
+ err_str = p_errorexp;
+ } else {
+ err_str = p_error;
+ }
+
+ self->has_errors = true;
+ self->lbl_preview_title->set_text(TTR("Error"));
+ self->lbl_preview->add_color_override("font_color", Color(1, 0.25f, 0, 1));
+ self->lbl_preview->set_text(err_str);
+}
+
+String RenameDialog::_regex(const String &pattern, const String &subject, const String &replacement) {
+
+ RegEx regex(pattern);
+
+ return regex.sub(subject, replacement, true);
+}
+
+String RenameDialog::_postprocess(const String &subject) {
+
+ int style_id = opt_style->get_selected();
+
+ String result = subject;
+
+ if (style_id == 1) {
+
+ // CamelCase to Under_Line
+ result = result.camelcase_to_underscore(true);
+ result = _regex("_+", result, "_");
+
+ } else if (style_id == 2) {
+
+ // Under_Line to CamelCase
+ RegEx pattern("_+(.?)");
+ Array matches = pattern.search_all(result);
+
+ // _ name would become empty. Ignore
+ if (matches.size() && result != "_") {
+ String buffer;
+ int start = 0;
+ int end = 0;
+ for (int i = 0; i < matches.size(); ++i) {
+ start = ((Ref<RegExMatch>)matches[i])->get_start(1);
+ buffer += result.substr(end, start - end - 1);
+ buffer += result.substr(start, 1).to_upper();
+ end = start + 1;
+ }
+ buffer += result.substr(end, result.size() - (end + 1));
+ result = buffer.replace("_", "").capitalize();
+ }
+ }
+
+ int case_id = opt_case->get_selected();
+
+ if (case_id == 1) {
+ // To Lowercase
+ result = result.to_lower();
+ } else if (case_id == 2) {
+ // To Upercase
+ result = result.to_upper();
+ }
+
+ return result;
+}
+
+void RenameDialog::_iterate_scene(const Node *node, const Array &selection, int *counter) {
+
+ if (!node)
+ return;
+
+ if (selection.has(node)) {
+
+ String new_name = _apply_rename(node, *counter);
+
+ if (node->get_name() != new_name) {
+ Pair<NodePath, String> rename_item;
+ rename_item.first = node->get_path();
+ rename_item.second = new_name;
+ to_rename.push_back(rename_item);
+ }
+
+ *counter += spn_count_step->get_value();
+ }
+
+ int *cur_counter = counter;
+ int level_counter = spn_count_start->get_value();
+
+ if (chk_per_level_counter->is_pressed()) {
+ cur_counter = &level_counter;
+ }
+
+ for (int i = 0; i < node->get_child_count(); ++i) {
+ _iterate_scene(node->get_child(i), selection, cur_counter);
+ }
+}
+
+void RenameDialog::rename() {
+
+ // Editor selection is not ordered via scene tree. Instead iterate
+ // over scene tree until all selected nodes are found in order.
+
+ EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
+ Array selected_node_list = editor_selection->get_selected_nodes();
+ Node *root_node = SceneTree::get_singleton()->get_edited_scene_root();
+
+ global_count = spn_count_start->get_value();
+ to_rename.clear();
+
+ // Forward recursive as opposed to the actual renaming.
+ _iterate_scene(root_node, selected_node_list, &global_count);
+
+ if (undo_redo && !to_rename.empty()) {
+
+ undo_redo->create_action(TTR("Batch Rename"));
+
+ // Make sure to iterate reversed so that child nodes will find parents.
+ for (int i = to_rename.size() - 1; i >= 0; --i) {
+
+ Node *n = root_node->get_node(to_rename[i].first);
+ const String &new_name = to_rename[i].second;
+
+ if (!n) {
+ ERR_PRINTS("Skipping missing node: " + to_rename[i].first.get_concatenated_subnames());
+ continue;
+ }
+
+ scene_tree_editor->emit_signal("node_prerename", n, new_name);
+ undo_redo->add_do_method(scene_tree_editor, "_rename_node", n->get_instance_id(), new_name);
+ undo_redo->add_undo_method(scene_tree_editor, "_rename_node", n->get_instance_id(), n->get_name());
+ }
+
+ undo_redo->commit_action();
+ }
+}
+
+void RenameDialog::reset() {
+
+ lock_preview_update = true;
+
+ lne_prefix->clear();
+ lne_suffix->clear();
+ lne_search->clear();
+ lne_replace->clear();
+
+ cbut_substitute->set_pressed(false);
+ cbut_regex->set_pressed(false);
+ cbut_process->set_pressed(false);
+
+ chk_per_level_counter->set_pressed(true);
+
+ spn_count_start->set_value(1);
+ spn_count_step->set_value(1);
+ spn_count_padding->set_value(1);
+
+ opt_style->select(0);
+ opt_case->select(0);
+
+ lock_preview_update = false;
+ _update_preview();
+}
+
+bool RenameDialog::_is_main_field(LineEdit *line_edit) {
+ return line_edit &&
+ (line_edit == lne_search || line_edit == lne_replace || line_edit == lne_prefix || line_edit == lne_suffix);
+}
+
+void RenameDialog::_insert_text(String text) {
+
+ LineEdit *focus_owner = Object::cast_to<LineEdit>(get_focus_owner());
+
+ if (_is_main_field(focus_owner)) {
+ focus_owner->selection_delete();
+ focus_owner->append_at_cursor(text);
+ _update_preview();
+ }
+}
+
+void RenameDialog::_features_toggled(bool pressed) {
+ if (pressed) {
+ tabc_features->show();
+ } else {
+ tabc_features->hide();
+ }
+
+ // Adjust to minimum size in y
+ Size2i size = get_size();
+ size.y = 0;
+ set_size(size);
+}
diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h
new file mode 100644
index 0000000000..c5ebc30c0c
--- /dev/null
+++ b/editor/rename_dialog.h
@@ -0,0 +1,119 @@
+/*************************************************************************/
+/* rename_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RENAME_DIALOG_H
+#define RENAME_DIALOG_H
+
+#include "scene/gui/check_box.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/spin_box.h"
+
+#include "editor/scene_tree_editor.h"
+#include "undo_redo.h"
+
+/**
+@author Blazej Floch
+*/
+
+class RenameDialog : public ConfirmationDialog {
+
+ GDCLASS(RenameDialog, ConfirmationDialog);
+
+ virtual void ok_pressed() { rename(); };
+ void _cancel_pressed(){};
+ void _features_toggled(bool pressed);
+ void _insert_text(String text);
+ void _update_substitute();
+ bool _is_main_field(LineEdit *line_edit);
+
+ void _iterate_scene(const Node *node, const Array &selection, int *count);
+ String _apply_rename(const Node *node, int count);
+ String _substitute(const String &subject, const Node *node, int count);
+ String _regex(const String &pattern, const String &subject, const String &replacement);
+ String _postprocess(const String &subject);
+ void _update_preview(String new_text = "");
+ void _update_preview_int(int new_value = 0);
+ static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type);
+
+ SceneTreeEditor *scene_tree_editor;
+ UndoRedo *undo_redo;
+ int global_count;
+
+ LineEdit *lne_search;
+ LineEdit *lne_replace;
+ LineEdit *lne_prefix;
+ LineEdit *lne_suffix;
+
+ TabContainer *tabc_features;
+
+ CheckButton *cbut_substitute;
+ CheckButton *cbut_regex;
+ CheckButton *cbut_process;
+ CheckBox *chk_per_level_counter;
+
+ Button *but_insert_name;
+ Button *but_insert_parent;
+ Button *but_insert_type;
+ Button *but_insert_scene;
+ Button *but_insert_root;
+ Button *but_insert_count;
+
+ SpinBox *spn_count_start;
+ SpinBox *spn_count_step;
+ SpinBox *spn_count_padding;
+
+ OptionButton *opt_style;
+ OptionButton *opt_case;
+
+ Label *lbl_preview_title;
+ Label *lbl_preview;
+
+ List<Pair<NodePath, String> > to_rename;
+ Node *preview_node;
+ bool lock_preview_update;
+ ErrorHandlerList eh;
+ bool has_errors;
+
+protected:
+ void _notification(int p_what){};
+ static void _bind_methods();
+ virtual void _post_popup();
+
+public:
+ void reset();
+ void rename();
+
+ RenameDialog(SceneTreeEditor *p_scene_tree_editor, UndoRedo *p_undo_redo = NULL);
+ ~RenameDialog(){};
+};
+
+#endif
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index ba661813d6..8b99a3d503 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -73,7 +73,9 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
if (!p_event->is_pressed() || p_event->is_echo())
return;
- if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
+ if (ED_IS_SHORTCUT("scene_tree/batch_rename", p_event)) {
+ _tool_selected(TOOL_BATCH_RENAME);
+ } else if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
_tool_selected(TOOL_NEW);
} else if (ED_IS_SHORTCUT("scene_tree/instance_scene", p_event)) {
_tool_selected(TOOL_INSTANCE);
@@ -285,6 +287,12 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
switch (p_tool) {
+ case TOOL_BATCH_RENAME: {
+ Tree *tree = scene_tree->get_scene_tree();
+ if (tree->is_anything_selected()) {
+ rename_dialog->popup_centered();
+ }
+ } break;
case TOOL_NEW: {
String preferred = "";
@@ -1862,6 +1870,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->clear();
+ menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/batch_rename"), TOOL_BATCH_RENAME);
if (selection.size() == 1) {
subresources.clear();
@@ -2055,6 +2064,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
filter_hbc->add_constant_override("separate", 0);
ToolButton *tb;
+ ED_SHORTCUT("scene_tree/batch_rename", TTR("Batch Rename"), KEY_MASK_CMD | KEY_F2);
ED_SHORTCUT("scene_tree/add_child_node", TTR("Add Child Node"), KEY_MASK_CMD | KEY_A);
ED_SHORTCUT("scene_tree/instance_scene", TTR("Instance Child Scene"));
ED_SHORTCUT("scene_tree/change_node_type", TTR("Change Type"));
@@ -2153,6 +2163,9 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
add_child(create_dialog);
create_dialog->connect("create", this, "_create");
+ rename_dialog = memnew(RenameDialog(scene_tree, &editor_data->get_undo_redo()));
+ add_child(rename_dialog);
+
script_create_dialog = memnew(ScriptCreateDialog);
add_child(script_create_dialog);
script_create_dialog->connect("script_created", this, "_script_created");
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index a4f36e31ee..fd7d616a80 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -36,6 +36,7 @@
#include "editor/editor_data.h"
#include "editor/editor_sub_scene.h"
#include "editor/groups_editor.h"
+#include "editor/rename_dialog.h"
#include "editor/reparent_dialog.h"
#include "editor/script_create_dialog.h"
#include "scene/animation/animation_player.h"
@@ -58,6 +59,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_NEW,
TOOL_INSTANCE,
+ TOOL_BATCH_RENAME,
TOOL_REPLACE,
TOOL_ATTACH_SCRIPT,
TOOL_CLEAR_SCRIPT,
@@ -90,6 +92,7 @@ class SceneTreeDock : public VBoxContainer {
int current_option;
CreateDialog *create_dialog;
+ RenameDialog *rename_dialog;
ToolButton *button_add;
ToolButton *button_instance;
diff --git a/main/main.cpp b/main/main.cpp
index fa60bd4e96..5959deb495 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -730,6 +730,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (debug_mode == "local") {
script_debugger = memnew(ScriptDebuggerLocal);
+ OS::get_singleton()->initialize_debugging();
}
FileAccessNetwork::configure();
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index 151a79a69f..adfad7803f 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -138,6 +138,12 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
sixDOFConstraint->getTranslationalLimitMotor()->m_damping = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
limits_lower[1][p_axis] = p_value;
set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][p_param]); // Reload bullet parameter
@@ -185,6 +191,10 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getTranslationalLimitMotor()->m_restitution;
case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING:
return sixDOFConstraint->getTranslationalLimitMotor()->m_damping;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
return limits_lower[1][p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
@@ -232,6 +242,9 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableMotor = flags[p_axis][p_flag];
break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag];
+ break;
default:
WARN_PRINT("This flag is not supported by Bullet engine");
return;
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 8d25dfec0d..a88ba477c6 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -330,10 +330,24 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
} break;
case MATH_LERP: {
VALIDATE_ARG_COUNT(3);
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
VALIDATE_ARG_NUM(2);
- r_ret = Math::lerp((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
+ const double t = (double)*p_args[2];
+ switch (p_args[0]->get_type() == p_args[1]->get_type() ? p_args[0]->get_type() : Variant::REAL) {
+ case Variant::VECTOR2: {
+ r_ret = ((Vector2)*p_args[0]).linear_interpolate((Vector2)*p_args[1], t);
+ } break;
+ case Variant::VECTOR3: {
+ r_ret = ((Vector3)*p_args[0]).linear_interpolate((Vector3)*p_args[1], t);
+ } break;
+ case Variant::COLOR: {
+ r_ret = ((Color)*p_args[0]).linear_interpolate((Color)*p_args[1], t);
+ } break;
+ default: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ r_ret = Math::lerp((double)*p_args[0], (double)*p_args[1], t);
+ } break;
+ }
} break;
case MATH_INVERSE_LERP: {
VALIDATE_ARG_COUNT(3);
@@ -1500,7 +1514,7 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
return mi;
} break;
case MATH_LERP: {
- MethodInfo mi("lerp", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
+ MethodInfo mi("lerp", PropertyInfo(Variant::NIL, "from"), PropertyInfo(Variant::NIL, "to"), PropertyInfo(Variant::REAL, "weight"));
mi.return_val.type = Variant::REAL;
return mi;
} break;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 6ed03d7aee..6fe137a386 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1643,9 +1643,9 @@ public:
List<String> args;
args.push_back("-digestalg");
- args.push_back("SHA1");
+ args.push_back("SHA-256");
args.push_back("-sigalg");
- args.push_back("MD5withRSA");
+ args.push_back("SHA256withRSA");
String tsa_url = EditorSettings::get_singleton()->get("export/android/timestamping_authority_url");
if (tsa_url != "") {
args.push_back("-tsa");
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 2ce55d98be..6d559520d7 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -193,7 +193,10 @@ def configure_msvc(env, manual_msvc_config):
env.AppendUnique(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo'])
env.AppendUnique(CXXFLAGS=['/TP']) # assume all sources are C++
if manual_msvc_config: # should be automatic if SCons found it
- env.Append(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"])
+ if os.getenv("WindowsSdkDir") is not None:
+ env.Append(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"])
+ else:
+ print("Missing environment variable: WindowsSdkDir")
env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED',
'RTAUDIO_ENABLED', 'WASAPI_ENABLED',
@@ -211,7 +214,10 @@ def configure_msvc(env, manual_msvc_config):
env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
if manual_msvc_config:
- env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"])
+ if os.getenv("WindowsSdkDir") is not None:
+ env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"])
+ else:
+ print("Missing environment variable: WindowsSdkDir")
## LTO
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index bed5781ae4..7b46608c55 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -152,6 +152,25 @@ void RedirectIOToConsole() {
// point to console as well
}
+BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
+ if (ScriptDebugger::get_singleton() == NULL)
+ return FALSE;
+
+ switch (dwCtrlType) {
+ case CTRL_C_EVENT:
+ ScriptDebugger::get_singleton()->set_depth(-1);
+ ScriptDebugger::get_singleton()->set_lines_left(1);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+void OS_Windows::initialize_debugging() {
+
+ SetConsoleCtrlHandler(HandlerRoutine, TRUE);
+}
+
void OS_Windows::initialize_core() {
crash_handler.initialize();
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 3d13627bfa..584f6fb334 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -294,6 +294,7 @@ public:
void disable_crash_handler();
bool is_disable_crash_handler() const;
+ virtual void initialize_debugging();
void force_process_input();
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 447bd9a090..60a7961293 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -351,7 +351,7 @@ void AnimatedSprite::_notification(int p_what) {
if (frame < 0)
return;
- float speed = frames->get_animation_speed(animation);
+ float speed = frames->get_animation_speed(animation) * speed_scale;
if (speed == 0)
return; //do nothing
@@ -481,6 +481,16 @@ int AnimatedSprite::get_frame() const {
return frame;
}
+void AnimatedSprite::set_speed_scale(float p_speed_scale) {
+
+ speed_scale = MAX(p_speed_scale, 0.0f);
+}
+
+float AnimatedSprite::get_speed_scale() const {
+
+ return speed_scale;
+}
+
void AnimatedSprite::set_centered(bool p_center) {
centered = p_center;
@@ -570,7 +580,7 @@ void AnimatedSprite::_reset_timeout() {
return;
if (frames.is_valid() && frames->has_animation(animation)) {
- float speed = frames->get_animation_speed(animation);
+ float speed = frames->get_animation_speed(animation) * speed_scale;
if (speed > 0) {
timeout = 1.0 / speed;
} else {
@@ -636,6 +646,9 @@ void AnimatedSprite::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite::set_frame);
ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite::get_frame);
+ ClassDB::bind_method(D_METHOD("set_speed_scale", "speed_scale"), &AnimatedSprite::set_speed_scale);
+ ClassDB::bind_method(D_METHOD("get_speed_scale"), &AnimatedSprite::get_speed_scale);
+
ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite::_res_changed);
ADD_SIGNAL(MethodInfo("frame_changed"));
@@ -644,6 +657,7 @@ void AnimatedSprite::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation");
ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame");
+ ADD_PROPERTYNO(PropertyInfo(Variant::REAL, "speed_scale"), "set_speed_scale", "get_speed_scale");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing");
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered");
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
@@ -658,6 +672,7 @@ AnimatedSprite::AnimatedSprite() {
vflip = false;
frame = 0;
+ speed_scale = 1.0f;
playing = false;
animation = "default";
timeout = 0;
diff --git a/scene/2d/animated_sprite.h b/scene/2d/animated_sprite.h
index c7606d88aa..7b91a1faef 100644
--- a/scene/2d/animated_sprite.h
+++ b/scene/2d/animated_sprite.h
@@ -129,6 +129,7 @@ class AnimatedSprite : public Node2D {
bool playing;
StringName animation;
int frame;
+ float speed_scale;
bool centered;
Point2 offset;
@@ -172,6 +173,9 @@ public:
void set_frame(int p_frame);
int get_frame() const;
+ void set_speed_scale(float p_speed_scale);
+ float get_speed_scale() const;
+
void set_centered(bool p_center);
bool is_centered() const;
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index bc39368c88..64d0771fab 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -68,31 +68,31 @@ bool Sprite::_edit_use_rect() const {
void Sprite::_get_rects(Rect2 &r_src_rect, Rect2 &r_dst_rect, bool &r_filter_clip) const {
- Size2 s;
- r_filter_clip = false;
+ Rect2 base_rect;
if (region) {
-
- s = region_rect.size;
- r_src_rect = region_rect;
r_filter_clip = region_filter_clip;
+ base_rect = region_rect;
} else {
- s = Size2(texture->get_size());
- s = s / Size2(hframes, vframes);
-
- r_src_rect.size = s;
- r_src_rect.position.x = float(frame % hframes) * s.x;
- r_src_rect.position.y = float(frame / hframes) * s.y;
+ r_filter_clip = false;
+ base_rect = Rect2(0, 0, texture->get_width(), texture->get_height());
}
- Point2 ofs = offset;
+ Size2 frame_size = base_rect.size / Size2(hframes, vframes);
+ Point2 frame_offset = Point2(frame % hframes, frame / hframes);
+ frame_offset *= frame_size;
+
+ r_src_rect.size = frame_size;
+ r_src_rect.position = base_rect.position + frame_offset;
+
+ Point2 dest_offset = offset;
if (centered)
- ofs -= s / 2;
+ dest_offset -= frame_size / 2;
if (Engine::get_singleton()->get_use_pixel_snap()) {
- ofs = ofs.floor();
+ dest_offset = dest_offset.floor();
}
- r_dst_rect = Rect2(ofs, s);
+ r_dst_rect = Rect2(dest_offset, frame_size);
if (hflip)
r_dst_rect.size.x = -r_dst_rect.size.x;
@@ -375,13 +375,13 @@ Rect2 Sprite::get_rect() const {
Size2i s;
if (region) {
-
s = region_rect.size;
} else {
s = texture->get_size();
- s = s / Point2(hframes, vframes);
}
+ s = s / Point2(hframes, vframes);
+
Point2 ofs = offset;
if (centered)
ofs -= s / 2;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 3d3f43d5c6..60766862cc 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -845,13 +845,13 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) {
mask |= TileSet::BIND_BOTTOMRIGHT;
}
} else if (tile_set->autotile_get_bitmask_mode(id) == TileSet::BITMASK_3X3) {
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
+ if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y - 1))) {
mask |= TileSet::BIND_TOPLEFT;
}
if (tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1))) {
mask |= TileSet::BIND_TOP;
}
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y - 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
+ if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y - 1))) {
mask |= TileSet::BIND_TOPRIGHT;
}
if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
@@ -861,13 +861,13 @@ void TileMap::update_cell_bitmask(int p_x, int p_y) {
if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
mask |= TileSet::BIND_RIGHT;
}
- if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y))) {
+ if (tile_set->is_tile_bound(id, get_cell(p_x - 1, p_y + 1))) {
mask |= TileSet::BIND_BOTTOMLEFT;
}
if (tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1))) {
mask |= TileSet::BIND_BOTTOM;
}
- if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x, p_y + 1)) && tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y))) {
+ if (tile_set->is_tile_bound(id, get_cell(p_x + 1, p_y + 1))) {
mask |= TileSet::BIND_BOTTOMRIGHT;
}
}
diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp
index 2e9f1a241a..b2d10006f7 100644
--- a/scene/3d/physics_joint.cpp
+++ b/scene/3d/physics_joint.cpp
@@ -716,6 +716,9 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_x/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_x", "get_param_x", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x");
@@ -734,6 +737,9 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_y", "get_param_y", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y");
@@ -752,6 +758,9 @@ void Generic6DOFJoint::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_LIMIT_SOFTNESS);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_RESTITUTION);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"), "set_param_z", "get_param_z", PARAM_LINEAR_DAMPING);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z");
@@ -769,6 +778,8 @@ void Generic6DOFJoint::_bind_methods() {
BIND_ENUM_CONSTANT(PARAM_LINEAR_LIMIT_SOFTNESS);
BIND_ENUM_CONSTANT(PARAM_LINEAR_RESTITUTION);
BIND_ENUM_CONSTANT(PARAM_LINEAR_DAMPING);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_TARGET_VELOCITY);
+ BIND_ENUM_CONSTANT(PARAM_LINEAR_MOTOR_FORCE_LIMIT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_LOWER_LIMIT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_UPPER_LIMIT);
BIND_ENUM_CONSTANT(PARAM_ANGULAR_LIMIT_SOFTNESS);
@@ -783,6 +794,7 @@ void Generic6DOFJoint::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT);
BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_LIMIT);
BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR);
+ BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_MOTOR);
BIND_ENUM_CONSTANT(FLAG_MAX);
}
@@ -912,6 +924,8 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_param_x(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7);
set_param_x(PARAM_LINEAR_RESTITUTION, 0.5);
set_param_x(PARAM_LINEAR_DAMPING, 1.0);
+ set_param_x(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
+ set_param_x(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
set_param_x(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_x(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_x(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -925,12 +939,15 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_flag_x(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_x(FLAG_ENABLE_LINEAR_LIMIT, true);
set_flag_x(FLAG_ENABLE_MOTOR, false);
+ set_flag_x(FLAG_ENABLE_LINEAR_MOTOR, false);
set_param_y(PARAM_LINEAR_LOWER_LIMIT, 0);
set_param_y(PARAM_LINEAR_UPPER_LIMIT, 0);
set_param_y(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7);
set_param_y(PARAM_LINEAR_RESTITUTION, 0.5);
set_param_y(PARAM_LINEAR_DAMPING, 1.0);
+ set_param_y(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
+ set_param_y(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
set_param_y(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_y(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_y(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -944,12 +961,15 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_flag_y(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_y(FLAG_ENABLE_LINEAR_LIMIT, true);
set_flag_y(FLAG_ENABLE_MOTOR, false);
+ set_flag_y(FLAG_ENABLE_LINEAR_MOTOR, false);
set_param_z(PARAM_LINEAR_LOWER_LIMIT, 0);
set_param_z(PARAM_LINEAR_UPPER_LIMIT, 0);
set_param_z(PARAM_LINEAR_LIMIT_SOFTNESS, 0.7);
set_param_z(PARAM_LINEAR_RESTITUTION, 0.5);
set_param_z(PARAM_LINEAR_DAMPING, 1.0);
+ set_param_z(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0);
+ set_param_z(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0);
set_param_z(PARAM_ANGULAR_LOWER_LIMIT, 0);
set_param_z(PARAM_ANGULAR_UPPER_LIMIT, 0);
set_param_z(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f);
@@ -963,4 +983,5 @@ Generic6DOFJoint::Generic6DOFJoint() {
set_flag_z(FLAG_ENABLE_ANGULAR_LIMIT, true);
set_flag_z(FLAG_ENABLE_LINEAR_LIMIT, true);
set_flag_z(FLAG_ENABLE_MOTOR, false);
+ set_flag_z(FLAG_ENABLE_LINEAR_MOTOR, false);
}
diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h
index 000109ac55..37870d6f30 100644
--- a/scene/3d/physics_joint.h
+++ b/scene/3d/physics_joint.h
@@ -249,6 +249,8 @@ public:
PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS,
PARAM_LINEAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION,
PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING,
+ PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
+ PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -265,6 +267,7 @@ public:
FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR,
+ FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX
};
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 304faed9bd..e9314ba8dd 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -124,7 +124,6 @@ private:
void shift_selection_check_post(bool);
void selection_fill_at_cursor();
- void selection_delete();
void set_window_pos(int p_pos);
void set_cursor_at_pixel_pos(int p_x);
@@ -158,6 +157,7 @@ public:
void select(int p_from = 0, int p_to = -1);
void select_all();
+ void selection_delete();
void deselect();
void delete_char();
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index a9402d6404..c5e4149782 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -297,7 +297,7 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_focused"), &OptionButton::_focused);
ClassDB::bind_method(D_METHOD("add_item", "label", "id"), &OptionButton::add_item, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id"), &OptionButton::add_icon_item);
+ ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id"), &OptionButton::add_icon_item, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("set_item_text", "idx", "text"), &OptionButton::set_item_text);
ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "texture"), &OptionButton::set_item_icon);
ClassDB::bind_method(D_METHOD("set_item_disabled", "idx", "disabled"), &OptionButton::set_item_disabled);
diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp
index 24b04c0c4a..1443d5efbf 100644
--- a/scene/main/instance_placeholder.cpp
+++ b/scene/main/instance_placeholder.cpp
@@ -52,6 +52,7 @@ bool InstancePlaceholder::_get(const StringName &p_name, Variant &r_ret) const {
}
return false;
}
+
void InstancePlaceholder::_get_property_list(List<PropertyInfo> *p_list) const {
for (const List<PropSet>::Element *E = stored_values.front(); E; E = E->next()) {
@@ -73,13 +74,14 @@ String InstancePlaceholder::get_instance_path() const {
return path;
}
-void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_scene) {
- ERR_FAIL_COND(!is_inside_tree());
+Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene> &p_custom_scene) {
+
+ ERR_FAIL_COND_V(!is_inside_tree(), NULL);
Node *base = get_parent();
if (!base)
- return;
+ return NULL;
Ref<PackedScene> ps;
if (p_custom_scene.is_valid())
@@ -88,7 +90,7 @@ void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_s
ps = ResourceLoader::load(path, "PackedScene");
if (!ps.is_valid())
- return;
+ return NULL;
Node *scene = ps->instance();
scene->set_name(get_name());
int pos = get_position_in_parent();
@@ -97,11 +99,20 @@ void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_s
scene->set(E->get().name, E->get().value);
}
- queue_delete();
+ if (p_replace) {
+ queue_delete();
+ base->remove_child(this);
+ }
- base->remove_child(this);
base->add_child(scene);
base->move_child(scene, pos);
+
+ return scene;
+}
+
+void InstancePlaceholder::replace_by_instance(const Ref<PackedScene> &p_custom_scene) {
+ //Deprecated by
+ create_instance(true, p_custom_scene);
}
Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) {
@@ -124,6 +135,7 @@ Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) {
void InstancePlaceholder::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stored_values", "with_order"), &InstancePlaceholder::get_stored_values, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("create_instance", "replace", "custom_scene"), &InstancePlaceholder::create_instance, DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("replace_by_instance", "custom_scene"), &InstancePlaceholder::replace_by_instance, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("get_instance_path"), &InstancePlaceholder::get_instance_path);
}
diff --git a/scene/main/instance_placeholder.h b/scene/main/instance_placeholder.h
index d70f1318ea..2158257c93 100644
--- a/scene/main/instance_placeholder.h
+++ b/scene/main/instance_placeholder.h
@@ -60,6 +60,7 @@ public:
Dictionary get_stored_values(bool p_with_order = false);
+ Node *create_instance(bool p_replace = false, const Ref<PackedScene> &p_custom_scene = Ref<PackedScene>());
void replace_by_instance(const Ref<PackedScene> &p_custom_scene = Ref<PackedScene>());
InstancePlaceholder();
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 11b663e413..9a9a19ed1a 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2168,9 +2168,7 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
p_control->set_position(gui.last_mouse_pos);
p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
p_control->raise();
- if (gui.drag_preview) {
- memdelete(gui.drag_preview);
- }
+
gui.drag_preview = p_control;
}
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index f01a4c2f64..08af26c24b 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -603,6 +603,8 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS);
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_RESTITUTION);
BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_DAMPING);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LOWER_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_UPPER_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS);
@@ -616,6 +618,7 @@ void PhysicsServer::_bind_methods() {
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT);
BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_MOTOR);
+ BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR);
ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &PhysicsServer::joint_get_type);
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 6a342b36d4..6712bee8dc 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -594,6 +594,8 @@ public:
G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS,
G6DOF_JOINT_LINEAR_RESTITUTION,
G6DOF_JOINT_LINEAR_DAMPING,
+ G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY,
+ G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT,
G6DOF_JOINT_ANGULAR_LOWER_LIMIT,
G6DOF_JOINT_ANGULAR_UPPER_LIMIT,
G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS,
@@ -611,6 +613,7 @@ public:
G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT,
G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT,
G6DOF_JOINT_FLAG_ENABLE_MOTOR,
+ G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR,
G6DOF_JOINT_FLAG_MAX
};