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.
The ESCN (exported scene) file format is identical to the TSCN file format, but
is used to indicate to Godot that the file has been exported from another
program and should not be edited by the user from within Godot.
Unlike SCN and TSCN files, during import, ESCN files are compiled to binary
SCN files stored inside the .import/
folder.
This reduces the data size and speeds up loading, as binary formats are faster
to load compared to text-based formats.
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
(sets the order of appearance in the tree. If absent, inherited nodes will take precedence over plain ones)
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
is a list ofNodePath()
which point to BoneAttachments belonging to this bone.
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¶
BoneAttachment node is an intermediate node to describe some node being parented
to a single bone in a Skeleton node. The BoneAttachment has a
bone_name=NameOfBone
attribute, and the corresponding bone being the parent has the
BoneAttachment node in its bound_children
list.
An example of one MeshInstance parented to a bone in 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¶
Resources are components that make up the nodes. For example, a MeshInstance node will have an accompanying ArrayMesh resource. The ArrayMesh resource may be either internal or external to the TSCN file.
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.
For example, to refer to the resource [ext_resource id=3 type="PackedScene"
path=....]
, you would use 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 always generates absolute paths relative to the resource directory and
thus prefixed with res://
, but paths relative to the TSCN file's location
are also valid.
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]
Like TSCN files, a TRES file may contain single-line comments starting with a
semicolon (;
). However, comments will be discarded when saving the resource
using the Godot editor.
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.
Unfortunately, documentation on the formats for these subresources isn't complete. Some examples can be found by inspecting saved resource files, but others can only be found by looking through Godot's source.
ArrayMesh¶
ArrayMesh consists of several surfaces, each in the format surface\Index={}
.
Each surface is a set of vertices and a material.
TSCN files support two surface formats:
For the old format, each surface has three essential keys:
primitive
arrays
morph_arrays
primitive
is an enumerate variable,primitive=4
which isPRIMITIVE_TRIANGLES
is frequently used.arrays
is a two-dimensional array, it contains:Vertex positions array
Normals array
Tangents array
Vertex colors array
UV array 1
UV array 2
Bone indexes array
Bone weights array
Vertex indexes array
morph_arrays
is an array of morphs. Each morph is exactly anarrays
without the vertex indexes array.
An example of 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¶
An animation resource consists of tracks. Besides, it has length
, loop
and step
applied to all the tracks.
length
andstep
are both durations in seconds.
Each track is described by a list of key-value pairs in the format
tracks/Id/Attribute
. Each track includes:
type
path
interp
keys
loop_wrap
imported
enabled
The
type
must be the first attribute of each track. The value oftype
can be:transform
value
method
The
path
has the formatNodePath(Path/To/Node:attribute)
. It's the path to the animated node or attribute, relative to the root node defined in the AnimationPlayer.The
interp
is the method to interpolate frames from the keyframes. It is an enum variable with one of the following values: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 )