mirror of
https://github.com/godotengine/godot.git
synced 2024-10-22 21:21:53 +00:00
Compare commits
108 Commits
e501c128e3
...
ba513dc5c8
Author | SHA1 | Date | |
---|---|---|---|
|
ba513dc5c8 | ||
|
b3bcb2dc14 | ||
|
a4ed24acef | ||
|
7815ccbdd5 | ||
|
66d19abdfa | ||
|
22822f71ac | ||
|
6ec3dc1fb5 | ||
|
7dbea98c49 | ||
|
8b5c20e2b0 | ||
|
55aeff19dc | ||
|
1a9628f937 | ||
|
677ebad7fc | ||
|
a14e9e99e5 | ||
|
178342b058 | ||
|
77da16ce69 | ||
|
291e4b78e2 | ||
|
b6547b0d06 | ||
|
7a438dc72e | ||
|
cb3c01a5fe | ||
|
c145e85011 | ||
|
ecc2eb73fc | ||
|
975f42227f | ||
|
4630cbc487 | ||
|
8be0061458 | ||
|
4ce5235fbd | ||
|
16d68c6be4 | ||
|
29fa4b18f1 | ||
|
5fb22327ee | ||
|
5e65747d90 | ||
|
4ad424234f | ||
|
fbd1643176 | ||
|
916d480686 | ||
|
5c65f80199 | ||
|
83ac274e25 | ||
|
44fa552343 | ||
|
80f0b33313 | ||
|
8e0c0d7837 | ||
|
58a7f9b4d8 | ||
|
f8c4a683d7 | ||
|
af6d260c17 | ||
|
17642692c5 | ||
|
35a20fa96a | ||
|
8c3e46b13b | ||
|
155cf6a5b6 | ||
|
610635e1c8 | ||
|
79f654ced5 | ||
|
4631a617e5 | ||
|
14fc9a545c | ||
|
4dd0b67ec9 | ||
|
e3790de461 | ||
|
4b37fb3f88 | ||
|
1435247de0 | ||
|
0ce4d8fcd3 | ||
|
cdf45f73ab | ||
|
f6279ffd56 | ||
|
e50b864b64 | ||
|
acc3786db2 | ||
|
be9e42c6a4 | ||
|
c6b94ca9b4 | ||
|
a2117f5796 | ||
|
7a936e8bac | ||
|
274076c5be | ||
|
25687c5b99 | ||
|
4e6d9813b2 | ||
|
f61fe2799c | ||
|
3d07fced0c | ||
|
009446a277 | ||
|
ebe1a2d7ec | ||
|
04692d83cb | ||
|
324659f0ca | ||
|
e4093b558a | ||
|
78dbd39d1e | ||
|
74328ac38e | ||
|
30a2a800dd | ||
|
6ccff9b009 | ||
|
c032acb865 | ||
|
7f108cfa12 | ||
|
e64662cb63 | ||
|
e7e0e65159 | ||
|
acab2d6c1c | ||
|
90c35f3978 | ||
|
7ee72d2f81 | ||
|
c12001a9dc | ||
|
9ed655d0eb | ||
|
db194f06e1 | ||
|
7261321d34 | ||
|
d29e7b6953 | ||
|
920fd47fa3 | ||
|
fb58ea6c89 | ||
|
de128812f3 | ||
|
e4b8cd2948 | ||
|
8d3e9aa7ae | ||
|
cef515506b | ||
|
140c6a612e | ||
|
5777a3fed5 | ||
|
0818408db5 | ||
|
0bc59c78de | ||
|
12d2c05936 | ||
|
9f6c88de89 | ||
|
84b15a2ea4 | ||
|
ecb56fca26 | ||
|
8f9ed35f8b | ||
|
4ef07cb9a5 | ||
|
705f51f97e | ||
|
fa48ed9945 | ||
|
5af917e763 | ||
|
461283887f | ||
|
1b376b32cd |
|
@ -799,8 +799,8 @@ if env["lto"] != "none":
|
|||
# This needs to come after `configure`, otherwise we don't have env.msvc.
|
||||
if not env.msvc:
|
||||
# Specifying GNU extensions support explicitly, which are supported by
|
||||
# both GCC and Clang. Both currently default to gnu11 and gnu++17.
|
||||
env.Prepend(CFLAGS=["-std=gnu11"])
|
||||
# both GCC and Clang. Both currently default to gnu17 and gnu++17.
|
||||
env.Prepend(CFLAGS=["-std=gnu17"])
|
||||
env.Prepend(CXXFLAGS=["-std=gnu++17"])
|
||||
else:
|
||||
# MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all
|
||||
|
@ -809,7 +809,7 @@ else:
|
|||
if cc_version_major < 16:
|
||||
print_warning("Visual Studio 2017 cannot specify a C-Standard.")
|
||||
else:
|
||||
env.Prepend(CFLAGS=["/std:c11"])
|
||||
env.Prepend(CFLAGS=["/std:c17"])
|
||||
# MSVC is non-conforming with the C++ standard by default, so we enable more conformance.
|
||||
# Note that this is still not complete conformance, as certain Windows-related headers
|
||||
# don't compile under complete conformance.
|
||||
|
|
|
@ -494,6 +494,7 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f
|
|||
}
|
||||
|
||||
void ProjectSettings::_convert_to_last_version(int p_from_version) {
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (p_from_version <= 3) {
|
||||
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
|
||||
for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
|
||||
|
@ -507,6 +508,22 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (p_from_version <= 5) {
|
||||
// Converts the device in events from -1 (emulated events) to -3 (all events).
|
||||
for (KeyValue<StringName, ProjectSettings::VariantContainer> &E : props) {
|
||||
if (String(E.key).begins_with("input/")) {
|
||||
Dictionary action = E.value.variant;
|
||||
Array events = action["events"];
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
Ref<InputEvent> x = events[i];
|
||||
if (x->get_device() == -1) { // -1 was the previous value (GH-97707).
|
||||
x->set_device(InputEvent::DEVICE_ID_ALL_DEVICES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1460,6 +1477,7 @@ ProjectSettings::ProjectSettings() {
|
|||
GLOBAL_DEF("display/window/size/transparent", false);
|
||||
GLOBAL_DEF("display/window/size/extend_to_title", false);
|
||||
GLOBAL_DEF("display/window/size/no_focus", false);
|
||||
GLOBAL_DEF("display/window/size/sharp_corners", false);
|
||||
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#define CORE_BIND_H
|
||||
|
||||
#include "core/debugger/engine_profiler.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/script_language.h"
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/extension/gdextension.h"
|
||||
#include "core/extension/gdextension_compat_hashes.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/xml_parser.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/script_language_extension.h"
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
#include "core/os/keyboard.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
const int InputEvent::DEVICE_ID_EMULATION = -1;
|
||||
const int InputEvent::DEVICE_ID_INTERNAL = -2;
|
||||
|
||||
void InputEvent::set_device(int p_device) {
|
||||
device = p_device;
|
||||
emit_changed();
|
||||
|
|
|
@ -62,8 +62,9 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static const int DEVICE_ID_EMULATION;
|
||||
static const int DEVICE_ID_INTERNAL;
|
||||
inline static constexpr int DEVICE_ID_EMULATION = -1;
|
||||
inline static constexpr int DEVICE_ID_INTERNAL = -2;
|
||||
inline static constexpr int DEVICE_ID_ALL_DEVICES = -3; // Signify that a given Action can be triggered by any device.
|
||||
|
||||
void set_device(int p_device);
|
||||
int get_device() const;
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
InputMap *InputMap::singleton = nullptr;
|
||||
|
||||
int InputMap::ALL_DEVICES = -1;
|
||||
|
||||
void InputMap::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
|
||||
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
|
||||
|
@ -163,7 +161,7 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
|
|||
int i = 0;
|
||||
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
|
||||
int device = E->get()->get_device();
|
||||
if (device == ALL_DEVICES || device == p_event->get_device()) {
|
||||
if (device == InputEvent::DEVICE_ID_ALL_DEVICES || device == p_event->get_device()) {
|
||||
if (E->get()->action_match(p_event, p_exact_match, p_action.deadzone, r_pressed, r_strength, r_raw_strength)) {
|
||||
if (r_event_index) {
|
||||
*r_event_index = i;
|
||||
|
|
|
@ -43,11 +43,6 @@ class InputMap : public Object {
|
|||
GDCLASS(InputMap, Object);
|
||||
|
||||
public:
|
||||
/**
|
||||
* A special value used to signify that a given Action can be triggered by any device
|
||||
*/
|
||||
static int ALL_DEVICES;
|
||||
|
||||
struct Action {
|
||||
int id;
|
||||
float deadzone;
|
||||
|
|
|
@ -121,7 +121,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
|
|||
d.get_key_list(&keys);
|
||||
|
||||
if (p_sort_keys) {
|
||||
keys.sort();
|
||||
keys.sort_custom<StringLikeVariantOrder>();
|
||||
}
|
||||
|
||||
bool first_key = true;
|
||||
|
|
|
@ -1268,6 +1268,11 @@ void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String
|
|||
return;
|
||||
}
|
||||
|
||||
// res files not supported for GDExtension.
|
||||
if (p_type == "GDExtension") {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> extensions;
|
||||
ClassDB::get_extensions_for_type(p_type, &extensions);
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#define OS_H
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/logger.h"
|
||||
#include "core/io/remote_filesystem_client.h"
|
||||
#include "core/os/time_enums.h"
|
||||
|
|
|
@ -389,6 +389,10 @@ void TranslationDomain::set_pseudolocalization_suffix(const String &p_suffix) {
|
|||
}
|
||||
|
||||
StringName TranslationDomain::pseudolocalize(const StringName &p_message) const {
|
||||
if (p_message.is_empty()) {
|
||||
return p_message;
|
||||
}
|
||||
|
||||
String message = p_message;
|
||||
int length = message.length();
|
||||
if (pseudolocalization.override_enabled) {
|
||||
|
|
|
@ -228,32 +228,41 @@ int TranslationServer::compare_locales(const String &p_locale_a, const String &p
|
|||
return 10;
|
||||
}
|
||||
|
||||
const String cache_key = p_locale_a + "|" + p_locale_b;
|
||||
const int *cached_result = locale_compare_cache.getptr(cache_key);
|
||||
if (cached_result) {
|
||||
return *cached_result;
|
||||
}
|
||||
|
||||
String locale_a = _standardize_locale(p_locale_a, true);
|
||||
String locale_b = _standardize_locale(p_locale_b, true);
|
||||
|
||||
if (locale_a == locale_b) {
|
||||
// Exact match.
|
||||
locale_compare_cache.insert(cache_key, 10);
|
||||
return 10;
|
||||
}
|
||||
|
||||
Vector<String> locale_a_elements = locale_a.split("_");
|
||||
Vector<String> locale_b_elements = locale_b.split("_");
|
||||
if (locale_a_elements[0] == locale_b_elements[0]) {
|
||||
// Matching language, both locales have extra parts.
|
||||
// Return number of matching elements.
|
||||
int matching_elements = 1;
|
||||
for (int i = 1; i < locale_a_elements.size(); i++) {
|
||||
for (int j = 1; j < locale_b_elements.size(); j++) {
|
||||
if (locale_a_elements[i] == locale_b_elements[j]) {
|
||||
matching_elements++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matching_elements;
|
||||
} else {
|
||||
if (locale_a_elements[0] != locale_b_elements[0]) {
|
||||
// No match.
|
||||
locale_compare_cache.insert(cache_key, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Matching language, both locales have extra parts.
|
||||
// Return number of matching elements.
|
||||
int matching_elements = 1;
|
||||
for (int i = 1; i < locale_a_elements.size(); i++) {
|
||||
for (int j = 1; j < locale_b_elements.size(); j++) {
|
||||
if (locale_a_elements[i] == locale_b_elements[j]) {
|
||||
matching_elements++;
|
||||
}
|
||||
}
|
||||
}
|
||||
locale_compare_cache.insert(cache_key, matching_elements);
|
||||
return matching_elements;
|
||||
}
|
||||
|
||||
String TranslationServer::get_locale_name(const String &p_locale) const {
|
||||
|
|
|
@ -46,6 +46,8 @@ class TranslationServer : public Object {
|
|||
Ref<TranslationDomain> doc_domain;
|
||||
HashMap<StringName, Ref<TranslationDomain>> custom_domains;
|
||||
|
||||
mutable HashMap<String, int> locale_compare_cache;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
static TranslationServer *singleton;
|
||||
|
|
|
@ -854,6 +854,19 @@ struct StringLikeVariantComparator {
|
|||
static bool compare(const Variant &p_lhs, const Variant &p_rhs);
|
||||
};
|
||||
|
||||
struct StringLikeVariantOrder {
|
||||
static _ALWAYS_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) {
|
||||
if (p_lhs.is_string() && p_rhs.is_string()) {
|
||||
return p_lhs.operator String() < p_rhs.operator String();
|
||||
}
|
||||
return p_lhs < p_rhs;
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool operator()(const Variant &p_lhs, const Variant &p_rhs) const {
|
||||
return compare(p_lhs, p_rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Variant::ObjData &Variant::_get_obj() {
|
||||
return *reinterpret_cast<ObjData *>(&_data._mem[0]);
|
||||
}
|
||||
|
|
|
@ -2245,7 +2245,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
|
|||
} else {
|
||||
List<Variant> keys;
|
||||
dict.get_key_list(&keys);
|
||||
keys.sort();
|
||||
keys.sort_custom<StringLikeVariantOrder>();
|
||||
|
||||
if (keys.is_empty()) {
|
||||
// Avoid unnecessary line break.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
[CanvasModulate] applies a color tint to all nodes on a canvas. Only one can be used to tint a canvas, but [CanvasLayer]s can be used to render things independently.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="2D lights and shadows">$DOCS_URL/tutorials/2d/2d_lights_and_shadows.html</link>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="color" type="Color" setter="set_color" getter="get_color" default="Color(1, 1, 1, 1)" keywords="colour">
|
||||
|
|
|
@ -1365,7 +1365,7 @@
|
|||
<constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the parent control layout direction.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection">
|
||||
<constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the current locale.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection">
|
||||
|
@ -1374,6 +1374,14 @@
|
|||
<constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection">
|
||||
Right-to-left layout direction.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the system locale.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection">
|
||||
Represents the size of the [enum LayoutDirection] enum.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead.">
|
||||
</constant>
|
||||
<constant name="TEXT_DIRECTION_INHERITED" value="3" enum="TextDirection">
|
||||
Text writing direction is the same as layout direction.
|
||||
</constant>
|
||||
|
|
|
@ -2099,7 +2099,11 @@
|
|||
<constant name="WINDOW_FLAG_MOUSE_PASSTHROUGH" value="7" enum="WindowFlags">
|
||||
All mouse events are passed to the underlying window of the same application.
|
||||
</constant>
|
||||
<constant name="WINDOW_FLAG_MAX" value="8" enum="WindowFlags">
|
||||
<constant name="WINDOW_FLAG_SHARP_CORNERS" value="8" enum="WindowFlags">
|
||||
Window style is overridden, forcing sharp corners.
|
||||
[b]Note:[/b] This flag is implemented only on Windows (11).
|
||||
</constant>
|
||||
<constant name="WINDOW_FLAG_MAX" value="9" enum="WindowFlags">
|
||||
Max value of the [enum WindowFlags].
|
||||
</constant>
|
||||
<constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent">
|
||||
|
|
52
doc/classes/EditorExport.xml
Normal file
52
doc/classes/EditorExport.xml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="EditorExport" inherits="Node" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
Hosts data related to a project's export configuration.
|
||||
</brief_description>
|
||||
<description>
|
||||
Editor-only singleton that hosts a project's [EditorExportPlatform], [EditorExportPreset], and [EditorExportPlugin] objects. Use this class to retrieve information about a project's export configuration.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="Export">$DOCS_URL/tutorials/export/index.html</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="get_export_platform">
|
||||
<return type="EditorExportPlatform" />
|
||||
<param index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the [EditorExportPlatform] at index [param idx]. [param idx] must be equal to or greater than [code]0[/code] and less than the result of [method get_export_platform_count].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_export_platform_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Returns the number of unique platforms available for export. This includes platforms that do not have an export preset in the current project.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_export_preset">
|
||||
<return type="EditorExportPreset" />
|
||||
<param index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the [EditorExportPreset] at index [param idx]. [param idx] must be equal to or greater than [code]0[/code] and less than the result of [method get_export_preset_count].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_export_preset_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Returns the number of export presets in the project.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<signals>
|
||||
<signal name="export_presets_runnable_updated">
|
||||
<description>
|
||||
Emitted when the [code]runnable[/code] property of an [EditorExportPreset] has been updated or when an [EditorExportPreset] has been added to or removed from the project.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="export_presets_updated">
|
||||
<description>
|
||||
Emitted when the properties of an [EditorExportPreset] have been updated.
|
||||
</description>
|
||||
</signal>
|
||||
</signals>
|
||||
</class>
|
|
@ -158,6 +158,20 @@
|
|||
Returns the name of the export operating system handled by this [EditorExportPlatform] class, as a friendly string. Possible return values are [code]Windows[/code], [code]Linux[/code], [code]macOS[/code], [code]Android[/code], [code]iOS[/code], and [code]Web[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_platform_features" qualifiers="const">
|
||||
<return type="String[]" />
|
||||
<description>
|
||||
Returns feature tags that are specific to the export platform. Some feature tags that may be included in this list are [code]mobile[/code], [code]pc[/code], [code]web[/code], [code]android[/code], [code]ios[/code], [code]linux[/code], [code]macos[/code], and [code]windows[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_preset_features" qualifiers="const">
|
||||
<return type="String[]" />
|
||||
<param index="0" name="preset" type="EditorExportPreset" />
|
||||
<description>
|
||||
Returns feature tags that are specific to [param preset], excluding custom features. Some feature tags that may be included in this list are texture formats ([code]etc2[/code], [code]bptc[/code], [code]s3tc[/code]), architectures ([code]x86_64[/code], [code]x86_32[/code], [code]arm64[/code], [code]arm32[/code], [code]rv64[/code], [code]riscv[/code], [code]ppc64[/code], [code]ppc[/code], [code]wasm32[/code], [code]wasm64[/code], [code]universal[/code]), and other features ([code]threads[/code], [code]nothreads[/code]).
|
||||
Use [method EditorExportPreset.get_custom_features] to get the custom features of an export preset.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_worst_message_type" qualifiers="const">
|
||||
<return type="int" enum="EditorExportPlatform.ExportMessageType" />
|
||||
<description>
|
||||
|
|
|
@ -115,6 +115,12 @@
|
|||
Returns the list of packs on which to base a patch export on.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_platform" qualifiers="const">
|
||||
<return type="EditorExportPlatform" />
|
||||
<description>
|
||||
Returns the [EditorExportPlatform] for this export preset.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_preset_name" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
|
|
|
@ -83,6 +83,12 @@
|
|||
Returns the edited (current) scene's root [Node].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_export" qualifiers="const">
|
||||
<return type="EditorExport" />
|
||||
<description>
|
||||
Returns the [EditorExport] singleton.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_editor_main_screen" qualifiers="const">
|
||||
<return type="VBoxContainer" />
|
||||
<description>
|
||||
|
|
|
@ -474,7 +474,7 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="line" type="String" />
|
||||
<description>
|
||||
Appends [param line] to the file followed by a line return character ([code]\n[/code]), encoding the text as UTF-8.
|
||||
Stores [param line] in the file followed by a newline character ([code]\n[/code]), encoding the text as UTF-8.
|
||||
</description>
|
||||
</method>
|
||||
<method name="store_pascal_string">
|
||||
|
@ -496,7 +496,7 @@
|
|||
<return type="void" />
|
||||
<param index="0" name="string" type="String" />
|
||||
<description>
|
||||
Appends [param string] to the file without a line return, encoding the text as UTF-8.
|
||||
Stores [param string] in the file without a newline character ([code]\n[/code]), encoding the text as UTF-8.
|
||||
[b]Note:[/b] This method is intended to be used to write text files. The string is stored as a UTF-8 encoded buffer without string length or terminating zero, which means that it can't be loaded back easily. If you want to store a retrievable string in a binary file, consider using [method store_pascal_string] instead. For retrieving strings from a text file, you can use [code]get_buffer(length).get_string_from_utf8()[/code] (if you know the length) or [method get_as_text].
|
||||
</description>
|
||||
</method>
|
||||
|
|
|
@ -164,7 +164,7 @@
|
|||
<member name="size" type="Vector2i" setter="set_size" getter="get_size" overrides="Window" default="Vector2i(640, 360)" />
|
||||
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default=""Save a File"" />
|
||||
<member name="use_native_dialog" type="bool" setter="set_use_native_dialog" getter="get_use_native_dialog" default="false">
|
||||
If [code]true[/code], [member access] is set to [constant ACCESS_FILESYSTEM], and it is supported by the current [DisplayServer], OS native dialog will be used instead of custom one.
|
||||
If [code]true[/code], and if supported by the current [DisplayServer], OS native dialog will be used instead of custom one.
|
||||
[b]Note:[/b] On Linux and macOS, sandboxed apps always use native dialogs to access the host file system.
|
||||
[b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks.
|
||||
[b]Note:[/b] Native dialogs are isolated from the base process, file dialog properties can't be modified once the dialog is shown.
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<method name="inspect_native_shader_code">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code.
|
||||
Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Shader.inspect_native_shader_code].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
<description>
|
||||
Called during the physics processing step of the main loop. Physics processing means that the frame rate is synced to the physics, i.e. the [param delta] variable should be constant. [param delta] is in seconds.
|
||||
It is only called if physics processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_physics_process].
|
||||
Processing happens in order of [member process_physics_priority], lower priority values are called first. Nodes with the same priority are processed in tree order, or top to bottom as seen in the editor (also known as pre-order traversal).
|
||||
Corresponds to the [constant NOTIFICATION_PHYSICS_PROCESS] notification in [method Object._notification].
|
||||
[b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan).
|
||||
</description>
|
||||
|
@ -83,6 +84,7 @@
|
|||
<description>
|
||||
Called during the processing step of the main loop. Processing happens at every frame and as fast as possible, so the [param delta] time since the previous frame is not constant. [param delta] is in seconds.
|
||||
It is only called if processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process].
|
||||
Processing happens in order of [member process_priority], lower priority values are called first. Nodes with the same priority are processed in tree order, or top to bottom as seen in the editor (also known as pre-order traversal).
|
||||
Corresponds to the [constant NOTIFICATION_PROCESS] notification in [method Object._notification].
|
||||
[b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan).
|
||||
</description>
|
||||
|
@ -1015,10 +1017,10 @@
|
|||
The node's processing behavior (see [enum ProcessMode]). To check if the node can process in its current mode, use [method can_process].
|
||||
</member>
|
||||
<member name="process_physics_priority" type="int" setter="set_physics_process_priority" getter="get_physics_process_priority" default="0">
|
||||
Similar to [member process_priority] but for [constant NOTIFICATION_PHYSICS_PROCESS], [method _physics_process] or the internal version.
|
||||
Similar to [member process_priority] but for [constant NOTIFICATION_PHYSICS_PROCESS], [method _physics_process], or [constant NOTIFICATION_INTERNAL_PHYSICS_PROCESS].
|
||||
</member>
|
||||
<member name="process_priority" type="int" setter="set_process_priority" getter="get_process_priority" default="0">
|
||||
The node's execution order of the process callbacks ([method _process], [method _physics_process], and internal processing). Nodes whose priority value is [i]lower[/i] call their process callbacks first, regardless of tree order.
|
||||
The node's execution order of the process callbacks ([method _process], [constant NOTIFICATION_PROCESS], and [constant NOTIFICATION_INTERNAL_PROCESS]). Nodes whose priority value is [i]lower[/i] call their process callbacks first, regardless of tree order.
|
||||
</member>
|
||||
<member name="process_thread_group" type="int" setter="set_process_thread_group" getter="get_process_thread_group" enum="Node.ProcessThreadGroup" default="0">
|
||||
Set the process thread group for this node (basically, whether it receives [constant NOTIFICATION_PROCESS], [constant NOTIFICATION_PHYSICS_PROCESS], [method _process] or [method _physics_process] (and the internal versions) on the main thread or in a sub-thread.
|
||||
|
|
|
@ -875,6 +875,10 @@
|
|||
[b]Note:[/b] Certain window managers can be configured to ignore the non-resizable status of a window. Do not rely on this setting as a guarantee that the window will [i]never[/i] be resizable.
|
||||
[b]Note:[/b] This setting is ignored on iOS.
|
||||
</member>
|
||||
<member name="display/window/size/sharp_corners" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], the main window uses sharp corners by default.
|
||||
[b]Note:[/b] This property is implemented only on Windows (11).
|
||||
</member>
|
||||
<member name="display/window/size/transparent" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], enables a window manager hint that the main window background [i]can[/i] be transparent. This does not make the background actually transparent. For the background to be transparent, the root viewport must also be made transparent by enabling [member rendering/viewport/transparent_background].
|
||||
[b]Note:[/b] To use a transparent splash screen, set [member application/boot_splash/bg_color] to [code]Color(0, 0, 0, 0)[/code].
|
||||
|
@ -2376,26 +2380,30 @@
|
|||
[b]Note:[/b] It is not recommended to use this setting together with [member rendering/2d/snap/snap_2d_transforms_to_pixel], as movement may appear even less smooth. Prefer only enabling that setting instead.
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/quality/msaa_2d" type="int" setter="" getter="" default="0">
|
||||
Sets the number of MSAA samples to use for 2D/Canvas rendering (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware, especially integrated graphics due to their limited memory bandwidth. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
Sets the number of multisample antialiasing (MSAA) samples to use for 2D/Canvas rendering (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware, especially integrated graphics due to their limited memory bandwidth. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
[b]Note:[/b] MSAA is only supported in the Forward+ and Mobile rendering methods, not Compatibility.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set the number of 2D MSAA samples at runtime, set [member Viewport.msaa_2d] or use [method RenderingServer.viewport_set_msaa_2d].
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/quality/msaa_3d" type="int" setter="" getter="" default="0">
|
||||
Sets the number of MSAA samples to use for 3D rendering (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware, especially integrated graphics due to their limited memory bandwidth. See also [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
Sets the number of multisample antialiasing (MSAA) samples to use for 3D rendering (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware, especially integrated graphics due to their limited memory bandwidth. See also [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set the number of 3D MSAA samples at runtime, set [member Viewport.msaa_3d] or use [method RenderingServer.viewport_set_msaa_3d].
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0">
|
||||
Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]).
|
||||
Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled].
|
||||
[b]Note:[/b] Screen-space antialiasing is only supported in the Forward+ and Mobile rendering methods, not Compatibility.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set the screen-space antialiasing mode at runtime, set [member Viewport.screen_space_aa] on the root [Viewport] instead, or use [method RenderingServer.viewport_set_screen_space_aa].
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], uses a fast post-processing filter to make banding significantly less visible in 3D. 2D rendering is [i]not[/i] affected by debanding unless the [member Environment.background_mode] is [constant Environment.BG_CANVAS].
|
||||
In some cases, debanding may introduce a slightly noticeable dithering pattern. It's recommended to enable debanding only when actually needed since the dithering pattern will make lossless-compressed screenshots larger.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set debanding at run-time, set [member Viewport.use_debanding] on the root [Viewport] instead.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set debanding at runtime, set [member Viewport.use_debanding] on the root [Viewport] instead, or use [method RenderingServer.viewport_set_use_debanding].
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false">
|
||||
Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]).
|
||||
Enables temporal antialiasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]).
|
||||
[b]Note:[/b] The implementation is not complete yet. Some visual instances such as particles and skinned meshes may show ghosting artifacts in motion.
|
||||
[b]Note:[/b] TAA is only supported in the Forward+ rendering method, not Mobile or Compatibility.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set TAA at runtime, set [member Viewport.use_taa] on the root [Viewport] instead, or use [method RenderingServer.viewport_set_use_taa].
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25">
|
||||
[b]Note:[/b] This property is only read when the project starts. To control the screen-space roughness limiter at runtime, call [method RenderingServer.screen_space_roughness_limiter_set_active] instead.
|
||||
|
|
|
@ -3917,7 +3917,7 @@
|
|||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="msaa" type="int" enum="RenderingServer.ViewportMSAA" />
|
||||
<description>
|
||||
Sets the multisample anti-aliasing mode for 2D/Canvas on the specified [param viewport] RID. See [enum ViewportMSAA] for options.
|
||||
Sets the multisample antialiasing mode for 2D/Canvas on the specified [param viewport] RID. See [enum ViewportMSAA] for options. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/msaa_2d] or [member Viewport.msaa_2d].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_msaa_3d">
|
||||
|
@ -3925,7 +3925,7 @@
|
|||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="msaa" type="int" enum="RenderingServer.ViewportMSAA" />
|
||||
<description>
|
||||
Sets the multisample anti-aliasing mode for 3D on the specified [param viewport] RID. See [enum ViewportMSAA] for options.
|
||||
Sets the multisample antialiasing mode for 3D on the specified [param viewport] RID. See [enum ViewportMSAA] for options. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/msaa_3d] or [member Viewport.msaa_3d].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_occlusion_culling_build_quality">
|
||||
|
@ -4007,7 +4007,7 @@
|
|||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="mode" type="int" enum="RenderingServer.ViewportScreenSpaceAA" />
|
||||
<description>
|
||||
Sets the viewport's screen-space antialiasing mode.
|
||||
Sets the viewport's screen-space antialiasing mode. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/screen_space_aa] or [member Viewport.screen_space_aa].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_sdf_oversize_and_scale">
|
||||
|
@ -4074,7 +4074,7 @@
|
|||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="enable" type="bool" />
|
||||
<description>
|
||||
If [code]true[/code], enables debanding on the specified viewport. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding].
|
||||
If [code]true[/code], enables debanding on the specified viewport. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding] or [member Viewport.use_debanding].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_use_hdr_2d">
|
||||
|
@ -4099,7 +4099,7 @@
|
|||
<param index="0" name="viewport" type="RID" />
|
||||
<param index="1" name="enable" type="bool" />
|
||||
<description>
|
||||
If [code]true[/code], use Temporal Anti-Aliasing. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/use_taa].
|
||||
If [code]true[/code], use temporal antialiasing. Equivalent to [member ProjectSettings.rendering/anti_aliasing/quality/use_taa] or [member Viewport.use_taa].
|
||||
</description>
|
||||
</method>
|
||||
<method name="viewport_set_use_xr">
|
||||
|
|
|
@ -35,6 +35,12 @@
|
|||
If argument [param get_groups] is true, parameter grouping hints will be provided.
|
||||
</description>
|
||||
</method>
|
||||
<method name="inspect_native_shader_code">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Only available when running in the editor. Opens a popup that visualizes the generated shader code, including all variants and internal shader code. See also [method Material.inspect_native_shader_code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_default_texture_parameter">
|
||||
<return type="void" />
|
||||
<param index="0" name="name" type="StringName" />
|
||||
|
|
|
@ -509,6 +509,12 @@
|
|||
<theme_item name="font_disabled_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 0.5)">
|
||||
Text [Color] for a [constant TreeItem.CELL_MODE_CHECK] mode cell when it's non-editable (see [method TreeItem.set_editable]).
|
||||
</theme_item>
|
||||
<theme_item name="font_hovered_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)">
|
||||
Text [Color] used when the item is hovered.
|
||||
</theme_item>
|
||||
<theme_item name="font_hovered_dimmed_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)">
|
||||
Text [Color] used when the item is hovered, while a button of the same item is hovered as the same time.
|
||||
</theme_item>
|
||||
<theme_item name="font_outline_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)">
|
||||
The tint of text outline of the item.
|
||||
</theme_item>
|
||||
|
@ -645,6 +651,9 @@
|
|||
<theme_item name="updown" data_type="icon" type="Texture2D">
|
||||
The updown arrow icon to display for the [constant TreeItem.CELL_MODE_RANGE] mode cell.
|
||||
</theme_item>
|
||||
<theme_item name="button_hover" data_type="style" type="StyleBox">
|
||||
[StyleBox] used when a button in the tree is hovered.
|
||||
</theme_item>
|
||||
<theme_item name="button_pressed" data_type="style" type="StyleBox">
|
||||
[StyleBox] used when a button in the tree is pressed.
|
||||
</theme_item>
|
||||
|
@ -666,6 +675,12 @@
|
|||
<theme_item name="focus" data_type="style" type="StyleBox">
|
||||
The focused style for the [Tree], drawn on top of everything.
|
||||
</theme_item>
|
||||
<theme_item name="hovered" data_type="style" type="StyleBox">
|
||||
[StyleBox] for the item being hovered.
|
||||
</theme_item>
|
||||
<theme_item name="hovered_dimmed" data_type="style" type="StyleBox">
|
||||
[StyleBox] for the item being hovered, while a button of the same item is hovered as the same time.
|
||||
</theme_item>
|
||||
<theme_item name="panel" data_type="style" type="StyleBox">
|
||||
The background style for the [Tree].
|
||||
</theme_item>
|
||||
|
|
|
@ -312,10 +312,12 @@
|
|||
[b]Note:[/b] [member mesh_lod_threshold] does not affect [GeometryInstance3D] visibility ranges (also known as "manual" LOD or hierarchical LOD).
|
||||
</member>
|
||||
<member name="msaa_2d" type="int" setter="set_msaa_2d" getter="get_msaa_2d" enum="Viewport.MSAA" default="0">
|
||||
The multisample anti-aliasing mode for 2D/Canvas rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of 2 or 4 is best unless targeting very high-end systems. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
The multisample antialiasing mode for 2D/Canvas rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of [constant Viewport.MSAA_2X] or [constant Viewport.MSAA_4X] is best unless targeting very high-end systems. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
See also [member ProjectSettings.rendering/anti_aliasing/quality/msaa_2d] and [method RenderingServer.viewport_set_msaa_2d].
|
||||
</member>
|
||||
<member name="msaa_3d" type="int" setter="set_msaa_3d" getter="get_msaa_3d" enum="Viewport.MSAA" default="0">
|
||||
The multisample anti-aliasing mode for 3D rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of 2 or 4 is best unless targeting very high-end systems. See also bilinear scaling 3d [member scaling_3d_mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
The multisample antialiasing mode for 3D rendering. A higher number results in smoother edges at the cost of significantly worse performance. A value of [constant Viewport.MSAA_2X] or [constant Viewport.MSAA_4X] is best unless targeting very high-end systems. See also bilinear scaling 3d [member scaling_3d_mode] for supersampling, which provides higher quality but is much more expensive. This has no effect on shader-induced aliasing or texture aliasing.
|
||||
See also [member ProjectSettings.rendering/anti_aliasing/quality/msaa_3d] and [method RenderingServer.viewport_set_msaa_3d].
|
||||
</member>
|
||||
<member name="own_world_3d" type="bool" setter="set_use_own_world_3d" getter="is_using_own_world_3d" default="false">
|
||||
If [code]true[/code], the viewport will use a unique copy of the [World3D] defined in [member world_3d].
|
||||
|
@ -365,6 +367,7 @@
|
|||
</member>
|
||||
<member name="screen_space_aa" type="int" setter="set_screen_space_aa" getter="get_screen_space_aa" enum="Viewport.ScreenSpaceAA" default="0">
|
||||
Sets the screen-space antialiasing method used. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry.
|
||||
See also [member ProjectSettings.rendering/anti_aliasing/quality/screen_space_aa] and [method RenderingServer.viewport_set_screen_space_aa].
|
||||
</member>
|
||||
<member name="sdf_oversize" type="int" setter="set_sdf_oversize" getter="get_sdf_oversize" enum="Viewport.SDFOversize" default="1">
|
||||
Controls how much of the original viewport's size should be covered by the 2D signed distance field. This SDF can be sampled in [CanvasItem] shaders and is also used for [GPUParticles2D] collision. Higher values allow portions of occluders located outside the viewport to still be taken into account in the generated signed distance field, at the cost of performance. If you notice particles falling through [LightOccluder2D]s as the occluders leave the viewport, increase this setting.
|
||||
|
@ -389,8 +392,9 @@
|
|||
If [code]true[/code], the viewport should render its background as transparent.
|
||||
</member>
|
||||
<member name="use_debanding" type="bool" setter="set_use_debanding" getter="is_using_debanding" default="false">
|
||||
If [code]true[/code], uses a fast post-processing filter to make banding significantly less visible in 3D. 2D rendering is [i]not[/i] affected by debanding unless the [member Environment.background_mode] is [constant Environment.BG_CANVAS]. See also [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding].
|
||||
If [code]true[/code], uses a fast post-processing filter to make banding significantly less visible in 3D. 2D rendering is [i]not[/i] affected by debanding unless the [member Environment.background_mode] is [constant Environment.BG_CANVAS].
|
||||
In some cases, debanding may introduce a slightly noticeable dithering pattern. It's recommended to enable debanding only when actually needed since the dithering pattern will make lossless-compressed screenshots larger.
|
||||
See also [member ProjectSettings.rendering/anti_aliasing/quality/use_debanding] and [method RenderingServer.viewport_set_use_debanding].
|
||||
</member>
|
||||
<member name="use_hdr_2d" type="bool" setter="set_use_hdr_2d" getter="is_using_hdr_2d" default="false">
|
||||
If [code]true[/code], 2D rendering will use an high dynamic range (HDR) format framebuffer matching the bit depth of the 3D framebuffer. When using the Forward+ renderer this will be an [code]RGBA16[/code] framebuffer, while when using the Mobile renderer it will be an [code]RGB10_A2[/code] framebuffer. Additionally, 2D rendering will take place in linear color space and will be converted to sRGB space immediately before blitting to the screen (if the Viewport is attached to the screen). Practically speaking, this means that the end result of the Viewport will not be clamped into the [code]0-1[/code] range and can be used in 3D rendering without color space adjustments. This allows 2D rendering to take advantage of effects requiring high dynamic range (e.g. 2D glow) as well as substantially improves the appearance of effects requiring highly detailed gradients.
|
||||
|
@ -402,8 +406,9 @@
|
|||
[b]Note:[/b] Due to memory constraints, occlusion culling is not supported by default in Web export templates. It can be enabled by compiling custom Web export templates with [code]module_raycast_enabled=yes[/code].
|
||||
</member>
|
||||
<member name="use_taa" type="bool" setter="set_use_taa" getter="is_using_taa" default="false">
|
||||
Enables Temporal Anti-Aliasing for this viewport. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion.
|
||||
Enables temporal antialiasing for this viewport. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion.
|
||||
[b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts.
|
||||
See also [member ProjectSettings.rendering/anti_aliasing/quality/use_taa] and [method RenderingServer.viewport_set_use_taa].
|
||||
</member>
|
||||
<member name="use_xr" type="bool" setter="set_use_xr" getter="is_using_xr" default="false">
|
||||
If [code]true[/code], the viewport will use the primary XR interface to render XR output. When applicable this can result in a stereoscopic image and the resulting render being output to a headset.
|
||||
|
|
|
@ -659,6 +659,11 @@
|
|||
If [member ProjectSettings.display/window/subwindows/embed_subwindows] is [code]false[/code], the position is in absolute screen coordinates. This typically applies to editor plugins. If the setting is [code]true[/code], the window's position is in the coordinates of its parent [Viewport].
|
||||
[b]Note:[/b] This property only works if [member initial_position] is set to [constant WINDOW_INITIAL_POSITION_ABSOLUTE].
|
||||
</member>
|
||||
<member name="sharp_corners" type="bool" setter="set_flag" getter="get_flag" default="false">
|
||||
If [code]true[/code], the [Window] will override the OS window style to display sharp corners.
|
||||
[b]Note:[/b] This property is implemented only on Windows (11).
|
||||
[b]Note:[/b] This property only works with native windows.
|
||||
</member>
|
||||
<member name="size" type="Vector2i" setter="set_size" getter="get_size" default="Vector2i(100, 100)">
|
||||
The window's size in pixels.
|
||||
</member>
|
||||
|
@ -842,7 +847,12 @@
|
|||
All mouse events are passed to the underlying window of the same application.
|
||||
[b]Note:[/b] This flag has no effect in embedded windows.
|
||||
</constant>
|
||||
<constant name="FLAG_MAX" value="8" enum="Flags">
|
||||
<constant name="FLAG_SHARP_CORNERS" value="8" enum="Flags">
|
||||
Window style is overridden, forcing sharp corners.
|
||||
[b]Note:[/b] This flag has no effect in embedded windows.
|
||||
[b]Note:[/b] This flag is implemented only on Windows (11).
|
||||
</constant>
|
||||
<constant name="FLAG_MAX" value="9" enum="Flags">
|
||||
Max value of the [enum Flags].
|
||||
</constant>
|
||||
<constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode">
|
||||
|
@ -878,7 +888,7 @@
|
|||
<constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the parent window layout direction.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection">
|
||||
<constant name="LAYOUT_DIRECTION_APPLICATION_LOCALE" value="1" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the current locale.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LTR" value="2" enum="LayoutDirection">
|
||||
|
@ -887,6 +897,14 @@
|
|||
<constant name="LAYOUT_DIRECTION_RTL" value="3" enum="LayoutDirection">
|
||||
Right-to-left layout direction.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_SYSTEM_LOCALE" value="4" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the system locale.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_MAX" value="5" enum="LayoutDirection">
|
||||
Represents the size of the [enum LayoutDirection] enum.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_LOCALE" value="1" enum="LayoutDirection" deprecated="Use [constant LAYOUT_DIRECTION_APPLICATION_LOCALE] instead.">
|
||||
</constant>
|
||||
<constant name="WINDOW_INITIAL_POSITION_ABSOLUTE" value="0" enum="WindowInitialPosition">
|
||||
Initial window position is determined by [member position].
|
||||
</constant>
|
||||
|
|
|
@ -2003,6 +2003,8 @@ static D3D12_BARRIER_LAYOUT _rd_texture_layout_to_d3d12_barrier_layout(RDD::Text
|
|||
switch (p_texture_layout) {
|
||||
case RDD::TEXTURE_LAYOUT_UNDEFINED:
|
||||
return D3D12_BARRIER_LAYOUT_UNDEFINED;
|
||||
case RDD::TEXTURE_LAYOUT_GENERAL:
|
||||
return D3D12_BARRIER_LAYOUT_COMMON;
|
||||
case RDD::TEXTURE_LAYOUT_STORAGE_OPTIMAL:
|
||||
return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS;
|
||||
case RDD::TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
|
@ -6175,6 +6177,8 @@ uint64_t RenderingDeviceDriverD3D12::api_trait_get(ApiTrait p_trait) {
|
|||
return false;
|
||||
case API_TRAIT_CLEARS_WITH_COPY_ENGINE:
|
||||
return false;
|
||||
case API_TRAIT_USE_GENERAL_IN_COPY_QUEUES:
|
||||
return true;
|
||||
default:
|
||||
return RenderingDeviceDriver::api_trait_get(p_trait);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "storage/texture_storage.h"
|
||||
|
||||
|
|
|
@ -230,6 +230,32 @@ TextureStorage::TextureStorage() {
|
|||
sdf_shader.shader_version = sdf_shader.shader.version_create();
|
||||
}
|
||||
|
||||
// Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods.
|
||||
|
||||
constexpr int placeholder_size = 4;
|
||||
texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8);
|
||||
// Draw a magenta/black checkerboard pattern.
|
||||
for (int i = 0; i < placeholder_size * placeholder_size; i++) {
|
||||
const int x = i % placeholder_size;
|
||||
const int y = i / placeholder_size;
|
||||
texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0));
|
||||
}
|
||||
|
||||
texture_2d_array_placeholder.push_back(texture_2d_placeholder);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cubemap_placeholder.push_back(texture_2d_placeholder);
|
||||
}
|
||||
|
||||
Ref<Image> texture_2d_placeholder_rotated;
|
||||
texture_2d_placeholder_rotated.instantiate();
|
||||
texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder);
|
||||
texture_2d_placeholder_rotated->rotate_90(CLOCKWISE);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees).
|
||||
texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated);
|
||||
}
|
||||
|
||||
#ifdef GL_API_ENABLED
|
||||
if (RasterizerGLES3::is_gles_over_gl()) {
|
||||
glEnable(GL_PROGRAM_POINT_SIZE);
|
||||
|
@ -1014,46 +1040,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
|||
}
|
||||
|
||||
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
texture_2d_initialize(p_texture, image);
|
||||
texture_2d_initialize(p_texture, texture_2d_placeholder);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
Vector<Ref<Image>> images;
|
||||
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
|
||||
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
|
||||
images.push_back(image);
|
||||
texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type);
|
||||
} else {
|
||||
//cube
|
||||
for (int i = 0; i < 6; i++) {
|
||||
images.push_back(image);
|
||||
}
|
||||
texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type);
|
||||
}
|
||||
|
||||
texture_2d_layered_initialize(p_texture, images, p_layered_type);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
|
||||
//this could be better optimized to reuse an existing image , done this way
|
||||
//for now to get it working
|
||||
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 0, 1, 1));
|
||||
|
||||
Vector<Ref<Image>> images;
|
||||
//cube
|
||||
for (int i = 0; i < 4; i++) {
|
||||
images.push_back(image);
|
||||
}
|
||||
|
||||
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
|
||||
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder);
|
||||
}
|
||||
|
||||
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "platform_gl.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
|
@ -521,6 +522,11 @@ public:
|
|||
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
|
||||
|
||||
Ref<Image> texture_2d_placeholder;
|
||||
Vector<Ref<Image>> texture_2d_array_placeholder;
|
||||
Vector<Ref<Image>> cubemap_placeholder;
|
||||
Vector<Ref<Image>> texture_3d_placeholder;
|
||||
|
||||
//these two APIs can be used together or in combination with the others.
|
||||
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
|
||||
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
|
||||
|
|
|
@ -96,6 +96,22 @@ _FORCE_INLINE_ ShaderStageUsage &operator|=(ShaderStageUsage &p_a, int p_b) {
|
|||
return p_a;
|
||||
}
|
||||
|
||||
enum StageResourceUsage : uint32_t {
|
||||
VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2),
|
||||
VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2),
|
||||
FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2),
|
||||
FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2),
|
||||
TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
|
||||
TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
|
||||
TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
|
||||
TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
|
||||
ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2),
|
||||
ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2),
|
||||
};
|
||||
|
||||
typedef LocalVector<__unsafe_unretained id<MTLResource>> ResourceVector;
|
||||
typedef HashMap<StageResourceUsage, ResourceVector> ResourceUsageMap;
|
||||
|
||||
enum class MDCommandBufferStateType {
|
||||
None,
|
||||
Render,
|
||||
|
@ -230,6 +246,7 @@ public:
|
|||
uint32_t index_offset = 0;
|
||||
LocalVector<id<MTLBuffer> __unsafe_unretained> vertex_buffers;
|
||||
LocalVector<NSUInteger> vertex_offsets;
|
||||
ResourceUsageMap resource_usage;
|
||||
// clang-format off
|
||||
enum DirtyFlag: uint8_t {
|
||||
DIRTY_NONE = 0b0000'0000,
|
||||
|
@ -271,8 +288,14 @@ public:
|
|||
blend_constants.reset();
|
||||
vertex_buffers.clear();
|
||||
vertex_offsets.clear();
|
||||
// Keep the keys, as they are likely to be used again.
|
||||
for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) {
|
||||
kv.value.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void end_encoding();
|
||||
|
||||
_FORCE_INLINE_ void mark_viewport_dirty() {
|
||||
if (viewports.is_empty()) {
|
||||
return;
|
||||
|
@ -356,13 +379,20 @@ public:
|
|||
} render;
|
||||
|
||||
// State specific for a compute pass.
|
||||
struct {
|
||||
struct ComputeState {
|
||||
MDComputePipeline *pipeline = nullptr;
|
||||
id<MTLComputeCommandEncoder> encoder = nil;
|
||||
ResourceUsageMap resource_usage;
|
||||
_FORCE_INLINE_ void reset() {
|
||||
pipeline = nil;
|
||||
encoder = nil;
|
||||
// Keep the keys, as they are likely to be used again.
|
||||
for (KeyValue<StageResourceUsage, LocalVector<__unsafe_unretained id<MTLResource>>> &kv : resource_usage) {
|
||||
kv.value.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void end_encoding();
|
||||
} compute;
|
||||
|
||||
// State specific to a blit pass.
|
||||
|
@ -632,19 +662,6 @@ public:
|
|||
MDRenderShader(CharString p_name, Vector<UniformSet> p_sets, MDLibrary *p_vert, MDLibrary *p_frag);
|
||||
};
|
||||
|
||||
enum StageResourceUsage : uint32_t {
|
||||
VertexRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_VERTEX * 2),
|
||||
VertexWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_VERTEX * 2),
|
||||
FragmentRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_FRAGMENT * 2),
|
||||
FragmentWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_FRAGMENT * 2),
|
||||
TesselationControlRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
|
||||
TesselationControlWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_CONTROL * 2),
|
||||
TesselationEvaluationRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
|
||||
TesselationEvaluationWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_TESSELATION_EVALUATION * 2),
|
||||
ComputeRead = (MTLResourceUsageRead << RDD::SHADER_STAGE_COMPUTE * 2),
|
||||
ComputeWrite = (MTLResourceUsageWrite << RDD::SHADER_STAGE_COMPUTE * 2),
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ StageResourceUsage &operator|=(StageResourceUsage &p_a, uint32_t p_b) {
|
||||
p_a = StageResourceUsage(uint32_t(p_a) | p_b);
|
||||
return p_a;
|
||||
|
@ -667,7 +684,13 @@ struct HashMapComparatorDefault<RDD::ShaderID> {
|
|||
|
||||
struct BoundUniformSet {
|
||||
id<MTLBuffer> buffer;
|
||||
HashMap<id<MTLResource>, StageResourceUsage> bound_resources;
|
||||
ResourceUsageMap usage_to_resources;
|
||||
|
||||
/// Perform a 2-way merge each key of `ResourceVector` resources from this set into the
|
||||
/// destination set.
|
||||
///
|
||||
/// Assumes the vectors of resources are sorted.
|
||||
void merge_into(ResourceUsageMap &p_dst) const;
|
||||
};
|
||||
|
||||
class API_AVAILABLE(macos(11.0), ios(14.0)) MDUniformSet {
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
void MDCommandBuffer::begin() {
|
||||
DEV_ASSERT(commandBuffer == nil);
|
||||
commandBuffer = queue.commandBuffer;
|
||||
commandBuffer = queue.commandBufferWithUnretainedReferences;
|
||||
}
|
||||
|
||||
void MDCommandBuffer::end() {
|
||||
|
@ -390,6 +390,38 @@ void MDCommandBuffer::render_set_blend_constants(const Color &p_constants) {
|
|||
}
|
||||
}
|
||||
|
||||
void BoundUniformSet::merge_into(ResourceUsageMap &p_dst) const {
|
||||
for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : usage_to_resources) {
|
||||
ResourceVector *resources = p_dst.getptr(keyval.key);
|
||||
if (resources == nullptr) {
|
||||
resources = &p_dst.insert(keyval.key, ResourceVector())->value;
|
||||
}
|
||||
// Reserve space for the new resources, assuming they are all added.
|
||||
resources->reserve(resources->size() + keyval.value.size());
|
||||
|
||||
uint32_t i = 0, j = 0;
|
||||
__unsafe_unretained id<MTLResource> *resources_ptr = resources->ptr();
|
||||
const __unsafe_unretained id<MTLResource> *keyval_ptr = keyval.value.ptr();
|
||||
// 2-way merge.
|
||||
while (i < resources->size() && j < keyval.value.size()) {
|
||||
if (resources_ptr[i] < keyval_ptr[j]) {
|
||||
i++;
|
||||
} else if (resources_ptr[i] > keyval_ptr[j]) {
|
||||
resources->insert(i, keyval_ptr[j]);
|
||||
i++;
|
||||
j++;
|
||||
} else {
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
// Append the remaining resources.
|
||||
for (; j < keyval.value.size(); j++) {
|
||||
resources->push_back(keyval_ptr[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MDCommandBuffer::_render_bind_uniform_sets() {
|
||||
DEV_ASSERT(type == MDCommandBufferStateType::Render);
|
||||
if (!render.dirty.has_flag(RenderState::DIRTY_UNIFORMS)) {
|
||||
|
@ -408,7 +440,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() {
|
|||
// Find the index of the next set bit.
|
||||
int index = __builtin_ctzll(set_uniforms);
|
||||
// Clear the set bit.
|
||||
set_uniforms &= ~(1ULL << index);
|
||||
set_uniforms &= (set_uniforms - 1);
|
||||
MDUniformSet *set = render.uniform_sets[index];
|
||||
if (set == nullptr || set->index >= (uint32_t)shader->sets.size()) {
|
||||
continue;
|
||||
|
@ -416,17 +448,7 @@ void MDCommandBuffer::_render_bind_uniform_sets() {
|
|||
UniformSet const &set_info = shader->sets[set->index];
|
||||
|
||||
BoundUniformSet &bus = set->boundUniformSetForShader(shader, device);
|
||||
|
||||
for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bus.bound_resources) {
|
||||
MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_VERTEX);
|
||||
if (usage != 0) {
|
||||
[enc useResource:keyval.key usage:usage stages:MTLRenderStageVertex];
|
||||
}
|
||||
usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_FRAGMENT);
|
||||
if (usage != 0) {
|
||||
[enc useResource:keyval.key usage:usage stages:MTLRenderStageFragment];
|
||||
}
|
||||
}
|
||||
bus.merge_into(render.resource_usage);
|
||||
|
||||
// Set the buffer for the vertex stage.
|
||||
{
|
||||
|
@ -545,8 +567,7 @@ void MDCommandBuffer::_end_render_pass() {
|
|||
// see: https://github.com/KhronosGroup/MoltenVK/blob/d20d13fe2735adb845636a81522df1b9d89c0fba/MoltenVK/MoltenVK/GPUObjects/MVKRenderPass.mm#L407
|
||||
}
|
||||
|
||||
[render.encoder endEncoding];
|
||||
render.encoder = nil;
|
||||
render.end_encoding();
|
||||
}
|
||||
|
||||
void MDCommandBuffer::_render_clear_render_area() {
|
||||
|
@ -792,10 +813,59 @@ void MDCommandBuffer::render_draw_indirect_count(RDD::BufferID p_indirect_buffer
|
|||
ERR_FAIL_MSG("not implemented");
|
||||
}
|
||||
|
||||
void MDCommandBuffer::RenderState::end_encoding() {
|
||||
if (encoder == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind all resources.
|
||||
for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) {
|
||||
if (keyval.value.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MTLResourceUsage vert_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_VERTEX);
|
||||
MTLResourceUsage frag_usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_FRAGMENT);
|
||||
if (vert_usage == frag_usage) {
|
||||
[encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex | MTLRenderStageFragment];
|
||||
} else {
|
||||
if (vert_usage != 0) {
|
||||
[encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:vert_usage stages:MTLRenderStageVertex];
|
||||
}
|
||||
if (frag_usage != 0) {
|
||||
[encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:frag_usage stages:MTLRenderStageFragment];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[encoder endEncoding];
|
||||
encoder = nil;
|
||||
}
|
||||
|
||||
void MDCommandBuffer::ComputeState::end_encoding() {
|
||||
if (encoder == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Bind all resources.
|
||||
for (KeyValue<StageResourceUsage, ResourceVector> const &keyval : resource_usage) {
|
||||
if (keyval.value.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
MTLResourceUsage usage = resource_usage_for_stage(keyval.key, RDD::ShaderStage::SHADER_STAGE_COMPUTE);
|
||||
if (usage != 0) {
|
||||
[encoder useResources:keyval.value.ptr() count:keyval.value.size() usage:usage];
|
||||
}
|
||||
}
|
||||
|
||||
[encoder endEncoding];
|
||||
encoder = nil;
|
||||
}
|
||||
|
||||
void MDCommandBuffer::render_end_pass() {
|
||||
DEV_ASSERT(type == MDCommandBufferStateType::Render);
|
||||
|
||||
[render.encoder endEncoding];
|
||||
render.end_encoding();
|
||||
render.reset();
|
||||
type = MDCommandBufferStateType::None;
|
||||
}
|
||||
|
@ -813,13 +883,7 @@ void MDCommandBuffer::compute_bind_uniform_set(RDD::UniformSetID p_uniform_set,
|
|||
|
||||
MDUniformSet *set = (MDUniformSet *)(p_uniform_set.id);
|
||||
BoundUniformSet &bus = set->boundUniformSetForShader(shader, device);
|
||||
|
||||
for (KeyValue<id<MTLResource>, StageResourceUsage> &keyval : bus.bound_resources) {
|
||||
MTLResourceUsage usage = resource_usage_for_stage(keyval.value, RDD::ShaderStage::SHADER_STAGE_COMPUTE);
|
||||
if (usage != 0) {
|
||||
[enc useResource:keyval.key usage:usage];
|
||||
}
|
||||
}
|
||||
bus.merge_into(compute.resource_usage);
|
||||
|
||||
uint32_t const *offset = set_info.offsets.getptr(RDD::SHADER_STAGE_COMPUTE);
|
||||
if (offset) {
|
||||
|
@ -848,7 +912,7 @@ void MDCommandBuffer::compute_dispatch_indirect(RDD::BufferID p_indirect_buffer,
|
|||
void MDCommandBuffer::_end_compute_dispatch() {
|
||||
DEV_ASSERT(type == MDCommandBufferStateType::Compute);
|
||||
|
||||
[compute.encoder endEncoding];
|
||||
compute.end_encoding();
|
||||
compute.reset();
|
||||
type = MDCommandBufferStateType::None;
|
||||
}
|
||||
|
@ -1052,7 +1116,20 @@ BoundUniformSet &MDUniformSet::boundUniformSetForShader(MDShader *p_shader, id<M
|
|||
}
|
||||
}
|
||||
|
||||
BoundUniformSet bs = { .buffer = enc_buffer, .bound_resources = bound_resources };
|
||||
SearchArray<__unsafe_unretained id<MTLResource>> search;
|
||||
ResourceUsageMap usage_to_resources;
|
||||
for (KeyValue<id<MTLResource>, StageResourceUsage> const &keyval : bound_resources) {
|
||||
ResourceVector *resources = usage_to_resources.getptr(keyval.value);
|
||||
if (resources == nullptr) {
|
||||
resources = &usage_to_resources.insert(keyval.value, ResourceVector())->value;
|
||||
}
|
||||
int64_t pos = search.bisect(resources->ptr(), resources->size(), keyval.key, true);
|
||||
if (pos == resources->size() || (*resources)[pos] != keyval.key) {
|
||||
resources->insert(pos, keyval.key);
|
||||
}
|
||||
}
|
||||
|
||||
BoundUniformSet bs = { .buffer = enc_buffer, .usage_to_resources = usage_to_resources };
|
||||
bound_uniforms.insert(p_shader, bs);
|
||||
return bound_uniforms.get(p_shader);
|
||||
}
|
||||
|
@ -1211,8 +1288,7 @@ vertex VaryingsPos vertClear(AttributesPos attributes [[stage_in]], constant Cle
|
|||
varyings.layer = uint(attributes.a_position.w);
|
||||
return varyings;
|
||||
}
|
||||
)",
|
||||
ClearAttKey::DEPTH_INDEX];
|
||||
)", ClearAttKey::DEPTH_INDEX];
|
||||
|
||||
return new_func(msl, @"vertClear", nil);
|
||||
}
|
||||
|
|
|
@ -2060,6 +2060,10 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
|
|||
|
||||
case BT::Sampler: {
|
||||
primary.dataType = MTLDataTypeSampler;
|
||||
primary.arrayLength = 1;
|
||||
for (uint32_t const &a : a_type.array) {
|
||||
primary.arrayLength *= a;
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
|
@ -2067,7 +2071,7 @@ Vector<uint8_t> RenderingDeviceDriverMetal::shader_compile_binary_from_spirv(Vec
|
|||
} break;
|
||||
}
|
||||
|
||||
// Find array length.
|
||||
// Find array length of image.
|
||||
if (basetype == BT::Image || basetype == BT::SampledImage) {
|
||||
primary.arrayLength = 1;
|
||||
for (uint32_t const &a : a_type.array) {
|
||||
|
|
|
@ -266,6 +266,7 @@ static const VkFormat RD_TO_VK_FORMAT[RDD::DATA_FORMAT_MAX] = {
|
|||
|
||||
static VkImageLayout RD_TO_VK_LAYOUT[RDD::TEXTURE_LAYOUT_MAX] = {
|
||||
VK_IMAGE_LAYOUT_UNDEFINED, // TEXTURE_LAYOUT_UNDEFINED
|
||||
VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_GENERAL
|
||||
VK_IMAGE_LAYOUT_GENERAL, // TEXTURE_LAYOUT_STORAGE_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // TEXTURE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
|
||||
|
@ -2636,11 +2637,13 @@ bool RenderingDeviceDriverVulkan::command_buffer_begin(CommandBufferID p_cmd_buf
|
|||
bool RenderingDeviceDriverVulkan::command_buffer_begin_secondary(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, uint32_t p_subpass, FramebufferID p_framebuffer) {
|
||||
// Reset is implicit (VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT).
|
||||
|
||||
Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);
|
||||
|
||||
VkCommandBufferInheritanceInfo inheritance_info = {};
|
||||
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
|
||||
inheritance_info.renderPass = (VkRenderPass)p_render_pass.id;
|
||||
inheritance_info.subpass = p_subpass;
|
||||
inheritance_info.framebuffer = (VkFramebuffer)p_framebuffer.id;
|
||||
inheritance_info.framebuffer = framebuffer->vk_framebuffer;
|
||||
|
||||
VkCommandBufferBeginInfo cmd_buf_begin_info = {};
|
||||
cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
|
@ -2950,12 +2953,16 @@ Error RenderingDeviceDriverVulkan::swap_chain_resize(CommandQueueID p_cmd_queue,
|
|||
fb_create_info.height = surface->height;
|
||||
fb_create_info.layers = 1;
|
||||
|
||||
VkFramebuffer framebuffer;
|
||||
VkFramebuffer vk_framebuffer;
|
||||
for (uint32_t i = 0; i < image_count; i++) {
|
||||
fb_create_info.pAttachments = &swap_chain->image_views[i];
|
||||
err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &framebuffer);
|
||||
err = vkCreateFramebuffer(vk_device, &fb_create_info, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER), &vk_framebuffer);
|
||||
ERR_FAIL_COND_V(err != VK_SUCCESS, ERR_CANT_CREATE);
|
||||
|
||||
Framebuffer *framebuffer = memnew(Framebuffer);
|
||||
framebuffer->vk_framebuffer = vk_framebuffer;
|
||||
framebuffer->swap_chain_image = swap_chain->images[i];
|
||||
framebuffer->swap_chain_image_subresource_range = view_create_info.subresourceRange;
|
||||
swap_chain->framebuffers.push_back(RDD::FramebufferID(framebuffer));
|
||||
}
|
||||
|
||||
|
@ -3024,7 +3031,10 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::swap_chain_acquire_framebuffer(C
|
|||
command_queue->pending_semaphores_for_fence.push_back(semaphore_index);
|
||||
|
||||
// Return the corresponding framebuffer to the new current image.
|
||||
return swap_chain->framebuffers[swap_chain->image_index];
|
||||
FramebufferID framebuffer_id = swap_chain->framebuffers[swap_chain->image_index];
|
||||
Framebuffer *framebuffer = (Framebuffer *)(framebuffer_id.id);
|
||||
framebuffer->swap_chain_acquired = true;
|
||||
return framebuffer_id;
|
||||
}
|
||||
|
||||
RDD::RenderPassID RenderingDeviceDriverVulkan::swap_chain_get_render_pass(SwapChainID p_swap_chain) {
|
||||
|
@ -3093,11 +3103,15 @@ RDD::FramebufferID RenderingDeviceDriverVulkan::framebuffer_create(RenderPassID
|
|||
}
|
||||
#endif
|
||||
|
||||
return FramebufferID(vk_framebuffer);
|
||||
Framebuffer *framebuffer = memnew(Framebuffer);
|
||||
framebuffer->vk_framebuffer = vk_framebuffer;
|
||||
return FramebufferID(framebuffer);
|
||||
}
|
||||
|
||||
void RenderingDeviceDriverVulkan::framebuffer_free(FramebufferID p_framebuffer) {
|
||||
vkDestroyFramebuffer(vk_device, (VkFramebuffer)p_framebuffer.id, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));
|
||||
Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);
|
||||
vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer, VKC::get_allocation_callbacks(VK_OBJECT_TYPE_FRAMEBUFFER));
|
||||
memdelete(framebuffer);
|
||||
}
|
||||
|
||||
/****************/
|
||||
|
@ -4315,10 +4329,25 @@ void RenderingDeviceDriverVulkan::render_pass_free(RenderPassID p_render_pass) {
|
|||
static_assert(ARRAYS_COMPATIBLE_FIELDWISE(RDD::RenderPassClearValue, VkClearValue));
|
||||
|
||||
void RenderingDeviceDriverVulkan::command_begin_render_pass(CommandBufferID p_cmd_buffer, RenderPassID p_render_pass, FramebufferID p_framebuffer, CommandBufferType p_cmd_buffer_type, const Rect2i &p_rect, VectorView<RenderPassClearValue> p_clear_values) {
|
||||
Framebuffer *framebuffer = (Framebuffer *)(p_framebuffer.id);
|
||||
if (framebuffer->swap_chain_acquired) {
|
||||
// Insert a barrier to wait for the acquisition of the framebuffer before the render pass begins.
|
||||
VkImageMemoryBarrier image_barrier = {};
|
||||
image_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
image_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
image_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
image_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
image_barrier.image = framebuffer->swap_chain_image;
|
||||
image_barrier.subresourceRange = framebuffer->swap_chain_image_subresource_range;
|
||||
vkCmdPipelineBarrier((VkCommandBuffer)p_cmd_buffer.id, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_barrier);
|
||||
framebuffer->swap_chain_acquired = false;
|
||||
}
|
||||
|
||||
VkRenderPassBeginInfo render_pass_begin = {};
|
||||
render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
render_pass_begin.renderPass = (VkRenderPass)p_render_pass.id;
|
||||
render_pass_begin.framebuffer = (VkFramebuffer)p_framebuffer.id;
|
||||
render_pass_begin.framebuffer = framebuffer->vk_framebuffer;
|
||||
|
||||
render_pass_begin.renderArea.offset.x = p_rect.position.x;
|
||||
render_pass_begin.renderArea.offset.y = p_rect.position.y;
|
||||
|
|
|
@ -366,6 +366,15 @@ public:
|
|||
/**** FRAMEBUFFER ****/
|
||||
/*********************/
|
||||
|
||||
struct Framebuffer {
|
||||
VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;
|
||||
|
||||
// Only filled in by a framebuffer created by a swap chain. Unused otherwise.
|
||||
VkImage swap_chain_image = VK_NULL_HANDLE;
|
||||
VkImageSubresourceRange swap_chain_image_subresource_range = {};
|
||||
bool swap_chain_acquired = false;
|
||||
};
|
||||
|
||||
virtual FramebufferID framebuffer_create(RenderPassID p_render_pass, VectorView<TextureID> p_attachments, uint32_t p_width, uint32_t p_height) override final;
|
||||
virtual void framebuffer_free(FramebufferID p_framebuffer) override final;
|
||||
|
||||
|
|
|
@ -1501,11 +1501,6 @@ void AnimationBezierTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
|
|||
}
|
||||
|
||||
box_selection_to = mm->get_position();
|
||||
|
||||
if (get_local_mouse_position().y < 0) {
|
||||
// Avoid cursor from going too above, so it does not lose focus with viewport.
|
||||
warp_mouse(Vector2(get_local_mouse_position().x, 0));
|
||||
}
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
|
|
|
@ -8763,7 +8763,7 @@ void AnimationMarkerEdit::_move_selection_commit() {
|
|||
void AnimationMarkerEdit::_delete_selected_markers() {
|
||||
if (selection.size()) {
|
||||
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||
undo_redo->create_action(TTR("Animation Delete Keys"));
|
||||
undo_redo->create_action(TTR("Animation Delete Markers"));
|
||||
for (const StringName &name : selection) {
|
||||
double time = animation->get_marker_time(name);
|
||||
undo_redo->add_do_method(animation.ptr(), "remove_marker", name);
|
||||
|
@ -8967,7 +8967,7 @@ AnimationMarkerEdit::AnimationMarkerEdit() {
|
|||
add_child(menu);
|
||||
menu->connect(SceneStringName(id_pressed), callable_mp(this, &AnimationMarkerEdit::_menu_selected));
|
||||
menu->add_shortcut(ED_SHORTCUT("animation_marker_edit/rename_marker", TTR("Rename Marker"), Key::R), MENU_KEY_RENAME);
|
||||
menu->add_shortcut(ED_SHORTCUT("animation_marker_edit/delete_selection", TTR("Delete Markers (s)"), Key::KEY_DELETE), MENU_KEY_DELETE);
|
||||
menu->add_shortcut(ED_SHORTCUT("animation_marker_edit/delete_selection", TTR("Delete Marker(s)"), Key::KEY_DELETE), MENU_KEY_DELETE);
|
||||
menu->add_shortcut(ED_SHORTCUT("animation_marker_edit/toggle_marker_names", TTR("Show All Marker Names"), Key::M), MENU_KEY_TOGGLE_MARKER_NAMES);
|
||||
|
||||
marker_insert_confirm = memnew(ConfirmationDialog);
|
||||
|
|
|
@ -277,11 +277,14 @@ Variant EditorDebuggerTree::get_drag_data(const Point2 &p_point) {
|
|||
}
|
||||
|
||||
String path = selected->get_text(0);
|
||||
const int icon_size = get_theme_constant(SNAME("class_icon_size"), EditorStringName(Editor));
|
||||
|
||||
HBoxContainer *hb = memnew(HBoxContainer);
|
||||
TextureRect *tf = memnew(TextureRect);
|
||||
tf->set_texture(selected->get_icon(0));
|
||||
tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
|
||||
tf->set_custom_minimum_size(Size2(icon_size, icon_size));
|
||||
tf->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
|
||||
tf->set_expand_mode(TextureRect::EXPAND_IGNORE_SIZE);
|
||||
hb->add_child(tf);
|
||||
Label *label = memnew(Label(path));
|
||||
hb->add_child(label);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "editor_profiler.h"
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "editor_visual_profiler.h"
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
@ -437,11 +438,7 @@ void EditorVisualProfiler::_notification(int p_what) {
|
|||
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_THEME_CHANGED:
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
if (is_layout_rtl()) {
|
||||
activate->set_icon(get_editor_theme_icon(SNAME("PlayBackwards")));
|
||||
} else {
|
||||
activate->set_icon(get_editor_theme_icon(SNAME("Play")));
|
||||
}
|
||||
activate->set_icon(get_editor_theme_icon(SNAME("Play")));
|
||||
clear_button->set_icon(get_editor_theme_icon(SNAME("Clear")));
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -248,11 +248,16 @@ void EditorFileSystem::_first_scan_filesystem() {
|
|||
ep.step(TTR("Scanning file structure..."), 0, true);
|
||||
nb_files_total = _scan_new_dir(first_scan_root_dir, d);
|
||||
|
||||
// Preloading GDExtensions file extensions to prevent looping on all the resource loaders
|
||||
// for each files in _first_scan_process_scripts.
|
||||
List<String> gdextension_extensions;
|
||||
ResourceLoader::get_recognized_extensions_for_type("GDExtension", &gdextension_extensions);
|
||||
|
||||
// This loads the global class names from the scripts and ensures that even if the
|
||||
// global_script_class_cache.cfg was missing or invalid, the global class names are valid in ScriptServer.
|
||||
// At the same time, to prevent looping multiple times in all files, it looks for extensions.
|
||||
ep.step(TTR("Loading global class names..."), 1, true);
|
||||
_first_scan_process_scripts(first_scan_root_dir, existing_class_names, extensions);
|
||||
_first_scan_process_scripts(first_scan_root_dir, gdextension_extensions, existing_class_names, extensions);
|
||||
|
||||
// Removing invalid global class to prevent having invalid paths in ScriptServer.
|
||||
_remove_invalid_global_class_names(existing_class_names);
|
||||
|
@ -276,16 +281,16 @@ void EditorFileSystem::_first_scan_filesystem() {
|
|||
ep.step(TTR("Starting file scan..."), 5, true);
|
||||
}
|
||||
|
||||
void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_scan_dir, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions) {
|
||||
void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_scan_dir, List<String> &p_gdextension_extensions, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions) {
|
||||
for (ScannedDirectory *scan_sub_dir : p_scan_dir->subdirs) {
|
||||
_first_scan_process_scripts(scan_sub_dir, p_existing_class_names, p_extensions);
|
||||
_first_scan_process_scripts(scan_sub_dir, p_gdextension_extensions, p_existing_class_names, p_extensions);
|
||||
}
|
||||
|
||||
for (const String &scan_file : p_scan_dir->files) {
|
||||
// Optimization to skip the ResourceLoader::get_resource_type for files
|
||||
// that are not scripts. Some loader get_resource_type methods read the file
|
||||
// which can be very slow on large projects.
|
||||
String ext = scan_file.get_extension().to_lower();
|
||||
const String ext = scan_file.get_extension().to_lower();
|
||||
bool is_script = false;
|
||||
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
|
||||
if (ScriptServer::get_language(i)->get_extension() == ext) {
|
||||
|
@ -293,24 +298,29 @@ void EditorFileSystem::_first_scan_process_scripts(const ScannedDirectory *p_sca
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!is_script) {
|
||||
continue; // Not a script.
|
||||
if (is_script) {
|
||||
const String path = p_scan_dir->full_path.path_join(scan_file);
|
||||
const String type = ResourceLoader::get_resource_type(path);
|
||||
|
||||
if (ClassDB::is_parent_class(type, SNAME("Script"))) {
|
||||
String script_class_extends;
|
||||
String script_class_icon_path;
|
||||
String script_class_name = _get_global_script_class(type, path, &script_class_extends, &script_class_icon_path);
|
||||
_register_global_class_script(path, path, type, script_class_name, script_class_extends, script_class_icon_path);
|
||||
|
||||
if (!script_class_name.is_empty()) {
|
||||
p_existing_class_names.insert(script_class_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String path = p_scan_dir->full_path.path_join(scan_file);
|
||||
String type = ResourceLoader::get_resource_type(path);
|
||||
|
||||
if (ClassDB::is_parent_class(type, SNAME("Script"))) {
|
||||
String script_class_extends;
|
||||
String script_class_icon_path;
|
||||
String script_class_name = _get_global_script_class(type, path, &script_class_extends, &script_class_icon_path);
|
||||
_register_global_class_script(path, path, type, script_class_name, script_class_extends, script_class_icon_path);
|
||||
|
||||
if (!script_class_name.is_empty()) {
|
||||
p_existing_class_names.insert(script_class_name);
|
||||
// Check for GDExtensions.
|
||||
if (p_gdextension_extensions.find(ext)) {
|
||||
const String path = p_scan_dir->full_path.path_join(scan_file);
|
||||
const String type = ResourceLoader::get_resource_type(path);
|
||||
if (type == SNAME("GDExtension")) {
|
||||
p_extensions.insert(path);
|
||||
}
|
||||
} else if (type == SNAME("GDExtension")) {
|
||||
p_extensions.insert(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ class EditorFileSystem : public Node {
|
|||
|
||||
void _scan_filesystem();
|
||||
void _first_scan_filesystem();
|
||||
void _first_scan_process_scripts(const ScannedDirectory *p_scan_dir, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions);
|
||||
void _first_scan_process_scripts(const ScannedDirectory *p_scan_dir, List<String> &p_gdextension_extensions, HashSet<String> &p_existing_class_names, HashSet<String> &p_extensions);
|
||||
|
||||
HashSet<String> late_update_files;
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ EditorUndoRedoManager *EditorInterface::get_editor_undo_redo() const {
|
|||
return EditorUndoRedoManager::get_singleton();
|
||||
}
|
||||
|
||||
EditorExport *EditorInterface::get_editor_export() const {
|
||||
return EditorExport::get_singleton();
|
||||
}
|
||||
|
||||
TypedArray<Texture2D> EditorInterface::_make_mesh_previews(const TypedArray<Mesh> &p_meshes, int p_preview_size) {
|
||||
Vector<Ref<Mesh>> meshes;
|
||||
|
||||
|
@ -557,6 +561,7 @@ void EditorInterface::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_selection"), &EditorInterface::get_selection);
|
||||
ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings);
|
||||
ClassDB::bind_method(D_METHOD("get_editor_undo_redo"), &EditorInterface::get_editor_undo_redo);
|
||||
ClassDB::bind_method(D_METHOD("get_editor_export"), &EditorInterface::get_editor_export);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ class EditorResourcePreview;
|
|||
class EditorSelection;
|
||||
class EditorSettings;
|
||||
class EditorUndoRedoManager;
|
||||
class EditorExport;
|
||||
class FileSystemDock;
|
||||
class Mesh;
|
||||
class Node;
|
||||
|
@ -103,6 +104,7 @@ public:
|
|||
EditorSelection *get_selection() const;
|
||||
Ref<EditorSettings> get_editor_settings() const;
|
||||
EditorUndoRedoManager *get_editor_undo_redo() const;
|
||||
EditorExport *get_editor_export() const;
|
||||
|
||||
Vector<Ref<Texture2D>> make_mesh_previews(const Vector<Ref<Mesh>> &p_meshes, Vector<Transform3D> *p_transforms, int p_preview_size);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "core/input/input.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/object/class_db.h"
|
||||
|
@ -4771,7 +4772,13 @@ Ref<Texture2D> EditorNode::_get_class_or_script_icon(const String &p_class, cons
|
|||
// Look for the native base type in the editor theme. This is relevant for
|
||||
// scripts extending other scripts and for built-in classes.
|
||||
String script_class_name = p_script->get_language()->get_global_class_name(p_script->get_path());
|
||||
String base_type = ScriptServer::get_global_class_native_base(script_class_name);
|
||||
String base_type;
|
||||
if (script_class_name.is_empty()) {
|
||||
base_type = p_script->get_instance_base_type();
|
||||
} else {
|
||||
base_type = ScriptServer::get_global_class_native_base(script_class_name);
|
||||
}
|
||||
|
||||
if (theme.is_valid() && theme->has_icon(base_type, EditorStringName(EditorIcons))) {
|
||||
return theme->get_icon(base_type, EditorStringName(EditorIcons));
|
||||
}
|
||||
|
@ -4836,6 +4843,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p
|
|||
Ref<Script> scr;
|
||||
if (ScriptServer::is_global_class(p_class)) {
|
||||
scr = EditorNode::get_editor_data().script_class_load_script(p_class);
|
||||
} else if (ResourceLoader::exists(p_class)) { // If the script is not a class_name we check if the script resource exists.
|
||||
scr = ResourceLoader::load(p_class);
|
||||
}
|
||||
|
||||
return _get_class_or_script_icon(p_class, scr, p_fallback, true);
|
||||
|
|
|
@ -121,7 +121,7 @@ String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, boo
|
|||
}
|
||||
|
||||
String EventListenerLineEdit::get_device_string(int p_device) {
|
||||
if (p_device == InputMap::ALL_DEVICES) {
|
||||
if (p_device == InputEvent::DEVICE_ID_ALL_DEVICES) {
|
||||
return TTR("All Devices");
|
||||
}
|
||||
return TTR("Device") + " " + itos(p_device);
|
||||
|
|
|
@ -120,8 +120,16 @@ void EditorExport::emit_presets_runnable_changed() {
|
|||
}
|
||||
|
||||
void EditorExport::_bind_methods() {
|
||||
_export_presets_updated = StringName("export_presets_updated", true);
|
||||
_export_presets_runnable_updated = StringName("export_presets_runnable_updated", true);
|
||||
|
||||
ADD_SIGNAL(MethodInfo(_export_presets_updated));
|
||||
ADD_SIGNAL(MethodInfo(_export_presets_runnable_updated));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_export_platform_count"), &EditorExport::get_export_platform_count);
|
||||
ClassDB::bind_method(D_METHOD("get_export_platform", "idx"), &EditorExport::get_export_platform);
|
||||
ClassDB::bind_method(D_METHOD("get_export_preset_count"), &EditorExport::get_export_preset_count);
|
||||
ClassDB::bind_method(D_METHOD("get_export_preset", "idx"), &EditorExport::get_export_preset);
|
||||
}
|
||||
|
||||
void EditorExport::add_export_platform(const Ref<EditorExportPlatform> &p_platform) {
|
||||
|
@ -139,7 +147,7 @@ void EditorExport::remove_export_platform(const Ref<EditorExportPlatform> &p_pla
|
|||
should_reload_presets = true;
|
||||
}
|
||||
|
||||
int EditorExport::get_export_platform_count() {
|
||||
int EditorExport::get_export_platform_count() const {
|
||||
return export_platforms.size();
|
||||
}
|
||||
|
||||
|
@ -442,9 +450,6 @@ EditorExport::EditorExport() {
|
|||
save_timer->set_one_shot(true);
|
||||
save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
|
||||
|
||||
_export_presets_updated = StringName("export_presets_updated", true);
|
||||
_export_presets_runnable_updated = StringName("export_presets_runnable_updated", true);
|
||||
|
||||
singleton = this;
|
||||
set_process(true);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
static EditorExport *get_singleton() { return singleton; }
|
||||
|
||||
void add_export_platform(const Ref<EditorExportPlatform> &p_platform);
|
||||
int get_export_platform_count();
|
||||
int get_export_platform_count() const;
|
||||
Ref<EditorExportPlatform> get_export_platform(int p_idx);
|
||||
void remove_export_platform(const Ref<EditorExportPlatform> &p_platform);
|
||||
|
||||
|
|
|
@ -326,11 +326,7 @@ Error EditorExportPlatform::_save_zip_patch_file(void *p_userdata, const String
|
|||
Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const {
|
||||
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
|
||||
ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>());
|
||||
if (EditorNode::get_singleton()->get_gui_base()->is_layout_rtl()) {
|
||||
return theme->get_icon(SNAME("PlayBackwards"), EditorStringName(EditorIcons));
|
||||
} else {
|
||||
return theme->get_icon(SNAME("Play"), EditorStringName(EditorIcons));
|
||||
}
|
||||
return theme->get_icon(SNAME("Play"), EditorStringName(EditorIcons));
|
||||
}
|
||||
|
||||
String EditorExportPlatform::find_export_template(const String &template_file_name, String *err) const {
|
||||
|
@ -534,6 +530,26 @@ HashSet<String> EditorExportPlatform::get_features(const Ref<EditorExportPreset>
|
|||
return result;
|
||||
}
|
||||
|
||||
TypedArray<String> EditorExportPlatform::get_platform_features_as_array() const {
|
||||
List<String> feature_list;
|
||||
get_platform_features(&feature_list);
|
||||
TypedArray<String> result;
|
||||
for (const String &E : feature_list) {
|
||||
result.push_back(E);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TypedArray<String> EditorExportPlatform::get_preset_features_as_array(const Ref<EditorExportPreset> &p_preset) const {
|
||||
List<String> feature_list;
|
||||
get_preset_features(p_preset, &feature_list);
|
||||
TypedArray<String> result;
|
||||
for (const String &E : feature_list) {
|
||||
result.push_back(E);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EditorExportPlatform::ExportNotifier::ExportNotifier(EditorExportPlatform &p_platform, const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
|
||||
HashSet<String> features = p_platform.get_features(p_preset, p_debug);
|
||||
Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins();
|
||||
|
@ -2299,6 +2315,9 @@ void EditorExportPlatform::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("ssh_run_on_remote_no_wait", "host", "port", "ssh_args", "cmd_args", "port_fwd"), &EditorExportPlatform::_ssh_run_on_remote_no_wait, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("ssh_push_to_remote", "host", "port", "scp_args", "src_file", "dst_file"), &EditorExportPlatform::ssh_push_to_remote);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_platform_features"), &EditorExportPlatform::get_platform_features_as_array);
|
||||
ClassDB::bind_method(D_METHOD("get_preset_features", "preset"), &EditorExportPlatform::get_preset_features_as_array);
|
||||
|
||||
ClassDB::bind_static_method("EditorExportPlatform", D_METHOD("get_forced_export_files"), &EditorExportPlatform::get_forced_export_files);
|
||||
|
||||
BIND_ENUM_CONSTANT(EXPORT_MESSAGE_NONE);
|
||||
|
|
|
@ -197,6 +197,8 @@ protected:
|
|||
void _unload_patches();
|
||||
|
||||
public:
|
||||
TypedArray<String> get_platform_features_as_array() const;
|
||||
TypedArray<String> get_preset_features_as_array(const Ref<EditorExportPreset> &p_preset) const;
|
||||
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const = 0;
|
||||
|
||||
struct ExportOption {
|
||||
|
|
|
@ -65,6 +65,8 @@ void EditorExportPreset::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("has", "property"), &EditorExportPreset::has);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_platform"), &EditorExportPreset::get_platform);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_files_to_export"), &EditorExportPreset::get_files_to_export);
|
||||
ClassDB::bind_method(D_METHOD("get_customized_files"), &EditorExportPreset::get_customized_files);
|
||||
ClassDB::bind_method(D_METHOD("get_customized_files_count"), &EditorExportPreset::get_customized_files_count);
|
||||
|
|
|
@ -1355,6 +1355,13 @@ EditorFileDialog::Access EditorFileDialog::get_access() const {
|
|||
void EditorFileDialog::_make_dir_confirm() {
|
||||
const String stripped_dirname = makedirname->get_text().strip_edges();
|
||||
|
||||
if (stripped_dirname.is_empty()) {
|
||||
error_dialog->set_text(TTR("The path specified is invalid."));
|
||||
error_dialog->popup_centered(Size2(250, 50) * EDSCALE);
|
||||
makedirname->set_text(""); // Reset label.
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir_access->dir_exists(stripped_dirname)) {
|
||||
error_dialog->set_text(TTR("Could not create folder. File with that name already exists."));
|
||||
error_dialog->popup_centered(Size2(250, 50) * EDSCALE);
|
||||
|
@ -1638,6 +1645,7 @@ void EditorFileDialog::_update_favorites() {
|
|||
|
||||
for (int i = 0; i < favorited_paths.size(); i++) {
|
||||
favorites->add_item(favorited_names[i], theme_cache.folder);
|
||||
favorites->set_item_tooltip(-1, favorited_paths[i]);
|
||||
favorites->set_item_metadata(-1, favorited_paths[i]);
|
||||
favorites->set_item_icon_modulate(-1, get_dir_icon_color(favorited_paths[i]));
|
||||
|
||||
|
@ -1719,6 +1727,7 @@ void EditorFileDialog::_update_recent() {
|
|||
|
||||
for (int i = 0; i < recentd_paths.size(); i++) {
|
||||
recent->add_item(recentd_names[i], theme_cache.folder);
|
||||
recent->set_item_tooltip(-1, recentd_paths[i]);
|
||||
recent->set_item_metadata(-1, recentd_paths[i]);
|
||||
recent->set_item_icon_modulate(-1, get_dir_icon_color(recentd_paths[i]));
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "editor_object_selector.h"
|
||||
|
||||
#include "editor/debugger/editor_debugger_inspector.h"
|
||||
#include "editor/editor_data.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
@ -131,6 +132,19 @@ void EditorObjectSelector::update_path() {
|
|||
Ref<Texture2D> obj_icon;
|
||||
if (Object::cast_to<MultiNodeEdit>(obj)) {
|
||||
obj_icon = EditorNode::get_singleton()->get_class_icon(Object::cast_to<MultiNodeEdit>(obj)->get_edited_class_name());
|
||||
} else if (Object::cast_to<EditorDebuggerRemoteObject>(obj)) {
|
||||
String class_name;
|
||||
Ref<Script> base_script = obj->get_script();
|
||||
if (base_script.is_valid()) {
|
||||
class_name = base_script->get_global_name();
|
||||
|
||||
if (class_name.is_empty()) {
|
||||
// If there is no class_name in this script we just take the script path.
|
||||
class_name = base_script->get_path();
|
||||
}
|
||||
}
|
||||
|
||||
obj_icon = EditorNode::get_singleton()->get_class_icon(class_name.is_empty() ? Object::cast_to<EditorDebuggerRemoteObject>(obj)->type_name : class_name);
|
||||
} else {
|
||||
obj_icon = EditorNode::get_singleton()->get_object_icon(obj);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ struct UniRange {
|
|||
};
|
||||
|
||||
// Unicode Character Blocks
|
||||
// Source: https://www.unicode.org/Public/14.0.0/ucd/Blocks.txt
|
||||
// Source: https://www.unicode.org/Public/16.0.0/ucd/Blocks.txt
|
||||
static UniRange unicode_ranges[] = {
|
||||
{ 0x0000, 0x007F, U"Basic Latin" },
|
||||
{ 0x0080, 0x00FF, U"Latin-1 Supplement" },
|
||||
|
@ -283,6 +283,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x10500, 0x1052F, U"Elbasan" },
|
||||
{ 0x10530, 0x1056F, U"Caucasian Albanian" },
|
||||
{ 0x10570, 0x105BF, U"Vithkuqi" },
|
||||
{ 0x105C0, 0x105FF, U"Todhri" },
|
||||
{ 0x10600, 0x1077F, U"Linear A" },
|
||||
{ 0x10780, 0x107BF, U"Latin Extended-F" },
|
||||
{ 0x10800, 0x1083F, U"Cypriot Syllabary" },
|
||||
|
@ -305,6 +306,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x10C00, 0x10C4F, U"Old Turkic" },
|
||||
{ 0x10C80, 0x10CFF, U"Old Hungarian" },
|
||||
{ 0x10D00, 0x10D3F, U"Hanifi Rohingya" },
|
||||
{ 0x10D40, 0x10D8F, U"Garay" },
|
||||
{ 0x10E60, 0x10E7F, U"Rumi Numeral Symbols" },
|
||||
{ 0x10E80, 0x10EBF, U"Yezidi" },
|
||||
{ 0x10EC0, 0x10EFF, U"Arabic Extended-C" },
|
||||
|
@ -324,12 +326,14 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x11280, 0x112AF, U"Multani" },
|
||||
{ 0x112B0, 0x112FF, U"Khudawadi" },
|
||||
{ 0x11300, 0x1137F, U"Grantha" },
|
||||
{ 0x11380, 0x113FF, U"Tulu-Tigalari" },
|
||||
{ 0x11400, 0x1147F, U"Newa" },
|
||||
{ 0x11480, 0x114DF, U"Tirhuta" },
|
||||
{ 0x11580, 0x115FF, U"Siddham" },
|
||||
{ 0x11600, 0x1165F, U"Modi" },
|
||||
{ 0x11660, 0x1167F, U"Mongolian Supplement" },
|
||||
{ 0x11680, 0x116CF, U"Takri" },
|
||||
{ 0x116D0, 0x116FF, U"Myanmar Extended-C" },
|
||||
{ 0x11700, 0x1174F, U"Ahom" },
|
||||
{ 0x11800, 0x1184F, U"Dogra" },
|
||||
{ 0x118A0, 0x118FF, U"Warang Citi" },
|
||||
|
@ -340,6 +344,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x11AB0, 0x11ABF, U"Unified Canadian Aboriginal Syllabics Extended-A" },
|
||||
{ 0x11AC0, 0x11AFF, U"Pau Cin Hau" },
|
||||
{ 0x11B00, 0x11B5F, U"Devanagari Extended-A" },
|
||||
{ 0x11BC0, 0x11BFF, U"Sunuwar" },
|
||||
{ 0x11C00, 0x11C6F, U"Bhaiksuki" },
|
||||
{ 0x11C70, 0x11CBF, U"Marchen" },
|
||||
{ 0x11D00, 0x11D5F, U"Masaram Gondi" },
|
||||
|
@ -354,12 +359,15 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x12F90, 0x12FFF, U"Cypro-Minoan" },
|
||||
{ 0x13000, 0x1342F, U"Egyptian Hieroglyphs" },
|
||||
{ 0x13430, 0x1343F, U"Egyptian Hieroglyph Format Controls" },
|
||||
{ 0x13460, 0x143FF, U"Egyptian Hieroglyphs Extended-A" },
|
||||
{ 0x14400, 0x1467F, U"Anatolian Hieroglyphs" },
|
||||
{ 0x16100, 0x1613F, U"Gurung Khema" },
|
||||
{ 0x16800, 0x16A3F, U"Bamum Supplement" },
|
||||
{ 0x16A40, 0x16A6F, U"Mro" },
|
||||
{ 0x16A70, 0x16ACF, U"Tangsa" },
|
||||
{ 0x16AD0, 0x16AFF, U"Bassa Vah" },
|
||||
{ 0x16B00, 0x16B8F, U"Pahawh Hmong" },
|
||||
{ 0x16D40, 0x16D7F, U"Kirat Rai" },
|
||||
{ 0x16E40, 0x16E9F, U"Medefaidrin" },
|
||||
{ 0x16F00, 0x16F9F, U"Miao" },
|
||||
{ 0x16FE0, 0x16FFF, U"Ideographic Symbols and Punctuation" },
|
||||
|
@ -374,6 +382,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x1B170, 0x1B2FF, U"Nushu" },
|
||||
{ 0x1BC00, 0x1BC9F, U"Duployan" },
|
||||
{ 0x1BCA0, 0x1BCAF, U"Shorthand Format Controls" },
|
||||
{ 0x1CC00, 0x1CEBF, U"Symbols for Legacy Computing Supplement" },
|
||||
{ 0x1CF00, 0x1CFCF, U"Znamenny Musical Notation" },
|
||||
{ 0x1D000, 0x1D0FF, U"Byzantine Musical Symbols" },
|
||||
{ 0x1D100, 0x1D1FF, U"Musical Symbols" },
|
||||
|
@ -391,6 +400,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x1E290, 0x1E2BF, U"Toto" },
|
||||
{ 0x1E2C0, 0x1E2FF, U"Wancho" },
|
||||
{ 0x1E4D0, 0x1E4FF, U"Nag Mundari" },
|
||||
{ 0x1E5D0, 0x1E5FF, U"Ol Onal" },
|
||||
{ 0x1E7E0, 0x1E7FF, U"Ethiopic Extended-B" },
|
||||
{ 0x1E800, 0x1E8DF, U"Mende Kikakui" },
|
||||
{ 0x1E900, 0x1E95F, U"Adlam" },
|
||||
|
@ -418,6 +428,7 @@ static UniRange unicode_ranges[] = {
|
|||
{ 0x2B740, 0x2B81F, U"CJK Unified Ideographs Extension D" },
|
||||
{ 0x2B820, 0x2CEAF, U"CJK Unified Ideographs Extension E" },
|
||||
{ 0x2CEB0, 0x2EBEF, U"CJK Unified Ideographs Extension F" },
|
||||
{ 0x2EBF0, 0x2EE5F, U"CJK Unified Ideographs Extension I" },
|
||||
{ 0x2F800, 0x2FA1F, U"CJK Compatibility Ideographs Supplement" },
|
||||
{ 0x30000, 0x3134F, U"CJK Unified Ideographs Extension G" },
|
||||
{ 0x31350, 0x323AF, U"CJK Unified Ideographs Extension H" },
|
||||
|
|
|
@ -551,18 +551,18 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
|
|||
}
|
||||
|
||||
void InputEventConfigurationDialog::_device_selection_changed(int p_option_button_index) {
|
||||
// Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
|
||||
// and option index 1 corresponds to device 0, etc...
|
||||
event->set_device(p_option_button_index - 1);
|
||||
// Option index 0 corresponds to "All Devices" (value of -3).
|
||||
// Otherwise subtract 1 as option index 1 corresponds to device 0, etc...
|
||||
event->set_device(p_option_button_index == 0 ? InputEvent::DEVICE_ID_ALL_DEVICES : p_option_button_index - 1);
|
||||
event_as_text->set_text(EventListenerLineEdit::get_event_text(event, true));
|
||||
}
|
||||
|
||||
void InputEventConfigurationDialog::_set_current_device(int p_device) {
|
||||
device_id_option->select(p_device + 1);
|
||||
device_id_option->select(p_device == InputEvent::DEVICE_ID_ALL_DEVICES ? 0 : p_device + 1);
|
||||
}
|
||||
|
||||
int InputEventConfigurationDialog::_get_current_device() const {
|
||||
return device_id_option->get_selected() - 1;
|
||||
return device_id_option->get_selected() == 0 ? InputEvent::DEVICE_ID_ALL_DEVICES : device_id_option->get_selected() - 1;
|
||||
}
|
||||
|
||||
void InputEventConfigurationDialog::_notification(int p_what) {
|
||||
|
@ -705,11 +705,12 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
|
|||
|
||||
device_id_option = memnew(OptionButton);
|
||||
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
for (int i = -1; i < 8; i++) {
|
||||
device_id_option->add_item(EventListenerLineEdit::get_device_string(InputEvent::DEVICE_ID_ALL_DEVICES));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
device_id_option->add_item(EventListenerLineEdit::get_device_string(i));
|
||||
}
|
||||
device_id_option->connect(SceneStringName(item_selected), callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
|
||||
_set_current_device(InputMap::ALL_DEVICES);
|
||||
_set_current_device(InputEvent::DEVICE_ID_ALL_DEVICES);
|
||||
device_container->add_child(device_id_option);
|
||||
|
||||
device_container->hide();
|
||||
|
|
|
@ -2006,30 +2006,34 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
|
|||
HBoxContainer *hb = memnew(HBoxContainer);
|
||||
add_child(hb);
|
||||
|
||||
HBoxContainer *playback_container = memnew(HBoxContainer);
|
||||
playback_container->set_layout_direction(LAYOUT_DIRECTION_LTR);
|
||||
hb->add_child(playback_container);
|
||||
|
||||
play_bw_from = memnew(Button);
|
||||
play_bw_from->set_theme_type_variation("FlatButton");
|
||||
play_bw_from->set_tooltip_text(TTR("Play Animation Backwards"));
|
||||
hb->add_child(play_bw_from);
|
||||
playback_container->add_child(play_bw_from);
|
||||
|
||||
play_bw = memnew(Button);
|
||||
play_bw->set_theme_type_variation("FlatButton");
|
||||
play_bw->set_tooltip_text(TTR("Play Animation Backwards from End"));
|
||||
hb->add_child(play_bw);
|
||||
playback_container->add_child(play_bw);
|
||||
|
||||
stop = memnew(Button);
|
||||
stop->set_theme_type_variation("FlatButton");
|
||||
stop->set_tooltip_text(TTR("Pause/Stop Animation"));
|
||||
hb->add_child(stop);
|
||||
playback_container->add_child(stop);
|
||||
|
||||
play = memnew(Button);
|
||||
play->set_theme_type_variation("FlatButton");
|
||||
play->set_tooltip_text(TTR("Play Animation from Start"));
|
||||
hb->add_child(play);
|
||||
playback_container->add_child(play);
|
||||
|
||||
play_from = memnew(Button);
|
||||
play_from->set_theme_type_variation("FlatButton");
|
||||
play_from->set_tooltip_text(TTR("Play Animation"));
|
||||
hb->add_child(play_from);
|
||||
playback_container->add_child(play_from);
|
||||
|
||||
frame = memnew(SpinBox);
|
||||
hb->add_child(frame);
|
||||
|
|
|
@ -153,7 +153,6 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C
|
|||
} break;
|
||||
case CONTAINER_PROJECT_SETTING_TAB_RIGHT: {
|
||||
ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(p_control);
|
||||
ProjectSettingsEditor::get_singleton()->get_tabs()->move_child(p_control, 1);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/file_access_memory.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/os/os.h"
|
||||
|
|
|
@ -44,7 +44,10 @@ LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
|
|||
|
||||
Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
|
||||
mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
|
||||
mat->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
|
||||
// Fade out probes when camera gets too close to them.
|
||||
mat->set_distance_fade(StandardMaterial3D::DISTANCE_FADE_PIXEL_DITHER);
|
||||
mat->set_distance_fade_min_distance(0.5);
|
||||
mat->set_distance_fade_max_distance(1.5);
|
||||
mat->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
|
||||
mat->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, false);
|
||||
mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
|
||||
|
|
|
@ -396,6 +396,7 @@ void ShaderEditorPlugin::_setup_popup_menu(PopupMenuType p_type, PopupMenu *p_me
|
|||
if (p_type == FILE) {
|
||||
p_menu->add_separator();
|
||||
p_menu->add_item(TTR("Open File in Inspector"), FILE_INSPECT);
|
||||
p_menu->add_item(TTR("Inspect Native Shader Code..."), FILE_INSPECT_NATIVE_SHADER_CODE);
|
||||
p_menu->add_separator();
|
||||
p_menu->add_shortcut(ED_SHORTCUT("shader_editor/close_file", TTR("Close File"), KeyModifierMask::CMD_OR_CTRL | Key::W), FILE_CLOSE);
|
||||
} else {
|
||||
|
@ -554,6 +555,12 @@ void ShaderEditorPlugin::_menu_item_pressed(int p_index) {
|
|||
EditorNode::get_singleton()->push_item(edited_shaders[index].shader_inc.ptr());
|
||||
}
|
||||
} break;
|
||||
case FILE_INSPECT_NATIVE_SHADER_CODE: {
|
||||
int index = shader_tabs->get_current_tab();
|
||||
if (edited_shaders[index].shader.is_valid()) {
|
||||
edited_shaders[index].shader->inspect_native_shader_code();
|
||||
}
|
||||
} break;
|
||||
case FILE_CLOSE: {
|
||||
_close_shader(shader_tabs->get_current_tab());
|
||||
} break;
|
||||
|
@ -754,6 +761,7 @@ void ShaderEditorPlugin::_set_file_specific_items_disabled(bool p_disabled) {
|
|||
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE), p_disabled);
|
||||
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_SAVE_AS), p_disabled);
|
||||
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT), p_disabled);
|
||||
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_INSPECT_NATIVE_SHADER_CODE), p_disabled);
|
||||
file_popup_menu->set_item_disabled(file_popup_menu->get_item_index(FILE_CLOSE), p_disabled);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ class ShaderEditorPlugin : public EditorPlugin {
|
|||
FILE_SAVE,
|
||||
FILE_SAVE_AS,
|
||||
FILE_INSPECT,
|
||||
FILE_INSPECT_NATIVE_SHADER_CODE,
|
||||
FILE_CLOSE,
|
||||
CLOSE_ALL,
|
||||
CLOSE_OTHER_TABS,
|
||||
|
|
|
@ -1986,6 +1986,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
|
|||
sub_vb->add_child(hfc);
|
||||
|
||||
playback_container = memnew(HBoxContainer);
|
||||
playback_container->set_layout_direction(LAYOUT_DIRECTION_LTR);
|
||||
hfc->add_child(playback_container);
|
||||
|
||||
play_bw_from = memnew(Button);
|
||||
|
@ -2013,7 +2014,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
|
|||
play_from->set_tooltip_text(TTR("Play selected animation from current pos. (D)"));
|
||||
playback_container->add_child(play_from);
|
||||
|
||||
playback_container->add_child(memnew(VSeparator));
|
||||
hfc->add_child(memnew(VSeparator));
|
||||
|
||||
autoplay->connect(SceneStringName(pressed), callable_mp(this, &SpriteFramesEditor::_autoplay_pressed));
|
||||
autoplay->set_toggle_mode(true);
|
||||
|
|
|
@ -2128,12 +2128,11 @@ void VisualShaderEditor::_update_nodes() {
|
|||
}
|
||||
}
|
||||
|
||||
Array keys = added.keys();
|
||||
keys.sort();
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
const Variant &key = keys.get(i);
|
||||
List<Variant> keys;
|
||||
added.get_key_list(&keys);
|
||||
keys.sort_custom<StringLikeVariantOrder>();
|
||||
|
||||
for (const Variant &key : keys) {
|
||||
const Dictionary &value = (Dictionary)added[key];
|
||||
|
||||
add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]);
|
||||
|
|
|
@ -88,7 +88,7 @@ void ProjectListItemControl::_notification(int p_what) {
|
|||
draw_style_box(get_theme_stylebox(SNAME("selected"), SNAME("Tree")), Rect2(Point2(), get_size()));
|
||||
}
|
||||
if (is_hovering) {
|
||||
draw_style_box(get_theme_stylebox(SNAME("hover"), SNAME("Tree")), Rect2(Point2(), get_size()));
|
||||
draw_style_box(get_theme_stylebox(SNAME("hovered"), SNAME("Tree")), Rect2(Point2(), get_size()));
|
||||
}
|
||||
|
||||
draw_line(Point2(0, get_size().y + 1), Point2(get_size().x, get_size().y + 1), get_theme_color(SNAME("guide_color"), SNAME("Tree")));
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "editor/editor_string_names.h"
|
||||
#include "editor/editor_translation_parser.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "editor/export/editor_export.h"
|
||||
#include "editor/export/editor_export_platform.h"
|
||||
#include "editor/export/editor_export_platform_extension.h"
|
||||
#include "editor/export/editor_export_platform_pc.h"
|
||||
|
@ -158,6 +159,7 @@ void register_editor_types() {
|
|||
GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
|
||||
GDREGISTER_CLASS(EditorSyntaxHighlighter);
|
||||
GDREGISTER_ABSTRACT_CLASS(EditorInterface);
|
||||
GDREGISTER_ABSTRACT_CLASS(EditorExport);
|
||||
GDREGISTER_CLASS(EditorExportPlugin);
|
||||
GDREGISTER_ABSTRACT_CLASS(EditorExportPlatform);
|
||||
GDREGISTER_ABSTRACT_CLASS(EditorExportPlatformPC);
|
||||
|
|
|
@ -945,6 +945,8 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
|
|||
|
||||
p_theme->set_color("custom_button_font_highlight", "Tree", p_config.font_hover_color);
|
||||
p_theme->set_color(SceneStringName(font_color), "Tree", p_config.font_color);
|
||||
p_theme->set_color("font_hovered_color", "Tree", p_config.mono_color);
|
||||
p_theme->set_color("font_hovered_dimmed_color", "Tree", p_config.font_color);
|
||||
p_theme->set_color("font_selected_color", "Tree", p_config.mono_color);
|
||||
p_theme->set_color("font_disabled_color", "Tree", p_config.font_disabled_color);
|
||||
p_theme->set_color("font_outline_color", "Tree", p_config.font_outline_color);
|
||||
|
@ -997,7 +999,13 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
|
|||
Ref<StyleBoxFlat> style_tree_hover = p_config.base_style->duplicate();
|
||||
style_tree_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.4));
|
||||
style_tree_hover->set_border_width_all(0);
|
||||
p_theme->set_stylebox("hover", "Tree", style_tree_hover);
|
||||
p_theme->set_stylebox("hovered", "Tree", style_tree_hover);
|
||||
p_theme->set_stylebox("button_hover", "Tree", style_tree_hover);
|
||||
|
||||
Ref<StyleBoxFlat> style_tree_hover_dimmed = p_config.base_style->duplicate();
|
||||
style_tree_hover_dimmed->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.2));
|
||||
style_tree_hover_dimmed->set_border_width_all(0);
|
||||
p_theme->set_stylebox("hovered_dimmed", "Tree", style_tree_hover_dimmed);
|
||||
|
||||
p_theme->set_stylebox("selected_focus", "Tree", style_tree_focus);
|
||||
p_theme->set_stylebox("selected", "Tree", style_tree_selected);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/io/file_access_zip.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/image_loader.h"
|
||||
#include "core/io/ip.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
|
@ -2412,6 +2413,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
if (bool(GLOBAL_GET("display/window/size/no_focus"))) {
|
||||
window_flags |= DisplayServer::WINDOW_FLAG_NO_FOCUS_BIT;
|
||||
}
|
||||
if (bool(GLOBAL_GET("display/window/size/sharp_corners"))) {
|
||||
window_flags |= DisplayServer::WINDOW_FLAG_SHARP_CORNERS_BIT;
|
||||
}
|
||||
window_mode = (DisplayServer::WindowMode)(GLOBAL_GET("display/window/size/mode").operator int());
|
||||
int initial_position_type = GLOBAL_GET("display/window/size/initial_position_type").operator int();
|
||||
if (initial_position_type == 0) { // Absolute.
|
||||
|
@ -3197,6 +3201,10 @@ Error Main::setup2(bool p_show_boot_logo) {
|
|||
}
|
||||
|
||||
id->set_emulate_mouse_from_touch(bool(GLOBAL_DEF_BASIC("input_devices/pointing/emulate_mouse_from_touch", true)));
|
||||
|
||||
if (editor) {
|
||||
id->set_emulate_mouse_from_touch(true);
|
||||
}
|
||||
}
|
||||
|
||||
OS::get_singleton()->benchmark_end_measure("Startup", "Setup Window and Boot");
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "image_compress_basisu.h"
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/print_string.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
|
|
@ -217,7 +217,7 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
|
|||
|
||||
List<Variant> keys;
|
||||
dict.get_key_list(&keys);
|
||||
keys.sort();
|
||||
keys.sort_custom<StringLikeVariantOrder>();
|
||||
|
||||
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
|
||||
if (E->prev()) {
|
||||
|
|
|
@ -693,10 +693,16 @@ void GDScript::_static_default_init() {
|
|||
continue;
|
||||
}
|
||||
if (type.builtin_type == Variant::ARRAY && type.has_container_element_type(0)) {
|
||||
const GDScriptDataType element_type = type.get_container_element_type(0);
|
||||
Array default_value;
|
||||
const GDScriptDataType &element_type = type.get_container_element_type(0);
|
||||
default_value.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
|
||||
static_variables.write[E.value.index] = default_value;
|
||||
} else if (type.builtin_type == Variant::DICTIONARY && type.has_container_element_types()) {
|
||||
const GDScriptDataType key_type = type.get_container_element_type_or_variant(0);
|
||||
const GDScriptDataType value_type = type.get_container_element_type_or_variant(1);
|
||||
Dictionary default_value;
|
||||
default_value.set_typed(key_type.builtin_type, key_type.native_type, key_type.script_type, value_type.builtin_type, value_type.native_type, value_type.script_type);
|
||||
static_variables.write[E.value.index] = default_value;
|
||||
} else {
|
||||
Variant default_value;
|
||||
Callable::CallError err;
|
||||
|
|
|
@ -1624,15 +1624,17 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
|
|||
valid = false;
|
||||
}
|
||||
|
||||
annotation->info = &valid_annotations[annotation->name];
|
||||
if (valid) {
|
||||
annotation->info = &valid_annotations[annotation->name];
|
||||
|
||||
if (!annotation->applies_to(p_valid_targets)) {
|
||||
if (annotation->applies_to(AnnotationInfo::SCRIPT)) {
|
||||
push_error(vformat(R"(Annotation "%s" must be at the top of the script, before "extends" and "class_name".)", annotation->name));
|
||||
} else {
|
||||
push_error(vformat(R"(Annotation "%s" is not allowed in this level.)", annotation->name));
|
||||
if (!annotation->applies_to(p_valid_targets)) {
|
||||
if (annotation->applies_to(AnnotationInfo::SCRIPT)) {
|
||||
push_error(vformat(R"(Annotation "%s" must be at the top of the script, before "extends" and "class_name".)", annotation->name));
|
||||
} else {
|
||||
push_error(vformat(R"(Annotation "%s" is not allowed in this level.)", annotation->name));
|
||||
}
|
||||
valid = false;
|
||||
}
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (check(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) {
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
@export
|
||||
func test():
|
||||
pass
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_PARSER_ERROR
|
||||
Annotation "@export" cannot be applied to a function.
|
|
@ -0,0 +1,3 @@
|
|||
@hello_world
|
||||
func test():
|
||||
pass
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_PARSER_ERROR
|
||||
Unrecognized annotation: "@hello_world".
|
|
@ -32,7 +32,7 @@ partial class EventSignals
|
|||
add => backing_MySignal += value;
|
||||
remove => backing_MySignal -= value;
|
||||
}
|
||||
protected void OnMySignal(string str, int num)
|
||||
protected void EmitSignalMySignal(string str, int num)
|
||||
{
|
||||
EmitSignal(SignalName.MySignal, str, num);
|
||||
}
|
||||
|
|
|
@ -807,7 +807,7 @@ partial class ExportedFields
|
|||
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@_fieldRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.@_fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
return properties;
|
||||
|
|
|
@ -925,7 +925,7 @@ partial class ExportedProperties
|
|||
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@PropertyRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)38, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
return properties;
|
||||
}
|
||||
|
|
|
@ -791,7 +791,7 @@ namespace Godot.SourceGenerators
|
|||
}
|
||||
}
|
||||
|
||||
hint = PropertyHint.DictionaryType;
|
||||
hint = PropertyHint.TypeString;
|
||||
|
||||
hintString = keyHintString != null && valueHintString != null ? $"{keyHintString};{valueHintString}" : null;
|
||||
return hintString != null;
|
||||
|
|
|
@ -282,7 +282,7 @@ namespace Godot.SourceGenerators
|
|||
.Append(" -= value;\n")
|
||||
.Append("}\n");
|
||||
|
||||
// Generate On{EventName} method to raise the event
|
||||
// Generate EmitSignal{EventName} method to raise the event
|
||||
|
||||
var invokeMethodSymbol = signalDelegate.InvokeMethodData.Method;
|
||||
int paramCount = invokeMethodSymbol.Parameters.Length;
|
||||
|
@ -291,7 +291,7 @@ namespace Godot.SourceGenerators
|
|||
"private" :
|
||||
"protected";
|
||||
|
||||
source.Append($" {raiseMethodModifiers} void On{signalName}(");
|
||||
source.Append($" {raiseMethodModifiers} void EmitSignal{signalName}(");
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
var paramSymbol = invokeMethodSymbol.Parameters[i];
|
||||
|
|
|
@ -3275,10 +3275,10 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
|
|||
|
||||
p_output.append(CLOSE_BLOCK_L1);
|
||||
|
||||
// Generate On{EventName} method to raise the event.
|
||||
// Generate EmitSignal{EventName} method to raise the event.
|
||||
if (!p_itype.is_singleton) {
|
||||
p_output.append(MEMBER_BEGIN "protected void ");
|
||||
p_output << "On" << p_isignal.proxy_name;
|
||||
p_output << "EmitSignal" << p_isignal.proxy_name;
|
||||
if (is_parameterless) {
|
||||
p_output.append("()\n" OPEN_BLOCK_L1 INDENT2);
|
||||
p_output << "EmitSignal(SignalName." << p_isignal.proxy_name << ");\n";
|
||||
|
|
|
@ -480,6 +480,8 @@ void NavMap::sync() {
|
|||
// connection, integration and path finding.
|
||||
_new_pm_edge_free_count = free_edges.size();
|
||||
|
||||
real_t sqr_edge_connection_margin = edge_connection_margin * edge_connection_margin;
|
||||
|
||||
for (int i = 0; i < free_edges.size(); i++) {
|
||||
const gd::Edge::Connection &free_edge = free_edges[i];
|
||||
Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos;
|
||||
|
@ -510,7 +512,7 @@ void NavMap::sync() {
|
|||
} else {
|
||||
other1 = other_edge_p1.lerp(other_edge_p2, (1.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
|
||||
}
|
||||
if (other1.distance_to(self1) > edge_connection_margin) {
|
||||
if (other1.distance_squared_to(self1) > sqr_edge_connection_margin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -521,7 +523,7 @@ void NavMap::sync() {
|
|||
} else {
|
||||
other2 = other_edge_p1.lerp(other_edge_p2, (0.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
|
||||
}
|
||||
if (other2.distance_to(self2) > edge_connection_margin) {
|
||||
if (other2.distance_squared_to(self2) > sqr_edge_connection_margin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -549,11 +551,11 @@ void NavMap::sync() {
|
|||
const Vector3 end = link->get_end_position();
|
||||
|
||||
gd::Polygon *closest_start_polygon = nullptr;
|
||||
real_t closest_start_distance = link_connection_radius;
|
||||
real_t closest_start_sqr_dist = link_connection_radius * link_connection_radius;
|
||||
Vector3 closest_start_point;
|
||||
|
||||
gd::Polygon *closest_end_polygon = nullptr;
|
||||
real_t closest_end_distance = link_connection_radius;
|
||||
real_t closest_end_sqr_dist = link_connection_radius * link_connection_radius;
|
||||
Vector3 closest_end_point;
|
||||
|
||||
// Create link to any polygons within the search radius of the start point.
|
||||
|
@ -564,11 +566,11 @@ void NavMap::sync() {
|
|||
for (uint32_t start_point_id = 2; start_point_id < start_poly.points.size(); start_point_id += 1) {
|
||||
const Face3 start_face(start_poly.points[0].pos, start_poly.points[start_point_id - 1].pos, start_poly.points[start_point_id].pos);
|
||||
const Vector3 start_point = start_face.get_closest_point_to(start);
|
||||
const real_t start_distance = start_point.distance_to(start);
|
||||
const real_t sqr_dist = start_point.distance_squared_to(start);
|
||||
|
||||
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
|
||||
if (start_distance <= link_connection_radius && start_distance < closest_start_distance) {
|
||||
closest_start_distance = start_distance;
|
||||
if (sqr_dist < closest_start_sqr_dist) {
|
||||
closest_start_sqr_dist = sqr_dist;
|
||||
closest_start_point = start_point;
|
||||
closest_start_polygon = &start_poly;
|
||||
}
|
||||
|
@ -581,11 +583,11 @@ void NavMap::sync() {
|
|||
for (uint32_t end_point_id = 2; end_point_id < end_poly.points.size(); end_point_id += 1) {
|
||||
const Face3 end_face(end_poly.points[0].pos, end_poly.points[end_point_id - 1].pos, end_poly.points[end_point_id].pos);
|
||||
const Vector3 end_point = end_face.get_closest_point_to(end);
|
||||
const real_t end_distance = end_point.distance_to(end);
|
||||
const real_t sqr_dist = end_point.distance_squared_to(end);
|
||||
|
||||
// Pick the polygon that is within our radius and is closer than anything we've seen yet.
|
||||
if (end_distance <= link_connection_radius && end_distance < closest_end_distance) {
|
||||
closest_end_distance = end_distance;
|
||||
if (sqr_dist < closest_end_sqr_dist) {
|
||||
closest_end_sqr_dist = sqr_dist;
|
||||
closest_end_point = end_point;
|
||||
closest_end_polygon = &end_poly;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "core/error/error_macros.h"
|
||||
#include "core/io/file_access_memory.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/print_string.h"
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "video_stream_theora.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/os/os.h"
|
||||
#include "scene/resources/image_texture.h"
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "image_saver_tinyexr.h"
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include <zlib.h> // Should come before including tinyexr.
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#ifndef IMAGE_SAVER_TINYEXR_H
|
||||
#define IMAGE_SAVER_TINYEXR_H
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/io/image.h"
|
||||
|
||||
Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
|
||||
Vector<uint8_t> save_exr_buffer(const Ref<Image> &p_img, bool p_grayscale);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "godot_plugin_config.h"
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/zip_io.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/export/editor_export_platform.h"
|
||||
|
|
|
@ -108,7 +108,7 @@ public final class PermissionsUtil {
|
|||
} else {
|
||||
PermissionInfo permissionInfo = getPermissionInfo(activity, permission);
|
||||
int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
if ((protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d(TAG, "Requesting permission " + permission);
|
||||
requestedPermissions.add(permission);
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public final class PermissionsUtil {
|
|||
try {
|
||||
PermissionInfo permissionInfo = getPermissionInfo(activity, permissionName);
|
||||
int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permissionName) != PackageManager.PERMISSION_GRANTED) {
|
||||
if ((protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permissionName) != PackageManager.PERMISSION_GRANTED) {
|
||||
activity.requestPermissions(new String[] { permissionName }, REQUEST_SINGLE_PERMISSION_REQ_CODE);
|
||||
return false;
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ public final class PermissionsUtil {
|
|||
} else {
|
||||
PermissionInfo permissionInfo = getPermissionInfo(context, manifestPermission);
|
||||
int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
|
||||
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(context, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
|
||||
if ((protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(context, manifestPermission) == PackageManager.PERMISSION_GRANTED) {
|
||||
grantedPermissions.add(manifestPermission);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1479,12 +1479,12 @@ DisplayServerWayland::DisplayServerWayland(const String &p_rendering_driver, Win
|
|||
driver_found = true;
|
||||
}
|
||||
}
|
||||
#endif // GLES3_ENABLED
|
||||
|
||||
if (!driver_found) {
|
||||
r_error = ERR_UNAVAILABLE;
|
||||
ERR_FAIL_MSG("Video driver not found.");
|
||||
}
|
||||
#endif // GLES3_ENABLED
|
||||
|
||||
cursor_set_shape(CURSOR_BUSY);
|
||||
|
||||
|
|
|
@ -75,6 +75,13 @@
|
|||
<member name="codesign/custom_options" type="PackedStringArray" setter="" getter="">
|
||||
Array of the additional command line arguments passed to the code signing tool.
|
||||
</member>
|
||||
<member name="codesign/entitlements/additional" type="String" setter="" getter="">
|
||||
Additional data added to the root [code]<dict>[/code] section of the [url=https://developer.apple.com/documentation/bundleresources/entitlements].entitlements[/url] file. The value should be an XML section with pairs of key-value elements, e.g.:
|
||||
[codeblock lang=text]
|
||||
<key>key_name</key>
|
||||
<string>value</string>
|
||||
[/codeblock]
|
||||
</member>
|
||||
<member name="codesign/entitlements/address_book" type="bool" setter="" getter="">
|
||||
Enable to allow access to contacts in the user's address book, if it's enabled you should also provide usage message in the [member privacy/address_book_usage_description] option. See [url=https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_personal-information_addressbook]com.apple.security.personal-information.addressbook[/url].
|
||||
</member>
|
||||
|
|
|
@ -327,7 +327,7 @@ bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportP
|
|||
}
|
||||
|
||||
bool advanced_options_enabled = p_preset->are_advanced_options_enabled();
|
||||
if (p_option.begins_with("privacy")) {
|
||||
if (p_option.begins_with("privacy") || p_option == "codesign/entitlements/additional") {
|
||||
return advanced_options_enabled;
|
||||
}
|
||||
}
|
||||
|
@ -501,6 +501,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
|
|||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_user_selected", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array()));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/additional", PROPERTY_HINT_MULTILINE_TEXT), ""));
|
||||
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
|
||||
|
||||
#ifdef MACOS_ENABLED
|
||||
|
@ -2126,6 +2127,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
|
|||
}
|
||||
}
|
||||
|
||||
const String &additional_entitlements = p_preset->get("codesign/entitlements/additional");
|
||||
if (!additional_entitlements.is_empty()) {
|
||||
ent_f->store_line(additional_entitlements);
|
||||
}
|
||||
|
||||
ent_f->store_line("</dict>");
|
||||
ent_f->store_line("</plist>");
|
||||
} else {
|
||||
|
@ -2288,6 +2294,14 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
|
|||
}
|
||||
}
|
||||
|
||||
if (FileAccess::exists(ent_path)) {
|
||||
print_verbose("entitlements:\n" + FileAccess::get_file_as_string(ent_path));
|
||||
}
|
||||
|
||||
if (FileAccess::exists(hlp_ent_path)) {
|
||||
print_verbose("helper entitlements:\n" + FileAccess::get_file_as_string(hlp_ent_path));
|
||||
}
|
||||
|
||||
// Clean up temporary entitlements files.
|
||||
if (FileAccess::exists(hlp_ent_path)) {
|
||||
DirAccess::remove_file_or_error(hlp_ent_path);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/io/image.h"
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/io/resource_saver.h"
|
||||
#include "core/os/os.h"
|
||||
|
|
|
@ -67,6 +67,18 @@
|
|||
#define DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 19
|
||||
#endif
|
||||
|
||||
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
|
||||
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
|
||||
#endif
|
||||
|
||||
#ifndef DWMWCP_DEFAULT
|
||||
#define DWMWCP_DEFAULT 0
|
||||
#endif
|
||||
|
||||
#ifndef DWMWCP_DONOTROUND
|
||||
#define DWMWCP_DONOTROUND 1
|
||||
#endif
|
||||
|
||||
#define WM_INDICATOR_CALLBACK_MESSAGE (WM_USER + 1)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
@ -1483,6 +1495,9 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
|
|||
if (p_flags & WINDOW_FLAG_ALWAYS_ON_TOP_BIT && p_mode != WINDOW_MODE_FULLSCREEN && p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN) {
|
||||
wd.always_on_top = true;
|
||||
}
|
||||
if (p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT) {
|
||||
wd.sharp_corners = true;
|
||||
}
|
||||
if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) {
|
||||
wd.no_focus = true;
|
||||
}
|
||||
|
@ -2297,6 +2312,12 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W
|
|||
wd.always_on_top = p_enabled;
|
||||
_update_window_style(p_window);
|
||||
} break;
|
||||
case WINDOW_FLAG_SHARP_CORNERS: {
|
||||
wd.sharp_corners = p_enabled;
|
||||
DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
|
||||
::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
|
||||
_update_window_style(p_window);
|
||||
} break;
|
||||
case WINDOW_FLAG_TRANSPARENT: {
|
||||
if (p_enabled) {
|
||||
// Enable per-pixel alpha.
|
||||
|
@ -3994,6 +4015,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
native_menu->_menu_activate(HMENU(lParam), (int)wParam);
|
||||
} break;
|
||||
case WM_CREATE: {
|
||||
{
|
||||
DWORD value = windows[window_id].sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
|
||||
::DwmSetWindowAttribute(windows[window_id].hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
|
||||
}
|
||||
if (is_dark_mode_supported() && dark_title_available) {
|
||||
BOOL value = is_dark_mode();
|
||||
|
||||
|
@ -5645,6 +5670,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
|||
wd_transient_parent->transient_children.insert(id);
|
||||
}
|
||||
|
||||
wd.sharp_corners = p_flags & WINDOW_FLAG_SHARP_CORNERS_BIT;
|
||||
{
|
||||
DWORD value = wd.sharp_corners ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT;
|
||||
::DwmSetWindowAttribute(wd.hWnd, DWMWA_WINDOW_CORNER_PREFERENCE, &value, sizeof(value));
|
||||
}
|
||||
|
||||
if (is_dark_mode_supported() && dark_title_available) {
|
||||
BOOL value = is_dark_mode();
|
||||
::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user