From dfab013abe50edf962a81f4b9e769ba86e8081b7 Mon Sep 17 00:00:00 2001 From: STEINNI Date: Wed, 29 Oct 2025 17:41:29 +0000 Subject: [PATCH] Load KF works --- app/assets/json/global/services.json | 8 +++ app/helpers/formBuilder.js | 7 ++- app/helpers/helpers3D.module.js | 2 +- app/models/KeyframesModel.js | 20 ++++++++ app/thirdparty/buildoz/buildoz.css | 4 +- app/views/editors/KeyframeView.html | 11 ++-- app/views/editors/KeyframeView.js | 57 +++++++++++++++++---- app/views/editors/modules/kfArena.module.js | 17 +++++- 8 files changed, 105 insertions(+), 21 deletions(-) diff --git a/app/assets/json/global/services.json b/app/assets/json/global/services.json index c83d619..c19be5a 100644 --- a/app/assets/json/global/services.json +++ b/app/assets/json/global/services.json @@ -17,6 +17,14 @@ } }, "/keyframes": { + "list": { + "uri": "/api/keyframes", + "method": "POST" + }, + "get": { + "uri": "/api/keyframes/{kfId}", + "method": "GET" + }, "create": { "uri": "/api/keyframes", "method": "PUT" diff --git a/app/helpers/formBuilder.js b/app/helpers/formBuilder.js index b79b216..a007f0f 100644 --- a/app/helpers/formBuilder.js +++ b/app/helpers/formBuilder.js @@ -6,7 +6,7 @@ if(!app.helpers) app.helpers = {} */ app.helpers.formBuilder = { - fieldsFromJSON(fieldsObj, fieldsValues, fieldsetLabel=null){ + fieldsFromJSON(fieldsObj, fieldsValues, fieldsetLabel=null, changeCB=null){ let allFields = [] for(const propName in fieldsObj){ const fieldRow = ui.create(`
`) @@ -18,11 +18,13 @@ app.helpers.formBuilder = { component.setAttribute('type','number') if('min' in fieldsObj[propName]) component.setAttribute('min', fieldsObj[propName].min) if('max' in fieldsObj[propName]) component.setAttribute('max', fieldsObj[propName].max) + if(typeof(changeCB) == 'function') component.addEventListener('input', (evt) => { changeCB(evt, component) }) break case 'string': component = document.createElement('input') component.setAttribute('name',propName) component.setAttribute('type','text') + if(typeof(changeCB) == 'function') component.addEventListener('input', (evt) => { changeCB(evt, component) }) break case 'boolean': component = document.createElement('bz-toggler') @@ -30,6 +32,7 @@ app.helpers.formBuilder = { component.setAttribute('trueValue','1') component.setAttribute('falseValue','0') fieldRow.append(component.el) + if(typeof(changeCB) == 'function') component.addEventListener('change', (evt) => { changeCB(evt, component) }) break case 'list': component = document.createElement('bz-select') @@ -37,6 +40,7 @@ app.helpers.formBuilder = { component.fillOptions( fieldsObj[propName].choices.map(item => { return({ markup: `${item}`, value: item}) })) + if(typeof(changeCB) == 'function') component.addEventListener('change', (evt) => { changeCB(evt, component) }) break default: console.warn(`Unknown field type ${fieldsObj[propName].type}`) @@ -90,5 +94,4 @@ app.helpers.formBuilder = { return(result) }, - } \ No newline at end of file diff --git a/app/helpers/helpers3D.module.js b/app/helpers/helpers3D.module.js index 3f81f56..07211e7 100644 --- a/app/helpers/helpers3D.module.js +++ b/app/helpers/helpers3D.module.js @@ -160,7 +160,7 @@ app.helpers.helpers3D = { }, getNamedParent(obj) { - while (obj && !obj.name) { + while (obj && ((!obj.name) || (obj.name.includes('_'))) ) { obj = obj.parent } return obj diff --git a/app/models/KeyframesModel.js b/app/models/KeyframesModel.js index 0d334a7..fe10482 100644 --- a/app/models/KeyframesModel.js +++ b/app/models/KeyframesModel.js @@ -5,6 +5,25 @@ class KeyframesModel extends WindozModel { this.ressource = '/keyframes' } + async list(kfId, prevKFId='') { + let endpoint = {...app.config.api[this.ressource].list} + const filters = {} + //Caution, undefined is != NULL here, because prev_kfId ull means root, while undefined means no filtering + if((typeof(kfId) != 'undefined') && (kfId!=='')) filters['kfId'] = kfId + if((typeof(prevKFId) != 'undefined') && (prevKFId!=='')) filters['prevKFId'] = prevKFId + return ( + this.request(endpoint.uri, endpoint.method, filters) + ) + } + + async getKeyframe(kfId){ + let endpoint = {...app.config.api[this.ressource].get} + endpoint.uri = endpoint.uri.replace('{kfId}', kfId) + return ( + this.request(endpoint.uri, endpoint.method, kfId) + ) + } + async create(kfData, prevKFId) { let endpoint = {...app.config.api[this.ressource].create} return ( @@ -24,6 +43,7 @@ class KeyframesModel extends WindozModel { const { position, speed, ...storeValues} = data[aid].values return({ aid: aid, + type: data[aid].type, storeValues: storeValues, gpsValues: { position: data[aid].values.position, speed: data[aid].values.speed } }) diff --git a/app/thirdparty/buildoz/buildoz.css b/app/thirdparty/buildoz/buildoz.css index 9297fe6..31f86b6 100644 --- a/app/thirdparty/buildoz/buildoz.css +++ b/app/thirdparty/buildoz/buildoz.css @@ -32,7 +32,7 @@ bz-select > button::after { bz-select > div.options-container{ pointer-events: none; position: absolute; - top: 2em; + top: 1.8em; left: 0; width: 100%; z-index: 99; @@ -45,7 +45,7 @@ bz-select option{ background-color: #DDD; border: 1px solid black; color: #000; - padding: 0.2em .2em .3em .5em; + padding: 0.2em .2em .5em .5em; margin: -1em 0 0 0; border-radius: 1em; height: 1em; diff --git a/app/views/editors/KeyframeView.html b/app/views/editors/KeyframeView.html index 14ac1fc..39b560d 100644 --- a/app/views/editors/KeyframeView.html +++ b/app/views/editors/KeyframeView.html @@ -33,7 +33,7 @@ text-align: center; margin-top: .3em; } - .kf-editor article.left-pane > section > bz-select{ margin: 0 0.5em 1em 0.5em; } + .kf-editor article.left-pane > section > bz-select{ margin: 1em 0.5em 1em 0.5em; } .kf-editor article.kfArena section{ padding: 0; height: 100%; @@ -62,7 +62,7 @@ color: #DDD; padding: 0 0 0 0; } - .kf-editor button[data-trigger="onAddAgent"] { background-color: #473; } + .kf-editor button[data-trigger="onAddAgent"] { background-color: #6B5; } .kf-editor button[data-trigger="onRemoveAgent"] { background-color: #A00; } .kf-editor button[data-trigger="onSaveKF"] { background-color: #367; } .kf-editor button[data-trigger="onResetKF"] { background-color: #A00; } @@ -76,16 +76,21 @@ margin-top: 1em; font-size: .8em; } + .kf-editor bz-select[data-output="keyframesSelector"]{ + margin-top:1em; + }

Agent type browser

- +

Keyframes browser

+ +
diff --git a/app/views/editors/KeyframeView.js b/app/views/editors/KeyframeView.js index 7a33f00..bd64e5a 100644 --- a/app/views/editors/KeyframeView.js +++ b/app/views/editors/KeyframeView.js @@ -44,6 +44,16 @@ class KeyframeView extends WindozDomContent { this.agentPreview.startRendering() this.agentPreview.animation = true + this.models.keyframes.list('', null).then(data => data.payload).then(kflist => { + this.outputs.keyframesSelector.fillOptions(kflist.map(item => { + return({ + markup: item.ekf_name, + value: item.ekf_uuid + }) + })) + }) + this.outputs.keyframesSelector.addEventListener('change',this.onChangeKeyframe.bind(this)) + this.kfArena = new app.LoadedModules.kfArena(this.outputs.kfArenaCanvas, this.agentSprites) this.kfArena.onclickAgent = this.onclickAgent.bind(this) this.kfArena.startRendering() @@ -70,6 +80,17 @@ class KeyframeView extends WindozDomContent { } } + async onChangeKeyframe(event){ + if(!this.outputs.keyframesSelector.value) return + let kfData = await this.models.keyframes.getKeyframe(this.outputs.keyframesSelector.value).then(data => data.payload) + this.currentKeyframe = { + kfId: kfData.info.ekf_uuid, + kfName: kfData.info.ekf_name, + prevKfId: kfData.info.ekf_prev_uuid, + } + this.kfArena.reloadAgents(kfData.agents) + } + onclickAgent(obj3D){ const aid = obj3D.name this.kfArena.highlighted3DObjects.length = 0 //truncate but keep the ref ! @@ -77,11 +98,13 @@ class KeyframeView extends WindozDomContent { this.currentlySelectedAid = null } else { // Select this.currentlySelectedAid = aid - this.kfArena.highlighted3DObjects.push(obj3D) - this.fillAgentProperties(aid, this.kfArena.agents[aid].props, this.kfArena.agents[aid].values) - this.notUserChange = true - this.outputs.agentsSelector.value = this.kfArena.agents[aid].type - this.notUserChange = false + if(this.kfArena.agents[aid]) { + this.kfArena.highlighted3DObjects.push(obj3D) + this.fillAgentProperties(aid, this.kfArena.agents[aid].props, this.kfArena.agents[aid].values) + this.notUserChange = true + this.outputs.agentsSelector.value = this.kfArena.agents[aid].type + this.notUserChange = false + } } this.updateKfButtons() } @@ -100,11 +123,18 @@ class KeyframeView extends WindozDomContent { else { this.outputs.btnSaveKF.disabled = true } } + onPropsChanged(evt, comp){ + console.log('onPropsChanged', comp, evt) + if(this.currentlySelectedAid && this.kfArena.agents[this.currentlySelectedAid]){ + + } + } + fillAgentProperties(aid, agentProps, agentValues = {}){ this.outputs.agentProperties.innerHTML = `
ID: ${aid}
` - this.outputs.agentProperties.append(...this.fieldsFromJSON(agentProps, agentValues, 'Internal properties')) + this.outputs.agentProperties.append(...this.fieldsFromJSON(agentProps, agentValues, 'Internal properties', this.onPropsChanged.bind(this))) this.outputs.agentProperties.append(...this.fieldsFromJSON({ "position.x": { label: "Position X", @@ -121,7 +151,7 @@ class KeyframeView extends WindozDomContent { type: "number", default: "0" }, - }, agentValues, 'Coordinates')) + }, agentValues, 'Coordinates', this.onPropsChanged.bind(this))) this.outputs.agentProperties.append(...this.fieldsFromJSON({ "speed.x": { label: "Speed X", @@ -138,21 +168,26 @@ class KeyframeView extends WindozDomContent { type: "number", default: "0" }, - }, agentValues, 'Speed vector')) + }, agentValues, 'Speed vector', this.onPropsChanged.bind(this))) this.outputs.btnAddAgent.disabled = false this.setupRefs() } async onSaveKF(evt){ + let result = { success: true } if(!this.currentKeyframe.kfId){ // Create first (and get new kfId) this.currentKeyframe.kfName = this.outputs.kfName.value - const result = await this.models.keyframes.create(this.currentKeyframe) + result = await this.models.keyframes.create(this.currentKeyframe) this.currentKeyframe.kfId = result.payload.kfId } else if(this.currentKeyframe.kfName != this.outputs.kfName.value){ //rename this.currentKeyframe.kfName = this.outputs.kfName.value - const result = await this.models.keyframes.rename(this.currentKeyframe) + result = await this.models.keyframes.rename(this.currentKeyframe) + console.log(result) } - await this.models.keyframes.save(this.currentKeyframe.kfId, this.kfArena.agents) + + if(result.success){ + await this.models.keyframes.save(this.currentKeyframe.kfId, this.kfArena.agents) + } } } diff --git a/app/views/editors/modules/kfArena.module.js b/app/views/editors/modules/kfArena.module.js index c8a31be..a28a67d 100644 --- a/app/views/editors/modules/kfArena.module.js +++ b/app/views/editors/modules/kfArena.module.js @@ -124,9 +124,12 @@ export class kfArena{ } - addAgent(typeId, aid, properties, values){ + addAgent(typeId, aid, properties, values){ console.log('==addAgent==>',typeId, aid, properties, values) const agentSprite = this.agentSprites.find(item => item.atp_id==typeId) - if(!agentSprite) return + if(!agentSprite) { + console.warn(`No sprite for type: ${typeId}`) + return + } const agentObj = this.agentFromJSON(aid, agentSprite.asp_3d) agentObj.position.set(values.position.x, values.position.z, values.position.y ) @@ -146,6 +149,16 @@ export class kfArena{ if(aid in this.agents) delete(this.agents[aid]) } + reloadAgents(agents){ + for(const aid in this.agents){ + this.removeAgent(aid) + } + console.log('====>', agents) + for(const agent of agents){ + this.addAgent(agent.ekfs_atp_id, agent.aid, agent.props, {...agent.gps_values, ...agent.store_values}) + } + } + // getAllAgents(){ // const agents = [] // scene.traverse(o => o.name && names.push(o.name))