import * as Attributes from "../core/Attributes" ; import { Asset } from "../assets/Asset" ; import { ReferenceArray } from "../serialization/ReferenceArray" ; import { BasePin } from "./Pin" ; import { Debug } from "../io/Debug" ; import { VoidSyncEvent } from "ts-events" ; import { SerializedObject } from "../core/SerializableObject" ; import { EngineEvents } from "../core/EngineEvents" ; import { BehaviorErrors } from "./BehaviorErrors" ; import { EditorBehaviorExecution } from "../editor/EditorBehaviorExecution" ; import { ICodeBlock } from "./ICodeBlock" ; hidden export namespace CodeBlockInternal { export const codeProperty = "_code" ; export const trimId = ( id ) => id . split ( "-" ) . join ( "" ) ; } @ Attributes . displayName ( "Program" ) @ Attributes . hasDedicatedEditor ( true ) export class CodeBlock extends Asset implements ICodeBlock { get version ( ) { return 7 ; } get pins ( ) { return this . _pins ; } get code ( ) { return this . _code ; } get program ( ) { return this . _program ; } get hasCompileErrors ( ) { return this . _hasCompileErrors ; } get runtimeError ( ) { return this . _runtimeError ; } get functions ( ) { return this . _functions ; } get isLoading ( ) { return this . _isLoading ; } set code ( code ) { this . _code = code ; this . clearErrors ( ) ; if ( this . _standaloneScript && this . _standaloneScript . parentNode ) { this . _standaloneScript . parentNode . removeChild ( this . _standaloneScript ) ; } try { console . assert ( this . templatePath ) ; const filePath = ( this . templatePath as string ) . replace ( " " , "_" ) . replace ( `.${ this . constructor . name }` , ".js" ) ; let runtimeCode = code ; if ( process . env . CONFIG === "editor" ) { runtimeCode = EditorBehaviorExecution . generateRuntimeCode ( this ) ; this . sourceInfo . sourcePath = filePath ; } const { protocol , hostname , port } = window . location ; const _port = ( port && port . length > 0 ) ? `:${ port }` : "" ; const finalCode = `${ runtimeCode }\r\n//# sourceURL=${ protocol }//${ hostname }${ _port }/${ filePath }` ; this . _standaloneScript = document . createElement ( "script" ) ; this . _standaloneScript . appendChild ( document . createTextNode ( finalCode ) ) ; ( document . head as HTMLHeadElement ) . appendChild ( this . _standaloneScript ) ; } catch ( e ) { this . logRuntimeError ( e . message ) ; } finally { const wasLoaded = this . _isLoaded ; this . _isLoading = false ; this . _isLoaded = true ; if ( ! wasLoaded ) { EngineEvents . assetLoaded . post ( this ) ; } BehaviorErrors . checkCodeBlock ( this ) ; } } event @ Attributes . unserializable ( ) pinChanged = new VoidSyncEvent ( ) ; hidden @ Attributes . unserializable ( ) sourceInfo : any ; protected _pins = new ReferenceArray ( BasePin ) ; protected _code = `
function onStart() {        
    return ExecutionStatus.Continue;
}

function onUpdate() {
    return ExecutionStatus.Finish;
}
` ; @ Attributes . unserializable ( ) private _program : any ; @ Attributes . unserializable ( ) private _functions ! : { [ functioName ] : Function ; } ; @ Attributes . unserializable ( ) private _isLoaded = false ; @ Attributes . unserializable ( ) private _isLoading = true ; @ Attributes . unserializable ( ) private _standaloneScript ! : HTMLScriptElement ; @ Attributes . unserializable ( ) private _scriptUrl ! : string ; @ Attributes . unserializable ( ) private _hasCompileErrors = false ; @ Attributes . unserializable ( ) private _runtimeError ? : [ string , number ] ; logRuntimeError ( message ) { Debug . logError ( `Error: '${ message }' in '${ this . templatePath }'` ) ; this . _runtimeError = [ message , Date . now ( ) ] ; } logCompileError ( message ) { Debug . logError ( `Error: '${ message }' in '${ this . templatePath }'` ) ; this . _hasCompileErrors = true ; } clearRuntimeErrors ( ) { delete this . _runtimeError ; } isLoaded ( ) { return this . _isLoaded ; } destroy ( ) { if ( this . _standaloneScript && this . _standaloneScript . parentNode ) { this . _standaloneScript . parentNode . removeChild ( this . _standaloneScript ) ; } super . destroy ( ) ; } setProperty ( property , value ) { super . setProperty ( property , value ) ; if ( property === CodeBlockInternal . codeProperty ) { this . code = value ; } } upgrade ( json , previousVersion ) { if ( previousVersion === 1 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /getComponent\(("|')UIImage("|')\)/g , 'getComponent("Image")' ) ; json . properties . _code = ( json . properties . _code as any ) . replace ( /getComponent\(("|')UIText("|')\)/g , 'getComponent("Text")' ) ; } else if ( previousVersion === 2 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /Engine.createFromPrefab/g , 'Engine.createEntity' ) ; } else if ( previousVersion === 3 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /Engine.root(\(\))?.findChild/g , "Engine.findEntity" ) . replace ( /transform.(_value.)?(position|rotation|scale|forward|right|up)/g , ( x , i , j ) => { let result = "transform." ; if ( i ) { result = `${ result }${ i }` ; } result = `${ result }world${ j [ 0 ] . toUpperCase ( ) + j . substring ( 1 ) }` ; return result ; } ) . replace ( /transform.(_value.)?local(Position|Rotation|Scale|Forward|Right|Up)/g , ( x , i , j ) => { let result = "transform." ; if ( i ) { result = `${ result }${ i }` ; } result = `${ result }${ j }` . toLowerCase ( ) ; return result ; } ) ; } else if ( previousVersion === 4 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /Engine.deltaTime/g , "Time.deltaTime" ) . replace ( /Engine.isOpenSource/g , "Project.isOpenSource" ) . replace ( /Engine.projectName/g , "Project.name" ) . replace ( /Engine.importToEditor/g , "Project.importToEditor" ) . replace ( /Engine.readSave/g , "SavedData.get" ) . replace ( /Engine.writeSave\([a-zA-Z]+\)/g , "SavedData.flush()" ) . replace ( /Engine.createEntity\(([a-zA-Z._]+)(, ([a-zA-Z 0-9\(\),]+))?\)/g , ( x , i , j , k ) => { if ( k ) { return `Entities.create(${ i }, { position: ${ k } })` ; } else { return `Entities.create(${ i })` ; } } ) . replace ( /Engine.destroyEntity\(([a-zA-Z0-9._]+)\)/g , ( x , i , j ) => `${ i }.destroy()` ) . replace ( /Engine.findEntity\((['"a-zA-Z0-9._]+)\)/g , ( x , i , j ) => `Entities.find(${ i })` ) . replace ( /Engine.getScreenSize\(\)/g , "Renderer.screenSize" ) . replace ( /Engine.loadScene\((['"a-zA-Z0-9_/.]+)\)/g , ( x , i , j ) => `Scenes.load(${ i })` ) . replace ( /Engine.loadAssetById\(([a-zA-Z0-9_.]+)\)/g , ( x , i , j ) => `Assets.loadById(${ i })` ) . replace ( /Engine.loadAsset\((['"a-zA-Z0-9._]+)\)/g , ( x , i , j ) => `Assets.load(${ i })` ) ; } else if ( previousVersion === 5 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /.owner./g , ".entity." ) . replace ( /.findEntities/g , ".filterChildren" ) . replace ( /getComponent\(["']([a-zA-Z]+)["']\)/g , ( x , i ) => `getComponentByName("${ i }")` ) . replace ( /setComponent\(["']([a-zA-Z]+)["']\)/g , ( x , i ) => `setComponentByName("${ i }")` ) . replace ( /getOrSetComponent\(["']([a-zA-Z]+)["']\)/g , ( x , i ) => `getOrSetComponentByName("${ i }")` ) ; } else if ( previousVersion === 6 ) { json . properties . _code = ( json . properties . _code as any ) . replace ( /getComponentByName\(["']([a-zA-Z]+)["']\)/g , ( x , i ) => `getComponent("${ i }")` ) ; } return json ; } private clearErrors ( ) { this . _hasCompileErrors = false ; this . clearRuntimeErrors ( ) ; BehaviorErrors . clear ( this ) ; } }