From ae960523cf8032272e3488b204cb522042831834 Mon Sep 17 00:00:00 2001 From: Josef Date: Sun, 19 May 2024 17:48:40 +0200 Subject: [PATCH] Timelines, VirtualCameras --- cpp-class-member.js | 140 +++++++++++++++--- create-cpp.js | 60 ++++++-- rokojori-action-library | 2 +- .../RJTimeLine.json | 13 ++ .../RJTimeLineManager.json | 45 ++++++ .../RJUpdatable.json | 5 +- .../RJVirtualCamera3D.json | 10 ++ .../RJVirtualCamera3DManager.json | 18 +++ .../_RJSequenceAction.json | 8 +- 9 files changed, 259 insertions(+), 42 deletions(-) create mode 100644 rokojori-action-library-definitions/RJTimeLine.json create mode 100644 rokojori-action-library-definitions/RJTimeLineManager.json create mode 100644 rokojori-action-library-definitions/RJVirtualCamera3D.json create mode 100644 rokojori-action-library-definitions/RJVirtualCamera3DManager.json diff --git a/cpp-class-member.js b/cpp-class-member.js index 22c7338..b736e3c 100644 --- a/cpp-class-member.js +++ b/cpp-class-member.js @@ -12,14 +12,24 @@ class CppClassMember isStatic = false; isSignal = false; type = "void"; + initialValue = null; parameters = []; constructor( nameDefinition, body ) { - if ( nameDefinition.endsWith( "()" ) ) + if ( nameDefinition.indexOf( "()" ) != -1) { this.isMethod = true; - nameDefinition = nameDefinition.replace( /\(\)$/, "" ); + + let typeRegex = /\(\)\s*(?:\:\s*(.+)\s*)?$/; + let result = typeRegex.exec( nameDefinition ); + + if ( result[ 1 ] ) + { + this.type = result[ 1 ]; + } + + nameDefinition = nameDefinition.replace( typeRegex, "" ); } let names = nameDefinition.split( /\s+/ ); @@ -48,6 +58,46 @@ class CppClassMember { this.parseMethodBody( body ); } + else + { + this.parseVariableBody( body ); + } + } + + get isMemberWithInitialValue() + { + return ! this.isMethod && this.initialValue !== null; + } + + getMemberInitializer() + { + return `${this.name} = ${this.initialValue};`; + } + + + parseVariableBody( body ) + { + 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 ); + + this.type = result[ 1 ]; + + this.initialValue = result[ 2 ] || null; + } parseMethodBody( body ) @@ -57,38 +107,50 @@ class CppClassMember return; } - this.type = body.type || "void"; - - let parameters = body.parameters; - - if ( ! parameters ) + if ( typeof body === "string" ) { + this.type = body; + return; } - for ( let i = 0; i < parameters.length; i++ ) + for ( let it in body ) { - let pm = parameters[ i ]; - - let cppParameter = new CppParameter(); - - for ( let it in pm ) + if ( ! body.hasOwnProperty( it ) ) { - if ( ! pm.hasOwnProperty( it ) ) - { - continue; - } - - cppParameter.name = it; - cppParameter.type = pm[ it ]; + continue; } + let cppParameter = new CppParameter(); + cppParameter.name = it; + cppParameter.type = body[ it ]; + this.parameters.push( cppParameter ); } + } getMethodBinding( className ) { + if ( ! this.isMethod ) + { + let type = stringToVariantType( this.type ); + + let bindings = []; + + bindings.push( `/* ${this.name}: ${this.type} */` ); + bindings.push( `ClassDB::bind_method(D_METHOD("get_${this.name}"), &${className}::get_${this.name});` ); + bindings.push( `ClassDB::bind_method(D_METHOD("set_${this.name}"), &${className}::set_${this.name});` ); + 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 " ); + + } + if ( this.isSignal ) { //ADD_SIGNAL(MethodInfo("session_supported", PropertyInfo(Variant::STRING, "session_mode"), PropertyInfo(Variant::BOOL, "supported"))); @@ -108,7 +170,16 @@ class CppClassMember } else if ( this.isVirtual ) { - return `GDVIRTUAL_BIND( ${this.name} );`; + let parameterInfos = ""; + + for ( let i = 0; i < this.parameters.length; i++ ) + { + let name = `, "${this.parameters[ i ].name}"`; + + parameterInfos += name; + } + + return `GDVIRTUAL_BIND( ${this.name}${parameterInfos} );`; } else { @@ -160,10 +231,28 @@ class CppClassMember } getVariableHeaderDefinition() + { + return `${this.type} get_${this.name}(); void set_${this.name}( ${this.type} p_${this.name} );` + //return `${this.type} ${this.name};` + } + + getPropertyHeaderDefinition() { return `${this.type} ${this.name};` } + getPropertyImplementation( className ) + { + let bindings = []; + + bindings.push( `/* ${this.name}: ${this.type} */` ); + bindings.push( `${this.type} ${className}::get_${this.name}() { return ${this.name}; }` ); + bindings.push( `void ${className}::set_${this.name}( ${this.type} p_${this.name} ) { ${this.name} = p_${this.name}; }` ); + bindings.push( ` ` ); + + return bindings.join( "\n" ); + } + } module.exports = @@ -175,6 +264,11 @@ module.exports = function stringToVariantType( stringType ) { + if ( /^TypedArray\<.+\>$/.test( stringType ) ) + { + return "ARRAY"; + } + switch( stringType ) { case "bool": return "BOOL"; @@ -222,5 +316,7 @@ function stringToVariantType( stringType ) case "PackedColorArray": return "PACKED_COLOR_ARRAY"; } - return null; + console.error( "Type could not be mapped: ", stringType ); + + return "OBJECT"; } \ No newline at end of file diff --git a/create-cpp.js b/create-cpp.js index a2d9a29..6107adf 100644 --- a/create-cpp.js +++ b/create-cpp.js @@ -3,7 +3,8 @@ const path = require( "path" ); const { loadJSON, getFiles, saveUTF8, getMatches, loadUTF8, insertText } = require( "./library.js" ); const { CppClassMember } = require( "./cpp-class-member.js" ); -function createCppHeader( className, extendingClassName, headerDefine, protectedMembers, publicMembers, includes ) +function createCppHeader( className, extendingClassName, headerDefine, protectedMembers, + publicMembers, includes ) { let cppHeader = @@ -15,7 +16,6 @@ let cppHeader = #define ${headerDefine} ${includes} -#include "./${extendingClassName}.h" class ${className} : public ${extendingClassName} @@ -44,7 +44,7 @@ return cppHeader; } -function createCppImplementation( className, boundMethods ) +function createCppImplementation( className, boundMethods, constructorExpressions, destructorExpressions, methodImplementations ) { let cppImplementation = @@ -61,14 +61,16 @@ void ${className}::_bind_methods() ${className}::${className}() { - + ${constructorExpressions} } ${className}::~${className}() { - + ${destructorExpressions} } +${methodImplementations} + ` return cppImplementation; @@ -87,6 +89,22 @@ function createTypeRegistration( className ) function createIncludes( className ) { + console.log( "Create include", className ); + + let godotClasses = + { + "Node" : "scene/main/node.h", + "Node2D" : "scene/2d/node_2d.h", + "Node3D" : "scene/3d/node_3d.h", + "Resource" : "core/io/resource.h" + } + + if ( godotClasses[ className ] ) + { + return `#include "${godotClasses[ className ]}"`; + } + + return `#include "./${className}.h"`; } @@ -228,13 +246,21 @@ async function createCppFiles( definitionPath, types, missingTypes ) let protectedMembers = grabMembers( data.protected ); let publicMembers = grabMembers( data.public ); - let protectedHeader = protectedMembers.map( p => p.getHeaderDefinition() ).join( "\n " ); - let publicHeader = publicMembers.map( p => p.getHeaderDefinition() ).join( "\n " ); + let allMembers = [].concat( protectedMembers ).concat( publicMembers ); - let protectedBindings = protectedMembers.map( p => p.getMethodBinding( className ) ); - let publicBindings = publicMembers.map( p => p.getMethodBinding( className ) ); - let bindings = protectedBindings.concat( publicBindings ).join( "\n " ); + let protectedHeader = protectedMembers.map( m => m.getHeaderDefinition() ).join( "\n " ); + let publicHeader = publicMembers.map( m => m.getHeaderDefinition() ).join( "\n " ); + + let properties = publicMembers.filter( m => ! m.isMethod ); + + let propertyDefinitions = properties.map( p => p.getPropertyHeaderDefinition() ).join( "\n " ); + + protectedHeader += "\n\n " + propertyDefinitions; + + let methodBindings = allMembers.map( m => m.getMethodBinding( className ) ).join( "\n " ); + + let initializers = allMembers.filter( m => m.isMemberWithInitialValue ).map( m => m.getMemberInitializer() ).join( "\n "); let includes = ""; @@ -243,8 +269,20 @@ async function createCppFiles( definitionPath, types, missingTypes ) includes = data.includes.map( inc => `#include "${inc}"` ); } + let extendingClassInclude = createIncludes( extendingClass ); + + includes += "\n" + extendingClassInclude; let header = createCppHeader( className, extendingClass, headerDefine, protectedHeader, publicHeader, includes ); - let implementation = createCppImplementation( className, bindings ); + + let constructorExpressions = initializers; + let destructorExpressions = ""; + let methodImplementations = ""; + + let propertyImplementations = properties.map( p => p.getPropertyImplementation( className ) ).join( "\n" ); + + methodImplementations += propertyImplementations; + + let implementation = createCppImplementation( className, methodBindings, constructorExpressions, destructorExpressions, methodImplementations ); //console.log( header ); //console.log( implementation ); diff --git a/rokojori-action-library b/rokojori-action-library index d6b9687..c19d8b7 160000 --- a/rokojori-action-library +++ b/rokojori-action-library @@ -1 +1 @@ -Subproject commit d6b968703d75749c4f7ded3abe5ec9beba97ae8d +Subproject commit c19d8b71d88206e99fa2c987d369ac713c275d41 diff --git a/rokojori-action-library-definitions/RJTimeLine.json b/rokojori-action-library-definitions/RJTimeLine.json new file mode 100644 index 0000000..602233a --- /dev/null +++ b/rokojori-action-library-definitions/RJTimeLine.json @@ -0,0 +1,13 @@ +{ + "class":"RJTimeLine:Resource", + + "public": + { + "isLooping": false, + "loopStart": 0, + "loopEnd": 16, + + "startSpeed": 1, + "autoStart": false + } +} \ No newline at end of file diff --git a/rokojori-action-library-definitions/RJTimeLineManager.json b/rokojori-action-library-definitions/RJTimeLineManager.json new file mode 100644 index 0000000..9a9616c --- /dev/null +++ b/rokojori-action-library-definitions/RJTimeLineManager.json @@ -0,0 +1,45 @@ +{ + "class":"RJTimeLineManager:RJNetworkNode", + + "includes":[ "./RJTimeLine.h" ], + + "public": + { + "virtual getTimeLineIndex():int" : { "timeLine":"Ref" }, + "virtual getTimeLineSize():int" : {}, + + "virtual createID():int" : {}, + + "virtual getLastPosition():double" : { "timeLineIndex":"int" }, + + "virtual getPosition():double" : { "timeLineIndex":"int" }, + "virtual setPosition()" : { "timeLineIndex":"int", "position":"double" }, + + "virtual getSpeed():double" : { "timeLineIndex":"int" }, + "virtual setSpeed()" : { "timeLineIndex":"int", "speed":"double" }, + + "virtual getPlayState():bool" : { "timeLineIndex":"int" }, + "virtual setPlayState()" : { "timeLineIndex":"int", "playState":"bool" }, + + "virtual scheduleEvent()" : + { + "timeLineIndex": "int", + "position": "double", + "callbackID": "int", + "isPersistent": "bool" + }, + + "virtual scheduleSpan()" : + { + "timeLineIndex": "int", + "startPosition": "double", + "endPosition": "double", + "callbackID": "int", + "isPersistent": "bool" + }, + + "signal onEvent()" : { "callbackID": "int" }, + + "signal onSpan()" : { "callbackID": "int", "spanType": "int" } + } +} \ No newline at end of file diff --git a/rokojori-action-library-definitions/RJUpdatable.json b/rokojori-action-library-definitions/RJUpdatable.json index 437ea5b..01ce60d 100644 --- a/rokojori-action-library-definitions/RJUpdatable.json +++ b/rokojori-action-library-definitions/RJUpdatable.json @@ -3,9 +3,6 @@ "public": { - "virtual update()": - { - "parameters":[ { "delta":"double" } ] - } + "virtual update()":{ "delta":"double" } } } \ No newline at end of file diff --git a/rokojori-action-library-definitions/RJVirtualCamera3D.json b/rokojori-action-library-definitions/RJVirtualCamera3D.json new file mode 100644 index 0000000..9a4e75e --- /dev/null +++ b/rokojori-action-library-definitions/RJVirtualCamera3D.json @@ -0,0 +1,10 @@ +{ + "class":"RJVirtualCamera3D:Node3D", + + "public": + { + "virtual getCameraPosition()": "Vector3", + "virtual getCameraRotation()": "Quaternion", + "virtual getCameraFOV()":"float" + } +} \ No newline at end of file diff --git a/rokojori-action-library-definitions/RJVirtualCamera3DManager.json b/rokojori-action-library-definitions/RJVirtualCamera3DManager.json new file mode 100644 index 0000000..10d9ea3 --- /dev/null +++ b/rokojori-action-library-definitions/RJVirtualCamera3DManager.json @@ -0,0 +1,18 @@ +{ + "class":"RJVirtualCamera3DManager:RJNetworkNode", + + "includes":[ "./RJVirtualCamera3D.h" ], + + "public": + { + "virtual getCamera():Ref" : { "cameraIndex": "int" }, + "virtual getCameraIndex():int" : { "timeLine":"Ref" }, + "virtual getCameraSize():int" : {}, + + "virtual getCameraPriority():float" : { "cameraIndex":"int" }, + "virtual setCameraPriority()" : { "cameraIndex":"int", "priority":"float" }, + + "cameraPrioritySmoothingCoefficient": 0.5, + "cameraPrioritySmoothingStepFPS": 120 + } +} \ No newline at end of file diff --git a/rokojori-action-library-definitions/_RJSequenceAction.json b/rokojori-action-library-definitions/_RJSequenceAction.json index 1684aed..c456e5c 100644 --- a/rokojori-action-library-definitions/_RJSequenceAction.json +++ b/rokojori-action-library-definitions/_RJSequenceAction.json @@ -3,9 +3,9 @@ "public": { - "virtual dispatchStart()" : { "type":"int" }, - "virtual dispatchCancel()" : { "parameters":[ { "id":"int" } ] }, - "virtual dispatchEnd()" : { "parameters":[ { "id":"int" } ] }, - "signal onSequenceDone()" : { "parameters":[ { "id":"int" } ] } + "virtual dispatchStart():int" : {}, + "virtual dispatchCancel()": { "id":"int" }, + "virtual dispatchEnd()" : { "id":"int" }, + "signal onSequenceDone()" : { "id":"int" } } } \ No newline at end of file