-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathTypeTreeNode.cs
More file actions
195 lines (157 loc) · 5.36 KB
/
TypeTreeNode.cs
File metadata and controls
195 lines (157 loc) · 5.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
using System;
using System.Collections.Generic;
using System.Text;
namespace UnityDataTools.FileSystem;
// A TypeTreeNode represents how a property of a serialized object was written to disk.
// See the TextDumper library for an example.
public class TypeTreeNode
{
int m_FirstChildNodeIndex;
int m_NextNodeIndex;
TypeTreeHandle m_Handle;
Lazy<List<TypeTreeNode>> m_Children;
Lazy<Type> m_CSharpType;
Lazy<bool> m_hasConstantSize;
// The type of the property (basic type like int or float or class names for objects)
public readonly string Type;
// The name of the property (e.g. m_IndexBuffer for a Mesh or m_Width for a Texture)
public readonly string Name;
// The size of the property (for basic types only, otherwise -1)
public readonly int Size;
// The offset of the property (mostly useless).
public readonly int Offset;
// Flags used for different things (e.g. field is an array, data alignment, etc.)
public readonly TypeTreeFlags Flags;
public readonly TypeTreeMetaFlags MetaFlags;
// Child nodes container.
public List<TypeTreeNode> Children => m_Children.Value;
// True if the field has no child.
public bool IsLeaf => m_FirstChildNodeIndex == 0;
// True if the field is a basic type. (int, float, char, etc.)
public bool IsBasicType => IsLeaf && Size > 0;
// True if the field is an array.
public bool IsArray => ((int)Flags & (int)TypeTreeFlags.IsArray) != 0;
// True if the field is a ManagedReferenceRegistry
public bool IsManagedReferenceRegistry => ((int)Flags & (int)TypeTreeFlags.IsManagedReferenceRegistry) != 0;
// C# type corresponding to the node type
public Type CSharpType => m_CSharpType.Value;
// True if the node has a constant size (it contains no array or other containers with variable size).
public bool HasConstantSize => m_hasConstantSize.Value;
[ThreadStatic]
static StringBuilder s_NodeType;
[ThreadStatic]
static StringBuilder s_NodeName;
// Properties are required to initialize the ThreadStatic members.
static StringBuilder NodeTypeBuilder
{
get
{
if (s_NodeType == null)
{
s_NodeType = new StringBuilder(512);
}
return s_NodeType;
}
}
static StringBuilder NodeNameBuilder
{
get
{
if (s_NodeName == null)
{
s_NodeName = new StringBuilder(512);
}
return s_NodeName;
}
}
internal TypeTreeNode(TypeTreeHandle typeTreeHandle, int nodeIndex)
{
m_Handle = typeTreeHandle;
var r = DllWrapper.GetTypeTreeNodeInfo(m_Handle, nodeIndex, NodeTypeBuilder, NodeTypeBuilder.Capacity, NodeNameBuilder, NodeNameBuilder.Capacity, out Offset, out Size, out Flags, out MetaFlags, out m_FirstChildNodeIndex, out m_NextNodeIndex);
UnityFileSystem.HandleErrors(r);
Type = NodeTypeBuilder.ToString();
Name = NodeNameBuilder.ToString();
m_Children = new Lazy<List<TypeTreeNode>>(GetChildren);
m_CSharpType = new Lazy<Type>(GetCSharpType);
m_hasConstantSize = new Lazy<bool>(GetHasConstantSize);
}
internal List<TypeTreeNode> GetChildren()
{
var children = new List<TypeTreeNode>();
var current = m_FirstChildNodeIndex;
while (current != 0)
{
var child = new TypeTreeNode(m_Handle, current);
children.Add(child);
current = child.m_NextNodeIndex;
}
return children;
}
bool GetHasConstantSize()
{
if (IsArray || CSharpType == typeof(string))
return false;
foreach (var child in Children)
{
if (!child.HasConstantSize)
return false;
}
return true;
}
Type GetCSharpType()
{
switch (Type)
{
case "int":
case "SInt32":
case "TypePtr":
return typeof(int);
case "unsigned int":
case "UInt32":
return typeof(uint);
case "float":
return typeof(float);
case "double":
return typeof(double);
case "SInt16":
return typeof(short);
case "UInt16":
return typeof(ushort);
case "SInt64":
return typeof(long);
case "FileSize":
case "UInt64":
return typeof(ulong);
case "SInt8":
return typeof(sbyte);
case "UInt8":
case "char":
return typeof(byte);
case "bool":
return typeof(bool);
case "string":
return typeof(string);
default:
{
if (Size == 8)
{
return typeof(long);
}
else if (Size == 4)
{
return typeof(int);
}
else if (Size == 2)
{
return typeof(short);
}
else if (Size == 1)
{
return typeof(sbyte);
}
return typeof(object);
}
}
throw new Exception($"Unknown type {Type}");
}
}