-
-
Save vmwxiong/eabc60834b32801f5a38de99f4acad80 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
constrainAttributes, | |
constrainSchema, | |
ExposeAttributes, | |
} from "../../@types"; | |
import { createScript } from "../../extensions/create-script-decorator"; | |
import { ScriptTypeBase } from "../../extensions/script-type-base"; | |
const attributes = constrainAttributes({ | |
test: { | |
type: "string", | |
}, | |
testJson: { | |
type: "json", | |
schema: constrainSchema([ | |
{ | |
name: "testAsset", | |
type: "asset", | |
assetType: "texture", | |
}, | |
]), | |
}, | |
testJsonArray: { | |
type: "json", | |
array: true, | |
schema: constrainSchema([ | |
{ | |
name: "firstName", | |
type: "string", | |
}, | |
{ | |
name: "age", | |
type: "number", | |
}, | |
]), | |
}, | |
testAsset: { | |
type: "asset", | |
assetType: "template", | |
}, | |
}); | |
export interface HelloWorld extends ExposeAttributes<typeof attributes> {} | |
@createScript() | |
export class HelloWorld extends ScriptTypeBase implements pc.ScriptType { | |
static readonly scriptName = "helloWorld"; | |
attributes = attributes; | |
initialize() { | |
console.log(this.test); | |
// Should be a string | |
console.log(this.testJsonArray[0].firstName); | |
// Should be a texture | |
console.log(this.testJson.testAsset.resource); | |
// Should be a template | |
console.log(this.testAsset.resource); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Animation, | |
Asset, | |
Color, | |
ContainerResource, | |
Curve, | |
Entity, | |
Font, | |
Material, | |
Model, | |
ModelComponent, | |
ScriptComponent, | |
Shader, | |
Sound, | |
Sprite, | |
StandardMaterial, | |
Template, | |
Texture, | |
Vec2, | |
Vec3, | |
Vec4, | |
} from "playcanvas"; | |
/** | |
* Supported attribute types | |
*/ | |
export type AttributeType = keyof AttributeNameMap; | |
export type AssetType = keyof AssetNameMap; | |
/** | |
* PlayCanvas attribute definition | |
*/ | |
export interface IAttributeDef { | |
type: AttributeType; | |
name?: string; | |
schema?: IAttributeDef[]; | |
default?: unknown; | |
title?: string; | |
description?: string; | |
placeholder?: string | string[]; | |
array?: boolean; | |
size?: number; | |
min?: number; | |
max?: number; | |
precision?: number; | |
step?: number; | |
assetType?: AssetType; | |
curves?: string[]; | |
color?: string; | |
enum?: Record<string, unknown>[]; | |
} | |
export interface INamedAttributeDef extends IAttributeDef { | |
name: string; | |
} | |
/** | |
* Attributes collection definition when define a script class | |
* @exports | |
*/ | |
export interface IAttributeCollection { | |
[key: string]: IAttributeDef; | |
} | |
// TODO: Many more | |
type ValueOf<T> = T[keyof T]; | |
export interface TypedAsset<T extends ValueOf<AssetNameMap>> extends Asset { | |
resource: T; | |
} | |
export interface StandardModelComponent extends ModelComponent { | |
material: StandardMaterial; | |
} | |
type JSONValue = | |
| string | |
| number | |
| boolean | |
| null | |
| JSONValue[] | |
| { [key: string]: JSONValue }; | |
type AssetNameMap = { | |
animation: Animation; | |
audio: Sound; | |
binary: ArrayBuffer; | |
container: ContainerResource; | |
cubemap: Texture; | |
css: string; | |
font: Font; | |
json: JSONValue; | |
html: string; | |
material: Material; | |
model: Model; | |
script: ScriptComponent; | |
shader: Shader; | |
sprite: Sprite; | |
template: Template; | |
text: string; | |
texture: Texture; | |
}; | |
type AttributeNameMap<SchemaType = unknown, GenericAssetType = Asset> = { | |
boolean: boolean; | |
number: number; | |
string: string; | |
json: SchemaType extends readonly INamedAttributeDef[] | |
? JSONFromSchema<SchemaType> | |
: never; | |
asset: GenericAssetType extends keyof AssetNameMap | |
? TypedAsset<AssetNameMap[GenericAssetType]> | |
: Asset; | |
entity: Entity; | |
rgb: Color; | |
rgba: Color; | |
vec2: Vec2; | |
vec3: Vec3; | |
vec4: Vec4; | |
curve: Curve; | |
}; | |
// Intentionally written as a distributive conditional type so that `SingleOrArray<boolean, T>` is T | T[] | |
type SingleOrArray<IsArray extends boolean | undefined, Type> = | |
IsArray extends true ? Array<Type> : Type; | |
/** | |
* Extend a class with this type and pass in its constrained attributes | |
* to directly map its attributes onto the class properties | |
*/ | |
export type ExposeAttributes<T extends IAttributeCollection> = { | |
[K in keyof T]: SingleOrArray< | |
T[K]["array"], | |
AttributeNameMap<T[K]["schema"], T[K]["assetType"]>[T[K]["type"]] | |
>; | |
}; | |
/** | |
* Wrap attributes with this in order to gain autocompletion and type inferences | |
*/ | |
export function constrainAttributes<T extends IAttributeCollection>(t: T) { | |
return t; | |
} | |
/** | |
* Wrap schemas with this in order to gain type inferences | |
*/ | |
export function constrainSchema< | |
N extends string, | |
T extends readonly (INamedAttributeDef & { name: N })[] | |
>(t: T) { | |
return t; | |
} | |
type JSONFromSchema<Schema extends ReadonlyArray<INamedAttributeDef>> = { | |
[Name in Schema[number]["name"]]: AttributeNameMap< | |
never, | |
Extract<Schema[number], { name: Name }>["assetType"] | |
>[Extract<Schema[number], { name: Name }>["type"]]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment