Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GLTF: Add import_pre_generate and export_post_convert extension steps #96465

Merged
merged 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions modules/gltf/doc_classes/GLTFDocumentExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<param index="1" name="gltf_node" type="GLTFNode" />
<param index="2" name="scene_node" type="Node" />
<description>
Part of the export process. This method is run after [method _export_preflight] and before [method _export_preserialize].
Part of the export process. This method is run after [method _export_preflight] and before [method _export_post_convert].
Runs when converting the data from a Godot scene node. This method can be used to process the Godot scene node data into a format that can be used by [method _export_node].
</description>
</method>
Expand All @@ -41,6 +41,15 @@
This method can be used to modify the final JSON of the generated glTF file.
</description>
</method>
<method name="_export_post_convert" qualifiers="virtual">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
<param index="1" name="root" type="Node" />
<description>
Part of the export process. This method is run after [method _convert_scene_node] and before [method _export_preserialize].
This method can be used to modify the converted node data structures before serialization with any additional data from the scene tree.
</description>
</method>
<method name="_export_preflight" qualifiers="virtual">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
Expand All @@ -54,7 +63,7 @@
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
<description>
Part of the export process. This method is run after [method _convert_scene_node] and before [method _get_saveable_image_formats].
Part of the export process. This method is run after [method _export_post_convert] and before [method _get_saveable_image_formats].
This method can be used to alter the state before performing serialization. It runs every time when generating a buffer with [method GLTFDocument.generate_buffer] or writing to the file system with [method GLTFDocument.write_to_filesystem].
</description>
</method>
Expand All @@ -64,7 +73,7 @@
<param index="1" name="gltf_node" type="GLTFNode" />
<param index="2" name="scene_parent" type="Node" />
<description>
Part of the import process. This method is run after [method _import_post_parse] and before [method _import_node].
Part of the import process. This method is run after [method _import_pre_generate] and before [method _import_node].
Runs when generating a Godot scene node from a GLTFNode. The returned node will be added to the scene tree. Multiple nodes can be generated in this step if they are added as a child of the returned node.
[b]Note:[/b] The [param scene_parent] parameter may be null if this is the single root node.
</description>
Expand Down Expand Up @@ -113,8 +122,16 @@
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
<description>
Part of the import process. This method is run after [method _parse_node_extensions] and before [method _generate_scene_node].
This method can be used to modify any of the data imported so far after parsing, before generating the nodes and then running the final per-node import step.
Part of the import process. This method is run after [method _parse_node_extensions] and before [method _import_pre_generate].
This method can be used to modify any of the data imported so far after parsing each node, but before generating the scene or any of its nodes.
</description>
</method>
<method name="_import_pre_generate" qualifiers="virtual">
<return type="int" enum="Error" />
<param index="0" name="state" type="GLTFState" />
<description>
Part of the import process. This method is run after [method _import_post_parse] and before [method _generate_scene_node].
This method can be used to modify or read from any of the processed data structures, before generating the nodes and then running the final per-node import step.
</description>
</method>
<method name="_import_preflight" qualifiers="virtual">
Expand Down
33 changes: 25 additions & 8 deletions modules/gltf/extensions/gltf_document_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ void GLTFDocumentExtension::_bind_methods() {
GDVIRTUAL_BIND(_parse_image_data, "state", "image_data", "mime_type", "ret_image");
GDVIRTUAL_BIND(_get_image_file_extension);
GDVIRTUAL_BIND(_parse_texture_json, "state", "texture_json", "ret_gltf_texture");
GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent");
GDVIRTUAL_BIND(_import_post_parse, "state");
GDVIRTUAL_BIND(_import_pre_generate, "state");
GDVIRTUAL_BIND(_generate_scene_node, "state", "gltf_node", "scene_parent");
GDVIRTUAL_BIND(_import_node, "state", "gltf_node", "json", "node");
GDVIRTUAL_BIND(_import_post, "state", "root");
// Export process.
GDVIRTUAL_BIND(_export_preflight, "state", "root");
GDVIRTUAL_BIND(_convert_scene_node, "state", "gltf_node", "scene_node");
GDVIRTUAL_BIND(_export_post_convert, "state", "root");
GDVIRTUAL_BIND(_export_preserialize, "state");
GDVIRTUAL_BIND(_get_saveable_image_formats);
GDVIRTUAL_BIND(_serialize_image_to_bytes, "state", "image", "image_dict", "image_format", "lossy_quality");
Expand Down Expand Up @@ -98,6 +100,20 @@ Error GLTFDocumentExtension::parse_texture_json(Ref<GLTFState> p_state, const Di
return err;
}

Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
Error err = OK;
GDVIRTUAL_CALL(_import_post_parse, p_state, err);
return err;
}

Error GLTFDocumentExtension::import_pre_generate(Ref<GLTFState> p_state) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
Error err = OK;
GDVIRTUAL_CALL(_import_pre_generate, p_state, err);
return err;
}

Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent) {
ERR_FAIL_COND_V(p_state.is_null(), nullptr);
ERR_FAIL_COND_V(p_gltf_node.is_null(), nullptr);
Expand All @@ -106,13 +122,6 @@ Node3D *GLTFDocumentExtension::generate_scene_node(Ref<GLTFState> p_state, Ref<G
return ret_node;
}

Error GLTFDocumentExtension::import_post_parse(Ref<GLTFState> p_state) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
Error err = OK;
GDVIRTUAL_CALL(_import_post_parse, p_state, err);
return err;
}

Error GLTFDocumentExtension::import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_dict, Node *p_node) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_gltf_node.is_null(), ERR_INVALID_PARAMETER);
Expand Down Expand Up @@ -145,6 +154,14 @@ void GLTFDocumentExtension::convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFN
GDVIRTUAL_CALL(_convert_scene_node, p_state, p_gltf_node, p_scene_node);
}

Error GLTFDocumentExtension::export_post_convert(Ref<GLTFState> p_state, Node *p_root) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(p_root, ERR_INVALID_PARAMETER);
Error err = OK;
GDVIRTUAL_CALL(_export_post_convert, p_state, p_root, err);
return err;
}

Error GLTFDocumentExtension::export_preserialize(Ref<GLTFState> p_state) {
ERR_FAIL_COND_V(p_state.is_null(), ERR_INVALID_PARAMETER);
Error err = OK;
Expand Down
6 changes: 5 additions & 1 deletion modules/gltf/extensions/gltf_document_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ class GLTFDocumentExtension : public Resource {
virtual String get_image_file_extension();
virtual Error parse_texture_json(Ref<GLTFState> p_state, const Dictionary &p_texture_json, Ref<GLTFTexture> r_gltf_texture);
virtual Error import_post_parse(Ref<GLTFState> p_state);
virtual Error import_pre_generate(Ref<GLTFState> p_state);
virtual Node3D *generate_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_parent);
virtual Error import_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Dictionary &r_json, Node *p_node);
virtual Error import_post(Ref<GLTFState> p_state, Node *p_node);
// Export process.
virtual Error export_preflight(Ref<GLTFState> p_state, Node *p_root);
virtual void convert_scene_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node, Node *p_scene_node);
virtual Error export_post_convert(Ref<GLTFState> p_state, Node *p_root);
virtual Error export_preserialize(Ref<GLTFState> p_state);
virtual Vector<String> get_saveable_image_formats();
virtual PackedByteArray serialize_image_to_bytes(Ref<GLTFState> p_state, Ref<Image> p_image, Dictionary p_image_dict, const String &p_image_format, float p_lossy_quality);
Expand All @@ -71,13 +73,15 @@ class GLTFDocumentExtension : public Resource {
GDVIRTUAL4R(Error, _parse_image_data, Ref<GLTFState>, PackedByteArray, String, Ref<Image>);
GDVIRTUAL0R(String, _get_image_file_extension);
GDVIRTUAL3R(Error, _parse_texture_json, Ref<GLTFState>, Dictionary, Ref<GLTFTexture>);
GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL1R(Error, _import_post_parse, Ref<GLTFState>);
GDVIRTUAL1R(Error, _import_pre_generate, Ref<GLTFState>);
GDVIRTUAL3R(Node3D *, _generate_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL4R(Error, _import_node, Ref<GLTFState>, Ref<GLTFNode>, Dictionary, Node *);
GDVIRTUAL2R(Error, _import_post, Ref<GLTFState>, Node *);
// Export process.
GDVIRTUAL2R(Error, _export_preflight, Ref<GLTFState>, Node *);
GDVIRTUAL3(_convert_scene_node, Ref<GLTFState>, Ref<GLTFNode>, Node *);
GDVIRTUAL2R(Error, _export_post_convert, Ref<GLTFState>, Node *);
GDVIRTUAL1R(Error, _export_preserialize, Ref<GLTFState>);
GDVIRTUAL0R(Vector<String>, _get_saveable_image_formats);
GDVIRTUAL5R(PackedByteArray, _serialize_image_to_bytes, Ref<GLTFState>, Ref<Image>, Dictionary, String, float);
Expand Down
12 changes: 12 additions & 0 deletions modules/gltf/gltf_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7205,6 +7205,12 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "glTF: Failed to create skeletons.");
err = _create_skins(p_state);
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "glTF: Failed to create skins.");
// Run pre-generate for each extension, in case an extension needs to do something before generating the scene.
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
err = ext->import_pre_generate(p_state);
ERR_CONTINUE(err != OK);
}
// Generate the node tree.
Node *single_root;
if (p_state->extensions_used.has("GODOT_single_root")) {
Expand Down Expand Up @@ -7439,6 +7445,12 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> p_state, uint
state->extensions_used.append("GODOT_single_root");
}
_convert_scene_node(state, p_node, -1, -1);
// Run post-convert for each extension, in case an extension needs to do something after converting the scene.
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
ERR_CONTINUE(ext.is_null());
Error err = ext->export_post_convert(p_state, p_node);
ERR_CONTINUE(err != OK);
}
return OK;
}

Expand Down
Loading