diff --git a/development/file_formats/tscn.rst b/development/file_formats/tscn.rst index 4c5837fbc..66e8f13cd 100644 --- a/development/file_formats/tscn.rst +++ b/development/file_formats/tscn.rst @@ -60,6 +60,190 @@ so on. For example, a spatial node looks like: [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 ) +The Scene Tree +-------------- + +The scene tree is made up of ... nodes! The heading of each node consists of +it's name, parent and (most of the time) a type. For example +:code:`[node type="Camera" name="PlayerCamera" parent="Player/Head"]` + +Other valid keywords include: + + - instance + - instance_placeholder + - owner + - index (if two nodes have the same name) + - groups + +The first node in the file should not have the :code:`parent=Path/To/Node` +entry in it's heading, and it is the scene root. All scene files should have +exactly one scene root. It it does not, Godot will fail to import the file. +The parent path of other nodes should be absolute, but without the scene +root's name. If it is a direct child of the scene root, it should be +:code:`"."`. Here is an example scene tree (but without any node content). +:: + + [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"] + +Similar to the internal resource, the document for each node is currently +incomplete. Fortunately it is easy to find out because you can simply +save a file with that node in it. Some example nodes are: + +:: + + [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 + +Node Path +~~~~~~~~~ + +A tree structure is not enough to represent the whole scene, Godot use +a :code:`NodePath(Path/To/Node)` structure to refer to another node or +attribute of the node anywhere in the scene tree. Some typical usages of +NodePath like mesh node use :code:`NodePath()` to point to its skeleton, +animation track use :code:`NodePath()` points to animated attribute in node. + +:: + + [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:") + ... + +Skeleton +~~~~~~~~~ +Skeleton node inherits Spatial node, besides that it may have a list +of bones described in key, value pair in the format :code:`bones/Id/Attribute=Value`, +attributes of bone consisits of + +- name +- parent +- rest +- pose +- enabled +- bound_children + +1) :code:`name` must put as the first attribute of each bone + +2) :code:`parent` is the index of parent bone in the bone list, with parent index, + the bone list is built to a bone tree + +3) :code:`rest` is the transform matrix of bone in rest position + +4) :code:`pose` is the pose matrix use :code:`rest` as basis + +5) :code:`bound_children` is a list of NodePath() points to + BoneAttachments belong to this bone + +An example of a skeleton node with two bones: + +:: + + [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 Skeleton node. The BoneAttachment has a :code:`bone_name=NameOfBone`, +and the corresponding bone being the parent has the BoneAttachment node +in its :code:`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 works as an animation lib. it has animations listed in the format +:code:`anim/Name=SubResource(ResourceId)`, each refers to a Animation +internal resource. All the animation resources use the root node of AnimationPlayer. +The root node is stored as :code:`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 = [ ] + + Resources --------- @@ -121,73 +305,129 @@ mesh having a material). In this case, the referring resource must appear before the reference to it. Thus, in the internal resources section of the file, order does matter. -Unfortunately, documentation on the formats for these subresources is -completely absent, and while some can be found through inspecting resources of -saved files, but others can only be found by looking through Godot's source. +Unfortunately, documentation on the formats for these subresources is not +complete, and while some can be found through inspecting resources of +saved files, others can only be found by looking through Godot's source. +ArrayMesh +~~~~~~~~~ +ArrayMesh consists of several surfaces, each in the format :code:`surface\Index={}`, +each surface is a set of vertex and a material. -The Scene Tree --------------- +TSCN support two format of surface, -The scene tree is made up of ... nodes! The heading of each node consists of -it's name, parent and (most of the time) a type. For example -:code:`[node type="Camera" name="PlayerCamera" parent="Player/Head"]` +1) for the old format, each surface has three essential keys: -Other valid keywords include: +- primitive +- arrays +- morph_arrays - - instance - - instance_placeholder - - owner - - index (if two nodes have the same name) - - groups + i) :code:`primitive` is an enumerate variable, :code:`primitive=4` which is + PRIMITIVE_TRIANGLES is frequently used. -The first node in the file should not have the :code:`parent=Path/To/Node` -entry in it's heading, and it is the scene root. All scene files should have -exactly one scene root. It it does not, Godot will fail to import the file. -The parent path of other nodes should be absolute, but without the scene -root's name. If it is a direct child of the scene root, it should be -:code:`"."`. Here is an example scene tree (but without any node content). -:: + ii) :code:`arrays` as name suggestes is an array of array, it contains: - [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"] - -Similar to the internal resource, the content for each node is currently -undocumented. Fortunately it is easy to find out because you can simply -save a file with that node in it. Some example nodes are: + 1) a array of vertex position + 2) tagents array + 3) vertex color array + 4) UV array 1 + 5) UV array 2 + 6) bone index array + 7) bone weight array + 8) vertex index array + + iii) :code:`morph_arrays` is an array of morph, each morph is exactly an + :code:`arrays` without vertex index array. + +An example of ArrayMesh: :: - [node type="CollisionShape" name="SphereCollision" parent="SpherePhysics"] + [sub_resource id=1 type="ArrayMesh"] - 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 ) + 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":[] + } + +Animation +~~~~~~~~~~ +An animation resource consists of tracks. Besides, it has 'length', 'loop' and +'step' applied to all the tracks. + +- length +- loop +- step + +1) :code:`length` and :code:`step` are both time in seconds + +Each track is described by a list of key, value pairt in the format :code:`tracks/Id/Attribute`, +it includs: + +- type +- path +- interp +- keys +- loop_wrap +- imported +- enabled - [node type="MeshInstance" name="Sphere" parent="SpherePhysics"] +1) The :code:`type` must be put as the first attribute of each track. + The value of :code:`type` can be: - 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 ) + - 'transform' + - 'value' + - 'method' +2) The :code:`path` has the format :code:`NodePath(Path/To/Node:Attribute)`. + It is the path from animation root node (property of AnimationPlayer) to the + animated node or attrbute. - [node type="OmniLight" name="Lamp" parent="."] +3) The :code:`interp` is the method to interpolate frames from the keyframes. + it is a enum variable and can has value: - 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 ) + - 0 (constant) + - 1 (linear) + - 2 (cubic) +4) The :code:`keys` is the keyframes, it appears as a PoolRealArray() + but have different structure for track with different type - [node type="Camera" name="Camera" parent="."] + - A transform track use every 12 real number in the :code:`keys` to describte a keyframe. + The first number is the timestamp, the second number is the transision (default 1.0 + in transform track), followed by a three number translation vector, followed by + four number rotation quaternion (x,y,z,w) and finally a three number scale vector. - 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 +:: + [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 )