import { Vector3 } from "../math/Vector3" ; import { Vector2 } from "../math/Vector2" ; import { Vector4 } from "../math/Vector4" ; import { Quaternion } from "../math/Quaternion" ; import { Color } from "../graphics/Color" ; import { Matrix44 , SerializableMatrix44 } from "../math/Matrix44" ; import { Matrix33 } from "../math/Matrix33" ; import { AABB } from "../math/AABB" ; import { UISize , SerializedUISize , UISizeType } from "../ui/UISize" ; import { VertexBuffer , SerializedVertexBuffer , VertexAttribute } from "../graphics/VertexBuffer" ; import { Rect } from "../ui/Rect" ; import { ArrayProperty , IArrayProperty , SerializedArrayProperty } from "./ArrayProperty" ; import { Debug } from "../io/Debug" ; import { ReferenceBase , Reference , SerializedReference } from "./Reference" ; import { ReferenceArray , ReferenceArrayBase , SerializedReferenceArray } from "./ReferenceArray" ; import { FileProperty } from "./FileProperty" ; import { ThumbnailProperty } from "./ThumbnailProperty" ; import { EntityReference } from "./EntityReference" ; import { Asset } from "../assets/Asset" ; import { ComponentReference , SerializedComponentReference } from "./ComponentReference" ; import { Range } from "./Range" ; import { Size , SerializedSize , SizeType } from "../core/Size" ; import { AssetReferenceArray , SerializedAssetReferenceArray } from "./AssetReferenceArray" ; import { AssetReference } from "./AssetReference" ; import { SerializerUtils } from "./SerializerUtils" ; import { NativeArray , INativeArray , NativeArrayFactory , NativeType } from "./NativeArray" ; import { SerializedObject , SerializableObject } from "../core/SerializableObject" ; import { NativeU8Array } from "./NativeU8Array" ; import { Plane } from "../math/Plane" ; import { Component } from "../core/Component" ; import { RTTI } from "../core/RTTI" ; import { Interfaces } from "../core/Interfaces" ; import { Constructor } from "../core/Types" ; hidden export namespace PropertyFactoryInternal { export const noOp = "_noOp" ; } class NativeSerializer < T > { type : Constructor < T > ; readProperty : ( json : T ) => T ; writeProperty ( data ) { return data ; } constructor ( ctor ) { this . type = ctor ; this . readProperty = ( json ) => { if ( typeof ( json ) === "object" ) { return new ctor ( ... Object . keys ( json ) . map ( k => json [ k ] ) ) ; } else { return json ; } } ; } } class NullSerializer < T > { type : Constructor < T > ; readProperty ( json ) { } writeProperty ( data ) { return PropertyFactoryInternal . noOp ; } constructor ( ctor ) { this . type = ctor ; } } export class PropertyFactory { static properties = { Vector3 : new NativeSerializer ( Vector3 ) , Vector2 : new NativeSerializer ( Vector2 ) , Vector4 : new NativeSerializer ( Vector4 ) , Quaternion : new NativeSerializer ( Quaternion ) , Color : new NativeSerializer ( Color ) , Matrix44 : new NullSerializer ( Matrix44 ) , SerializableMatrix44 : new NativeSerializer ( SerializableMatrix44 ) , Matrix33 : new NullSerializer ( Matrix33 ) , Rect : new NativeSerializer ( Rect ) , FileProperty : new NativeSerializer ( FileProperty ) , ThumbnailProperty : new NativeSerializer ( ThumbnailProperty ) , String : new NativeSerializer ( String ) , Number : new NativeSerializer ( Number ) , Boolean : new NativeSerializer ( Boolean ) , Range : new NativeSerializer ( Range ) , NativeArray : { type : NativeArray , readProperty : ( json ) => { return NativeArrayFactory . create ( json . typeName , json . data ) ; } , writeProperty : ( a ) : { typeName : string ; data : NativeType [ ] ; } => { return { typeName : a . typeName , data : a . data } ; } } , NativeU8Array : { type : NativeU8Array , readProperty : ( data ) => { return new NativeU8Array ( data ) ; } , writeProperty : ( a ) => { return a . serialize ( ) ; } } , Object : { type : Object , readProperty : ( json ) => { return JSON . parse ( JSON . stringify ( json ) ) ; } , writeProperty : ( obj ) => { return obj ; } } , AABB : { type : AABB , readProperty : ( json ) => { const { min , max } = json ; return new AABB ( new Vector3 ( min . x , min . y , min . z ) , new Vector3 ( max . x , max . y , max . z ) ) ; } , writeProperty : ( p ) => { return { min : { x : p . min . x , y : p . min . y , z : p . min . z } , max : { x : p . max . x , y : p . max . y , z : p . max . z } } ; } } , Plane : { type : Plane , readProperty : ( json ) => { const { normal , distFromOrigin } = json ; return new Plane ( new Vector3 ( normal . x , normal . y , normal . z ) , distFromOrigin ) ; } , writeProperty : ( p ) => { const { x , y , z } = p . normal ; return { normal : { x : x , y : y , z : z } , distFromOrigin : p . distFromOrigin } ; } } , UISize : { type : UISize , readProperty : ( json ) => { let uiSize = new UISize ( ) ; if ( typeof ( json . type ) === "object" ) { uiSize . type = ( json . type as any ) . value ; } else { uiSize . type = json . type ; } uiSize . value = json . value ; return uiSize ; } , writeProperty : ( p ) : { type : UISizeType ; value : number ; } => { return { type : p . type , value : p . value } ; } } , Size : { type : Size , readProperty : ( json ) => { let size = new Size ( ) ; if ( typeof ( json . type ) === "object" ) { size . type = ( json . type as any ) . value ; } else { size . type = json . type ; } size . value = json . value ; return size ; } , writeProperty : ( p ) : { type : SizeType ; value : number ; } => { return { type : p . type , value : p . value } ; } } , VertexBuffer : { type : VertexBuffer , readProperty : ( json ) => { let vb = new VertexBuffer ( ) ; for ( let attribute of Object . keys ( json . attributes ) ) { vb . setAttribute ( attribute as VertexAttribute , json . attributes [ attribute ] ) ; } vb . primitiveType = json . primitiveType ; vb . isDynamic = json . isDynamic ; vb . name = json . name ; vb . indices = json . indices ; return vb ; } , writeProperty : ( vb ) : SerializedVertexBuffer => { return { attributes : vb . attributes , vertexCount : vb . vertexCount , primitiveType : vb . primitiveType , isDynamic : vb . isDynamic , name : vb . name , indices : vb . indices } ; } } , ArrayProperty : { type : ArrayProperty , readProperty : ( json ) => { let data = [ ] ; data . length = json . data . length ; for ( let i = 0 ; i < json . data . length ; ++ i ) { SerializerUtils . deserializeProperty ( data , i , json . typeName , json . data [ i ] ) ; } if ( RTTI . isObjectOfType ( json . typeName , "SerializableObject" ) ) { return Interfaces . factory . createObjectArray ( json . typeName , data ) ; } else { if ( json . typeName in PropertyFactory . properties ) { return new ArrayProperty ( PropertyFactory . properties [ json . typeName ] . type , data ) ; } else { Debug . logError ( `Unknown type: ${ json . typeName }` ) ; return undefined ; } } } , writeProperty : ( p ) : SerializedArrayProperty => { let isObject = RTTI . isObjectOfType ( p . typeName ( ) , "SerializableObject" ) ; return { typeName : p . typeName ( ) , data : p . getData ( ) . map ( d => { let element = SerializerUtils . serializeProperty ( d , p . typeName ( ) ) ; if ( isObject ) { delete element . typeName ; } return element ; } ) } ; } } , Reference : { type : Reference , readProperty : ( json ) => { if ( json . data ) { let obj = Interfaces . factory . createObject ( json . data . typeName as string ) ; if ( obj !== null ) { obj . deserialize ( json . data ) ; } return Interfaces . factory . createReference ( json . baseTypeName , obj as SerializableObject ) as ReferenceBase ; } else { return Interfaces . factory . createReference ( json . baseTypeName ) as ReferenceBase ; } } , writeProperty : ( p ) : SerializedReference => { let instance = p . getInstance ( ) ; return { baseTypeName : p . baseTypeName ( ) , data : instance ? instance . serialize ( ) as SerializedObject : undefined } ; } } , ReferenceArray : { type : ReferenceArray , readProperty : ( json ) => { let data = json . data . map ( d => PropertyFactory . properties . Reference . readProperty ( d ) ) ; return Interfaces . factory . createReferenceArray ( json . typeName , data ) ; } , writeProperty : ( p ) : SerializedReferenceArray => { return { typeName : p . typeName ( ) , data : p . getData ( ) . map ( r => PropertyFactory . properties . Reference . writeProperty ( r ) ) } ; } } , AssetReferenceArray : { type : AssetReferenceArray , readProperty : ( json ) => { let data = [ ] ; data . length = json . data . length ; for ( let i = 0 ; i < json . data . length ; ++ i ) { SerializerUtils . deserializeProperty ( data , i , "AssetReference" , json . data [ i ] ) ; } return Interfaces . factory . createAssetReferenceArray ( json . typeName , data ) ; } , writeProperty : ( p ) : SerializedAssetReferenceArray => { return { typeName : p . typeName ( ) , data : p . data . map ( r => SerializerUtils . serializeProperty ( r ) ) } ; } } , EntityReference : { type : EntityReference , readProperty : ( json ) => new EntityReference ( json ) , writeProperty : ( p ) => p . id } , ComponentReference : { type : ComponentReference , readProperty : ( json ) => { const typeName = json . typeName || ( json as any ) . componentTypeName ; const ref = Interfaces . factory . createComponentReference ( typeName ) as ComponentReference < Component > ; ref . entityId = json . entityId ; return ref ; } , writeProperty : ( p ) : SerializedComponentReference => { return { entityId : p . entityId , typeName : p . typeName } ; } } } ; }