Skip to content

glTF import: use literal node names instead of filename-prefixed variant names - #3

Open
NilssonCreative with Copilot wants to merge 7 commits into
masterfrom
copilot/improve-gltf-loader-importer-support
Open

glTF import: use literal node names instead of filename-prefixed variant names#3
NilssonCreative with Copilot wants to merge 7 commits into
masterfrom
copilot/improve-gltf-loader-importer-support

Conversation

Copilot AI commented Apr 29, 2026

Copy link
Copy Markdown

Imported glTF content items were named {filename}-{nodeName} (e.g. car-WheelHub_FL), cluttering the Content Browser and making it harder to reference assets by their Blender-authored names.

Changes

  • content_database_mesh.go: Remove baseName prefix from ImportVariant.Name for both mesh nodes and empty nodes — variants now use the literal name from the glTF (e.g. WheelHub_FL instead of car-WheelHub_FL). The template file itself retains the filename as its name.
// Before
v := ImportVariant{
    Name: fmt.Sprintf("%s-%s", baseName, parts[len(parts)-1]),
    ...
}

// After
v := ImportVariant{
    Name: parts[len(parts)-1],
    ...
}

The same change applies to the empty-node loop. nodeVariants and variantToContentId mappings in the scene template builder are unaffected since they key off the variant name consistently.

The orange plain-axes gizmo for Empties (SpawnEmptyGizmo) was already wired up in both stage_spawner.go (drag-from-browser) and editor_stage_manager.go (stage load) — the naming fix ensures those paths are reached.

Original prompt

Improve glTF loader and importer support for Blender Empties in NilssonCreative/Kaiju.

The goal is to ensure that Blender Empties are imported with their original names (no filename prefixing) and are visually represented in the Kaiju editor as orange plain axes gizmos, matching the Blender experience.

Key tasks:

  1. Update src/editor/project/project_database/content_database/content_database_mesh.go:
    • Remove the baseName prefix when creating ImportVariant names for both meshes and empties. Use the literal node/mesh name from the glTF file.
    • Ensure the nodeVariants mapping uses these literal names.
  2. Ensure src/editor/editor_workspace/stage_workspace/stage_spawner.go correctly identifies empty variants (where km.IsEmpty is true) and calls editor_stage_manager.SpawnEmptyGizmo to provide the visual representation in the viewport.
  3. Verify that the scene template builder in content_database_mesh.go (meshBuildSceneTemplate) uses the new literal naming scheme to correctly link entities to their imported content items.
  4. Ensure the visual gizmo in src/editor/editor_stage_manager/empty_gizmo.go is correctly registered and visible when an Empty is spawned or loaded into a stage.

The user explicitly requested: 'Importing the gltf should import all content and not use a specific naming scheme.' and 'Make sure that there is some visual representation of the Empties in the editor, like in blender.'

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: I had Copilot add support for blender Empties exported in gltf in a new branch on GitHub.com/NilssonCreative/Kaiju yesterday.

The importing succeeds but i can only see meshes and materials in the editor.
I have no idea how to access the empty-nodes from the editor or code in my project.

Assistant: The support for Blender Empties was added in the copilot/improve-gltf-loader-empties-support branch. Based on the changes, here is how you can access the empty nodes in both the editor and your code.

1. In the Editor

The loader now treats Empties as a special type of "Mesh" variant.

  • Visibility: Empties are now visible in the viewport as Orange Plain Axes (similar to Blender's default look).
  • Selection: You can click the axes to select them. They have a small invisible bounding box (AABB) for picking.
  • Content Browser: When you import a .gltf or .glb, a separate content item is created for each Empty, named {FileName}-{EmptyName}.
  • Scene Templates: If your file has multiple nodes, the importer now automatically generates a Template file named after your model. Dragging this Template into the stage will spawn the entire hierarchy at once, including all meshes and empties at their correct relative positions.

2. In Code

The load_result.Result has been updated with several helpers to make working with Empties easy.

Getting all Empties or a specific one

result, err := loaders.GLTF("models/my_model.glb", host.AssetDatabase())
if err != nil { ... }

// Option A: Get all empty nodes
empties := result.Empties()
for _, e := range empties {
    fmt.Printf("Found empty: %s at %v\n", e.Name, e.Position)
}

// Option B: Look up a specific empty by its Blender name
hub := result.NodeByName("WheelHub_FL")
if hub != nil && hub.IsEmpty {
    // Found it!
}

Handling Nested Hierarchies (World Space)

If your Empties are nested inside other nodes in Blender, their Position field only contains the local transform relative to the parent. To get the actual world-space position (to attach a Kaiju Entity, for example), use the new NodeWorldTransform helper:

// Calculate the absolute world position/rotation/scale
worldPos, worldRot, worldScale := result.NodeWorldTransform(int(hub.Id))

// Use it to position a new Entity
entity := engine.NewEntity(host.WorkGroup())
entity.Transform.SetPosition(worldPos)
entity.Transform.SetRotation(worldRot.ToEuler())
entity.Transform.SetScale(worldScale)

Accessing Blender Custom Properties

If you added Custom Properties in Blender's "Object Properties" tab, they are automatically mapped to the Attributes field:

if val, ok := hub.Attributes["my_custom_setting"]; ok {
    // Process the property (exported as JSON 'extras' in glTF)
    fmt.Println("Custom setting:", val)
}

Summary of Key API Changes:

  • load_result.Node: Now has an IsEmpty bool flag and a Children []int32 slice.
  • load_result.Result:
    • Empties() []*Node: Returns all nodes marked as empties.
    • NodeWorldTransform(index) (Vec3, Quaternion, Vec3): Computes the inherited transform.
  • stages.EmptyMeshId: A sentinel string ("ed_empty") used to identify empties in the engine's stage format.

User: The Empties doesn't show up in Kaiju editor after importing the gltf containing a body mesh and four wheel-hub-empties.

Assistant: The issue likely stems from how the `Import...

This pull request was created from Copilot chat.

Copilot AI and others added 5 commits April 28, 2026 09:58
… documentation

Agent-Logs-Url: https://github.com/NilssonCreative/kaiju/sessions/a011bfcb-340f-4e3f-8618-693b43149107

Co-authored-by: NilssonCreative <9530207+NilssonCreative@users.noreply.github.com>
…des as stage entities

Agent-Logs-Url: https://github.com/NilssonCreative/kaiju/sessions/219520b9-7fea-42aa-9d50-244ac8995454

Co-authored-by: NilssonCreative <9530207+NilssonCreative@users.noreply.github.com>
Agent-Logs-Url: https://github.com/NilssonCreative/kaiju/sessions/f16919c6-d422-4065-939f-84fd6ee17c3b

Co-authored-by: NilssonCreative <9530207+NilssonCreative@users.noreply.github.com>
…on import

Agent-Logs-Url: https://github.com/NilssonCreative/kaiju/sessions/6fb32cac-467f-446a-8bc1-63bcdb8e7a61

Co-authored-by: NilssonCreative <9530207+NilssonCreative@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve glTF loader for Blender Empties support glTF import: use literal node names instead of filename-prefixed variant names Apr 29, 2026
Copilot AI requested a review from NilssonCreative April 29, 2026 09:45
@NilssonCreative
NilssonCreative marked this pull request as ready for review April 29, 2026 09:55

@NilssonCreative NilssonCreative left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea

@NilssonCreative

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request.

Co-authored-by: NilssonCreative <9530207+NilssonCreative@users.noreply.github.com>

Copilot AI commented Apr 29, 2026

Copy link
Copy Markdown
Author

@copilot resolve the merge conflicts in this pull request.

Merge conflicts resolved in commit a059dc2. The merge integrates master's embedded texture extraction (for GLB files with inline textures) while preserving our Empty-node support (IsEmpty flag, Children links, matrix decomposition) and the literal naming scheme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants