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:
Descritor de Arquivo
Recursos externos
Recursos internos
Nós
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
nome
deve ser o primeiro atributo de cada osso.parent
é o índice do osso pai na lista de ossos, com índice pai, a lista de ossos é construída em uma árvore de ossos.rest
é a matriz de transformação do osso em sua posição de "repouso".pose
é a matriz de pose; userest
como base.bound_children
é uma lista deNodePath()
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:
No formato antigo, cada superfície tem três chaves essenciais:
primitive
arrays
morph_arrays
primitive
é uma variável enumerada,primitive=4
que éPRIMITIVE_TRIANGLES
é freqüentemente usado.arrays
é uma matriz bidimensional que contém:Array de posições de vértice
Matriz de normais
Matriz de tangentes
Matriz de cores de vértice
UV array 1
UV array 2
Bone indexes array
Matriz de pesos ósseos
Matriz de índices de vértice
morph_arrays
é um array de morfos. Cada morph é exatamente umarrays
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.
length
estep
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
O
type
deve ser o primeiro atributo de cada faixa. O valor detype
pode ser:transform
value
method
O
path
tem o formatoNodePath(Path/To/Node:attribute)
. É o caminho para o nó ou atributo animado, relativo ao nó raiz definido no AnimationPlayer.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)
The
keys
correspond to the keyframes. It appears as aPoolRealArray()
, 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 )