Merge pull request #66026 from aaronfranke/gltf-extension

Change the way GLTFDocumentExtension classes are registered
This commit is contained in:
Rémi Verschelde 2022-11-20 11:44:05 +01:00
commit d5d83eefd3
No known key found for this signature in database
GPG key ID: C3336907360768E1
11 changed files with 69 additions and 69 deletions

View file

@ -50,6 +50,15 @@
<description>
</description>
</method>
<method name="register_gltf_document_extension" qualifiers="static">
<return type="void" />
<param index="0" name="extension" type="GLTFDocumentExtension" />
<param index="1" name="first_priority" type="bool" default="false" />
<description>
Registers this GLTFDocumentExtension instance with GLTFDocument. If [param first_priority] is true, this extension will be ran first. Otherwise, it will be ran last.
[b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
</description>
</method>
<method name="write_to_filesystem">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
@ -58,8 +67,4 @@
</description>
</method>
</methods>
<members>
<member name="extensions" type="GLTFDocumentExtension[]" setter="set_extensions" getter="get_extensions" default="[]">
</member>
</members>
</class>

View file

@ -5,6 +5,8 @@
</brief_description>
<description>
Extends the functionality of the [GLTFDocument] class by allowing you to run arbitrary code at various stages of GLTF import or export.
To use, make a new class extending GLTFDocumentExtension, override any methods you need, make an instance of your class, and register it using [method GLTFDocument.register_gltf_document_extension].
[b]Note:[/b] Like GLTFDocument itself, all GLTFDocumentExtension classes must be stateless in order to function properly. If you need to store data, use the [code]set_additional_data[/code] and [code]get_additional_data[/code] methods in [GLTFState] or [GLTFNode].
</description>
<tutorials>
</tutorials>
@ -61,7 +63,9 @@
<method name="_import_preflight" qualifiers="virtual">
<return type="int" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="extensions" type="PackedStringArray" />
<description>
This callback is run first. It is used to determine if this GLTFDocumentExtension class should be used for importing a given GLTF file. If [constant OK], the import will use this GLTFDocumentExtension class.
</description>
</method>
</methods>

View file

@ -33,9 +33,6 @@
#ifdef TOOLS_ENABLED
#include "../gltf_document_extension.h"
#include "../gltf_state.h"
#include "editor/import/resource_importer_scene.h"
class Animation;

View file

@ -32,7 +32,7 @@
void GLTFDocumentExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_supported_extensions);
GDVIRTUAL_BIND(_import_preflight, "state");
GDVIRTUAL_BIND(_import_preflight, "state", "extensions");
GDVIRTUAL_BIND(_import_post_parse, "state");
GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_import_post, "state", "root");
@ -55,10 +55,10 @@ Error GLTFDocumentExtension::import_post(Ref<GLTFState> p_state, Node *p_root) {
return Error(err);
}
Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state) {
Error GLTFDocumentExtension::import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions) {
ERR_FAIL_NULL_V(p_state, ERR_INVALID_PARAMETER);
int err = OK;
GDVIRTUAL_CALL(_import_preflight, p_state, err);
GDVIRTUAL_CALL(_import_preflight, p_state, p_extensions, err);
return Error(err);
}

View file

@ -31,8 +31,7 @@
#ifndef GLTF_DOCUMENT_EXTENSION_H
#define GLTF_DOCUMENT_EXTENSION_H
#include "gltf_state.h"
#include "structures/gltf_node.h"
#include "../gltf_state.h"
class GLTFDocumentExtension : public Resource {
GDCLASS(GLTFDocumentExtension, Resource);
@ -42,7 +41,7 @@ protected:
public:
virtual Vector<String> get_supported_extensions();
virtual Error import_preflight(Ref<GLTFState> p_state);
virtual Error import_preflight(Ref<GLTFState> p_state, Vector<String> p_extensions);
virtual Error import_post_parse(Ref<GLTFState> p_state);
virtual Error export_post(Ref<GLTFState> p_state);
virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
@ -50,7 +49,7 @@ public:
virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
virtual Error export_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
GDVIRTUAL0R(Vector<String>, _get_supported_extensions);
GDVIRTUAL1R(int, _import_preflight, Ref<GLTFState>);
GDVIRTUAL2R(int, _import_preflight, Ref<GLTFState>, Vector<String>);
GDVIRTUAL1R(int, _import_post_parse, Ref<GLTFState>);
GDVIRTUAL4R(int, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL2R(int, _import_post, Ref<GLTFState>, Node *);

View file

@ -30,7 +30,7 @@
#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_state.h"
#include "../gltf_state.h"
#include "core/error/error_macros.h"
#include "scene/3d/mesh_instance_3d.h"

View file

@ -31,8 +31,6 @@
#include "gltf_document.h"
#include "extensions/gltf_spec_gloss.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_state.h"
#include "core/crypto/crypto_core.h"
@ -215,8 +213,7 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) {
return Error::FAILED;
}
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->export_post(state);
ERR_FAIL_COND_V(err != OK, err);
@ -454,8 +451,7 @@ Error GLTFDocument::_serialize_nodes(Ref<GLTFState> state) {
node["children"] = children;
}
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
ERR_CONTINUE(!state->scene_nodes.find(i));
Error err = ext->export_node(state, gltf_node, node, state->scene_nodes[i]);
@ -6586,11 +6582,13 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess>
state->major_version = version.get_slice(".", 0).to_int();
state->minor_version = version.get_slice(".", 1).to_int();
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
document_extensions.clear();
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_preflight(state);
ERR_FAIL_COND_V(err != OK, err);
err = ext->import_preflight(state, state->json["extensionsUsed"]);
if (err == OK) {
document_extensions.push_back(ext);
}
}
err = _parse_gltf_state(state, p_path, p_bake_fps);
@ -6728,14 +6726,8 @@ void GLTFDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("write_to_filesystem", "state", "path"),
&GLTFDocument::write_to_filesystem);
ClassDB::bind_method(D_METHOD("set_extensions", "extensions"),
&GLTFDocument::set_extensions);
ClassDB::bind_method(D_METHOD("get_extensions"),
&GLTFDocument::get_extensions);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "extensions", PROPERTY_HINT_ARRAY_TYPE,
vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "GLTFDocumentExtension"),
PROPERTY_USAGE_DEFAULT),
"set_extensions", "get_extensions");
ClassDB::bind_static_method("GLTFDocument", D_METHOD("register_gltf_document_extension", "extension", "first_priority"),
&GLTFDocument::register_gltf_document_extension, DEFVAL(false));
}
void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
@ -6752,22 +6744,20 @@ void GLTFDocument::_build_parent_hierachy(Ref<GLTFState> state) {
}
}
void GLTFDocument::set_extensions(TypedArray<GLTFDocumentExtension> p_extensions) {
document_extensions = p_extensions;
}
Vector<Ref<GLTFDocumentExtension>> GLTFDocument::all_document_extensions;
TypedArray<GLTFDocumentExtension> GLTFDocument::get_extensions() const {
return document_extensions;
}
GLTFDocument::GLTFDocument() {
bool is_editor = ::Engine::get_singleton()->is_editor_hint();
if (is_editor) {
return;
void GLTFDocument::register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority) {
if (all_document_extensions.find(p_extension) == -1) {
if (p_first_priority) {
all_document_extensions.insert(0, p_extension);
} else {
all_document_extensions.push_back(p_extension);
}
}
Ref<GLTFDocumentExtensionConvertImporterMesh> extension_editor;
extension_editor.instantiate();
document_extensions.push_back(extension_editor);
}
void GLTFDocument::unregister_all_gltf_document_extensions() {
all_document_extensions.clear();
}
PackedByteArray GLTFDocument::_serialize_glb_buffer(Ref<GLTFState> state, Error *r_err) {
@ -6852,8 +6842,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
}
for (KeyValue<GLTFNodeIndex, Node *> E : state->scene_nodes) {
ERR_CONTINUE(!E.value);
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
ERR_CONTINUE(!state->json.has("nodes"));
Array nodes = state->json["nodes"];
@ -6865,8 +6854,7 @@ Node *GLTFDocument::generate_scene(Ref<GLTFState> state, int32_t p_bake_fps) {
ERR_CONTINUE(err != OK);
}
}
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post(state, root);
ERR_CONTINUE(err != OK);
@ -6880,11 +6868,13 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32
state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS;
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
document_extensions.clear();
for (Ref<GLTFDocumentExtension> ext : all_document_extensions) {
ERR_CONTINUE(ext.is_null());
Error err = ext->export_preflight(p_node);
ERR_FAIL_COND_V(err != OK, FAILED);
if (err == OK) {
document_extensions.push_back(ext);
}
}
_convert_scene_node(state, p_node, -1, -1);
if (!state->buffers.size()) {
@ -6906,8 +6896,7 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa
state->base_path = p_base_path.get_base_dir();
err = _parse(state, state->base_path, file_access, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post_parse(state);
ERR_FAIL_COND_V(err != OK, err);
@ -7030,8 +7019,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
r_state->base_path = base_path;
err = _parse(r_state, base_path, f, p_bake_fps);
ERR_FAIL_COND_V(err != OK, err);
for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_post_parse(r_state);
ERR_FAIL_COND_V(err != OK, err);
@ -7053,8 +7041,7 @@ Error GLTFDocument::_parse_gltf_extensions(Ref<GLTFState> state) {
supported_extensions.insert("KHR_lights_punctual");
supported_extensions.insert("KHR_materials_pbrSpecularGlossiness");
supported_extensions.insert("KHR_texture_transform");
for (int ext_i = 0; ext_i < document_extensions.size(); ext_i++) {
Ref<GLTFDocumentExtension> ext = document_extensions[ext_i];
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
Vector<String> ext_supported_extensions = ext->get_supported_extensions();
for (int i = 0; i < ext_supported_extensions.size(); ++i) {

View file

@ -31,7 +31,7 @@
#ifndef GLTF_DOCUMENT_H
#define GLTF_DOCUMENT_H
#include "gltf_defines.h"
#include "extensions/gltf_document_extension.h"
#include "structures/gltf_animation.h"
#include "scene/3d/bone_attachment_3d.h"
@ -44,13 +44,13 @@
class GLTFDocument : public Resource {
GDCLASS(GLTFDocument, Resource);
TypedArray<GLTFDocumentExtension> document_extensions;
static Vector<Ref<GLTFDocumentExtension>> all_document_extensions;
Vector<Ref<GLTFDocumentExtension>> document_extensions;
private:
const float BAKE_FPS = 30.0f;
public:
GLTFDocument();
const int32_t JOINT_GROUP_SIZE = 4;
enum {
@ -76,8 +76,8 @@ protected:
static void _bind_methods();
public:
void set_extensions(TypedArray<GLTFDocumentExtension> p_extensions);
TypedArray<GLTFDocumentExtension> get_extensions() const;
static void register_gltf_document_extension(Ref<GLTFDocumentExtension> p_extension, bool p_first_priority = false);
static void unregister_all_gltf_document_extensions();
private:
void _build_parent_hierachy(Ref<GLTFState> state);

View file

@ -32,11 +32,10 @@
#ifndef _3D_DISABLED
#include "extensions/gltf_document_extension_convert_importer_mesh.h"
#include "extensions/gltf_light.h"
#include "extensions/gltf_spec_gloss.h"
#include "gltf_document.h"
#include "gltf_document_extension.h"
#include "gltf_document_extension_convert_importer_mesh.h"
#include "gltf_state.h"
#include "structures/gltf_accessor.h"
#include "structures/gltf_animation.h"
@ -109,6 +108,11 @@ static void _editor_init() {
}
#endif // TOOLS_ENABLED
#define GLTF_REGISTER_DOCUMENT_EXTENSION(m_doc_ext_class) \
Ref<m_doc_ext_class> extension_##m_doc_ext_class; \
extension_##m_doc_ext_class.instantiate(); \
GLTFDocument::register_gltf_document_extension(extension_##m_doc_ext_class);
void initialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
// glTF API available at runtime.
@ -128,6 +132,11 @@ void initialize_gltf_module(ModuleInitializationLevel p_level) {
GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFTexture);
GDREGISTER_CLASS(GLTFTextureSampler);
// Register GLTFDocumentExtension classes with GLTFDocument.
bool is_editor = ::Engine::get_singleton()->is_editor_hint();
if (!is_editor) {
GLTF_REGISTER_DOCUMENT_EXTENSION(GLTFDocumentExtensionConvertImporterMesh);
}
}
#ifdef TOOLS_ENABLED
@ -161,6 +170,7 @@ void uninitialize_gltf_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
GLTFDocument::unregister_all_gltf_document_extensions();
}
#endif // _3D_DISABLED

View file

@ -30,8 +30,6 @@
#include "gltf_buffer_view.h"
#include "../gltf_document_extension.h"
void GLTFBufferView::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer);
ClassDB::bind_method(D_METHOD("set_buffer", "buffer"), &GLTFBufferView::set_buffer);