Merge pull request #36784 from akien-mga/3.2-cherrypicks
Cherry-picks for the 3.2 branch (future 3.2.1) - 3rd batch
This commit is contained in:
commit
ea2e976cdd
26
SConstruct
26
SConstruct
|
@ -291,6 +291,7 @@ if selected_platform in platform_list:
|
||||||
if env["extra_suffix"] != '':
|
if env["extra_suffix"] != '':
|
||||||
env.extra_suffix += '.' + env["extra_suffix"]
|
env.extra_suffix += '.' + env["extra_suffix"]
|
||||||
|
|
||||||
|
# Environment flags
|
||||||
CCFLAGS = env.get('CCFLAGS', '')
|
CCFLAGS = env.get('CCFLAGS', '')
|
||||||
env['CCFLAGS'] = ''
|
env['CCFLAGS'] = ''
|
||||||
env.Append(CCFLAGS=str(CCFLAGS).split())
|
env.Append(CCFLAGS=str(CCFLAGS).split())
|
||||||
|
@ -307,17 +308,28 @@ if selected_platform in platform_list:
|
||||||
env['LINKFLAGS'] = ''
|
env['LINKFLAGS'] = ''
|
||||||
env.Append(LINKFLAGS=str(LINKFLAGS).split())
|
env.Append(LINKFLAGS=str(LINKFLAGS).split())
|
||||||
|
|
||||||
|
# Platform specific flags
|
||||||
flag_list = platform_flags[selected_platform]
|
flag_list = platform_flags[selected_platform]
|
||||||
for f in flag_list:
|
for f in flag_list:
|
||||||
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
|
if not (f[0] in ARGUMENTS): # allow command line to override platform flags
|
||||||
env[f[0]] = f[1]
|
env[f[0]] = f[1]
|
||||||
|
|
||||||
# must happen after the flags, so when flags are used by configure, stuff happens (ie, ssl on x11)
|
# Must happen after the flags definition, so that they can be used by platform detect
|
||||||
detect.configure(env)
|
detect.configure(env)
|
||||||
|
|
||||||
# Enable C++11 support
|
# Set our C and C++ standard requirements.
|
||||||
|
# Prepending to make it possible to override
|
||||||
|
# This needs to come after `configure`, otherwise we don't have env.msvc.
|
||||||
if not env.msvc:
|
if not env.msvc:
|
||||||
env.Append(CXXFLAGS=['-std=c++11'])
|
# Specifying GNU extensions support explicitly, which are supported by
|
||||||
|
# both GCC and Clang. This mirrors GCC and Clang's current default
|
||||||
|
# compile flags if no -std is specified.
|
||||||
|
env.Prepend(CFLAGS=['-std=gnu11'])
|
||||||
|
env.Prepend(CXXFLAGS=['-std=gnu++14'])
|
||||||
|
else:
|
||||||
|
# MSVC doesn't have clear C standard support, /std only covers C++.
|
||||||
|
# We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
|
||||||
|
env.Prepend(CCFLAGS=['/std:c++14'])
|
||||||
|
|
||||||
# Configure compiler warnings
|
# Configure compiler warnings
|
||||||
if env.msvc:
|
if env.msvc:
|
||||||
|
@ -338,12 +350,13 @@ if selected_platform in platform_list:
|
||||||
# Force to use Unicode encoding
|
# Force to use Unicode encoding
|
||||||
env.Append(MSVC_FLAGS=['/utf8'])
|
env.Append(MSVC_FLAGS=['/utf8'])
|
||||||
else: # Rest of the world
|
else: # Rest of the world
|
||||||
|
version = methods.get_compiler_version(env) or [-1, -1]
|
||||||
|
|
||||||
shadow_local_warning = []
|
shadow_local_warning = []
|
||||||
all_plus_warnings = ['-Wwrite-strings']
|
all_plus_warnings = ['-Wwrite-strings']
|
||||||
|
|
||||||
if methods.using_gcc(env):
|
if methods.using_gcc(env):
|
||||||
version = methods.get_compiler_version(env)
|
if version[0] >= 7:
|
||||||
if version != None and version[0] >= '7':
|
|
||||||
shadow_local_warning = ['-Wshadow-local']
|
shadow_local_warning = ['-Wshadow-local']
|
||||||
|
|
||||||
if (env["warnings"] == 'extra'):
|
if (env["warnings"] == 'extra'):
|
||||||
|
@ -357,8 +370,7 @@ if selected_platform in platform_list:
|
||||||
'-Wduplicated-branches', '-Wduplicated-cond',
|
'-Wduplicated-branches', '-Wduplicated-cond',
|
||||||
'-Wstringop-overflow=4', '-Wlogical-op'])
|
'-Wstringop-overflow=4', '-Wlogical-op'])
|
||||||
env.Append(CXXFLAGS=['-Wnoexcept', '-Wplacement-new=1'])
|
env.Append(CXXFLAGS=['-Wnoexcept', '-Wplacement-new=1'])
|
||||||
version = methods.get_compiler_version(env)
|
if version[0] >= 9:
|
||||||
if version != None and version[0] >= '9':
|
|
||||||
env.Append(CCFLAGS=['-Wattribute-alias=2'])
|
env.Append(CCFLAGS=['-Wattribute-alias=2'])
|
||||||
elif (env["warnings"] == 'all'):
|
elif (env["warnings"] == 'all'):
|
||||||
env.Append(CCFLAGS=['-Wall'] + shadow_local_warning)
|
env.Append(CCFLAGS=['-Wall'] + shadow_local_warning)
|
||||||
|
|
|
@ -598,9 +598,9 @@ private:
|
||||||
bool _list_skip_hidden;
|
bool _list_skip_hidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
class _Marshalls : public Reference {
|
class _Marshalls : public Object {
|
||||||
|
|
||||||
GDCLASS(_Marshalls, Reference);
|
GDCLASS(_Marshalls, Object);
|
||||||
|
|
||||||
static _Marshalls *singleton;
|
static _Marshalls *singleton;
|
||||||
|
|
||||||
|
|
|
@ -1174,7 +1174,7 @@ Error Expression::_get_token(Token &r_token) {
|
||||||
if (is_float)
|
if (is_float)
|
||||||
r_token.value = num.to_double();
|
r_token.value = num.to_double();
|
||||||
else
|
else
|
||||||
r_token.value = num.to_int();
|
r_token.value = num.to_int64();
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
|
} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
|
||||||
|
|
|
@ -348,7 +348,7 @@ void InputEventKey::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "scancode"), "set_scancode", "get_scancode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "scancode"), "set_scancode", "get_scancode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "echo"), "set_echo", "is_echo");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo");
|
||||||
}
|
}
|
||||||
|
|
||||||
InputEventKey::InputEventKey() {
|
InputEventKey::InputEventKey() {
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
The [JavaScript] singleton.
|
The [JavaScript] singleton.
|
||||||
[b]Note:[/b] Only implemented on HTML5.
|
[b]Note:[/b] Only implemented on HTML5.
|
||||||
</member>
|
</member>
|
||||||
<member name="Marshalls" type="Reference" setter="" getter="">
|
<member name="Marshalls" type="Marshalls" setter="" getter="">
|
||||||
The [Marshalls] singleton.
|
The [Marshalls] singleton.
|
||||||
</member>
|
</member>
|
||||||
<member name="NavigationMeshGenerator" type="EditorNavigationMeshGenerator" setter="" getter="">
|
<member name="NavigationMeshGenerator" type="EditorNavigationMeshGenerator" setter="" getter="">
|
||||||
|
|
|
@ -54,6 +54,13 @@
|
||||||
Returns the world-space controller position.
|
Returns the world-space controller position.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="get_tracker_id" qualifiers="const">
|
||||||
|
<return type="int">
|
||||||
|
</return>
|
||||||
|
<description>
|
||||||
|
Returns the internal tracker ID. This uniquely identifies the tracker per tracker type and matches the ID you need to specify for nodes such as the [ARVRController] and [ARVRAnchor] nodes.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="get_tracks_orientation" qualifiers="const">
|
<method name="get_tracks_orientation" qualifiers="const">
|
||||||
<return type="bool">
|
<return type="bool">
|
||||||
</return>
|
</return>
|
||||||
|
|
|
@ -14,6 +14,12 @@
|
||||||
array[2] = "Three"
|
array[2] = "Three"
|
||||||
print(array[-2]) # Three.
|
print(array[-2]) # Three.
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
|
Arrays can be concatenated using the [code]+[/code] operator:
|
||||||
|
[codeblock]
|
||||||
|
var array1 = ["One", 2]
|
||||||
|
var array2 = [3, "Four"]
|
||||||
|
print(array1 + array2) # ["One", 2, 3, "Four"]
|
||||||
|
[/codeblock]
|
||||||
Arrays are always passed by reference.
|
Arrays are always passed by reference.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
Concave polygon shape resource, which can be set into a [PhysicsBody] or area. This shape is created by feeding a list of triangles.
|
Concave polygon shape resource, which can be set into a [PhysicsBody] or area. This shape is created by feeding a list of triangles.
|
||||||
|
Note: when used for collision, [ConcavePolygonShape] is intended to work with static [PhysicsBody] nodes like [StaticBody] and will not work with [KinematicBody] or [RigidBody] with a mode other than Static.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
|
|
@ -147,10 +147,10 @@
|
||||||
If [code]true[/code], it is running inside the editor. Useful for tool scripts.
|
If [code]true[/code], it is running inside the editor. Useful for tool scripts.
|
||||||
</member>
|
</member>
|
||||||
<member name="iterations_per_second" type="int" setter="set_iterations_per_second" getter="get_iterations_per_second" default="60">
|
<member name="iterations_per_second" type="int" setter="set_iterations_per_second" getter="get_iterations_per_second" default="60">
|
||||||
The number of fixed iterations per second (for fixed process and physics).
|
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around tunneling issues, but keep in mind doing so will increase CPU usage.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
|
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
|
||||||
Controls how much physic ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows to smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
|
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows to smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
|
||||||
</member>
|
</member>
|
||||||
<member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0">
|
<member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0">
|
||||||
The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit.
|
The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<class name="Marshalls" inherits="Reference" version="3.2">
|
<class name="Marshalls" inherits="Object" version="3.2">
|
||||||
<brief_description>
|
<brief_description>
|
||||||
Data transformation (marshalling) and encoding helpers.
|
Data transformation (marshalling) and encoding helpers.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
|
|
|
@ -84,8 +84,7 @@
|
||||||
<argument index="0" name="id" type="int">
|
<argument index="0" name="id" type="int">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Returns a generated item preview (a 3D rendering in isometric perspective).
|
When running in the editor, returns a generated item preview (a 3D rendering in isometric perspective). When used in a running project, returns the manually-defined item preview which can be set using [method set_item_preview]. Returns an empty [Texture] if no preview was manually set in a running project.
|
||||||
[b]Note:[/b] Since item previews are only generated in an editor context, this function will return an empty [Texture] in a running project.
|
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_item_shapes" qualifiers="const">
|
<method name="get_item_shapes" qualifiers="const">
|
||||||
|
|
|
@ -326,7 +326,7 @@
|
||||||
<return type="float">
|
<return type="float">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
Returns the time elapsed since the last physics-bound frame (see [method _physics_process]). This is always a constant value in physics processing unless the frames per second is changed via [member Engine.target_fps].
|
Returns the time elapsed since the last physics-bound frame (see [method _physics_process]). This is always a constant value in physics processing unless the frames per second is changed via [member Engine.iterations_per_second].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_position_in_parent" qualifiers="const">
|
<method name="get_position_in_parent" qualifiers="const">
|
||||||
|
@ -745,7 +745,7 @@
|
||||||
<argument index="0" name="enable" type="bool">
|
<argument index="0" name="enable" type="bool">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Enables or disables physics (i.e. fixed framerate) processing. When a node is being processed, it will receive a [constant NOTIFICATION_PHYSICS_PROCESS] at a fixed (usually 60 FPS, see [member Engine.target_fps] to change) interval (and the [method _physics_process] callback will be called if exists). Enabled automatically if [method _physics_process] is overridden. Any calls to this before [method _ready] will be ignored.
|
Enables or disables physics (i.e. fixed framerate) processing. When a node is being processed, it will receive a [constant NOTIFICATION_PHYSICS_PROCESS] at a fixed (usually 60 FPS, see [member Engine.iterations_per_second] to change) interval (and the [method _physics_process] callback will be called if exists). Enabled automatically if [method _physics_process] is overridden. Any calls to this before [method _ready] will be ignored.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_physics_process_internal">
|
<method name="set_physics_process_internal">
|
||||||
|
|
|
@ -956,10 +956,12 @@
|
||||||
Enables [member Viewport.physics_object_picking] on the root viewport.
|
Enables [member Viewport.physics_object_picking] on the root viewport.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/common/physics_fps" type="int" setter="" getter="" default="60">
|
<member name="physics/common/physics_fps" type="int" setter="" getter="" default="60">
|
||||||
Frames per second used in the physics. Physics always needs a fixed amount of frames per second.
|
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run.
|
||||||
|
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.iterations_per_second] instead.
|
||||||
</member>
|
</member>
|
||||||
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
|
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
|
||||||
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
|
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
|
||||||
|
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
|
||||||
</member>
|
</member>
|
||||||
<member name="rendering/environment/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
|
<member name="rendering/environment/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
|
||||||
Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
|
Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
<argument index="0" name="RID" type="RID">
|
<argument index="0" name="RID" type="RID">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Adds the object with the given [RID] to the list of objects excluded from the collision check.
|
Adds the [PhysicsBody] object with the given [RID] to the list of [PhysicsBody] objects excluded from the collision check.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="clear_excluded_objects">
|
<method name="clear_excluded_objects">
|
||||||
<return type="void">
|
<return type="void">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
Clears the list of objects excluded from the collision check.
|
Clears the list of [PhysicsBody] objects excluded from the collision check.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_hit_length">
|
<method name="get_hit_length">
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
<argument index="0" name="RID" type="RID">
|
<argument index="0" name="RID" type="RID">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Removes the given [RID] from the list of objects excluded from the collision check.
|
Removes the given [RID] from the list of [PhysicsBody] objects excluded from the collision check.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
|
|
|
@ -310,7 +310,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
|
||||||
if (p_pipe_mutex) {
|
if (p_pipe_mutex) {
|
||||||
p_pipe_mutex->lock();
|
p_pipe_mutex->lock();
|
||||||
}
|
}
|
||||||
(*r_pipe) += buf;
|
(*r_pipe) += String::utf8(buf);
|
||||||
if (p_pipe_mutex) {
|
if (p_pipe_mutex) {
|
||||||
p_pipe_mutex->unlock();
|
p_pipe_mutex->unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2480,6 +2480,9 @@ void AnimationTrackEdit::_path_entered(const String &p_text) {
|
||||||
|
|
||||||
bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const {
|
bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const {
|
||||||
|
|
||||||
|
if (root == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
RES res;
|
RES res;
|
||||||
Vector<StringName> leftover_path;
|
Vector<StringName> leftover_path;
|
||||||
Node *node = root->get_node_and_resource(animation->track_get_path(track), res, leftover_path);
|
Node *node = root->get_node_and_resource(animation->track_get_path(track), res, leftover_path);
|
||||||
|
|
|
@ -1261,7 +1261,7 @@ void CodeTextEditor::clone_lines_down() {
|
||||||
text_editor->cursor_set_line(cursor_new_line);
|
text_editor->cursor_set_line(cursor_new_line);
|
||||||
text_editor->cursor_set_column(cursor_new_column);
|
text_editor->cursor_set_column(cursor_new_column);
|
||||||
if (selection_active) {
|
if (selection_active) {
|
||||||
text_editor->select(to_line, to_column, 2 * to_line - from_line, 2 * to_column - from_column);
|
text_editor->select(to_line, to_column, 2 * to_line - from_line, to_line == from_line ? 2 * to_column - from_column : to_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
text_editor->end_complex_operation();
|
text_editor->end_complex_operation();
|
||||||
|
|
|
@ -500,7 +500,6 @@ Control *ConnectionsDockTree::make_custom_tooltip(const String &p_text) const {
|
||||||
String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]";
|
String text = TTR("Signal:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]";
|
||||||
text += p_text.get_slice("::", 1).strip_edges() + "\n";
|
text += p_text.get_slice("::", 1).strip_edges() + "\n";
|
||||||
text += p_text.get_slice("::", 2).strip_edges();
|
text += p_text.get_slice("::", 2).strip_edges();
|
||||||
help_bit->set_text(text);
|
|
||||||
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
||||||
return help_bit;
|
return help_bit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,10 +435,14 @@ void EditorData::restore_editor_global_states() {
|
||||||
|
|
||||||
void EditorData::paste_object_params(Object *p_object) {
|
void EditorData::paste_object_params(Object *p_object) {
|
||||||
|
|
||||||
|
ERR_FAIL_NULL(p_object);
|
||||||
|
undo_redo.create_action(TTR("Paste Params"));
|
||||||
for (List<PropertyData>::Element *E = clipboard.front(); E; E = E->next()) {
|
for (List<PropertyData>::Element *E = clipboard.front(); E; E = E->next()) {
|
||||||
|
String name = E->get().name;
|
||||||
p_object->set(E->get().name, E->get().value);
|
undo_redo.add_do_property(p_object, name, E->get().value);
|
||||||
|
undo_redo.add_undo_property(p_object, name, p_object->get(name));
|
||||||
}
|
}
|
||||||
|
undo_redo.commit_action();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EditorData::call_build() {
|
bool EditorData::call_build() {
|
||||||
|
|
|
@ -691,7 +691,7 @@ void EditorFileDialog::update_file_name() {
|
||||||
String base_name = file_str.get_basename();
|
String base_name = file_str.get_basename();
|
||||||
Vector<String> filter_substr = filter_str.split(";");
|
Vector<String> filter_substr = filter_str.split(";");
|
||||||
if (filter_substr.size() >= 2) {
|
if (filter_substr.size() >= 2) {
|
||||||
file_str = base_name + "." + filter_substr[1].strip_edges().to_lower();
|
file_str = base_name + "." + filter_substr[0].strip_edges().lstrip("*.").to_lower();
|
||||||
} else {
|
} else {
|
||||||
file_str = base_name + "." + filter_str.get_extension().strip_edges().to_lower();
|
file_str = base_name + "." + filter_str.get_extension().strip_edges().to_lower();
|
||||||
}
|
}
|
||||||
|
|
|
@ -778,10 +778,20 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const {
|
||||||
help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
|
help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
|
||||||
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
|
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
|
||||||
|
|
||||||
String text = TTR("Property:") + " [u][b]" + p_text.get_slice("::", 0) + "[/b][/u]\n";
|
Vector<String> slices = p_text.split("::", false);
|
||||||
text += p_text.get_slice("::", 1).strip_edges();
|
if (!slices.empty()) {
|
||||||
help_bit->set_text(text);
|
String property_name = slices[0].strip_edges();
|
||||||
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
String text = TTR("Property:") + " [u][b]" + property_name + "[/b][/u]";
|
||||||
|
|
||||||
|
if (slices.size() > 1) {
|
||||||
|
String property_doc = slices[1].strip_edges();
|
||||||
|
if (property_name != property_doc) {
|
||||||
|
text += "\n" + property_doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
||||||
|
}
|
||||||
|
|
||||||
return help_bit;
|
return help_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,10 +1015,20 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons
|
||||||
help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
|
help_bit->add_style_override("panel", get_stylebox("panel", "TooltipPanel"));
|
||||||
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
|
help_bit->get_rich_text()->set_fixed_size_to_width(360 * EDSCALE);
|
||||||
|
|
||||||
String text = "[u][b]" + p_text.get_slice("::", 0) + "[/b][/u]\n";
|
Vector<String> slices = p_text.split("::", false);
|
||||||
text += p_text.get_slice("::", 1).strip_edges();
|
if (!slices.empty()) {
|
||||||
help_bit->set_text(text);
|
String property_name = slices[0].strip_edges();
|
||||||
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
String text = "[u][b]" + property_name + "[/b][/u]";
|
||||||
|
|
||||||
|
if (slices.size() > 1) {
|
||||||
|
String property_doc = slices[1].strip_edges();
|
||||||
|
if (property_name != property_doc) {
|
||||||
|
text += "\n" + property_doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
help_bit->call_deferred("set_text", text); //hack so it uses proper theme once inside scene
|
||||||
|
}
|
||||||
|
|
||||||
return help_bit;
|
return help_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -855,6 +855,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
||||||
Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
|
Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
|
||||||
int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height() + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
|
int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height() + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
|
||||||
style_panel_invisible_top->set_expand_margin_size(MARGIN_TOP, -stylebox_offset);
|
style_panel_invisible_top->set_expand_margin_size(MARGIN_TOP, -stylebox_offset);
|
||||||
|
style_panel_invisible_top->set_default_margin(MARGIN_TOP, 0);
|
||||||
theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
|
theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
|
||||||
|
|
||||||
// LineEdit
|
// LineEdit
|
||||||
|
|
|
@ -547,9 +547,7 @@ void ExportTemplateManager::_notification(int p_what) {
|
||||||
bool ExportTemplateManager::can_install_android_template() {
|
bool ExportTemplateManager::can_install_android_template() {
|
||||||
|
|
||||||
const String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
|
const String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
|
||||||
return FileAccess::exists(templates_dir.plus_file("android_source.zip")) &&
|
return FileAccess::exists(templates_dir.plus_file("android_source.zip"));
|
||||||
FileAccess::exists(templates_dir.plus_file("android_release.apk")) &&
|
|
||||||
FileAccess::exists(templates_dir.plus_file("android_debug.apk"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error ExportTemplateManager::install_android_template() {
|
Error ExportTemplateManager::install_android_template() {
|
||||||
|
|
|
@ -533,6 +533,12 @@ FindInFilesPanel::FindInFilesPanel() {
|
||||||
_status_label = memnew(Label);
|
_status_label = memnew(Label);
|
||||||
hbc->add_child(_status_label);
|
hbc->add_child(_status_label);
|
||||||
|
|
||||||
|
_refresh_button = memnew(Button);
|
||||||
|
_refresh_button->set_text(TTR("Refresh"));
|
||||||
|
_refresh_button->connect("pressed", this, "_on_refresh_button_clicked");
|
||||||
|
_refresh_button->hide();
|
||||||
|
hbc->add_child(_refresh_button);
|
||||||
|
|
||||||
_cancel_button = memnew(Button);
|
_cancel_button = memnew(Button);
|
||||||
_cancel_button->set_text(TTR("Cancel"));
|
_cancel_button->set_text(TTR("Cancel"));
|
||||||
_cancel_button->connect("pressed", this, "_on_cancel_button_clicked");
|
_cancel_button->connect("pressed", this, "_on_cancel_button_clicked");
|
||||||
|
@ -616,6 +622,7 @@ void FindInFilesPanel::start_search() {
|
||||||
_finder->start();
|
_finder->start();
|
||||||
|
|
||||||
update_replace_buttons();
|
update_replace_buttons();
|
||||||
|
_refresh_button->hide();
|
||||||
_cancel_button->show();
|
_cancel_button->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +633,7 @@ void FindInFilesPanel::stop_search() {
|
||||||
_status_label->set_text("");
|
_status_label->set_text("");
|
||||||
update_replace_buttons();
|
update_replace_buttons();
|
||||||
set_progress_visible(false);
|
set_progress_visible(false);
|
||||||
|
_refresh_button->show();
|
||||||
_cancel_button->hide();
|
_cancel_button->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,9 +736,14 @@ void FindInFilesPanel::_on_finished() {
|
||||||
_status_label->set_text(TTR("Search complete"));
|
_status_label->set_text(TTR("Search complete"));
|
||||||
update_replace_buttons();
|
update_replace_buttons();
|
||||||
set_progress_visible(false);
|
set_progress_visible(false);
|
||||||
|
_refresh_button->show();
|
||||||
_cancel_button->hide();
|
_cancel_button->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FindInFilesPanel::_on_refresh_button_clicked() {
|
||||||
|
start_search();
|
||||||
|
}
|
||||||
|
|
||||||
void FindInFilesPanel::_on_cancel_button_clicked() {
|
void FindInFilesPanel::_on_cancel_button_clicked() {
|
||||||
stop_search();
|
stop_search();
|
||||||
}
|
}
|
||||||
|
@ -905,6 +918,7 @@ void FindInFilesPanel::_bind_methods() {
|
||||||
ClassDB::bind_method("_on_result_found", &FindInFilesPanel::_on_result_found);
|
ClassDB::bind_method("_on_result_found", &FindInFilesPanel::_on_result_found);
|
||||||
ClassDB::bind_method("_on_item_edited", &FindInFilesPanel::_on_item_edited);
|
ClassDB::bind_method("_on_item_edited", &FindInFilesPanel::_on_item_edited);
|
||||||
ClassDB::bind_method("_on_finished", &FindInFilesPanel::_on_finished);
|
ClassDB::bind_method("_on_finished", &FindInFilesPanel::_on_finished);
|
||||||
|
ClassDB::bind_method("_on_refresh_button_clicked", &FindInFilesPanel::_on_refresh_button_clicked);
|
||||||
ClassDB::bind_method("_on_cancel_button_clicked", &FindInFilesPanel::_on_cancel_button_clicked);
|
ClassDB::bind_method("_on_cancel_button_clicked", &FindInFilesPanel::_on_cancel_button_clicked);
|
||||||
ClassDB::bind_method("_on_result_selected", &FindInFilesPanel::_on_result_selected);
|
ClassDB::bind_method("_on_result_selected", &FindInFilesPanel::_on_result_selected);
|
||||||
ClassDB::bind_method("_on_replace_text_changed", &FindInFilesPanel::_on_replace_text_changed);
|
ClassDB::bind_method("_on_replace_text_changed", &FindInFilesPanel::_on_replace_text_changed);
|
||||||
|
|
|
@ -163,6 +163,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void _on_result_found(String fpath, int line_number, int begin, int end, String text);
|
void _on_result_found(String fpath, int line_number, int begin, int end, String text);
|
||||||
void _on_finished();
|
void _on_finished();
|
||||||
|
void _on_refresh_button_clicked();
|
||||||
void _on_cancel_button_clicked();
|
void _on_cancel_button_clicked();
|
||||||
void _on_result_selected();
|
void _on_result_selected();
|
||||||
void _on_item_edited();
|
void _on_item_edited();
|
||||||
|
@ -190,6 +191,7 @@ private:
|
||||||
Label *_search_text_label;
|
Label *_search_text_label;
|
||||||
Tree *_results_display;
|
Tree *_results_display;
|
||||||
Label *_status_label;
|
Label *_status_label;
|
||||||
|
Button *_refresh_button;
|
||||||
Button *_cancel_button;
|
Button *_cancel_button;
|
||||||
ProgressBar *_progress_bar;
|
ProgressBar *_progress_bar;
|
||||||
Map<String, TreeItem *> _file_items;
|
Map<String, TreeItem *> _file_items;
|
||||||
|
|
|
@ -2179,6 +2179,8 @@ Error EditorSceneImporterGLTF::_map_skin_joints_indices_to_skeleton_bone_indices
|
||||||
const GLTFNodeIndex node_i = skin.joints_original[joint_index];
|
const GLTFNodeIndex node_i = skin.joints_original[joint_index];
|
||||||
const GLTFNode *node = state.nodes[node_i];
|
const GLTFNode *node = state.nodes[node_i];
|
||||||
|
|
||||||
|
skin.joint_i_to_name.insert(joint_index, node->name);
|
||||||
|
|
||||||
const int bone_index = skeleton.godot_skeleton->find_bone(node->name);
|
const int bone_index = skeleton.godot_skeleton->find_bone(node->name);
|
||||||
ERR_FAIL_COND_V(bone_index < 0, FAILED);
|
ERR_FAIL_COND_V(bone_index < 0, FAILED);
|
||||||
|
|
||||||
|
@ -2200,12 +2202,18 @@ Error EditorSceneImporterGLTF::_create_skins(GLTFState &state) {
|
||||||
const bool has_ibms = !gltf_skin.inverse_binds.empty();
|
const bool has_ibms = !gltf_skin.inverse_binds.empty();
|
||||||
|
|
||||||
for (int joint_i = 0; joint_i < gltf_skin.joints_original.size(); ++joint_i) {
|
for (int joint_i = 0; joint_i < gltf_skin.joints_original.size(); ++joint_i) {
|
||||||
int bone_i = gltf_skin.joint_i_to_bone_i[joint_i];
|
|
||||||
|
|
||||||
|
Transform xform;
|
||||||
if (has_ibms) {
|
if (has_ibms) {
|
||||||
skin->add_bind(bone_i, gltf_skin.inverse_binds[joint_i]);
|
xform = gltf_skin.inverse_binds[joint_i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.use_named_skin_binds) {
|
||||||
|
StringName name = gltf_skin.joint_i_to_name[joint_i];
|
||||||
|
skin->add_named_bind(name, xform);
|
||||||
} else {
|
} else {
|
||||||
skin->add_bind(bone_i, Transform());
|
int bone_i = gltf_skin.joint_i_to_bone_i[joint_i];
|
||||||
|
skin->add_bind(bone_i, xform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2991,6 +2999,7 @@ Node *EditorSceneImporterGLTF::import_scene(const String &p_path, uint32_t p_fla
|
||||||
|
|
||||||
state.major_version = version.get_slice(".", 0).to_int();
|
state.major_version = version.get_slice(".", 0).to_int();
|
||||||
state.minor_version = version.get_slice(".", 1).to_int();
|
state.minor_version = version.get_slice(".", 1).to_int();
|
||||||
|
state.use_named_skin_binds = p_flags & IMPORT_USE_NAMED_SKIN_BINDS;
|
||||||
|
|
||||||
/* STEP 0 PARSE SCENE */
|
/* STEP 0 PARSE SCENE */
|
||||||
Error err = _parse_scenes(state);
|
Error err = _parse_scenes(state);
|
||||||
|
|
|
@ -231,6 +231,7 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
|
||||||
// A mapping from the joint indices (in the order of joints_original) to the
|
// A mapping from the joint indices (in the order of joints_original) to the
|
||||||
// Godot Skeleton's bone_indices
|
// Godot Skeleton's bone_indices
|
||||||
Map<int, int> joint_i_to_bone_i;
|
Map<int, int> joint_i_to_bone_i;
|
||||||
|
Map<int, StringName> joint_i_to_name;
|
||||||
|
|
||||||
// The Actual Skin that will be created as a mapping between the IBM's of this skin
|
// The Actual Skin that will be created as a mapping between the IBM's of this skin
|
||||||
// to the generated skeleton for the mesh instances.
|
// to the generated skeleton for the mesh instances.
|
||||||
|
@ -298,6 +299,8 @@ class EditorSceneImporterGLTF : public EditorSceneImporter {
|
||||||
int minor_version;
|
int minor_version;
|
||||||
Vector<uint8_t> glb_data;
|
Vector<uint8_t> glb_data;
|
||||||
|
|
||||||
|
bool use_named_skin_binds;
|
||||||
|
|
||||||
Vector<GLTFNode *> nodes;
|
Vector<GLTFNode *> nodes;
|
||||||
Vector<Vector<uint8_t> > buffers;
|
Vector<Vector<uint8_t> > buffers;
|
||||||
Vector<GLTFBufferView> buffer_views;
|
Vector<GLTFBufferView> buffer_views;
|
||||||
|
|
|
@ -1171,6 +1171,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files (.mesh),Files (.tres)"), meshes_out ? 1 : 0));
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/light_baking", PROPERTY_HINT_ENUM, "Disabled,Enable,Gen Lightmaps", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
|
||||||
|
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
|
||||||
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
|
r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
|
||||||
|
@ -1313,6 +1314,9 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
||||||
if (int(p_options["materials/location"]) == 0)
|
if (int(p_options["materials/location"]) == 0)
|
||||||
import_flags |= EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES;
|
import_flags |= EditorSceneImporter::IMPORT_MATERIALS_IN_INSTANCES;
|
||||||
|
|
||||||
|
if (bool(p_options["skins/use_named_skins"]))
|
||||||
|
import_flags |= EditorSceneImporter::IMPORT_USE_NAMED_SKIN_BINDS;
|
||||||
|
|
||||||
Error err = OK;
|
Error err = OK;
|
||||||
List<String> missing_deps; // for now, not much will be done with this
|
List<String> missing_deps; // for now, not much will be done with this
|
||||||
Node *scene = importer->import_scene(src_path, import_flags, fps, &missing_deps, &err);
|
Node *scene = importer->import_scene(src_path, import_flags, fps, &missing_deps, &err);
|
||||||
|
|
|
@ -59,7 +59,8 @@ public:
|
||||||
IMPORT_GENERATE_TANGENT_ARRAYS = 256,
|
IMPORT_GENERATE_TANGENT_ARRAYS = 256,
|
||||||
IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 512,
|
IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 512,
|
||||||
IMPORT_MATERIALS_IN_INSTANCES = 1024,
|
IMPORT_MATERIALS_IN_INSTANCES = 1024,
|
||||||
IMPORT_USE_COMPRESSION = 2048
|
IMPORT_USE_COMPRESSION = 2048,
|
||||||
|
IMPORT_USE_NAMED_SKIN_BINDS = 4096,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -143,8 +143,8 @@ static void _plot_triangle(Vector2 *vertices, const Vector2 &p_offset, bool p_tr
|
||||||
|
|
||||||
int px = xi, py = yi;
|
int px = xi, py = yi;
|
||||||
int sx = px, sy = py;
|
int sx = px, sy = py;
|
||||||
sx = CLAMP(sx, 0, src_width);
|
sx = CLAMP(sx, 0, src_width - 1);
|
||||||
sy = CLAMP(sy, 0, src_height);
|
sy = CLAMP(sy, 0, src_height - 1);
|
||||||
Color color = p_src_image->get_pixel(sx, sy);
|
Color color = p_src_image->get_pixel(sx, sy);
|
||||||
if (p_transposed) {
|
if (p_transposed) {
|
||||||
SWAP(px, py);
|
SWAP(px, py);
|
||||||
|
@ -165,8 +165,8 @@ static void _plot_triangle(Vector2 *vertices, const Vector2 &p_offset, bool p_tr
|
||||||
for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) {
|
for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) {
|
||||||
int px = xi, py = yi;
|
int px = xi, py = yi;
|
||||||
int sx = px, sy = py;
|
int sx = px, sy = py;
|
||||||
sx = CLAMP(sx, 0, src_width);
|
sx = CLAMP(sx, 0, src_width - 1);
|
||||||
sy = CLAMP(sy, 0, src_height);
|
sy = CLAMP(sy, 0, src_height - 1);
|
||||||
Color color = p_src_image->get_pixel(sx, sy);
|
Color color = p_src_image->get_pixel(sx, sy);
|
||||||
if (p_transposed) {
|
if (p_transposed) {
|
||||||
SWAP(px, py);
|
SWAP(px, py);
|
||||||
|
|
|
@ -107,6 +107,9 @@ void ImportDock::set_edit_path(const String &p_path) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
params->paths.clear();
|
||||||
|
params->paths.push_back(p_path);
|
||||||
|
|
||||||
_update_options(config);
|
_update_options(config);
|
||||||
|
|
||||||
List<Ref<ResourceImporter> > importers;
|
List<Ref<ResourceImporter> > importers;
|
||||||
|
@ -129,8 +132,6 @@ void ImportDock::set_edit_path(const String &p_path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params->paths.clear();
|
|
||||||
params->paths.push_back(p_path);
|
|
||||||
import->set_disabled(false);
|
import->set_disabled(false);
|
||||||
import_as->set_disabled(false);
|
import_as->set_disabled(false);
|
||||||
preset->set_disabled(false);
|
preset->set_disabled(false);
|
||||||
|
@ -145,7 +146,7 @@ void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
|
||||||
|
|
||||||
params->properties.clear();
|
params->properties.clear();
|
||||||
params->values.clear();
|
params->values.clear();
|
||||||
params->checking = false;
|
params->checking = params->paths.size() > 1;
|
||||||
params->checked.clear();
|
params->checked.clear();
|
||||||
|
|
||||||
for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
|
for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
|
||||||
|
|
|
@ -76,7 +76,6 @@ void InspectorDock::_menu_option(int p_option) {
|
||||||
editor_data->apply_changes_in_editors();
|
editor_data->apply_changes_in_editors();
|
||||||
if (current)
|
if (current)
|
||||||
editor_data->paste_object_params(current);
|
editor_data->paste_object_params(current);
|
||||||
editor_data->get_undo_redo().clear_history();
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OBJECT_UNIQUE_RESOURCES: {
|
case OBJECT_UNIQUE_RESOURCES: {
|
||||||
|
|
|
@ -455,7 +455,7 @@ MeshInstanceEditor::MeshInstanceEditor() {
|
||||||
options->get_popup()->add_separator();
|
options->get_popup()->add_separator();
|
||||||
options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
|
options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
|
||||||
options->get_popup()->add_item(TTR("Create Single Convex Collision Siblings"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
|
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
|
||||||
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
|
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
|
||||||
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options."));
|
options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options."));
|
||||||
|
|
|
@ -3211,7 +3211,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
|
||||||
scripts_vbox->add_child(script_list);
|
scripts_vbox->add_child(script_list);
|
||||||
script_list->set_custom_minimum_size(Size2(150, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
|
script_list->set_custom_minimum_size(Size2(150, 60) * EDSCALE); //need to give a bit of limit to avoid it from disappearing
|
||||||
script_list->set_v_size_flags(SIZE_EXPAND_FILL);
|
script_list->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||||
script_split->set_split_offset(140);
|
script_split->set_split_offset(70 * EDSCALE);
|
||||||
_sort_list_on_update = true;
|
_sort_list_on_update = true;
|
||||||
script_list->connect("gui_input", this, "_script_list_gui_input", varray(), CONNECT_DEFERRED);
|
script_list->connect("gui_input", this, "_script_list_gui_input", varray(), CONNECT_DEFERRED);
|
||||||
script_list->set_allow_rmb_select(true);
|
script_list->set_allow_rmb_select(true);
|
||||||
|
|
24
methods.py
24
methods.py
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import os.path
|
|
||||||
import re
|
import re
|
||||||
import glob
|
import glob
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -626,14 +625,23 @@ def detect_darwin_sdk_path(platform, env):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_compiler_version(env):
|
def get_compiler_version(env):
|
||||||
# Not using this method on clang because it returns 4.2.1 # https://reviews.llvm.org/D56803
|
"""
|
||||||
if using_gcc(env):
|
Returns an array of version numbers as ints: [major, minor, patch].
|
||||||
version = decode_utf8(subprocess.check_output([env['CXX'], '-dumpversion']).strip())
|
The return array should have at least two values (major, minor).
|
||||||
else:
|
"""
|
||||||
version = decode_utf8(subprocess.check_output([env['CXX'], '--version']).strip())
|
if not env.msvc:
|
||||||
match = re.search('[0-9][0-9.]*', version)
|
# Not using -dumpversion as some GCC distros only return major, and
|
||||||
|
# Clang used to return hardcoded 4.2.1: # https://reviews.llvm.org/D56803
|
||||||
|
try:
|
||||||
|
version = decode_utf8(subprocess.check_output([env.subst(env['CXX']), '--version']).strip())
|
||||||
|
except (subprocess.CalledProcessError, OSError):
|
||||||
|
print("Couldn't parse CXX environment variable to infer compiler version.")
|
||||||
|
return None
|
||||||
|
else: # TODO: Implement for MSVC
|
||||||
|
return None
|
||||||
|
match = re.search('[0-9]+\.[0-9.]+', version)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
return match.group().split('.')
|
return list(map(int, match.group().split('.')))
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -726,9 +726,6 @@ void SpaceBullet::check_ghost_overlaps() {
|
||||||
|
|
||||||
other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z));
|
other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z));
|
||||||
|
|
||||||
if (other_body_shape->isConcave())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
btTransform other_shape_transform(otherObject->get_bt_shape_transform(z));
|
btTransform other_shape_transform(otherObject->get_bt_shape_transform(z));
|
||||||
other_shape_transform.getOrigin() *= other_body_scale;
|
other_shape_transform.getOrigin() *= other_body_scale;
|
||||||
|
|
||||||
|
|
|
@ -490,9 +490,13 @@
|
||||||
<argument index="2" name="weight" type="float">
|
<argument index="2" name="weight" type="float">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Returns a normalized value considering the given range.
|
Returns a normalized value considering the given range. This is the opposite of [method lerp].
|
||||||
[codeblock]
|
[codeblock]
|
||||||
inverse_lerp(3, 5, 4) # Returns 0.5
|
var middle = lerp(20, 30, 0.75)
|
||||||
|
# `middle` is now 27.5.
|
||||||
|
# Now, we pretend to have forgotten the original ratio and want to get it back.
|
||||||
|
var ratio = inverse_lerp(20, 30, 27.5)
|
||||||
|
# `ratio` is now 0.75.
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
@ -567,7 +571,7 @@
|
||||||
<argument index="2" name="weight" type="float">
|
<argument index="2" name="weight" type="float">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Linearly interpolates between two values by a normalized value.
|
Linearly interpolates between two values by a normalized value. This is the opposite of [method inverse_lerp].
|
||||||
If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float].
|
If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float].
|
||||||
If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method).
|
If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method).
|
||||||
[codeblock]
|
[codeblock]
|
||||||
|
@ -587,7 +591,7 @@
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Linearly interpolates between two angles (in radians) by a normalized value.
|
Linearly interpolates between two angles (in radians) by a normalized value.
|
||||||
Similar to [method lerp] but interpolate correctly when the angles wrap around [constant @GDScript.TAU].
|
Similar to [method lerp], but interpolates correctly when the angles wrap around [constant @GDScript.TAU].
|
||||||
[codeblock]
|
[codeblock]
|
||||||
extends Sprite
|
extends Sprite
|
||||||
var elapsed = 0.0
|
var elapsed = 0.0
|
||||||
|
@ -605,7 +609,13 @@
|
||||||
<argument index="0" name="nrg" type="float">
|
<argument index="0" name="nrg" type="float">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Converts from linear energy to decibels (audio).
|
Converts from linear energy to decibels (audio). This can be used to implement volume sliders that behave as expected (since volume isn't linear). Example:
|
||||||
|
[codeblock]
|
||||||
|
# "Slider" refers to a node that inherits Range such as HSlider or VSlider.
|
||||||
|
# Its range must be configured to go from 0 to 1.
|
||||||
|
# Change the bus name if you'd like to change the volume of a specific bus only.
|
||||||
|
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear2db($Slider.value))
|
||||||
|
[/codeblock]
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="load">
|
<method name="load">
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using GodotTools.Ides.Rider;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using Directory = System.IO.Directory;
|
using Directory = System.IO.Directory;
|
||||||
using Environment = System.Environment;
|
using Environment = System.Environment;
|
||||||
|
@ -54,6 +55,12 @@ namespace GodotTools.Build
|
||||||
|
|
||||||
return msbuildPath;
|
return msbuildPath;
|
||||||
}
|
}
|
||||||
|
case BuildManager.BuildTool.JetBrainsMsBuild:
|
||||||
|
var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName);
|
||||||
|
if (!File.Exists(editorPath))
|
||||||
|
throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}");
|
||||||
|
var riderDir = new FileInfo(editorPath).Directory.Parent;
|
||||||
|
return Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe");
|
||||||
default:
|
default:
|
||||||
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GodotTools.Build;
|
using GodotTools.Build;
|
||||||
|
using GodotTools.Ides.Rider;
|
||||||
using GodotTools.Internals;
|
using GodotTools.Internals;
|
||||||
using GodotTools.Utils;
|
using GodotTools.Utils;
|
||||||
using static GodotTools.Internals.Globals;
|
using static GodotTools.Internals.Globals;
|
||||||
|
@ -16,6 +17,7 @@ namespace GodotTools
|
||||||
|
|
||||||
public const string PropNameMsbuildMono = "MSBuild (Mono)";
|
public const string PropNameMsbuildMono = "MSBuild (Mono)";
|
||||||
public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)";
|
public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)";
|
||||||
|
public const string PropNameMsbuildJetBrains = "MSBuild (JetBrains Rider)";
|
||||||
|
|
||||||
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
|
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
|
||||||
public const string MsBuildLogFileName = "msbuild_log.txt";
|
public const string MsBuildLogFileName = "msbuild_log.txt";
|
||||||
|
@ -23,7 +25,8 @@ namespace GodotTools
|
||||||
public enum BuildTool
|
public enum BuildTool
|
||||||
{
|
{
|
||||||
MsBuildMono,
|
MsBuildMono,
|
||||||
MsBuildVs
|
MsBuildVs,
|
||||||
|
JetBrainsMsBuild
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
|
private static void RemoveOldIssuesFile(BuildInfo buildInfo)
|
||||||
|
@ -181,7 +184,7 @@ namespace GodotTools
|
||||||
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, config);
|
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, config);
|
||||||
|
|
||||||
// Add Godot defines
|
// Add Godot defines
|
||||||
string constants = buildTool == BuildTool.MsBuildVs ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
|
string constants = buildTool != BuildTool.MsBuildMono ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
|
||||||
|
|
||||||
foreach (var godotDefine in godotDefines)
|
foreach (var godotDefine in godotDefines)
|
||||||
constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};";
|
constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};";
|
||||||
|
@ -189,7 +192,7 @@ namespace GodotTools
|
||||||
if (Internal.GodotIsRealTDouble())
|
if (Internal.GodotIsRealTDouble())
|
||||||
constants += "GODOT_REAL_T_IS_DOUBLE;";
|
constants += "GODOT_REAL_T_IS_DOUBLE;";
|
||||||
|
|
||||||
constants += buildTool == BuildTool.MsBuildVs ? "\"" : "\\\"";
|
constants += buildTool != BuildTool.MsBuildMono ? "\"" : "\\\"";
|
||||||
|
|
||||||
buildInfo.CustomProperties.Add(constants);
|
buildInfo.CustomProperties.Add(constants);
|
||||||
|
|
||||||
|
@ -245,10 +248,14 @@ namespace GodotTools
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
// Build tool settings
|
// Build tool settings
|
||||||
|
|
||||||
EditorDef("mono/builds/build_tool", OS.IsWindows ? BuildTool.MsBuildVs : BuildTool.MsBuildMono);
|
|
||||||
|
|
||||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||||
|
var msbuild = BuildTool.MsBuildMono;
|
||||||
|
if (OS.IsWindows)
|
||||||
|
msbuild = RiderPathManager.IsRider((string) editorSettings.GetSetting(RiderPathManager.EditorPathSettingName))
|
||||||
|
? BuildTool.JetBrainsMsBuild
|
||||||
|
: BuildTool.MsBuildVs;
|
||||||
|
|
||||||
|
EditorDef("mono/builds/build_tool", msbuild);
|
||||||
|
|
||||||
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||||
{
|
{
|
||||||
|
@ -256,7 +263,7 @@ namespace GodotTools
|
||||||
["name"] = "mono/builds/build_tool",
|
["name"] = "mono/builds/build_tool",
|
||||||
["hint"] = Godot.PropertyHint.Enum,
|
["hint"] = Godot.PropertyHint.Enum,
|
||||||
["hint_string"] = OS.IsWindows ?
|
["hint_string"] = OS.IsWindows ?
|
||||||
$"{PropNameMsbuildMono},{PropNameMsbuildVs}" :
|
$"{PropNameMsbuildMono},{PropNameMsbuildVs},{PropNameMsbuildJetBrains}" :
|
||||||
$"{PropNameMsbuildMono}"
|
$"{PropNameMsbuildMono}"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ using Environment = System.Environment;
|
||||||
using File = System.IO.File;
|
using File = System.IO.File;
|
||||||
using Path = System.IO.Path;
|
using Path = System.IO.Path;
|
||||||
using OS = GodotTools.Utils.OS;
|
using OS = GodotTools.Utils.OS;
|
||||||
|
// ReSharper disable UnassignedField.Local
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
// ReSharper disable UnassignedField.Global
|
||||||
|
// ReSharper disable MemberHidesStaticFromOuterClass
|
||||||
|
|
||||||
namespace GodotTools.Ides.Rider
|
namespace GodotTools.Ides.Rider
|
||||||
{
|
{
|
||||||
|
@ -131,28 +135,45 @@ namespace GodotTools.Ides.Rider
|
||||||
if (OS.IsWindows)
|
if (OS.IsWindows)
|
||||||
{
|
{
|
||||||
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
return Path.Combine(localAppData, @"JetBrains\Toolbox\apps\Rider");
|
return GetToolboxRiderRootPath(localAppData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OS.IsOSX)
|
if (OS.IsOSX)
|
||||||
{
|
{
|
||||||
var home = Environment.GetEnvironmentVariable("HOME");
|
var home = Environment.GetEnvironmentVariable("HOME");
|
||||||
if (!string.IsNullOrEmpty(home))
|
if (string.IsNullOrEmpty(home))
|
||||||
{
|
return string.Empty;
|
||||||
return Path.Combine(home, @"Library/Application Support/JetBrains/Toolbox/apps/Rider");
|
var localAppData = Path.Combine(home, @"Library/Application Support");
|
||||||
}
|
return GetToolboxRiderRootPath(localAppData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OS.IsUnixLike())
|
if (OS.IsUnixLike())
|
||||||
{
|
{
|
||||||
var home = Environment.GetEnvironmentVariable("HOME");
|
var home = Environment.GetEnvironmentVariable("HOME");
|
||||||
if (!string.IsNullOrEmpty(home))
|
if (string.IsNullOrEmpty(home))
|
||||||
{
|
return string.Empty;
|
||||||
return Path.Combine(home, @".local/share/JetBrains/Toolbox/apps/Rider");
|
var localAppData = Path.Combine(home, @".local/share");
|
||||||
}
|
return GetToolboxRiderRootPath(localAppData);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("Unexpected OS.");
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static string GetToolboxRiderRootPath(string localAppData)
|
||||||
|
{
|
||||||
|
var toolboxPath = Path.Combine(localAppData, @"JetBrains\Toolbox");
|
||||||
|
var settingsJson = Path.Combine(toolboxPath, ".settings.json");
|
||||||
|
|
||||||
|
if (File.Exists(settingsJson))
|
||||||
|
{
|
||||||
|
var path = SettingsJson.GetInstallLocationFromJson(File.ReadAllText(settingsJson));
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
toolboxPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
var toolboxRiderRootPath = Path.Combine(toolboxPath, @"apps\Rider");
|
||||||
|
return toolboxRiderRootPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ProductInfo GetBuildVersion(string path)
|
internal static ProductInfo GetBuildVersion(string path)
|
||||||
|
@ -197,20 +218,29 @@ namespace GodotTools.Ides.Rider
|
||||||
|
|
||||||
private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
|
private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
|
||||||
{
|
{
|
||||||
|
using (var key = Registry.CurrentUser.OpenSubKey(registryKey))
|
||||||
|
{
|
||||||
|
CollectPathsFromRegistry(installPaths, key);
|
||||||
|
}
|
||||||
using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
|
using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
|
||||||
{
|
{
|
||||||
if (key == null) return;
|
CollectPathsFromRegistry(installPaths, key);
|
||||||
foreach (var subkeyName in key.GetSubKeyNames().Where(a => a.Contains("Rider")))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CollectPathsFromRegistry(List<string> installPaths, RegistryKey key)
|
||||||
|
{
|
||||||
|
if (key == null) return;
|
||||||
|
foreach (var subkeyName in key.GetSubKeyNames().Where(a => a.Contains("Rider")))
|
||||||
|
{
|
||||||
|
using (var subkey = key.OpenSubKey(subkeyName))
|
||||||
{
|
{
|
||||||
using (var subkey = key.OpenSubKey(subkeyName))
|
var folderObject = subkey?.GetValue("InstallLocation");
|
||||||
{
|
if (folderObject == null) continue;
|
||||||
var folderObject = subkey?.GetValue("InstallLocation");
|
var folder = folderObject.ToString();
|
||||||
if (folderObject == null) continue;
|
var possiblePath = Path.Combine(folder, @"bin\rider64.exe");
|
||||||
var folder = folderObject.ToString();
|
if (File.Exists(possiblePath))
|
||||||
var possiblePath = Path.Combine(folder, @"bin\rider64.exe");
|
installPaths.Add(possiblePath);
|
||||||
if (File.Exists(possiblePath))
|
|
||||||
installPaths.Add(possiblePath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,8 +256,8 @@ namespace GodotTools.Ides.Rider
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D
|
// use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D
|
||||||
var historyFile = Path.Combine(channelDir, ".history.json");
|
var historyFile = Path.Combine(channelDir, ".history.json");
|
||||||
if (File.Exists(historyFile))
|
if (File.Exists(historyFile))
|
||||||
{
|
{
|
||||||
var json = File.ReadAllText(historyFile);
|
var json = File.ReadAllText(historyFile);
|
||||||
|
@ -255,14 +285,14 @@ namespace GodotTools.Ides.Rider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// changes in toolbox json files format may brake the logic above, so return all found Rider installations
|
// changes in toolbox json files format may brake the logic above, so return all found Rider installations
|
||||||
return Directory.GetDirectories(channelDir)
|
return Directory.GetDirectories(channelDir)
|
||||||
.SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir));
|
.SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// do not write to Debug.Log, just log it.
|
// do not write to Debug.Log, just log it.
|
||||||
Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
|
Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string[0];
|
return new string[0];
|
||||||
|
@ -288,6 +318,27 @@ namespace GodotTools.Ides.Rider
|
||||||
// Note that Unity disable this warning in the generated C# projects
|
// Note that Unity disable this warning in the generated C# projects
|
||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
class SettingsJson
|
||||||
|
{
|
||||||
|
public string install_location;
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
public static string GetInstallLocationFromJson(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject<SettingsJson>(json).install_location;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
Logger.Warn($"Failed to get install_location from json {json}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
class ToolboxHistory
|
class ToolboxHistory
|
||||||
{
|
{
|
||||||
|
@ -372,7 +423,6 @@ namespace GodotTools.Ides.Rider
|
||||||
[Serializable]
|
[Serializable]
|
||||||
class ActiveApplication
|
class ActiveApplication
|
||||||
{
|
{
|
||||||
// ReSharper disable once InconsistentNaming
|
|
||||||
public List<string> builds;
|
public List<string> builds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +430,7 @@ namespace GodotTools.Ides.Rider
|
||||||
|
|
||||||
public struct RiderInfo
|
public struct RiderInfo
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once NotAccessedField.Global
|
||||||
public bool IsToolbox;
|
public bool IsToolbox;
|
||||||
public string Presentation;
|
public string Presentation;
|
||||||
public Version BuildNumber;
|
public Version BuildNumber;
|
||||||
|
|
|
@ -9,13 +9,13 @@ namespace GodotTools.Ides.Rider
|
||||||
{
|
{
|
||||||
public static class RiderPathManager
|
public static class RiderPathManager
|
||||||
{
|
{
|
||||||
private static readonly string editorPathSettingName = "mono/editor/editor_path_optional";
|
public static readonly string EditorPathSettingName = "mono/editor/editor_path_optional";
|
||||||
|
|
||||||
private static string GetRiderPathFromSettings()
|
private static string GetRiderPathFromSettings()
|
||||||
{
|
{
|
||||||
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
|
||||||
if (editorSettings.HasSetting(editorPathSettingName))
|
if (editorSettings.HasSetting(EditorPathSettingName))
|
||||||
return (string)editorSettings.GetSetting(editorPathSettingName);
|
return (string)editorSettings.GetSetting(EditorPathSettingName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,22 +25,22 @@ namespace GodotTools.Ides.Rider
|
||||||
var editor = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor");
|
var editor = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor");
|
||||||
if (editor == ExternalEditorId.Rider)
|
if (editor == ExternalEditorId.Rider)
|
||||||
{
|
{
|
||||||
if (!editorSettings.HasSetting(editorPathSettingName))
|
if (!editorSettings.HasSetting(EditorPathSettingName))
|
||||||
{
|
{
|
||||||
Globals.EditorDef(editorPathSettingName, "Optional");
|
Globals.EditorDef(EditorPathSettingName, "Optional");
|
||||||
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary
|
||||||
{
|
{
|
||||||
["type"] = Variant.Type.String,
|
["type"] = Variant.Type.String,
|
||||||
["name"] = editorPathSettingName,
|
["name"] = EditorPathSettingName,
|
||||||
["hint"] = PropertyHint.File,
|
["hint"] = PropertyHint.File,
|
||||||
["hint_string"] = ""
|
["hint_string"] = ""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var riderPath = (string)editorSettings.GetSetting(editorPathSettingName);
|
var riderPath = (string)editorSettings.GetSetting(EditorPathSettingName);
|
||||||
if (IsRiderAndExists(riderPath))
|
if (IsRiderAndExists(riderPath))
|
||||||
{
|
{
|
||||||
Globals.EditorDef(editorPathSettingName, riderPath);
|
Globals.EditorDef(EditorPathSettingName, riderPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,17 +50,15 @@ namespace GodotTools.Ides.Rider
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var newPath = paths.Last().Path;
|
var newPath = paths.Last().Path;
|
||||||
Globals.EditorDef(editorPathSettingName, newPath);
|
Globals.EditorDef(EditorPathSettingName, newPath);
|
||||||
editorSettings.SetSetting(editorPathSettingName, newPath);
|
editorSettings.SetSetting(EditorPathSettingName, newPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsRider(string path)
|
public static bool IsRider(string path)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
var fileInfo = new FileInfo(path);
|
var fileInfo = new FileInfo(path);
|
||||||
var filename = fileInfo.Name.ToLowerInvariant();
|
var filename = fileInfo.Name.ToLowerInvariant();
|
||||||
|
@ -81,8 +79,8 @@ namespace GodotTools.Ides.Rider
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var newPath = paths.Last().Path;
|
var newPath = paths.Last().Path;
|
||||||
editorSettings.SetSetting(editorPathSettingName, newPath);
|
editorSettings.SetSetting(EditorPathSettingName, newPath);
|
||||||
Globals.EditorDef(editorPathSettingName, newPath);
|
Globals.EditorDef(EditorPathSettingName, newPath);
|
||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace Godot
|
||||||
|
|
||||||
public static void Print(params object[] what)
|
public static void Print(params object[] what)
|
||||||
{
|
{
|
||||||
godot_icall_GD_print(Array.ConvertAll(what, x => x.ToString()));
|
godot_icall_GD_print(Array.ConvertAll(what, x => x?.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintStack()
|
public static void PrintStack()
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
var regex = RegEx.new()
|
var regex = RegEx.new()
|
||||||
regex.compile("\\w-(\\d+)")
|
regex.compile("\\w-(\\d+)")
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
The search pattern must be escaped first for gdscript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code].
|
The search pattern must be escaped first for GDScript before it is escaped for the expression. For example, [code]compile("\\d+")[/code] would be read by RegEx as [code]\d+[/code]. Similarly, [code]compile("\"(?:\\\\.|[^\"])*\"")[/code] would be read as [code]"(?:\\.|[^"])*"[/code].
|
||||||
Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using functions such as [method RegExMatch.get_string] and [method RegExMatch.get_start].
|
Using [method search] you can find the pattern within the given text. If a pattern is found, [RegExMatch] is returned and you can retrieve details of the results using functions such as [method RegExMatch.get_string] and [method RegExMatch.get_start].
|
||||||
[codeblock]
|
[codeblock]
|
||||||
var regex = RegEx.new()
|
var regex = RegEx.new()
|
||||||
|
@ -35,6 +35,8 @@
|
||||||
# Would print 01 03 3f 42
|
# Would print 01 03 3f 42
|
||||||
# Note that d0c would not match
|
# Note that d0c would not match
|
||||||
[/codeblock]
|
[/codeblock]
|
||||||
|
[b]Note:[/b] Godot's regex implementation is based on the [url=https://www.pcre.org/]PCRE2[/url] library. You can view the full pattern reference [url=https://www.pcre.org/current/doc/html/pcre2pattern.html]here[/url].
|
||||||
|
[b]Tip:[/b] You can use [url=https://regexr.com/]Regexr[/url] to test regular expressions online.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
|
|
@ -57,7 +57,8 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
|
||||||
|
|
||||||
if (todo) {
|
if (todo) {
|
||||||
//end of file!
|
//end of file!
|
||||||
if (vorbis_stream->loop && mixed > 0) {
|
bool is_not_empty = mixed > 0 || stb_vorbis_stream_length_in_samples(ogg_stream) > 0;
|
||||||
|
if (vorbis_stream->loop && is_not_empty) {
|
||||||
//loop
|
//loop
|
||||||
seek(vorbis_stream->loop_offset);
|
seek(vorbis_stream->loop_offset);
|
||||||
loops++;
|
loops++;
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<description>
|
<description>
|
||||||
Adds a mapping to forward the external [code]port[/code] (between 1 and 65535) on the default gateway (see [method get_gateway]) to the [code]internal_port[/code] on the local machine for the given protocol [code]proto[/code] (either [code]TCP[/code] or [code]UDP[/code], with UDP being the default). If a port mapping for the given port and protocol combination already exists on that gateway device, this method tries to overwrite it. If that is not desired, you can retrieve the gateway manually with [method get_gateway] and call [method add_port_mapping] on it, if any.
|
Adds a mapping to forward the external [code]port[/code] (between 1 and 65535) on the default gateway (see [method get_gateway]) to the [code]internal_port[/code] on the local machine for the given protocol [code]proto[/code] (either [code]TCP[/code] or [code]UDP[/code], with UDP being the default). If a port mapping for the given port and protocol combination already exists on that gateway device, this method tries to overwrite it. If that is not desired, you can retrieve the gateway manually with [method get_gateway] and call [method add_port_mapping] on it, if any.
|
||||||
If [code]internal_port[/code] is [code]0[/code] (the default), the same port number is used for both the external and the internal port (the [code]port[/code] value).
|
If [code]internal_port[/code] is [code]0[/code] (the default), the same port number is used for both the external and the internal port (the [code]port[/code] value).
|
||||||
The description ([code]desc[/code]) is shown in some router UIs and can be used to point out which application added the mapping, and the lifetime of the mapping can be limited by [code]duration[/code]. However, some routers are incompatible with one or both of these, so use with caution and add fallback logic in case of errors to retry without them if in doubt.
|
The description ([code]desc[/code]) is shown in some router UIs and can be used to point out which application added the mapping. The mapping's lease duration can be limited by specifying a [code]duration[/code] (in seconds). However, some routers are incompatible with one or both of these, so use with caution and add fallback logic in case of errors to retry without them if in doubt.
|
||||||
See [enum UPNPResult] for possible return values.
|
See [enum UPNPResult] for possible return values.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
|
|
@ -355,7 +355,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_modifier = false | p_modifiers.empty();
|
bool in_modifier = p_modifiers.empty();
|
||||||
for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) {
|
for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) {
|
||||||
if (E->get().findn(F->get()) != -1)
|
if (E->get().findn(F->get()) != -1)
|
||||||
in_modifier = true;
|
in_modifier = true;
|
||||||
|
|
|
@ -205,7 +205,6 @@ def configure(env):
|
||||||
|
|
||||||
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/include"])
|
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/include"])
|
||||||
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++abi/include"])
|
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++abi/include"])
|
||||||
env.Append(CXXFLAGS=["-std=gnu++14"])
|
|
||||||
|
|
||||||
# Disable exceptions and rtti on non-tools (template) builds
|
# Disable exceptions and rtti on non-tools (template) builds
|
||||||
if env['tools']:
|
if env['tools']:
|
||||||
|
|
|
@ -337,7 +337,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
|
||||||
Vector<String> props = dp.split("\n");
|
Vector<String> props = dp.split("\n");
|
||||||
String vendor;
|
String vendor;
|
||||||
String device;
|
String device;
|
||||||
d.description + "Device ID: " + d.id + "\n";
|
d.description = "Device ID: " + d.id + "\n";
|
||||||
d.api_level = 0;
|
d.api_level = 0;
|
||||||
for (int j = 0; j < props.size(); j++) {
|
for (int j = 0; j < props.size(); j++) {
|
||||||
|
|
||||||
|
|
|
@ -1012,10 +1012,10 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
|
||||||
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, mousedown, mouse_button_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, mousedown, mouse_button_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback)
|
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, wheel, wheel_callback)
|
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, wheel, wheel_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchstart, touch_press_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, touchstart, touch_press_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchmove, touchmove_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, touchmove, touchmove_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchend, touch_press_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, touchend, touch_press_callback)
|
||||||
SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchcancel, touch_press_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, touchcancel, touch_press_callback)
|
||||||
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keydown, keydown_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keydown, keydown_callback)
|
||||||
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keypress, keypress_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keypress, keypress_callback)
|
||||||
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keyup, keyup_callback)
|
SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keyup, keyup_callback)
|
||||||
|
|
|
@ -2713,7 +2713,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||||
if (p_pipe_mutex) {
|
if (p_pipe_mutex) {
|
||||||
p_pipe_mutex->lock();
|
p_pipe_mutex->lock();
|
||||||
}
|
}
|
||||||
(*r_pipe) += buf;
|
(*r_pipe) += String::utf8(buf);
|
||||||
if (p_pipe_mutex) {
|
if (p_pipe_mutex) {
|
||||||
p_pipe_mutex->unlock();
|
p_pipe_mutex->unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,15 +180,14 @@ def configure(env):
|
||||||
env.Append(LINKFLAGS=['-pipe'])
|
env.Append(LINKFLAGS=['-pipe'])
|
||||||
|
|
||||||
# Check for gcc version >= 6 before adding -no-pie
|
# Check for gcc version >= 6 before adding -no-pie
|
||||||
|
version = get_compiler_version(env) or [-1, -1]
|
||||||
if using_gcc(env):
|
if using_gcc(env):
|
||||||
version = get_compiler_version(env)
|
if version[0] >= 6:
|
||||||
if version != None and version[0] >= '6':
|
|
||||||
env.Append(CCFLAGS=['-fpie'])
|
env.Append(CCFLAGS=['-fpie'])
|
||||||
env.Append(LINKFLAGS=['-no-pie'])
|
env.Append(LINKFLAGS=['-no-pie'])
|
||||||
# Do the same for clang should be fine with Clang 4 and higher
|
# Do the same for clang should be fine with Clang 4 and higher
|
||||||
if using_clang(env):
|
if using_clang(env):
|
||||||
version = get_compiler_version(env)
|
if version[0] >= 4:
|
||||||
if version != None and version[0] >= '4':
|
|
||||||
env.Append(CCFLAGS=['-fpie'])
|
env.Append(CCFLAGS=['-fpie'])
|
||||||
env.Append(LINKFLAGS=['-no-pie'])
|
env.Append(LINKFLAGS=['-no-pie'])
|
||||||
|
|
||||||
|
|
|
@ -128,9 +128,9 @@ Transform2D Camera2D::get_camera_transform() {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (v_ofs < 0) {
|
if (v_ofs < 0) {
|
||||||
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs;
|
|
||||||
} else {
|
|
||||||
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs;
|
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs;
|
||||||
|
} else {
|
||||||
|
camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
v_offset_changed = false;
|
v_offset_changed = false;
|
||||||
|
|
|
@ -40,6 +40,7 @@ void SkinReference::_skin_changed() {
|
||||||
if (skeleton_node) {
|
if (skeleton_node) {
|
||||||
skeleton_node->_make_dirty();
|
skeleton_node->_make_dirty();
|
||||||
}
|
}
|
||||||
|
skeleton_version = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkinReference::_bind_methods() {
|
void SkinReference::_bind_methods() {
|
||||||
|
@ -321,10 +322,49 @@ void Skeleton::_notification(int p_what) {
|
||||||
if (E->get()->bind_count != bind_count) {
|
if (E->get()->bind_count != bind_count) {
|
||||||
VS::get_singleton()->skeleton_allocate(skeleton, bind_count);
|
VS::get_singleton()->skeleton_allocate(skeleton, bind_count);
|
||||||
E->get()->bind_count = bind_count;
|
E->get()->bind_count = bind_count;
|
||||||
|
E->get()->skin_bone_indices.resize(bind_count);
|
||||||
|
E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (E->get()->skeleton_version != version) {
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < bind_count; i++) {
|
||||||
|
StringName bind_name = skin->get_bind_name(i);
|
||||||
|
|
||||||
|
if (bind_name != StringName()) {
|
||||||
|
//bind name used, use this
|
||||||
|
bool found = false;
|
||||||
|
for (int j = 0; j < len; j++) {
|
||||||
|
if (bonesptr[j].name == bind_name) {
|
||||||
|
E->get()->skin_bone_indices_ptrs[i] = j;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
ERR_PRINT("Skin bind #" + itos(i) + " contains named bind '" + String(bind_name) + "' but Skeleton has no bone by that name.");
|
||||||
|
E->get()->skin_bone_indices_ptrs[i] = 0;
|
||||||
|
}
|
||||||
|
} else if (skin->get_bind_bone(i) >= 0) {
|
||||||
|
int bind_index = skin->get_bind_bone(i);
|
||||||
|
if (bind_index >= len) {
|
||||||
|
ERR_PRINT("Skin bind #" + itos(i) + " contains bone index bind: " + itos(bind_index) + " , which is greater than the skeleton bone count: " + itos(len) + ".");
|
||||||
|
E->get()->skin_bone_indices_ptrs[i] = 0;
|
||||||
|
} else {
|
||||||
|
E->get()->skin_bone_indices_ptrs[i] = bind_index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("Skin bind #" + itos(i) + " does not contain a name nor a bone index.");
|
||||||
|
E->get()->skin_bone_indices_ptrs[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
E->get()->skeleton_version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < bind_count; i++) {
|
for (uint32_t i = 0; i < bind_count; i++) {
|
||||||
uint32_t bone_index = skin->get_bind_bone(i);
|
uint32_t bone_index = E->get()->skin_bone_indices_ptrs[i];
|
||||||
ERR_CONTINUE(bone_index >= (uint32_t)len);
|
ERR_CONTINUE(bone_index >= (uint32_t)len);
|
||||||
vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
|
vs->skeleton_bone_set_transform(skeleton, i, bonesptr[bone_index].pose_global * skin->get_bind_pose(i));
|
||||||
}
|
}
|
||||||
|
@ -366,6 +406,7 @@ void Skeleton::add_bone(const String &p_name) {
|
||||||
b.name = p_name;
|
b.name = p_name;
|
||||||
bones.push_back(b);
|
bones.push_back(b);
|
||||||
process_order_dirty = true;
|
process_order_dirty = true;
|
||||||
|
version++;
|
||||||
_make_dirty();
|
_make_dirty();
|
||||||
update_gizmo();
|
update_gizmo();
|
||||||
}
|
}
|
||||||
|
@ -517,7 +558,7 @@ void Skeleton::clear_bones() {
|
||||||
|
|
||||||
bones.clear();
|
bones.clear();
|
||||||
process_order_dirty = true;
|
process_order_dirty = true;
|
||||||
|
version++;
|
||||||
_make_dirty();
|
_make_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,6 +890,7 @@ void Skeleton::_bind_methods() {
|
||||||
Skeleton::Skeleton() {
|
Skeleton::Skeleton() {
|
||||||
|
|
||||||
dirty = false;
|
dirty = false;
|
||||||
|
version = 1;
|
||||||
process_order_dirty = true;
|
process_order_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,9 @@ class SkinReference : public Reference {
|
||||||
RID skeleton;
|
RID skeleton;
|
||||||
Ref<Skin> skin;
|
Ref<Skin> skin;
|
||||||
uint32_t bind_count = 0;
|
uint32_t bind_count = 0;
|
||||||
|
uint64_t skeleton_version = 0;
|
||||||
|
Vector<uint32_t> skin_bone_indices;
|
||||||
|
uint32_t *skin_bone_indices_ptrs;
|
||||||
void _skin_changed();
|
void _skin_changed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -122,6 +125,8 @@ private:
|
||||||
void _make_dirty();
|
void _make_dirty();
|
||||||
bool dirty;
|
bool dirty;
|
||||||
|
|
||||||
|
uint64_t version;
|
||||||
|
|
||||||
// bind helpers
|
// bind helpers
|
||||||
Array _get_bound_child_nodes_to_bone(int p_bone) const {
|
Array _get_bound_child_nodes_to_bone(int p_bone) const {
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,6 @@ void Tween::_add_pending_command(StringName p_key, const Variant &p_arg1, const
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
// Add the specified arguments to the command
|
// Add the specified arguments to the command
|
||||||
// TODO: Make this a switch statement?
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
cmd.arg[0] = p_arg1;
|
cmd.arg[0] = p_arg1;
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
|
@ -459,6 +458,20 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Variant::RECT2: {
|
||||||
|
// Get the Rect2 for initial and delta value
|
||||||
|
Rect2 i = initial_val;
|
||||||
|
Rect2 d = delta_val;
|
||||||
|
Rect2 r;
|
||||||
|
|
||||||
|
// Execute the equation for the position and size of Rect2
|
||||||
|
APPLY_EQUATION(position.x);
|
||||||
|
APPLY_EQUATION(position.y);
|
||||||
|
APPLY_EQUATION(size.x);
|
||||||
|
APPLY_EQUATION(size.y);
|
||||||
|
result = r;
|
||||||
|
} break;
|
||||||
|
|
||||||
case Variant::VECTOR3: {
|
case Variant::VECTOR3: {
|
||||||
// Get vectors for initial and delta values
|
// Get vectors for initial and delta values
|
||||||
Vector3 i = initial_val;
|
Vector3 i = initial_val;
|
||||||
|
@ -473,6 +486,55 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Variant::TRANSFORM2D: {
|
||||||
|
// Get the transforms for initial and delta values
|
||||||
|
Transform2D i = initial_val;
|
||||||
|
Transform2D d = delta_val;
|
||||||
|
Transform2D r;
|
||||||
|
|
||||||
|
// Execute the equation on the transforms and mutate the r transform
|
||||||
|
// This uses the custom APPLY_EQUATION macro defined above
|
||||||
|
APPLY_EQUATION(elements[0][0]);
|
||||||
|
APPLY_EQUATION(elements[0][1]);
|
||||||
|
APPLY_EQUATION(elements[1][0]);
|
||||||
|
APPLY_EQUATION(elements[1][1]);
|
||||||
|
APPLY_EQUATION(elements[2][0]);
|
||||||
|
APPLY_EQUATION(elements[2][1]);
|
||||||
|
result = r;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Variant::QUAT: {
|
||||||
|
// Get the quaternian for the initial and delta values
|
||||||
|
Quat i = initial_val;
|
||||||
|
Quat d = delta_val;
|
||||||
|
Quat r;
|
||||||
|
|
||||||
|
// Execute the equation on the quaternian values and mutate the r quaternian
|
||||||
|
// This uses the custom APPLY_EQUATION macro defined above
|
||||||
|
APPLY_EQUATION(x);
|
||||||
|
APPLY_EQUATION(y);
|
||||||
|
APPLY_EQUATION(z);
|
||||||
|
APPLY_EQUATION(w);
|
||||||
|
result = r;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case Variant::AABB: {
|
||||||
|
// Get the AABB's for the initial and delta values
|
||||||
|
AABB i = initial_val;
|
||||||
|
AABB d = delta_val;
|
||||||
|
AABB r;
|
||||||
|
|
||||||
|
// Execute the equation for the position and size of the AABB's and mutate the r AABB
|
||||||
|
// This uses the custom APPLY_EQUATION macro defined above
|
||||||
|
APPLY_EQUATION(position.x);
|
||||||
|
APPLY_EQUATION(position.y);
|
||||||
|
APPLY_EQUATION(position.z);
|
||||||
|
APPLY_EQUATION(size.x);
|
||||||
|
APPLY_EQUATION(size.y);
|
||||||
|
APPLY_EQUATION(size.z);
|
||||||
|
result = r;
|
||||||
|
} break;
|
||||||
|
|
||||||
case Variant::BASIS: {
|
case Variant::BASIS: {
|
||||||
// Get the basis for initial and delta values
|
// Get the basis for initial and delta values
|
||||||
Basis i = initial_val;
|
Basis i = initial_val;
|
||||||
|
@ -493,52 +555,6 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Variant::TRANSFORM2D: {
|
|
||||||
// Get the transforms for initial and delta values
|
|
||||||
Transform2D i = initial_val;
|
|
||||||
Transform2D d = delta_val;
|
|
||||||
Transform2D r;
|
|
||||||
|
|
||||||
// Execute the equation on the transforms and mutate the r transform
|
|
||||||
// This uses the custom APPLY_EQUATION macro defined above
|
|
||||||
APPLY_EQUATION(elements[0][0]);
|
|
||||||
APPLY_EQUATION(elements[0][1]);
|
|
||||||
APPLY_EQUATION(elements[1][0]);
|
|
||||||
APPLY_EQUATION(elements[1][1]);
|
|
||||||
APPLY_EQUATION(elements[2][0]);
|
|
||||||
APPLY_EQUATION(elements[2][1]);
|
|
||||||
result = r;
|
|
||||||
} break;
|
|
||||||
case Variant::QUAT: {
|
|
||||||
// Get the quaternian for the initial and delta values
|
|
||||||
Quat i = initial_val;
|
|
||||||
Quat d = delta_val;
|
|
||||||
Quat r;
|
|
||||||
|
|
||||||
// Execute the equation on the quaternian values and mutate the r quaternian
|
|
||||||
// This uses the custom APPLY_EQUATION macro defined above
|
|
||||||
APPLY_EQUATION(x);
|
|
||||||
APPLY_EQUATION(y);
|
|
||||||
APPLY_EQUATION(z);
|
|
||||||
APPLY_EQUATION(w);
|
|
||||||
result = r;
|
|
||||||
} break;
|
|
||||||
case Variant::AABB: {
|
|
||||||
// Get the AABB's for the initial and delta values
|
|
||||||
AABB i = initial_val;
|
|
||||||
AABB d = delta_val;
|
|
||||||
AABB r;
|
|
||||||
|
|
||||||
// Execute the equation for the position and size of the AABB's and mutate the r AABB
|
|
||||||
// This uses the custom APPLY_EQUATION macro defined above
|
|
||||||
APPLY_EQUATION(position.x);
|
|
||||||
APPLY_EQUATION(position.y);
|
|
||||||
APPLY_EQUATION(position.z);
|
|
||||||
APPLY_EQUATION(size.x);
|
|
||||||
APPLY_EQUATION(size.y);
|
|
||||||
APPLY_EQUATION(size.z);
|
|
||||||
result = r;
|
|
||||||
} break;
|
|
||||||
case Variant::TRANSFORM: {
|
case Variant::TRANSFORM: {
|
||||||
// Get the transforms for the initial and delta values
|
// Get the transforms for the initial and delta values
|
||||||
Transform i = initial_val;
|
Transform i = initial_val;
|
||||||
|
@ -561,6 +577,7 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
||||||
APPLY_EQUATION(origin.z);
|
APPLY_EQUATION(origin.z);
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Variant::COLOR: {
|
case Variant::COLOR: {
|
||||||
// Get the Color for initial and delta value
|
// Get the Color for initial and delta value
|
||||||
Color i = initial_val;
|
Color i = initial_val;
|
||||||
|
@ -575,6 +592,7 @@ Variant Tween::_run_equation(InterpolateData &p_data) {
|
||||||
APPLY_EQUATION(a);
|
APPLY_EQUATION(a);
|
||||||
result = r;
|
result = r;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
// If unknown, just return the initial value
|
// If unknown, just return the initial value
|
||||||
result = initial_val;
|
result = initial_val;
|
||||||
|
@ -1129,26 +1147,18 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
|
||||||
delta_val = final_val.operator Vector2() - initial_val.operator Vector2();
|
delta_val = final_val.operator Vector2() - initial_val.operator Vector2();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Variant::RECT2: {
|
||||||
|
// Build a new Rect2 and use the new position and sizes to make a delta
|
||||||
|
Rect2 i = initial_val;
|
||||||
|
Rect2 f = final_val;
|
||||||
|
delta_val = Rect2(f.position - i.position, f.size - i.size);
|
||||||
|
} break;
|
||||||
|
|
||||||
case Variant::VECTOR3:
|
case Variant::VECTOR3:
|
||||||
// Convert to Vectors and find the delta
|
// Convert to Vectors and find the delta
|
||||||
delta_val = final_val.operator Vector3() - initial_val.operator Vector3();
|
delta_val = final_val.operator Vector3() - initial_val.operator Vector3();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant::BASIS: {
|
|
||||||
// Build a new basis which is the delta between the initial and final values
|
|
||||||
Basis i = initial_val;
|
|
||||||
Basis f = final_val;
|
|
||||||
delta_val = Basis(f.elements[0][0] - i.elements[0][0],
|
|
||||||
f.elements[0][1] - i.elements[0][1],
|
|
||||||
f.elements[0][2] - i.elements[0][2],
|
|
||||||
f.elements[1][0] - i.elements[1][0],
|
|
||||||
f.elements[1][1] - i.elements[1][1],
|
|
||||||
f.elements[1][2] - i.elements[1][2],
|
|
||||||
f.elements[2][0] - i.elements[2][0],
|
|
||||||
f.elements[2][1] - i.elements[2][1],
|
|
||||||
f.elements[2][2] - i.elements[2][2]);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Variant::TRANSFORM2D: {
|
case Variant::TRANSFORM2D: {
|
||||||
// Build a new transform which is the difference between the initial and final values
|
// Build a new transform which is the difference between the initial and final values
|
||||||
Transform2D i = initial_val;
|
Transform2D i = initial_val;
|
||||||
|
@ -1175,6 +1185,21 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
|
||||||
delta_val = AABB(f.position - i.position, f.size - i.size);
|
delta_val = AABB(f.position - i.position, f.size - i.size);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Variant::BASIS: {
|
||||||
|
// Build a new basis which is the delta between the initial and final values
|
||||||
|
Basis i = initial_val;
|
||||||
|
Basis f = final_val;
|
||||||
|
delta_val = Basis(f.elements[0][0] - i.elements[0][0],
|
||||||
|
f.elements[0][1] - i.elements[0][1],
|
||||||
|
f.elements[0][2] - i.elements[0][2],
|
||||||
|
f.elements[1][0] - i.elements[1][0],
|
||||||
|
f.elements[1][1] - i.elements[1][1],
|
||||||
|
f.elements[1][2] - i.elements[1][2],
|
||||||
|
f.elements[2][0] - i.elements[2][0],
|
||||||
|
f.elements[2][1] - i.elements[2][1],
|
||||||
|
f.elements[2][2] - i.elements[2][2]);
|
||||||
|
} break;
|
||||||
|
|
||||||
case Variant::TRANSFORM: {
|
case Variant::TRANSFORM: {
|
||||||
// Build a new transform which is the difference between the initial and final values
|
// Build a new transform which is the difference between the initial and final values
|
||||||
Transform i = initial_val;
|
Transform i = initial_val;
|
||||||
|
@ -1203,10 +1228,34 @@ bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final
|
||||||
delta_val = Color(f.r - i.r, f.g - i.g, f.b - i.b, f.a - i.a);
|
delta_val = Color(f.r - i.r, f.g - i.g, f.b - i.b, f.a - i.a);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default: {
|
||||||
// TODO: Should move away from a 'magic string'?
|
static Variant::Type supported_types[] = {
|
||||||
ERR_PRINT("Invalid param type, except(int/real/vector2/vector/matrix/matrix32/quat/aabb/transform/color)");
|
Variant::BOOL,
|
||||||
|
Variant::INT,
|
||||||
|
Variant::REAL,
|
||||||
|
Variant::VECTOR2,
|
||||||
|
Variant::RECT2,
|
||||||
|
Variant::VECTOR3,
|
||||||
|
Variant::TRANSFORM2D,
|
||||||
|
Variant::QUAT,
|
||||||
|
Variant::AABB,
|
||||||
|
Variant::BASIS,
|
||||||
|
Variant::TRANSFORM,
|
||||||
|
Variant::COLOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
int length = *(&supported_types + 1) - supported_types;
|
||||||
|
String error_msg = "Invalid parameter type. Supported types are: ";
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
error_msg += ", ";
|
||||||
|
}
|
||||||
|
error_msg += Variant::get_type_name(supported_types[i]);
|
||||||
|
}
|
||||||
|
error_msg += ".";
|
||||||
|
ERR_PRINT(error_msg);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -680,13 +680,17 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
|
||||||
const PropertyInfo &pi = properties[i].first;
|
const PropertyInfo &pi = properties[i].first;
|
||||||
Variant &var = properties[i].second;
|
Variant &var = properties[i].second;
|
||||||
|
|
||||||
WeakRef *ref = Object::cast_to<WeakRef>(var);
|
|
||||||
if (ref) {
|
|
||||||
var = ref->get_ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
RES res = var;
|
RES res = var;
|
||||||
|
|
||||||
|
if (var.get_type() == Variant::OBJECT && var.is_ref()) {
|
||||||
|
REF r = var;
|
||||||
|
if (r.is_valid()) {
|
||||||
|
res = *r;
|
||||||
|
} else {
|
||||||
|
res = RES();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Array prop;
|
Array prop;
|
||||||
prop.push_back(pi.name);
|
prop.push_back(pi.name);
|
||||||
prop.push_back(pi.type);
|
prop.push_back(pi.type);
|
||||||
|
|
|
@ -462,6 +462,11 @@ void Control::_update_canvas_item_transform() {
|
||||||
Transform2D xform = _get_internal_transform();
|
Transform2D xform = _get_internal_transform();
|
||||||
xform[2] += get_position();
|
xform[2] += get_position();
|
||||||
|
|
||||||
|
// We use a little workaround to avoid flickering when moving the pivot with _edit_set_pivot()
|
||||||
|
if (is_inside_tree() && Math::abs(Math::sin(data.rotation * 4.0f)) < 0.00001f && get_viewport()->is_snap_controls_to_pixels_enabled()) {
|
||||||
|
xform[2] = xform[2].round();
|
||||||
|
}
|
||||||
|
|
||||||
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
|
VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1844,6 +1844,42 @@ void TextEdit::_consume_pair_symbol(CharType ch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String line = text[cursor.line];
|
||||||
|
|
||||||
|
bool in_single_quote = false;
|
||||||
|
bool in_double_quote = false;
|
||||||
|
|
||||||
|
int c = 0;
|
||||||
|
while (c < line.length()) {
|
||||||
|
if (line[c] == '\\') {
|
||||||
|
c++; // Skip quoted anything.
|
||||||
|
|
||||||
|
if (cursor.column == c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (line[c] == '\'' && !in_double_quote) {
|
||||||
|
in_single_quote = !in_single_quote;
|
||||||
|
} else if (line[c] == '"' && !in_single_quote) {
|
||||||
|
in_double_quote = !in_double_quote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
|
||||||
|
if (cursor.column == c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow inserting duplicated quotes while already in string
|
||||||
|
if ((in_single_quote || in_double_quote) && (ch == '"' || ch == '\'')) {
|
||||||
|
insert_text_at_cursor(ch_single);
|
||||||
|
cursor_set_column(cursor_position_to_move);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
insert_text_at_cursor(ch_pair);
|
insert_text_at_cursor(ch_pair);
|
||||||
cursor_set_column(cursor_position_to_move);
|
cursor_set_column(cursor_position_to_move);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "mesh_library.h"
|
#include "mesh_library.h"
|
||||||
#include "core/engine.h"
|
|
||||||
|
|
||||||
bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
|
bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
|
|
||||||
|
@ -202,11 +201,6 @@ Transform MeshLibrary::get_item_navmesh_transform(int p_item) const {
|
||||||
|
|
||||||
Ref<Texture> MeshLibrary::get_item_preview(int p_item) const {
|
Ref<Texture> MeshLibrary::get_item_preview(int p_item) const {
|
||||||
|
|
||||||
if (!Engine::get_singleton()->is_editor_hint()) {
|
|
||||||
ERR_PRINT("MeshLibrary item previews are only generated in an editor context, which means they aren't available in a running project.");
|
|
||||||
return Ref<Texture>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Texture>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
ERR_FAIL_COND_V_MSG(!item_map.has(p_item), Ref<Texture>(), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'.");
|
||||||
return item_map[p_item].preview;
|
return item_map[p_item].preview;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,24 @@ void Skin::add_bind(int p_bone, const Transform &p_pose) {
|
||||||
set_bind_pose(index, p_pose);
|
set_bind_pose(index, p_pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Skin::add_named_bind(const String &p_name, const Transform &p_pose) {
|
||||||
|
|
||||||
|
uint32_t index = bind_count;
|
||||||
|
set_bind_count(bind_count + 1);
|
||||||
|
set_bind_name(index, p_name);
|
||||||
|
set_bind_pose(index, p_pose);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Skin::set_bind_name(int p_index, const StringName &p_name) {
|
||||||
|
ERR_FAIL_INDEX(p_index, bind_count);
|
||||||
|
bool notify_change = (binds_ptr[p_index].name != StringName()) != (p_name != StringName());
|
||||||
|
binds_ptr[p_index].name = p_name;
|
||||||
|
emit_changed();
|
||||||
|
if (notify_change) {
|
||||||
|
_change_notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Skin::set_bind_bone(int p_index, int p_bone) {
|
void Skin::set_bind_bone(int p_index, int p_bone) {
|
||||||
ERR_FAIL_INDEX(p_index, bind_count);
|
ERR_FAIL_INDEX(p_index, bind_count);
|
||||||
binds_ptr[p_index].bone = p_bone;
|
binds_ptr[p_index].bone = p_bone;
|
||||||
|
@ -75,6 +93,9 @@ bool Skin::_set(const StringName &p_name, const Variant &p_value) {
|
||||||
if (what == "bone") {
|
if (what == "bone") {
|
||||||
set_bind_bone(index, p_value);
|
set_bind_bone(index, p_value);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (what == "name") {
|
||||||
|
set_bind_name(index, p_value);
|
||||||
|
return true;
|
||||||
} else if (what == "pose") {
|
} else if (what == "pose") {
|
||||||
set_bind_pose(index, p_value);
|
set_bind_pose(index, p_value);
|
||||||
return true;
|
return true;
|
||||||
|
@ -95,6 +116,9 @@ bool Skin::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
if (what == "bone") {
|
if (what == "bone") {
|
||||||
r_ret = get_bind_bone(index);
|
r_ret = get_bind_bone(index);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (what == "name") {
|
||||||
|
r_ret = get_bind_name(index);
|
||||||
|
return true;
|
||||||
} else if (what == "pose") {
|
} else if (what == "pose") {
|
||||||
r_ret = get_bind_pose(index);
|
r_ret = get_bind_pose(index);
|
||||||
return true;
|
return true;
|
||||||
|
@ -105,7 +129,8 @@ bool Skin::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
void Skin::_get_property_list(List<PropertyInfo> *p_list) const {
|
void Skin::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"));
|
p_list->push_back(PropertyInfo(Variant::INT, "bind_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"));
|
||||||
for (int i = 0; i < get_bind_count(); i++) {
|
for (int i = 0; i < get_bind_count(); i++) {
|
||||||
p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"));
|
p_list->push_back(PropertyInfo(Variant::STRING, "bind/" + itos(i) + "/name"));
|
||||||
|
p_list->push_back(PropertyInfo(Variant::INT, "bind/" + itos(i) + "/bone", PROPERTY_HINT_RANGE, "0,16384,1,or_greater", get_bind_name(i) != StringName() ? PROPERTY_USAGE_NOEDITOR : PROPERTY_USAGE_DEFAULT));
|
||||||
p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose"));
|
p_list->push_back(PropertyInfo(Variant::TRANSFORM, "bind/" + itos(i) + "/pose"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,6 +145,9 @@ void Skin::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_bind_pose", "bind_index", "pose"), &Skin::set_bind_pose);
|
ClassDB::bind_method(D_METHOD("set_bind_pose", "bind_index", "pose"), &Skin::set_bind_pose);
|
||||||
ClassDB::bind_method(D_METHOD("get_bind_pose", "bind_index"), &Skin::get_bind_pose);
|
ClassDB::bind_method(D_METHOD("get_bind_pose", "bind_index"), &Skin::get_bind_pose);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_bind_name", "bind_index", "name"), &Skin::set_bind_name);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_bind_name", "bind_index"), &Skin::get_bind_name);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_bind_bone", "bind_index", "bone"), &Skin::set_bind_bone);
|
ClassDB::bind_method(D_METHOD("set_bind_bone", "bind_index", "bone"), &Skin::set_bind_bone);
|
||||||
ClassDB::bind_method(D_METHOD("get_bind_bone", "bind_index"), &Skin::get_bind_bone);
|
ClassDB::bind_method(D_METHOD("get_bind_bone", "bind_index"), &Skin::get_bind_bone);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@ class Skin : public Resource {
|
||||||
GDCLASS(Skin, Resource)
|
GDCLASS(Skin, Resource)
|
||||||
|
|
||||||
struct Bind {
|
struct Bind {
|
||||||
int bone;
|
int bone = -1;
|
||||||
|
StringName name;
|
||||||
Transform pose;
|
Transform pose;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,9 +59,11 @@ public:
|
||||||
inline int get_bind_count() const { return bind_count; }
|
inline int get_bind_count() const { return bind_count; }
|
||||||
|
|
||||||
void add_bind(int p_bone, const Transform &p_pose);
|
void add_bind(int p_bone, const Transform &p_pose);
|
||||||
|
void add_named_bind(const String &p_name, const Transform &p_pose);
|
||||||
|
|
||||||
void set_bind_bone(int p_index, int p_bone);
|
void set_bind_bone(int p_index, int p_bone);
|
||||||
void set_bind_pose(int p_index, const Transform &p_pose);
|
void set_bind_pose(int p_index, const Transform &p_pose);
|
||||||
|
void set_bind_name(int p_index, const StringName &p_name);
|
||||||
|
|
||||||
inline int get_bind_bone(int p_index) const {
|
inline int get_bind_bone(int p_index) const {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -69,6 +72,13 @@ public:
|
||||||
return binds_ptr[p_index].bone;
|
return binds_ptr[p_index].bone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline StringName get_bind_name(int p_index) const {
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
ERR_FAIL_INDEX_V(p_index, bind_count, StringName());
|
||||||
|
#endif
|
||||||
|
return binds_ptr[p_index].name;
|
||||||
|
}
|
||||||
|
|
||||||
inline Transform get_bind_pose(int p_index) const {
|
inline Transform get_bind_pose(int p_index) const {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
ERR_FAIL_INDEX_V(p_index, bind_count, Transform());
|
ERR_FAIL_INDEX_V(p_index, bind_count, Transform());
|
||||||
|
|
|
@ -38,6 +38,7 @@ void ARVRPositionalTracker::_bind_methods() {
|
||||||
|
|
||||||
// this class is read only from GDScript, so we only have access to getters..
|
// this class is read only from GDScript, so we only have access to getters..
|
||||||
ClassDB::bind_method(D_METHOD("get_type"), &ARVRPositionalTracker::get_type);
|
ClassDB::bind_method(D_METHOD("get_type"), &ARVRPositionalTracker::get_type);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_tracker_id"), &ARVRPositionalTracker::get_tracker_id);
|
||||||
ClassDB::bind_method(D_METHOD("get_name"), &ARVRPositionalTracker::get_name);
|
ClassDB::bind_method(D_METHOD("get_name"), &ARVRPositionalTracker::get_name);
|
||||||
ClassDB::bind_method(D_METHOD("get_joy_id"), &ARVRPositionalTracker::get_joy_id);
|
ClassDB::bind_method(D_METHOD("get_joy_id"), &ARVRPositionalTracker::get_joy_id);
|
||||||
ClassDB::bind_method(D_METHOD("get_tracks_orientation"), &ARVRPositionalTracker::get_tracks_orientation);
|
ClassDB::bind_method(D_METHOD("get_tracks_orientation"), &ARVRPositionalTracker::get_tracks_orientation);
|
||||||
|
|
Loading…
Reference in New Issue