Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
绑定到外部库
模块
在 自定义 C++ 模块 中提到的 Summator(求和器)示例非常适合用来制作小型的自定义模块,但如果你想使用一个更大、更复杂的外部库该怎么办呢?接下来,让我们通过一个例子来看看吧——使用的是 Festival,这是一个用 C++ 编写的语音合成(文字转语音)库。
要绑定到外部库, 请设置类似于Summator示例的模块目录:
godot/modules/tts/
接下来,创建 TTS 类的头文件:
#pragma once
#include "core/object/ref_counted.h"
class TTS : public RefCounted {
GDCLASS(TTS, RefCounted);
protected:
static void _bind_methods();
public:
bool say_text(String p_txt);
TTS();
};
然后添加 cpp 文件。
#include "tts.h"
#include <festival.h>
bool TTS::say_text(String p_txt) {
//convert Godot String to Godot CharString to C string
return festival_say_text(p_txt.ascii().get_data());
}
void TTS::_bind_methods() {
ClassDB::bind_method(D_METHOD("say_text", "txt"), &TTS::say_text);
}
TTS::TTS() {
festival_initialize(true, 210000); //not the best way to do it as this should only ever be called once.
}
和以前一样, 需要以某种方式注册新类, 因此还需要创建两个文件:
register_types.h
register_types.cpp
重要
这些文件必须在模块的顶层文件夹中(SCsub 和 config.py 文件旁边),这样才能正确注册模块。
这些文件应包含以下内容:
void initialize_tts_module(ModuleInitializationLevel p_level);
void uninitialize_tts_module(ModuleInitializationLevel p_level);
/* yes, the word in the middle must be the same as the module folder name */
#include "register_types.h"
#include "core/object/class_db.h"
#include "tts.h"
void initialize_tts_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ClassDB::register_class<TTS>();
}
void uninitialize_tts_module(ModuleInitializationLevel p_level) {
// Nothing to do here in this example.
}
接下来需要创建一个 SCsub 文件,让构建系统编译该模块:
Import('env')
env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp") # Add all cpp files to the build
你需要在你的机器上安装这个外部库,以获取 .a 库文件。关于如何针对你的操作系统进行安装,请查阅该库的官方文档以获取具体的操作说明。为了方便参考,我们在下方提供了 Linux 系统的安装命令。
sudo apt-get install festival festival-dev # Installs festival and speech_tools libraries
apt-cache search festvox-* # Displays list of voice packages
sudo apt-get install festvox-don festvox-rablpc16k festvox-kallpc16k festvox-kdlpc16k # Installs voices
重要
Festival使用的声音(以及任何其他潜在的外部/第三方资源)都有不同的许可证和使用条款;其中一些(如果不是大多数)可能会对Godot产生问题, 即使Festival库本身是与MIT许可证兼容. 请务必检查许可证和使用条款.
外部库也需要被安装到你的模块之中,这样编译器就可以访问到源代码,保持模块独立于外界环境。可以使用如下的 git 命令从 modules/tts/ 目录安装 festival 和 speech_tools:
git clone https://github.com/festvox/festival
git clone https://github.com/festvox/speech_tools
如果不希望将外部仓库的源文件提交到你的仓库中,你可以通过将它们添加为子模块(从 modules/tts/ 目录中)来链接它们,如下所示:
git submodule add https://github.com/festvox/festival
git submodule add https://github.com/festvox/speech_tools
重要
请注意,Godot 的官方仓库中并不使用 Git 子模块(submodules)。如果你正在开发一个打算合并进 Godot 主仓库的模块,那么你不应该使用子模块。如果你的模块最终没能被合并进去,你随时可以尝试将这个外部库封装成一个 GDExtension 来使用。
要添加供编译器查看的包含目录,可以将其追加到环境的路径中:
# These paths are relative to /modules/tts/
env_tts.Append(CPPPATH=["speech_tools/include", "festival/src/include"])
# LIBPATH and LIBS need to be set on the real "env" (not the clone)
# to link the specified libraries to the Godot executable.
# This is an absolute path where your .a libraries reside.
# If using a relative path, you must convert it to a
# full path using a utility function, such as `Dir('...').abspath`.
env.Append(LIBPATH=[Dir('libpath').abspath])
# Check with the documentation of the external library to see which library
# files should be included/linked.
env.Append(LIBS=['Festival', 'estools', 'estbase', 'eststring'])
如果要在构建模块时添加自定义编译器标志, 则需要首先克隆 env, 这样它就不会将这些标志添加到整个Godot构建中(这可能会导致错误). 带有自定义标志的示例 SCsub:
Import('env')
env_tts = env.Clone()
env_tts.add_source_files(env.modules_sources, "*.cpp")
# Append CCFLAGS flags for both C and C++ code.
env_tts.Append(CCFLAGS=['-O2'])
# If you need to, you can:
# - Append CFLAGS for C code only.
# - Append CXXFLAGS for C++ code only.
最终模块应如下所示:
godot/modules/tts/festival/
godot/modules/tts/libpath/libestbase.a
godot/modules/tts/libpath/libestools.a
godot/modules/tts/libpath/libeststring.a
godot/modules/tts/libpath/libFestival.a
godot/modules/tts/speech_tools/
godot/modules/tts/config.py
godot/modules/tts/tts.h
godot/modules/tts/tts.cpp
godot/modules/tts/register_types.h
godot/modules/tts/register_types.cpp
godot/modules/tts/SCsub
使用模块
现在, 你可以通过任何脚本使用新创建的模块:
var t = TTS.new()
var script = "Hello world. This is a test!"
var is_spoken = t.say_text(script)
print('is_spoken: ', is_spoken)
如果说出文本, 输出将是 is_spoken:True .