@needle-tools/needle-component-compiler 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +21 -0
- package/Readme.md +8 -1
- package/dist/MaterialColorHandler.cs +11 -0
- package/dist/NavigationManager.cs +13 -0
- package/dist/PointOfInterest.cs +14 -0
- package/package.json +2 -3
- package/src/component-compiler.js +41 -19
- package/src/component-compiler.ts +39 -19
- package/src/test.ts +32 -3
- package/src/types.js +2 -0
package/Changelog.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this package will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [1.1.0] - 2022-06-15
|
|
8
|
+
- allow adding ``@type(MyNamespace.MyType)`` to class declaration
|
|
9
|
+
|
|
10
|
+
## [1.1.0] - 2022-06-13
|
|
11
|
+
- add ``@type(MyNamespace.MyType)`` decorator for fields to specifiy C# type
|
|
12
|
+
- add minimal docs to readme
|
|
13
|
+
- dont emit comments anymore
|
|
14
|
+
- make created classes partial
|
|
15
|
+
|
|
16
|
+
## [1.0.1] - 2022-05-29
|
|
17
|
+
- disable all warnings for generated scripts
|
|
18
|
+
- add mesh and texture types
|
|
19
|
+
|
|
20
|
+
## [1.0.0] - 2022-04-22
|
|
21
|
+
- initial release
|
package/Readme.md
CHANGED
|
@@ -4,4 +4,11 @@ Little helper package to transpile typescript files to Unity C# components.
|
|
|
4
4
|
Please run ``npm install`` first before using.
|
|
5
5
|
|
|
6
6
|
### Usage
|
|
7
|
-
``node <path to>/component-compiler.js <output_directory> <path_to/my_script.ts>``
|
|
7
|
+
``node <path to>/component-compiler.js <output_directory> <path_to/my_script.ts>``
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Command decorators
|
|
11
|
+
- ``@dont-generate-component`` add before class to skip generating a component
|
|
12
|
+
- ``@generate-component`` to enforce generating a component (not required)
|
|
13
|
+
- ``@serializeField`` field decorator, similar to ``[SerializeField]``
|
|
14
|
+
- ``@type(MyNamespace.MyType)`` field decorator, specifiy C# type of field
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// auto generated code - do not edit directly
|
|
2
|
+
|
|
3
|
+
#pragma warning disable
|
|
4
|
+
|
|
5
|
+
namespace Needle.Typescript.GeneratedComponents
|
|
6
|
+
{
|
|
7
|
+
public partial class NavigationManager : RoomEntity
|
|
8
|
+
{
|
|
9
|
+
public float @fl = 1f;
|
|
10
|
+
public void nav_forward(){}
|
|
11
|
+
public void nav_backward(){}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// auto generated code - do not edit directly
|
|
2
|
+
|
|
3
|
+
#pragma warning disable
|
|
4
|
+
|
|
5
|
+
namespace Needle.Typescript.GeneratedComponents
|
|
6
|
+
{
|
|
7
|
+
public partial class PointOfInterest : UnityEngine.MonoBehaviour
|
|
8
|
+
{
|
|
9
|
+
public float @myVal = 12f;
|
|
10
|
+
public void myFunction(){}
|
|
11
|
+
public UnityEngine.Camera @view;
|
|
12
|
+
public string @test = "123";
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/needle-component-compiler",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Compile mock unity components from typescript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,6 +16,5 @@
|
|
|
16
16
|
"name": "Needle",
|
|
17
17
|
"email": "help@needle.tools",
|
|
18
18
|
"url": "https://needle.tools/"
|
|
19
|
-
}
|
|
20
|
-
"license": "ISC"
|
|
19
|
+
}
|
|
21
20
|
}
|
|
@@ -11,6 +11,7 @@ var exportNextClassCommand = "@generate-component";
|
|
|
11
11
|
var dontExportNextClassCommand = "@dont-generate-component";
|
|
12
12
|
// add above field to add [SerializeField] attribute
|
|
13
13
|
var serializeCommand = "@serializeField";
|
|
14
|
+
var typePattern = new RegExp("@type ?\((?<type>.+)\)");
|
|
14
15
|
// will be set to true when e.g. a comment for export is found
|
|
15
16
|
var exportNextClass = false;
|
|
16
17
|
var dontExportNextClass = false;
|
|
@@ -65,6 +66,7 @@ var ExportContext = /** @class */ (function () {
|
|
|
65
66
|
return ExportContext;
|
|
66
67
|
}());
|
|
67
68
|
var contexts = [];
|
|
69
|
+
var lastTypeFound = null;
|
|
68
70
|
function run(program, outputDir, sourceFile) {
|
|
69
71
|
if (!fs.existsSync(outputDir)) {
|
|
70
72
|
console.error("Output directory does not exist: \"" + outputDir + "\"");
|
|
@@ -76,16 +78,18 @@ function run(program, outputDir, sourceFile) {
|
|
|
76
78
|
ts.forEachChild(node, traverseFile);
|
|
77
79
|
}
|
|
78
80
|
function visit(node) {
|
|
79
|
-
var _a, _b, _c;
|
|
81
|
+
var _a, _b, _c, _d;
|
|
80
82
|
var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
|
|
81
|
-
if (
|
|
82
|
-
|
|
83
|
-
context.indentLevel
|
|
84
|
-
|
|
83
|
+
if (context) {
|
|
84
|
+
if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
|
|
85
|
+
while (context.indentLevel > 0) {
|
|
86
|
+
context.indentLevel -= 1;
|
|
87
|
+
context.append("}\n");
|
|
88
|
+
}
|
|
89
|
+
context.flush();
|
|
90
|
+
context = null;
|
|
91
|
+
contexts.pop();
|
|
85
92
|
}
|
|
86
|
-
context.flush();
|
|
87
|
-
context = null;
|
|
88
|
-
contexts.pop();
|
|
89
93
|
}
|
|
90
94
|
console.log("\t", ts.SyntaxKind[node.kind]);
|
|
91
95
|
var commentRanges = ts.getLeadingCommentRanges(sourceFile.getFullText(), node.getFullStart());
|
|
@@ -105,13 +109,23 @@ function run(program, outputDir, sourceFile) {
|
|
|
105
109
|
}
|
|
106
110
|
else if (comment.includes(serializeCommand))
|
|
107
111
|
serializeField = true;
|
|
108
|
-
else
|
|
109
|
-
context.appendLine(comment);
|
|
110
112
|
}
|
|
111
113
|
if (comment.includes(exportNextClassCommand))
|
|
112
114
|
exportNextClass = true;
|
|
113
115
|
if (comment.includes(dontExportNextClassCommand))
|
|
114
116
|
dontExportNextClass = true;
|
|
117
|
+
var match = typePattern.exec(comment);
|
|
118
|
+
if (match && match.groups) {
|
|
119
|
+
// for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
|
|
120
|
+
// so we remove them
|
|
121
|
+
var type = match.groups["type"];
|
|
122
|
+
if (type.startsWith("("))
|
|
123
|
+
type = type.slice(1);
|
|
124
|
+
if (type.endsWith(")"))
|
|
125
|
+
type = type.slice(0, -1);
|
|
126
|
+
console.log("found type: ", type);
|
|
127
|
+
lastTypeFound = type;
|
|
128
|
+
}
|
|
115
129
|
}
|
|
116
130
|
}
|
|
117
131
|
switch (node.kind) {
|
|
@@ -122,6 +136,7 @@ function run(program, outputDir, sourceFile) {
|
|
|
122
136
|
case ts.SyntaxKind.Decorator:
|
|
123
137
|
break;
|
|
124
138
|
case ts.SyntaxKind.MethodDeclaration:
|
|
139
|
+
lastTypeFound = null;
|
|
125
140
|
serializeField = false;
|
|
126
141
|
resetExportNextClass();
|
|
127
142
|
if (!context)
|
|
@@ -131,8 +146,8 @@ function run(program, outputDir, sourceFile) {
|
|
|
131
146
|
// const isCoroutine = func.asteriskToken;
|
|
132
147
|
if (meth.name) {
|
|
133
148
|
var paramsStr = "";
|
|
134
|
-
for (var
|
|
135
|
-
var param = _e
|
|
149
|
+
for (var _e = 0, _f = meth.parameters; _e < _f.length; _e++) {
|
|
150
|
+
var param = _f[_e];
|
|
136
151
|
if (!param || !param.name)
|
|
137
152
|
continue;
|
|
138
153
|
if (paramsStr.length > 0)
|
|
@@ -158,15 +173,15 @@ function run(program, outputDir, sourceFile) {
|
|
|
158
173
|
console.log(name_1);
|
|
159
174
|
if (name_1.startsWith("\"@") || name_1.startsWith("\"$") || name_1.startsWith("$"))
|
|
160
175
|
break;
|
|
161
|
-
var typeString = tryResolveTypeRecursive(node);
|
|
176
|
+
var typeString = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : tryResolveTypeRecursive(node);
|
|
162
177
|
if (typeString === undefined) {
|
|
163
178
|
context.append("// Could not resolve type \"" + ((_c = vardec.type) === null || _c === void 0 ? void 0 : _c.getText()) + "\"\n");
|
|
164
179
|
}
|
|
165
180
|
var prefix = typeString === undefined ? "// " : "";
|
|
166
181
|
var assignment = "";
|
|
167
182
|
if (typeString !== undefined) {
|
|
168
|
-
for (var
|
|
169
|
-
var ch = _g
|
|
183
|
+
for (var _g = 0, _h = node.getChildren(); _g < _h.length; _g++) {
|
|
184
|
+
var ch = _h[_g];
|
|
170
185
|
switch (ch.kind) {
|
|
171
186
|
case ts.SyntaxKind.FalseKeyword:
|
|
172
187
|
case ts.SyntaxKind.TrueKeyword:
|
|
@@ -197,27 +212,34 @@ function run(program, outputDir, sourceFile) {
|
|
|
197
212
|
context.appendLine("[UnityEngine.SerializeField]");
|
|
198
213
|
}
|
|
199
214
|
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";\n");
|
|
215
|
+
lastTypeFound = null;
|
|
200
216
|
break;
|
|
201
217
|
case ts.SyntaxKind.ClassDeclaration:
|
|
202
218
|
serializeField = false;
|
|
203
219
|
var dec = node;
|
|
204
220
|
// a class must inherit a component
|
|
205
|
-
if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
|
|
221
|
+
if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
|
|
206
222
|
resetExportNextClass();
|
|
207
|
-
var name_2 = dec.name.escapedText;
|
|
223
|
+
var name_2 = (_d = dec.name) === null || _d === void 0 ? void 0 : _d.escapedText;
|
|
208
224
|
console.log("Found class: ", name_2);
|
|
209
225
|
var newContext = new ExportContext(outputDir, name_2 + ".cs");
|
|
210
|
-
newContext.appendLine("// auto generated code - do not edit");
|
|
226
|
+
newContext.appendLine("// auto generated code - do not edit directly");
|
|
227
|
+
newContext.appendLine("");
|
|
228
|
+
newContext.appendLine("#pragma warning disable");
|
|
229
|
+
newContext.appendLine("");
|
|
211
230
|
newContext.appendLine("namespace Needle.Typescript.GeneratedComponents");
|
|
212
231
|
newContext.appendLine("{");
|
|
213
232
|
newContext.indentLevel += 1;
|
|
214
233
|
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
215
|
-
|
|
234
|
+
var typeName = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : "UnityEngine.MonoBehaviour";
|
|
235
|
+
console.log(name_2 + " inherits " + typeName);
|
|
236
|
+
newContext.appendLine("public partial class " + name_2 + " : " + typeName);
|
|
216
237
|
newContext.appendLine("{");
|
|
217
238
|
newContext.indentLevel += 1;
|
|
218
239
|
newContext.classEnd = dec.end;
|
|
219
240
|
contexts.push(newContext);
|
|
220
241
|
}
|
|
242
|
+
lastTypeFound = null;
|
|
221
243
|
break;
|
|
222
244
|
}
|
|
223
245
|
function testInheritsComponent(node) {
|
|
@@ -11,6 +11,7 @@ const exportNextClassCommand = "@generate-component";
|
|
|
11
11
|
const dontExportNextClassCommand = "@dont-generate-component";
|
|
12
12
|
// add above field to add [SerializeField] attribute
|
|
13
13
|
const serializeCommand = "@serializeField";
|
|
14
|
+
const typePattern = new RegExp("@type ?\((?<type>.+)\)");
|
|
14
15
|
|
|
15
16
|
// will be set to true when e.g. a comment for export is found
|
|
16
17
|
let exportNextClass: boolean = false;
|
|
@@ -80,6 +81,8 @@ class ExportContext {
|
|
|
80
81
|
|
|
81
82
|
const contexts: ExportContext[] = [];
|
|
82
83
|
|
|
84
|
+
let lastTypeFound: string | null = null;
|
|
85
|
+
|
|
83
86
|
export function run(program: ts.Program, outputDir: string, sourceFile: ts.SourceFile) {
|
|
84
87
|
|
|
85
88
|
if (!fs.existsSync(outputDir)) {
|
|
@@ -97,14 +100,16 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
97
100
|
function visit(node: ts.Node) {
|
|
98
101
|
let context: ExportContext | null = contexts.length > 0 ? contexts[contexts.length - 1] : null;
|
|
99
102
|
|
|
100
|
-
if (context
|
|
101
|
-
|
|
102
|
-
context.indentLevel
|
|
103
|
-
|
|
103
|
+
if (context) {
|
|
104
|
+
if (context?.classEnd > 0 && node.pos >= context?.classEnd) {
|
|
105
|
+
while (context.indentLevel > 0) {
|
|
106
|
+
context.indentLevel -= 1;
|
|
107
|
+
context.append("}\n");
|
|
108
|
+
}
|
|
109
|
+
context.flush();
|
|
110
|
+
context = null;
|
|
111
|
+
contexts.pop();
|
|
104
112
|
}
|
|
105
|
-
context.flush();
|
|
106
|
-
context = null;
|
|
107
|
-
contexts.pop();
|
|
108
113
|
}
|
|
109
114
|
console.log("\t", ts.SyntaxKind[node.kind]);
|
|
110
115
|
|
|
@@ -125,13 +130,21 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
125
130
|
}
|
|
126
131
|
else if (comment.includes(serializeCommand))
|
|
127
132
|
serializeField = true;
|
|
128
|
-
else
|
|
129
|
-
context.appendLine(comment);
|
|
130
133
|
}
|
|
131
134
|
if (comment.includes(exportNextClassCommand))
|
|
132
135
|
exportNextClass = true;
|
|
133
136
|
if (comment.includes(dontExportNextClassCommand))
|
|
134
137
|
dontExportNextClass = true;
|
|
138
|
+
const match = typePattern.exec(comment);
|
|
139
|
+
if (match && match.groups) {
|
|
140
|
+
// for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
|
|
141
|
+
// so we remove them
|
|
142
|
+
let type = match.groups["type"];
|
|
143
|
+
if (type.startsWith("(")) type = type.slice(1);
|
|
144
|
+
if (type.endsWith(")")) type = type.slice(0, -1);
|
|
145
|
+
console.log("found type: ", type);
|
|
146
|
+
lastTypeFound = type;
|
|
147
|
+
}
|
|
135
148
|
}
|
|
136
149
|
}
|
|
137
150
|
|
|
@@ -143,6 +156,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
143
156
|
case ts.SyntaxKind.Decorator:
|
|
144
157
|
break;
|
|
145
158
|
case ts.SyntaxKind.MethodDeclaration:
|
|
159
|
+
lastTypeFound = null;
|
|
146
160
|
serializeField = false;
|
|
147
161
|
resetExportNextClass();
|
|
148
162
|
if (!context) break;
|
|
@@ -174,7 +188,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
174
188
|
const name = vardec.name.getText();
|
|
175
189
|
console.log(name);
|
|
176
190
|
if (name.startsWith("\"@") || name.startsWith("\"$") || name.startsWith("$")) break;
|
|
177
|
-
let typeString = tryResolveTypeRecursive(node);
|
|
191
|
+
let typeString = lastTypeFound ?? tryResolveTypeRecursive(node);
|
|
178
192
|
if (typeString === undefined) {
|
|
179
193
|
context.append("// Could not resolve type \"" + vardec.type?.getText() + "\"\n");
|
|
180
194
|
}
|
|
@@ -212,28 +226,35 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
212
226
|
context.appendLine("[UnityEngine.SerializeField]");
|
|
213
227
|
}
|
|
214
228
|
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";\n");
|
|
229
|
+
lastTypeFound = null;
|
|
215
230
|
break;
|
|
216
231
|
|
|
217
232
|
case ts.SyntaxKind.ClassDeclaration:
|
|
218
233
|
serializeField = false;
|
|
219
234
|
const dec = <ts.ClassDeclaration>node;
|
|
220
235
|
// a class must inherit a component
|
|
221
|
-
if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
|
|
236
|
+
if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
|
|
222
237
|
resetExportNextClass();
|
|
223
|
-
const name = dec.name
|
|
238
|
+
const name = dec.name?.escapedText;
|
|
224
239
|
console.log("Found class: ", name);
|
|
225
240
|
const newContext = new ExportContext(outputDir, name + ".cs");
|
|
226
|
-
newContext.appendLine("// auto generated code - do not edit")
|
|
241
|
+
newContext.appendLine("// auto generated code - do not edit directly");
|
|
242
|
+
newContext.appendLine("");
|
|
243
|
+
newContext.appendLine("#pragma warning disable");
|
|
244
|
+
newContext.appendLine("");
|
|
227
245
|
newContext.appendLine("namespace Needle.Typescript.GeneratedComponents");
|
|
228
246
|
newContext.appendLine("{");
|
|
229
247
|
newContext.indentLevel += 1;
|
|
230
248
|
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
231
|
-
|
|
249
|
+
const typeName = lastTypeFound ?? "UnityEngine.MonoBehaviour";
|
|
250
|
+
console.log(name + " inherits " + typeName);
|
|
251
|
+
newContext.appendLine("public partial class " + name + " : " + typeName);
|
|
232
252
|
newContext.appendLine("{");
|
|
233
253
|
newContext.indentLevel += 1;
|
|
234
254
|
newContext.classEnd = dec.end;
|
|
235
255
|
contexts.push(newContext);
|
|
236
256
|
}
|
|
257
|
+
lastTypeFound = null;
|
|
237
258
|
break;
|
|
238
259
|
}
|
|
239
260
|
|
|
@@ -275,7 +296,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
275
296
|
if (!node) return undefined;
|
|
276
297
|
|
|
277
298
|
// skip decorators (e.g. @serializable() may break array generation)
|
|
278
|
-
if(node.kind === ts.SyntaxKind.Decorator)
|
|
299
|
+
if (node.kind === ts.SyntaxKind.Decorator)
|
|
279
300
|
return undefined;
|
|
280
301
|
|
|
281
302
|
let typeName = node?.getText();
|
|
@@ -323,12 +344,11 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
323
344
|
console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
324
345
|
res = tryResolveTypeRecursive(child);
|
|
325
346
|
}
|
|
326
|
-
|
|
327
|
-
if(ts.isTypeReferenceNode(node)){
|
|
347
|
+
|
|
348
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
328
349
|
const typeRef = node as ts.TypeReferenceNode;
|
|
329
350
|
const typeName = typeRef.typeName.getText();
|
|
330
|
-
switch(typeName)
|
|
331
|
-
{
|
|
351
|
+
switch (typeName) {
|
|
332
352
|
case "Array":
|
|
333
353
|
res += "[]";
|
|
334
354
|
return res;
|
package/src/test.ts
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
1
|
|
|
2
2
|
// @generate-component
|
|
3
3
|
|
|
4
|
+
//@type (RoomEntity)
|
|
5
|
+
export class NavigationManager extends RoomEntity {
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
fl:number = 1;
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
nav_forward() {
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
nav_backward() {
|
|
14
|
+
|
|
15
|
+
}
|
|
9
16
|
}
|
|
10
17
|
|
|
18
|
+
|
|
19
|
+
// export class PointOfInterest extends Behaviour {
|
|
20
|
+
|
|
21
|
+
// myVal:number = 12;
|
|
22
|
+
|
|
23
|
+
// // @type(HELLO)
|
|
24
|
+
// myFunction(){
|
|
25
|
+
|
|
26
|
+
// }
|
|
27
|
+
|
|
28
|
+
// // @type(UnityEngine.Camera)
|
|
29
|
+
// view?:Camera;
|
|
30
|
+
// test:string = "123";
|
|
31
|
+
// // test
|
|
32
|
+
// }
|
|
33
|
+
|
|
34
|
+
// export class MaterialColorHandler extends Behaviour {
|
|
35
|
+
|
|
36
|
+
// @serializeable(Renderer)
|
|
37
|
+
// renderer?: Renderer[];
|
|
38
|
+
// }
|
|
39
|
+
|
|
11
40
|
// export class MyArray extends Behaviour {
|
|
12
41
|
|
|
13
42
|
// arr? : Array<number> = [1,2,3];
|
package/src/types.js
CHANGED
|
@@ -37,6 +37,8 @@ const dict = {
|
|
|
37
37
|
// Rendering
|
|
38
38
|
"Renderer" : "UnityEngine.Renderer",
|
|
39
39
|
"Material" : "UnityEngine.Material",
|
|
40
|
+
"Mesh" : "UnityEngine.Mesh",
|
|
41
|
+
"Texture" : "UnityEngine.Texture",
|
|
40
42
|
// UI
|
|
41
43
|
"Text" : "UnityEngine.UI.Text",
|
|
42
44
|
"Image" : "UnityEngine.UI.Image",
|