import { RJLog } from "../../library/RJLog"; import { GodotTypes } from "../GodotTypes"; import { MemberInitializer } from "../MemberInitializer"; import { MemberType } from "../MemberType"; import { Member } from "./Member"; export class Field extends Member { static readonly Node = "Node"; static readonly Resource = "Resource"; constructor( memberInitializer:MemberInitializer ) { super( MemberType.Field, memberInitializer ); } isReference = false; referenceType = ""; isProperty = false; propertySignalName = ""; propertyActionName = ""; parseBody( body:any ) { if ( typeof body === "boolean" ) { this.type = "bool"; this.initialValue = body + ""; return; } if ( typeof body === "number" ) { this.type = "float"; this.initialValue = body + ""; return; } let regex = /((?:\w|\<|\>)+)(?:\s*\=\s*(.+))?/; let result = regex.exec( body ); let typeOrRefRegex = /^(Ref|Resource|Node)/; let typeResult = result[ 1 ] this.isReference = typeOrRefRegex.test( typeResult ); // RJLog.log( "Is Reference", this.name, this.isReference, typeResult ); if ( this.isReference ) { this.referenceType = refRegex.test( typeResult ) ? refRegex.exec( typeResult )[ 1 ] : typeOrRefRegex.exec( typeResult )[ 1 ]; // RJLog.log( "referenceType", body, `"${this.referenceType}"`, typeResult ); if ( Field.Node === this.referenceType ) { typeResult = typeResult.replace( typeOrRefRegex, "" ).replace( />$/, ""); typeResult = typeResult + "*"; } else { typeResult = typeResult.replace( typeOrRefRegex, "Ref<" ); if ( result.length >= 2 ) { this.initialValue = result[ 2 ]; } } } this.type = typeResult; this.initialValue = result[ 2 ] || null; } getFieldDeclaration() { let fieldInfo = "\n " + this.info() + "\n "; if ( Field.Node === this.referenceType ) { return `${fieldInfo}${this.type} ${this.name} = nullptr;`; } return `${fieldInfo}${this.type} ${this.name};` } getHeaderDefinition():string { let fieldInfo = "\n " + this.info() + "\n "; if ( Field.Node === this.referenceType ) { return `${fieldInfo}${this.type} get_${this.name}() const; void set_${this.name}( ${this.type} p_${this.name} );`; } if ( Field.Resource === this.referenceType ) { return `${fieldInfo}${this.type} get_${this.name}() const; void set_${this.name}( const ${this.type} &p_${this.name} );`; } return `${fieldInfo}${this.type} get_${this.name}(); void set_${this.name}( ${this.type} p_${this.name} );` } getBindings( className:string ):string { let bindings = []; bindings.push( `// ${this.name}: ${this.type}` ); bindings.push( `ClassDB::bind_method( D_METHOD( "set_${this.name}", "${this.name}" ), &${className}::set_${this.name} );` ); bindings.push( `ClassDB::bind_method( D_METHOD( "get_${this.name}"), &${className}::get_${this.name});` ); if ( this.isReference ) { // ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "reference_property", PROPERTY_HINT_NODE_TYPE), "set_reference_property", "get_reference_property"); // RJLog.log( "Searching propertyHint:", this.name, this.type, this.referenceType ); let propertyHint = GodotTypes.stringToPropertyHint( this.referenceType ); bindings.push( `ADD_PROPERTY( PropertyInfo(Variant::OBJECT, "${this.name}", ${propertyHint} ), "set_${this.name}", "get_${this.name}" );` ); } else { let type = GodotTypes.stringToVariantType( this.type ); bindings.push( `ADD_PROPERTY(PropertyInfo( Variant::${type}, "${this.name}" ), "set_${this.name}", "get_${this.name}" );` ); } bindings.push( ` ` ); //ClassDB::bind_method(D_METHOD("set_color", "color"), &GLTFLight::set_color); //ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color"); // Color return bindings.join( "\n " ); } getFieldImplementation( className:string ) { let implementations = []; implementations.push( `// ${this.name}: ${this.type}` ); let eventCallbacks = ""; if ( this.isProperty ) { eventCallbacks += `\n`; eventCallbacks += `\n emit_signal( SNAME( "${this.propertySignalName}" ) );`; eventCallbacks += `\n`; eventCallbacks += `\n if ( ${this.propertyActionName} != NULL )`; eventCallbacks += `\n {`; eventCallbacks += `\n ${this.propertyActionName}->trigger();`; eventCallbacks += `\n }`; } let n = this.isProperty ? "\n" : ""; let n2 = this.isProperty ? "\n " : ""; if ( Field.Node === this.referenceType ) { implementations.push( `${this.type} ${className}::get_${this.name}() const { return ${this.name}; }` ); implementations.push( `void ${className}::set_${this.name}( ${this.type} p_${this.name} ) ${n}{${n2} ${this.name} = p_${this.name};${eventCallbacks} ${n}}` ); } else if ( Field.Resource === this.referenceType ) { implementations.push( `${this.type} ${className}::get_${this.name}() const { return ${this.name}; }` ); implementations.push( `void ${className}::set_${this.name}( const ${this.type} &p_${this.name} ) ${n}{${n2} ${this.name} = p_${this.name};${eventCallbacks} ${n}}` ); } else { implementations.push( `${this.type} ${className}::get_${this.name}() { return ${this.name}; }` ); implementations.push( `void ${className}::set_${this.name}( ${this.type} p_${this.name} ) ${n}{${n2} ${this.name} = p_${this.name};${eventCallbacks} ${n}}` ); } implementations.push( ` ` ); return implementations.join( "\n" ); } get hasInitializer() { return this.initialValue !== null; } getInitializer() { return `${this.name} = ${this.initialValue};`; } }