summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editor/editor_inspector.cpp14
-rw-r--r--modules/msdfgen/SCsub2
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSpawner.xml32
-rw-r--r--modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml25
-rw-r--r--modules/multiplayer/doc_classes/SceneReplicationConfig.xml10
-rw-r--r--modules/multiplayer/multiplayer_spawner.cpp13
-rw-r--r--modules/multiplayer/multiplayer_spawner.h6
-rw-r--r--modules/multiplayer/scene_replication_interface.cpp9
-rw-r--r--modules/text_server_adv/SCsub24
-rw-r--r--modules/text_server_adv/text_server_adv.cpp18
-rw-r--r--modules/text_server_fb/SCsub4
11 files changed, 119 insertions, 38 deletions
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 57acc0b2c5..133a4a3398 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -2479,6 +2479,8 @@ void EditorInspector::update_tree() {
_parse_added_editors(main_vbox, ped);
}
+ StringName type_name;
+
// Get the lists of editors for properties.
for (List<PropertyInfo>::Element *E_property = plist.front(); E_property; E_property = E_property->next()) {
PropertyInfo &p = E_property->get();
@@ -2549,6 +2551,7 @@ void EditorInspector::update_tree() {
category_vbox = nullptr; //reset
String type = p.name;
+ type_name = p.name;
// Set the category icon.
if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) {
@@ -2582,18 +2585,17 @@ void EditorInspector::update_tree() {
if (use_doc_hints) {
// Sets the category tooltip to show documentation.
- StringName type2 = p.name;
- if (!class_descr_cache.has(type2)) {
+ if (!class_descr_cache.has(type_name)) {
String descr;
DocTools *dd = EditorHelp::get_doc_data();
- HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type2);
+ HashMap<String, DocData::ClassDoc>::Iterator E = dd->class_list.find(type_name);
if (E) {
descr = DTR(E->value.brief_description);
}
- class_descr_cache[type2] = descr;
+ class_descr_cache[type_name] = descr;
}
- category->set_tooltip(p.name + "::" + (class_descr_cache[type2].is_empty() ? "" : class_descr_cache[type2]));
+ category->set_tooltip(p.name + "::" + (class_descr_cache[type_name].is_empty() ? "" : class_descr_cache[type_name]));
}
// Add editors at the start of a category.
@@ -2864,7 +2866,7 @@ void EditorInspector::update_tree() {
// Build the doc hint, to use as tooltip.
// Get the class name.
- StringName classname = object->get_class_name();
+ StringName classname = type_name == "" ? object->get_class_name() : type_name;
if (!object_class.is_empty()) {
classname = object_class;
}
diff --git a/modules/msdfgen/SCsub b/modules/msdfgen/SCsub
index 227369f4bd..0c269bc7f4 100644
--- a/modules/msdfgen/SCsub
+++ b/modules/msdfgen/SCsub
@@ -36,7 +36,7 @@ if env["builtin_msdfgen"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_msdfgen.Append(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"])
+ env_msdfgen.Prepend(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"])
lib = env_msdfgen.add_library("msdfgen_builtin", thirdparty_sources)
thirdparty_obj += lib
diff --git a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
index 44ab34f52c..881796ed26 100644
--- a/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
+++ b/modules/multiplayer/doc_classes/MultiplayerSpawner.xml
@@ -1,65 +1,83 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerSpawner" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Automatically replicates spawnable nodes from the authority to other multiplayer peers.
</brief_description>
<description>
- This node uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way.
+ Spawnable scenes can be configured in the editor or through code (see [method add_spawnable_scene]).
+ Also supports custom node spawns through [method spawn], calling [method _spawn_custom] on all peers.
+
+ Internally, [MultiplayerSpawner] uses [method MultiplayerAPI.object_configuration_add] to notify spawns passing the spawned node as the [code]object[/code] and itself as the [code]configuration[/code], and [method MultiplayerAPI.object_configuration_remove] to notify despawns in a similar way.
</description>
<tutorials>
</tutorials>
<methods>
<method name="_spawn_custom" qualifiers="virtual">
- <return type="Object" />
+ <return type="Node" />
<argument index="0" name="data" type="Variant" />
<description>
+ Method called on all peers when a custom spawn was requested by the authority using [method spawn]. Should return a [Node] that is not in the scene tree.
+
+ [b]Note:[/b] Spawned nodes should [b]not[/b] be added to the scene with `add_child`. This is done automatically.
</description>
</method>
<method name="add_spawnable_scene">
<return type="void" />
<argument index="0" name="path" type="String" />
<description>
+ Adds a scene path to spawnable scenes, making it automatically replicated from the multiplayer authority to other peers when added as children of the node pointed by [member spawn_path].
</description>
</method>
<method name="clear_spawnable_scenes">
<return type="void" />
<description>
+ Clears all spawnable scenes. Does not despawn existing instances on remote peers.
</description>
</method>
<method name="get_spawnable_scene" qualifiers="const">
<return type="String" />
- <argument index="0" name="path" type="int" />
+ <argument index="0" name="index" type="int" />
<description>
+ Returns the spawnable scene path by index.
</description>
</method>
<method name="get_spawnable_scene_count" qualifiers="const">
<return type="int" />
<description>
+ Returns the count of spawnable scene paths.
</description>
</method>
<method name="spawn">
<return type="Node" />
<argument index="0" name="data" type="Variant" default="null" />
<description>
+ Requests a custom spawn, with [code]data[/code] passed to [method _spawn_custom] on all peers. Returns the locally spawned node instance already inside the scene tree, and added as a child of the node pointed by [member spawn_path].
+
+ [b]Note:[/b] Spawnable scenes are spawned automatically. [method spawn] is only needed for custom spawns.
</description>
</method>
</methods>
<members>
<member name="spawn_limit" type="int" setter="set_spawn_limit" getter="get_spawn_limit" default="0">
+ Maximum nodes that is allowed to be spawned by this spawner. Includes both spawnable scenes and custom spawns.
+
+ When set to [code]0[/code] (the default), there is no limit.
</member>
<member name="spawn_path" type="NodePath" setter="set_spawn_path" getter="get_spawn_path" default="NodePath(&quot;&quot;)">
+ Path to the spawn root. Spawnable scenes that are added as direct children are replicated to other peers.
</member>
</members>
<signals>
<signal name="despawned">
- <argument index="0" name="scene_id" type="int" />
- <argument index="1" name="node" type="Node" />
+ <argument index="0" name="node" type="Node" />
<description>
+ Emitted when a spawnable scene or custom spawn was despawned by the multiplayer authority. Only called on puppets.
</description>
</signal>
<signal name="spawned">
- <argument index="0" name="scene_id" type="int" />
- <argument index="1" name="node" type="Node" />
+ <argument index="0" name="node" type="Node" />
<description>
+ Emitted when a spawnable scene or custom spawn was spawned by the multiplayer authority. Only called on puppets.
</description>
</signal>
</signals>
diff --git a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
index ebd1b50201..a2ea64061c 100644
--- a/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
+++ b/modules/multiplayer/doc_classes/MultiplayerSynchronizer.xml
@@ -1,9 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="MultiplayerSynchronizer" inherits="Node" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Synchronizes properties from the multiplayer authority to the remote peers.
</brief_description>
<description>
- The [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way.
+ By default, [MultiplayerSynchronizer] synchronizes configured properties to all peers.
+ Visiblity can be handled directly with [method set_visibility_for] or as-needed with [method add_visibility_filter] and [method update_visibility].
+
+ [MultiplayerSpawner]s will handle nodes according to visibility of synchronizers as long as the node at [member root_path] was spawned by one.
+
+ Internally, [MultiplayerSynchronizer] uses [method MultiplayerAPI.object_configuration_add] to notify synchronization start passing the [Node] at [member root_path] as the [code]object[/code] and itself as the [code]configuration[/code], and uses [method MultiplayerAPI.object_configuration_remove] to notify synchronization end in a similar way.
</description>
<tutorials>
</tutorials>
@@ -12,18 +18,23 @@
<return type="void" />
<argument index="0" name="filter" type="Callable" />
<description>
+ Adds a peer visibility filter for this synchronizer.
+
+ [code]filter[/code] should take a peer id [int] and return a [bool].
</description>
</method>
<method name="get_visibility_for" qualifiers="const">
<return type="bool" />
<argument index="0" name="peer" type="int" />
<description>
+ Queries the current visibility for peer [code]peer[/code].
</description>
</method>
<method name="remove_visibility_filter">
<return type="void" />
<argument index="0" name="filter" type="Callable" />
<description>
+ Removes a peer visiblity filter from this synchronizer.
</description>
</method>
<method name="set_visibility_for">
@@ -31,40 +42,52 @@
<argument index="0" name="peer" type="int" />
<argument index="1" name="visible" type="bool" />
<description>
+ Sets the visibility of [code]peer[/code] to [code]visible[/code]. If [code]peer[/code] is [code]0[/code], the value of [member public_visibility] will be updated instead.
</description>
</method>
<method name="update_visibility">
<return type="void" />
<argument index="0" name="for_peer" type="int" default="0" />
<description>
+ Updates the visibility of [code]peer[/code] according to visibility filters. If [code]peer[/code] is [code]0[/code] (the default), all peers' visibilties are updated.
</description>
</method>
</methods>
<members>
<member name="public_visibility" type="bool" setter="set_visibility_public" getter="is_visibility_public" default="true">
+ Whether synchronization should be visible to all peers by default. See [method set_visibility_for] and [method add_visibility_filter] for ways of configuring fine-grained visibility options.
</member>
<member name="replication_config" type="SceneReplicationConfig" setter="set_replication_config" getter="get_replication_config">
+ Resource containing which properties to synchronize.
</member>
<member name="replication_interval" type="float" setter="set_replication_interval" getter="get_replication_interval" default="0.0">
+ Time interval between synchronizes. When set to [code]0.0[/code] (the default), synchronizes happen every network process frame.
</member>
<member name="root_path" type="NodePath" setter="set_root_path" getter="get_root_path" default="NodePath(&quot;..&quot;)">
+ Node path that replicated properties are relative to.
+ If [member root_path] was spawned by a [MultiplayerSpawner], the node will be also be spawned and despawned based on this synchronizer visibility options.
</member>
<member name="visibility_update_mode" type="int" setter="set_visibility_update_mode" getter="get_visibility_update_mode" enum="MultiplayerSynchronizer.VisibilityUpdateMode" default="0">
+ Specifies when visibility filters are updated (see [enum VisibilityUpdateMode] for options).
</member>
</members>
<signals>
<signal name="visibility_changed">
<argument index="0" name="for_peer" type="int" />
<description>
+ Emitted when visibility of [code]for_peer[/code] is updated. See [method update_visibility].
</description>
</signal>
</signals>
<constants>
<constant name="VISIBILITY_PROCESS_IDLE" value="0" enum="VisibilityUpdateMode">
+ Visibility filters are updated every idle process frame.
</constant>
<constant name="VISIBILITY_PROCESS_PHYSICS" value="1" enum="VisibilityUpdateMode">
+ Visibility filters are updated every physics process frame.
</constant>
<constant name="VISIBILITY_PROCESS_NONE" value="2" enum="VisibilityUpdateMode">
+ Visibility filters are not updated automatically, and must be updated manually by calling [method update_visibility].
</constant>
</constants>
</class>
diff --git a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
index 1d6dec2f92..fc91592c7a 100644
--- a/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
+++ b/modules/multiplayer/doc_classes/SceneReplicationConfig.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SceneReplicationConfig" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
+ Configuration for properties to synchronize with a [MultiplayerSynchronizer].
</brief_description>
<description>
</description>
@@ -12,35 +13,41 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="index" type="int" default="-1" />
<description>
+ Adds the property identified by the given [code]path[/code] to the list of the properties being synchronized, optionally passing an [code]index[/code].
</description>
</method>
<method name="get_properties" qualifiers="const">
<return type="NodePath[]" />
<description>
+ Returns a list of synchronized property [NodePath]s.
</description>
</method>
<method name="has_property" qualifiers="const">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the given [code]path[/code] is configured for synchronization.
</description>
</method>
<method name="property_get_index" qualifiers="const">
<return type="int" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Finds the index of the given [code]path[/code].
</description>
</method>
<method name="property_get_spawn">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn.
</description>
</method>
<method name="property_get_sync">
<return type="bool" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Returns whether the property identified by the given [code]path[/code] is configured to be synchronized on process.
</description>
</method>
<method name="property_set_spawn">
@@ -48,6 +55,7 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="enabled" type="bool" />
<description>
+ Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on spawn.
</description>
</method>
<method name="property_set_sync">
@@ -55,12 +63,14 @@
<argument index="0" name="path" type="NodePath" />
<argument index="1" name="enabled" type="bool" />
<description>
+ Sets whether the property identified by the given [code]path[/code] is configured to be synchronized on process.
</description>
</method>
<method name="remove_property">
<return type="void" />
<argument index="0" name="path" type="NodePath" />
<description>
+ Removes the property identified by the given [code]path[/code] from the configuration.
</description>
</method>
</methods>
diff --git a/modules/multiplayer/multiplayer_spawner.cpp b/modules/multiplayer/multiplayer_spawner.cpp
index f5edffbb0c..e8f3aecc69 100644
--- a/modules/multiplayer/multiplayer_spawner.cpp
+++ b/modules/multiplayer/multiplayer_spawner.cpp
@@ -126,7 +126,7 @@ void MultiplayerSpawner::_set_spawnable_scenes(const Vector<String> &p_scenes) {
void MultiplayerSpawner::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_spawnable_scene", "path"), &MultiplayerSpawner::add_spawnable_scene);
ClassDB::bind_method(D_METHOD("get_spawnable_scene_count"), &MultiplayerSpawner::get_spawnable_scene_count);
- ClassDB::bind_method(D_METHOD("get_spawnable_scene", "path"), &MultiplayerSpawner::get_spawnable_scene);
+ ClassDB::bind_method(D_METHOD("get_spawnable_scene", "index"), &MultiplayerSpawner::get_spawnable_scene);
ClassDB::bind_method(D_METHOD("clear_spawnable_scenes"), &MultiplayerSpawner::clear_spawnable_scenes);
ClassDB::bind_method(D_METHOD("_get_spawnable_scenes"), &MultiplayerSpawner::_get_spawnable_scenes);
@@ -146,8 +146,8 @@ void MultiplayerSpawner::_bind_methods() {
GDVIRTUAL_BIND(_spawn_custom, "data");
- ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("despawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("spawned", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
}
void MultiplayerSpawner::_update_spawn_node() {
@@ -277,12 +277,11 @@ Node *MultiplayerSpawner::instantiate_scene(int p_id) {
Node *MultiplayerSpawner::instantiate_custom(const Variant &p_data) {
ERR_FAIL_COND_V_MSG(spawn_limit && spawn_limit <= tracked_nodes.size(), nullptr, "Spawn limit reached!");
- Object *obj = nullptr;
Node *node = nullptr;
- if (GDVIRTUAL_CALL(_spawn_custom, p_data, obj)) {
- node = Object::cast_to<Node>(obj);
+ if (GDVIRTUAL_CALL(_spawn_custom, p_data, node)) {
+ return node;
}
- return node;
+ ERR_FAIL_V_MSG(nullptr, "Method '_spawn_custom' is not implemented on this peer.");
}
Node *MultiplayerSpawner::spawn(const Variant &p_data) {
diff --git a/modules/multiplayer/multiplayer_spawner.h b/modules/multiplayer/multiplayer_spawner.h
index 80bb878a74..fc3befc2d4 100644
--- a/modules/multiplayer/multiplayer_spawner.h
+++ b/modules/multiplayer/multiplayer_spawner.h
@@ -91,7 +91,9 @@ protected:
void _get_property_list(List<PropertyInfo> *p_list) const;
#endif
public:
- Node *get_spawn_node() const { return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr; }
+ Node *get_spawn_node() const {
+ return spawn_node.is_valid() ? Object::cast_to<Node>(ObjectDB::get_instance(spawn_node)) : nullptr;
+ }
void add_spawnable_scene(const String &p_path);
int get_spawnable_scene_count() const;
@@ -110,7 +112,7 @@ public:
Node *instantiate_custom(const Variant &p_data);
Node *instantiate_scene(int p_idx);
- GDVIRTUAL1R(Object *, _spawn_custom, const Variant &);
+ GDVIRTUAL1R(Node *, _spawn_custom, const Variant &);
MultiplayerSpawner() {}
};
diff --git a/modules/multiplayer/scene_replication_interface.cpp b/modules/multiplayer/scene_replication_interface.cpp
index c89270fbe8..6e3dbfab47 100644
--- a/modules/multiplayer/scene_replication_interface.cpp
+++ b/modules/multiplayer/scene_replication_interface.cpp
@@ -396,6 +396,8 @@ Error SceneReplicationInterface::on_spawn_receive(int p_from, const uint8_t *p_b
pending_buffer_size = state_len;
}
parent->add_child(node);
+ spawner->emit_signal(SNAME("spawned"), node);
+
pending_spawn = ObjectID();
pending_buffer = nullptr;
pending_buffer_size = 0;
@@ -411,10 +413,17 @@ Error SceneReplicationInterface::on_despawn_receive(int p_from, const uint8_t *p
Error err = rep_state->peer_del_remote(p_from, net_id, &node);
ERR_FAIL_COND_V(err != OK, err);
ERR_FAIL_COND_V(!node, ERR_BUG);
+
+ MultiplayerSpawner *spawner = rep_state->get_spawner(node->get_instance_id());
+ ERR_FAIL_COND_V(!spawner, ERR_DOES_NOT_EXIST);
+ ERR_FAIL_COND_V(p_from != spawner->get_multiplayer_authority(), ERR_UNAUTHORIZED);
+
if (node->get_parent() != nullptr) {
node->get_parent()->remove_child(node);
}
node->queue_delete();
+ spawner->emit_signal(SNAME("despawned"), node);
+
return OK;
}
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 2d764a4006..d212fe62b4 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -117,11 +117,11 @@ if env["builtin_harfbuzz"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_harfbuzz.Append(CPPPATH=["#thirdparty/harfbuzz/src"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"])
if env["builtin_icu"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"])
if freetype_enabled:
@@ -132,9 +132,9 @@ if env["builtin_harfbuzz"]:
]
)
if env["builtin_freetype"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/freetype/include"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/freetype/include"])
if env["builtin_graphite"]:
- env_harfbuzz.Append(CPPPATH=["#thirdparty/graphite/include"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"])
if env["platform"] == "android" or env["platform"] == "linuxbsd":
@@ -146,7 +146,7 @@ if env["builtin_harfbuzz"]:
else:
env_harfbuzz.Append(CCFLAGS=["-DHB_NO_MT"])
- env_text_server_adv.Append(CPPPATH=["#thirdparty/harfbuzz/src"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
lib = env_harfbuzz.add_library("harfbuzz_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -209,7 +209,7 @@ if env["builtin_graphite"] and freetype_enabled:
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- env_graphite.Append(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"])
+ env_graphite.Prepend(CPPPATH=["#thirdparty/graphite/src", "#thirdparty/graphite/include"])
env_graphite.Append(
CCFLAGS=[
"-DGRAPHITE2_STATIC",
@@ -447,11 +447,11 @@ if env["builtin_icu"]:
if env_icu["tools"]:
env_icu.Depends("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name)
env_icu.Command("#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/" + icu_data_name, make_icu_data)
- env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/"])
else:
thirdparty_sources += ["icu_data/icudata_stub.cpp"]
- env_icu.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
env_icu.Append(
CXXFLAGS=[
"-DU_STATIC_IMPLEMENTATION",
@@ -480,7 +480,7 @@ if env["builtin_icu"]:
if env_text_server_adv["tools"]:
env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"])
- env_text_server_adv.Append(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
lib = env_icu.add_library("icu_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -504,13 +504,13 @@ if env["builtin_icu"]:
module_obj = []
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/msdfgen"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/freetype/include"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/freetype/include"])
if env["builtin_graphite"] and freetype_enabled:
- env_text_server_adv.Append(CPPPATH=["#thirdparty/graphite/include"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_text_server_adv.add_source_files(module_obj, "*.cpp")
env.modules_sources += module_obj
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index fa234081f0..64788bfeff 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1359,7 +1359,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
fd->underline_position = (-FT_MulFix(fd->face->underline_position, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale;
fd->underline_thickness = (FT_MulFix(fd->face->underline_thickness, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale;
+#if HB_VERSION_ATLEAST(3, 3, 0)
hb_font_set_synthetic_slant(fd->hb_handle, p_font_data->transform[0][1]);
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 3.3.0, synthetic slant offset correction disabled.
+#endif
+#endif
if (!p_font_data->face_init) {
// Get style flags and name.
@@ -1626,6 +1632,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
for (unsigned int i = 0; i < count; i++) {
Dictionary ftr;
+#if HB_VERSION_ATLEAST(2, 1, 0)
hb_ot_name_id_t lbl_id;
if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GSUB, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) {
PackedInt32Array lbl;
@@ -1635,6 +1642,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw());
ftr["label"] = String((const char32_t *)lbl.ptr());
}
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled.
+#endif
+#endif
ftr["type"] = _get_tag_type(feature_tags[i]);
ftr["hidden"] = _get_tag_hidden(feature_tags[i]);
@@ -1649,6 +1661,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
for (unsigned int i = 0; i < count; i++) {
Dictionary ftr;
+#if HB_VERSION_ATLEAST(2, 1, 0)
hb_ot_name_id_t lbl_id;
if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GPOS, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) {
PackedInt32Array lbl;
@@ -1658,6 +1671,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw());
ftr["label"] = String((const char32_t *)lbl.ptr());
}
+#else
+#ifndef _MSC_VER
+#warning Building with HarfBuzz < 2.1.0, readable OpenType feature names disabled.
+#endif
+#endif
ftr["type"] = _get_tag_type(feature_tags[i]);
ftr["hidden"] = _get_tag_hidden(feature_tags[i]);
diff --git a/modules/text_server_fb/SCsub b/modules/text_server_fb/SCsub
index 121f38fcd5..ca9322e450 100644
--- a/modules/text_server_fb/SCsub
+++ b/modules/text_server_fb/SCsub
@@ -9,9 +9,9 @@ msdfgen_enabled = env.module_check_dependencies("text_server_fb", ["msdfgen"], T
env_text_server_fb = env_modules.Clone()
if env["builtin_msdfgen"] and msdfgen_enabled:
- env_text_server_fb.Append(CPPPATH=["#thirdparty/msdfgen"])
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
if env["builtin_freetype"] and freetype_enabled:
- env_text_server_fb.Append(CPPPATH=["#thirdparty/freetype/include"])
+ env_text_server_fb.Prepend(CPPPATH=["#thirdparty/freetype/include"])
env_text_server_fb.add_source_files(env.modules_sources, "*.cpp")