Formato de arquivo TSCN

The TSCN (text scene) file format represents a single scene tree inside Godot. Unlike binary SCN files, TSCN files have the advantage of being mostly human-readable and easy for version control systems to manage.

O formato de arquivo ESCN (cena exportada) é idêntico ao formato de arquivo TSCN, mas é usado para indicar ao Godot que o arquivo foi exportado de outro programa e não deve ser editado pelo usuário de dentro do Godot. Ao contrário dos arquivos SCN e TSCN, durante a importação, os arquivos ESCN são compilados em arquivos SCN binários armazenados dentro da pasta .import/. Isso reduz o tamanho dos dados e acelera o carregamento, pois os formatos binários são mais rápidos de carregar em comparação com os formatos baseados em texto.

Para quem procura uma descrição completa, a análise é tratada no arquivo `resource_format_text.cpp<https://github.com/godotengine/godot/blob/master/scene/resources/resource_format_text.cpp>`_ na classe ResourceFormatLoaderText.

Estrutura do arquivo

Existem cinco seções principais dentro do arquivo TSCN:

  1. Descritor de Arquivo

  2. Recursos externos

  3. Recursos internos

  4. Nós

  5. Conexões

The file descriptor looks like [gd_scene load_steps=3 format=2] and should be the first entry in the file. The load_steps parameter is equal to the total amount of resources (internal and external) plus one (for the file itself). If the file has no resources, load_steps is omitted. The engine will still load the file correctly if load_steps is incorrect, but this will affect loading bars and any other piece of code relying on that value.

Estas seções devem aparecer em ordem, mas pode ser difícil distingui-las. A única diferença entre elas é o primeiro elemento no título de todos os itens da seção. Por exemplo, o cabeçalho de todos os recursos externos deve começar com [ext_resource .....].

Um arquivo TSCN pode conter comentários de uma única linha começando com um ponto e vírgula (;). No entanto, os comentários serão descartados ao salvar o arquivo usando o editor do Godot.

Entradas dentro do arquivo

Um título se parece com [<resource_type> key=value key=value key=value ...] onde resource_type é um dos seguintes:

  • ext_resource

  • sub_resource

  • node

  • connection

Abaixo de cada título, vem zero ou mais pares key = value. Os valores podem ser tipos de dados complexos, como Matrizes, Transformações, Cores e assim por diante. Por exemplo, um nó espacial se parece com:

[node name="Cube" type="Spatial" parent="."]
transform=Transform( 1.0, 0.0, 0.0 ,0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 )

A árvore da cena

A árvore da cena é composta de... nós! O título de cada nó consiste em seu nome, pai e (na maioria das vezes) um tipo. Por exemplo [node type="Camera" name="PlayerCamera" parent="Player/Head"]

Outras palavras-chave válidas incluem:

  • instance

  • instance_placeholder

  • owner

  • index (define a ordem de aparição na árvore. Se ausente, os nós herdados terão precedência sobre os simples)

  • groups

O primeiro nó no arquivo, que também é a raiz da cena, não deve ter uma entrada parent=Caminho/Para/Nó em seu cabeçalho. Todos os arquivos de cena devem ter exatamente uma raiz de cena. Caso contrário, o Godot não conseguirá importar o arquivo. O caminho pai de outros nós deve ser absoluto, mas não deve conter o nome da raiz da cena. Se o nó for filho direto da raiz da cena, o caminho deve ser ".". Aqui está um exemplo de árvore de cena (mas sem qualquer conteúdo de nó):

[node name="Player" type="Spatial"]             ; The scene root
[node name="Arm" parent="." type="Spatial"]     ; Parented to the scene root
[node name="Hand" parent="Arm" type="Spatial"]
[node name="Finger" parent="Arm/Hand" type="Spatial"]

Semelhante ao recurso interno, o documento para cada nó está incompleto no momento. Felizmente, é fácil descobrir porque você pode simplesmente salvar um arquivo com esse nó nele. Alguns exemplos de nós são:

[node type="CollisionShape" name="SphereCollision" parent="SpherePhysics"]

shape = SubResource(8)
transform = Transform( 1.0 , 0.0 , -0.0 , 0.0 , -4.371138828673793e-08 , 1.0 , -0.0 , -1.0 , -4.371138828673793e-08 ,0.0 ,0.0 ,-0.0  )


[node type="MeshInstance" name="Sphere" parent="SpherePhysics"]

mesh = SubResource(9)
transform = Transform( 1.0 , 0.0 , -0.0 , 0.0 , 1.0 , -0.0 , -0.0 , -0.0 , 1.0 ,0.0 ,0.0 ,-0.0  )


[node type="OmniLight" name="Lamp" parent="."]

light_energy = 1.0
light_specular = 1.0
transform = Transform( -0.29086464643478394 , -0.7711008191108704 , 0.5663931369781494 , -0.05518905818462372 , 0.6045246720314026 , 0.7946722507476807 , -0.9551711678504944 , 0.199883371591568 , -0.21839118003845215 ,4.076245307922363 ,7.3235554695129395 ,-1.0054539442062378  )
omni_range = 30
shadow_enabled = true
light_negative = false
light_color = Color( 1.0, 1.0, 1.0, 1.0 )


[node type="Camera" name="Camera" parent="."]

projection = 0
near = 0.10000000149011612
fov = 50
transform = Transform( 0.6859206557273865 , -0.32401350140571594 , 0.6515582203865051 , 0.0 , 0.8953956365585327 , 0.44527143239974976 , -0.7276763319969177 , -0.3054208755493164 , 0.6141703724861145 ,14.430776596069336 ,10.093015670776367 ,13.058500289916992  )
far = 100.0

NodePath

Uma estrutura em árvore não é suficiente para representar toda a cena. Godot usa uma estrutura NodePath(Caminho/Para/Nó) para se referir a outro nó ou atributo do nó em qualquer lugar na árvore de cena. Por exemplo, MeshInstance usa NodePath() para apontar para seu esqueleto. Da mesma forma, as trilhas de animação usam NodePath() para apontar para as propriedades do nó a serem animadas.

[node name="mesh" type="MeshInstance" parent="Armature001"]

mesh = SubResource(1)
skeleton = NodePath("..:")
[sub_resource id=3 type="Animation"]

...
tracks/0/type = "transform
tracks/0/path = NodePath("Cube:")
...

Esqueleto

O nó Skeleton herda o nó Spatial, mas também pode ter uma lista de ossos descritos em pares de valores-chave no formato bones/Id/Attribute=Value. Os atributos ósseos consistem em:

  • name

  • parent

  • rest

  • pose

  • enabled

  • bound_children

  1. nome deve ser o primeiro atributo de cada osso.

  2. parent é o índice do osso pai na lista de ossos, com índice pai, a lista de ossos é construída em uma árvore de ossos.

  3. rest é a matriz de transformação do osso em sua posição de "repouso".

  4. pose é a matriz de pose; use rest como base.

  5. bound_children é uma lista de NodePath() que aponta para BoneAttachments pertencentes a este osso.

Eis um exemplo de um nó esqueleto com dois ossos:

[node name="Skeleton" type="Skeleton" parent="Armature001" index="0"]

bones/0/name = "Bone.001"
bones/0/parent = -1
bones/0/rest = Transform( 1, 0, 0, 0, 0, -1, 0, 1, 0, 0.038694, 0.252999, 0.0877164 )
bones/0/pose = Transform( 1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
bones/0/enabled = true
bones/0/bound_children = [  ]
bones/1/name = "Bone.002"
bones/1/parent = 0
bones/1/rest = Transform( 0.0349042, 0.99939, 0.000512929, -0.721447, 0.0248417, 0.692024, 0.691589, -0.0245245, 0.721874, 0, 5.96046e-08, -1.22688 )
bones/1/pose = Transform( 1.0, 0.0, -0.0, 0.0, 1.0, -0.0, -0.0, -0.0, 1.0, 0.0, 0.0, -0.0 )
bones/1/enabled = true
bones/1/bound_children = [  ]

BoneAttachment

O nó BoneAttachment é um nó intermediário para descrever algum nó sendo pai de um único osso em um nó Skeleton. O BoneAttachment tem um atributo bone_name=NameOfBone, e o osso correspondente sendo o pai tem o nó BoneAttachment em sua lista bound_children.

Um exemplo de uma MeshInstance ligada a um osso no Skeleton:

[node name="Armature" type="Skeleton" parent="."]

transform = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, -0.0219986, 0.0125825, 0.0343127)
bones/0/name = "Bone"
bones/0/parent = -1
bones/0/rest = Transform(1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0)
bones/0/pose = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0)
bones/0/enabled = true
bones/0/bound_children = [NodePath("BoneAttachment:")]

[node name="BoneAttachment" type="BoneAttachment" parent="Armature"]

bone_name = "Bone"

[node name="Cylinder" type="MeshInstance" parent="Armature/BoneAttachment"]

mesh = SubResource(1)
transform = Transform(1.0, 0.0, 0.0, 0.0, 1.86265e-09, 1.0, 0.0, -1.0, 0.0, 0.0219986, -0.0343127, 2.25595)

AnimationPlayer

AnimationPlayer funciona como uma biblioteca de animações. Ele armazena animações listadas no formato anim/Name=SubResource(ResourceId); cada linha se refere a um recurso Animation. Todos os recursos de animação usam o nó raiz do AnimationPlayer. O nó raíz é armazenado como root_node=NodePath(Path/To/Node).

[node name="AnimationPlayer" type="AnimationPlayer" parent="." index="1"]

root_node = NodePath("..")
autoplay = ""
playback_process_mode = 1
playback_default_blend_time = 0.0
playback_speed = 1.0
anims/default = SubResource( 2 )
blend_times = [  ]

Recursos

Recursos são componentes que compõem os nós. Por exemplo, um nó MeshInstance terá um recurso ArrayMesh associado. O recurso ArrayMesh pode ser interno ou externo ao arquivo TSCN.

Referências aos recursos são tratadas por números id no cabeçalho do recurso. Recursos externos e internos são referidos com ExtResource(id) e SubResource(id), respectivamente. Como há métodos diferentes para se referir a recursos internos e externos, você pode ter o mesmo ID para recursos internos e externos.

Por exemplo, para se referir ao recurso [ext_resource id=3 type="PackedScene" path=....], você usaria ExtResource(3).

Recursos externos

Recursos externos são links para recursos não contidos no próprio arquivo TSCN. Um recurso externo consiste em um caminho, um tipo e um ID.

Godot sempre gera caminhos absolutos relativos ao diretório de recursos e, portanto, prefixados com res://, mas caminhos relativos à localização do arquivo TSCN também são válidos.

Alguns exemplos de recursos externos são:

[ext_resource path="res://characters/player.dae" type="PackedScene" id=1]
[ext_resource path="metal.tres" type="Material" id=2]

Como os arquivos TSCN, um arquivo TRES pode conter comentários de uma única linha começando com um ponto e vírgula (;). No entanto, os comentários serão descartados ao salvar o recurso usando o editor Godot.

Recursos internos

Um arquivo TSCN pode conter malhas, materiais e outros dados. Eles estão contidos na seção internal resources do arquivo. O título de um recurso interno é semelhante ao de recursos externos, exceto pelo fato de não ter um caminho. Os recursos internos também têm pares key = value em cada título. Por exemplo, uma forma de colisão de cápsula se parece com:

[sub_resource type="CapsuleShape" id=2]

radius = 0.5
height = 3.0

Alguns recursos internos contêm links para outros recursos internos (como uma malha com um material). Nesse caso, o recurso de referência deve aparecer antes da referência a ele. Isso significa que a ordem é importante na seção de recursos internos do arquivo.

Infelizmente, a documentação sobre os formatos desses sub-recursos está incompleta. Alguns exemplos podem ser encontrados inspecionando arquivos de recursos salvos, mas outros só podem ser encontrados examinando o código-fonte do Godot.

ArrayMesh

ArrayMesh consiste em várias superfícies, cada uma no formato surface\Index={}. Cada superfície é um conjunto de vértices e um material.

Arquivos TSCN suportam dois formatos de superfície:

  1. No formato antigo, cada superfície tem três chaves essenciais:

  • primitive

  • arrays

  • morph_arrays

    1. primitive é uma variável enumerada, primitive=4 que é PRIMITIVE_TRIANGLES é freqüentemente usado.

    2. arrays é uma matriz bidimensional que contém:

      1. Array de posições de vértice

      2. Matriz de normais

      3. Matriz de tangentes

      4. Matriz de cores de vértice

      5. UV array 1

      6. UV array 2

      7. Bone indexes array

      8. Matriz de pesos ósseos

      9. Matriz de índices de vértice

    3. morph_arrays é um array de morfos. Cada morph é exatamente um arrays sem o array de índices de vértices.

Um exemplo de ArrayMesh:

[sub_resource id=1 type="ArrayMesh"]

surfaces/0 = {
    "primitive":4,
    "arrays":[
        Vector3Array(0.0, 1.0, -1.0, 0.866025, -1.0, -0.5, 0.0, -1.0, -1.0, 0.866025, 1.0, -0.5, 0.866025, -1.0, 0.5, 0.866025, 1.0, 0.5, -8.74228e-08, -1.0, 1.0, -8.74228e-08, 1.0, 1.0, -0.866025, -1.0, 0.5, -0.866025, 1.0, 0.5, -0.866025, -1.0, -0.5, -0.866025, 1.0, -0.5),
        Vector3Array(0.0, 0.609973, -0.792383, 0.686239, -0.609973, -0.396191, 0.0, -0.609973, -0.792383, 0.686239, 0.609973, -0.396191, 0.686239, -0.609973, 0.396191, 0.686239, 0.609973, 0.396191, 0.0, -0.609973, 0.792383, 0.0, 0.609973, 0.792383, -0.686239, -0.609973, 0.396191, -0.686239, 0.609973, 0.396191, -0.686239, -0.609973, -0.396191, -0.686239, 0.609973, -0.396191),
        null, ; No Tangents,
        null, ; no Vertex Colors,
        null, ; No UV1,
        null, ; No UV2,
        null, ; No Bones,
        null, ; No Weights,
        IntArray(0, 2, 1, 3, 1, 4, 5, 4, 6, 7, 6, 8, 0, 5, 9, 9, 8, 10, 11, 10, 2, 1, 10, 8, 0, 1, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 5, 0, 3, 0, 9, 11, 9, 5, 7, 9, 10, 11, 11, 2, 0, 10, 1, 2, 1, 6, 4, 6, 1, 8)
    ],
    "morph_arrays":[]
}

Animação

Um recurso de animação consiste em faixas. Além disso, possui length, loop e step aplicados a todas as faixas.

  1. length e step são durações em segundos.

Cada faixa é descrita por uma lista de pares chave-valor no formato tracks/Id/Attribute. Cada faixa inclui:

  • type

  • path

  • interp

  • keys

  • loop_wrap

  • imported

  • enabled

  1. O type deve ser o primeiro atributo de cada faixa. O valor de type pode ser:

    • transform

    • value

    • method

  2. O path tem o formato NodePath(Path/To/Node:attribute). É o caminho para o nó ou atributo animado, relativo ao nó raiz definido no AnimationPlayer.

  3. O interp é o método para interpolar quadros dos quadros-chave. É uma variável enum com um dos seguintes valores:

    • 0 (constante)

    • 1 (linear)

    • 2 (cubic)

  4. The keys correspond to the keyframes. It appears as a PoolRealArray(), but may have a different structure for tracks with different types.

    • A Transform track uses every 12 real numbers in the keys to describe a keyframe. The first number is the timestamp. The second number is the transition followed by a 3-number translation vector, followed by a 4-number rotation quaternion (X, Y, Z, W) and finally a 3-number scale vector. The default transition in a Transform track is 1.0.

[sub_resource type="Animation" id=2]

length = 4.95833
loop = false
step = 0.1
tracks/0/type = "transform"
tracks/0/path = NodePath("Armature001")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = true
tracks/0/enabled = true
tracks/0/keys = PoolRealArray( 0, 1, -0.0358698, -0.829927, 0.444204, 0, 0, 0, 1, 0.815074, 0.815074, 0.815074, 4.95833, 1, -0.0358698, -0.829927, 0.444204, 0, 0, 0, 1, 0.815074, 0.815074, 0.815074 )
tracks/1/type = "transform"
tracks/1/path = NodePath("Armature001/Skeleton:Bone.001")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = true
tracks/1/enabled = false
tracks/1/keys = PoolRealArray( 0, 1, 0, 5.96046e-08, 0, 0, 0, 0, 1, 1, 1, 1, 4.95833, 1, 0, 5.96046e-08, 0, 0, 0, 0, 1, 1, 1, 1 )