Load KF works
This commit is contained in:
@@ -17,6 +17,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/keyframes": {
|
"/keyframes": {
|
||||||
|
"list": {
|
||||||
|
"uri": "/api/keyframes",
|
||||||
|
"method": "POST"
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"uri": "/api/keyframes/{kfId}",
|
||||||
|
"method": "GET"
|
||||||
|
},
|
||||||
"create": {
|
"create": {
|
||||||
"uri": "/api/keyframes",
|
"uri": "/api/keyframes",
|
||||||
"method": "PUT"
|
"method": "PUT"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ if(!app.helpers) app.helpers = {}
|
|||||||
*/
|
*/
|
||||||
app.helpers.formBuilder = {
|
app.helpers.formBuilder = {
|
||||||
|
|
||||||
fieldsFromJSON(fieldsObj, fieldsValues, fieldsetLabel=null){
|
fieldsFromJSON(fieldsObj, fieldsValues, fieldsetLabel=null, changeCB=null){
|
||||||
let allFields = []
|
let allFields = []
|
||||||
for(const propName in fieldsObj){
|
for(const propName in fieldsObj){
|
||||||
const fieldRow = ui.create(`<div class="cols-2"><label>${fieldsObj[propName].label}</label></div>`)
|
const fieldRow = ui.create(`<div class="cols-2"><label>${fieldsObj[propName].label}</label></div>`)
|
||||||
@@ -18,11 +18,13 @@ app.helpers.formBuilder = {
|
|||||||
component.setAttribute('type','number')
|
component.setAttribute('type','number')
|
||||||
if('min' in fieldsObj[propName]) component.setAttribute('min', fieldsObj[propName].min)
|
if('min' in fieldsObj[propName]) component.setAttribute('min', fieldsObj[propName].min)
|
||||||
if('max' in fieldsObj[propName]) component.setAttribute('max', fieldsObj[propName].max)
|
if('max' in fieldsObj[propName]) component.setAttribute('max', fieldsObj[propName].max)
|
||||||
|
if(typeof(changeCB) == 'function') component.addEventListener('input', (evt) => { changeCB(evt, component) })
|
||||||
break
|
break
|
||||||
case 'string':
|
case 'string':
|
||||||
component = document.createElement('input')
|
component = document.createElement('input')
|
||||||
component.setAttribute('name',propName)
|
component.setAttribute('name',propName)
|
||||||
component.setAttribute('type','text')
|
component.setAttribute('type','text')
|
||||||
|
if(typeof(changeCB) == 'function') component.addEventListener('input', (evt) => { changeCB(evt, component) })
|
||||||
break
|
break
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
component = document.createElement('bz-toggler')
|
component = document.createElement('bz-toggler')
|
||||||
@@ -30,6 +32,7 @@ app.helpers.formBuilder = {
|
|||||||
component.setAttribute('trueValue','1')
|
component.setAttribute('trueValue','1')
|
||||||
component.setAttribute('falseValue','0')
|
component.setAttribute('falseValue','0')
|
||||||
fieldRow.append(component.el)
|
fieldRow.append(component.el)
|
||||||
|
if(typeof(changeCB) == 'function') component.addEventListener('change', (evt) => { changeCB(evt, component) })
|
||||||
break
|
break
|
||||||
case 'list':
|
case 'list':
|
||||||
component = document.createElement('bz-select')
|
component = document.createElement('bz-select')
|
||||||
@@ -37,6 +40,7 @@ app.helpers.formBuilder = {
|
|||||||
component.fillOptions( fieldsObj[propName].choices.map(item => {
|
component.fillOptions( fieldsObj[propName].choices.map(item => {
|
||||||
return({ markup: `${item}`, value: item})
|
return({ markup: `${item}`, value: item})
|
||||||
}))
|
}))
|
||||||
|
if(typeof(changeCB) == 'function') component.addEventListener('change', (evt) => { changeCB(evt, component) })
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.warn(`Unknown field type ${fieldsObj[propName].type}`)
|
console.warn(`Unknown field type ${fieldsObj[propName].type}`)
|
||||||
@@ -90,5 +94,4 @@ app.helpers.formBuilder = {
|
|||||||
return(result)
|
return(result)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ app.helpers.helpers3D = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getNamedParent(obj) {
|
getNamedParent(obj) {
|
||||||
while (obj && !obj.name) {
|
while (obj && ((!obj.name) || (obj.name.includes('_'))) ) {
|
||||||
obj = obj.parent
|
obj = obj.parent
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
|
|||||||
@@ -5,6 +5,25 @@ class KeyframesModel extends WindozModel {
|
|||||||
this.ressource = '/keyframes'
|
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) {
|
async create(kfData, prevKFId) {
|
||||||
let endpoint = {...app.config.api[this.ressource].create}
|
let endpoint = {...app.config.api[this.ressource].create}
|
||||||
return (
|
return (
|
||||||
@@ -24,6 +43,7 @@ class KeyframesModel extends WindozModel {
|
|||||||
const { position, speed, ...storeValues} = data[aid].values
|
const { position, speed, ...storeValues} = data[aid].values
|
||||||
return({
|
return({
|
||||||
aid: aid,
|
aid: aid,
|
||||||
|
type: data[aid].type,
|
||||||
storeValues: storeValues,
|
storeValues: storeValues,
|
||||||
gpsValues: { position: data[aid].values.position, speed: data[aid].values.speed }
|
gpsValues: { position: data[aid].values.position, speed: data[aid].values.speed }
|
||||||
})
|
})
|
||||||
|
|||||||
Vendored
+2
-2
@@ -32,7 +32,7 @@ bz-select > button::after {
|
|||||||
bz-select > div.options-container{
|
bz-select > div.options-container{
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2em;
|
top: 1.8em;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
@@ -45,7 +45,7 @@ bz-select option{
|
|||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
color: #000;
|
color: #000;
|
||||||
padding: 0.2em .2em .3em .5em;
|
padding: 0.2em .2em .5em .5em;
|
||||||
margin: -1em 0 0 0;
|
margin: -1em 0 0 0;
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: .3em;
|
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{
|
.kf-editor article.kfArena section{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
color: #DDD;
|
color: #DDD;
|
||||||
padding: 0 0 0 0;
|
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="onRemoveAgent"] { background-color: #A00; }
|
||||||
.kf-editor button[data-trigger="onSaveKF"] { background-color: #367; }
|
.kf-editor button[data-trigger="onSaveKF"] { background-color: #367; }
|
||||||
.kf-editor button[data-trigger="onResetKF"] { background-color: #A00; }
|
.kf-editor button[data-trigger="onResetKF"] { background-color: #A00; }
|
||||||
@@ -76,16 +76,21 @@
|
|||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
}
|
}
|
||||||
|
.kf-editor bz-select[data-output="keyframesSelector"]{
|
||||||
|
margin-top:1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="kf-editor cols-3">
|
<div class="kf-editor cols-3">
|
||||||
<article eiccard class="left-pane">
|
<article eiccard class="left-pane">
|
||||||
<section class="selector">
|
<section class="selector">
|
||||||
<header><h1>Agent type browser</h1></header>
|
<header><h1>Agent type browser</h1></header>
|
||||||
<canvas data-output="agentSampleCanvas"></canvas>
|
<canvas data-output="agentSampleCanvas"></canvas>
|
||||||
<bz-select label="Agent type..." data-output="agentsSelector"></bz-select>
|
<bz-select label="Select agent type..." data-output="agentsSelector"></bz-select>
|
||||||
</section>
|
</section>
|
||||||
<section class="browser">
|
<section class="browser">
|
||||||
<header><h1>Keyframes browser</h1></header>
|
<header><h1>Keyframes browser</h1></header>
|
||||||
|
<!-- Temporary... -->
|
||||||
|
<bz-select label="Existing keyframes..." data-output="keyframesSelector"></bz-select>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
<article eiccard class="kfArena">
|
<article eiccard class="kfArena">
|
||||||
|
|||||||
@@ -44,6 +44,16 @@ class KeyframeView extends WindozDomContent {
|
|||||||
this.agentPreview.startRendering()
|
this.agentPreview.startRendering()
|
||||||
this.agentPreview.animation = true
|
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 = new app.LoadedModules.kfArena(this.outputs.kfArenaCanvas, this.agentSprites)
|
||||||
this.kfArena.onclickAgent = this.onclickAgent.bind(this)
|
this.kfArena.onclickAgent = this.onclickAgent.bind(this)
|
||||||
this.kfArena.startRendering()
|
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){
|
onclickAgent(obj3D){
|
||||||
const aid = obj3D.name
|
const aid = obj3D.name
|
||||||
this.kfArena.highlighted3DObjects.length = 0 //truncate but keep the ref !
|
this.kfArena.highlighted3DObjects.length = 0 //truncate but keep the ref !
|
||||||
@@ -77,11 +98,13 @@ class KeyframeView extends WindozDomContent {
|
|||||||
this.currentlySelectedAid = null
|
this.currentlySelectedAid = null
|
||||||
} else { // Select
|
} else { // Select
|
||||||
this.currentlySelectedAid = aid
|
this.currentlySelectedAid = aid
|
||||||
this.kfArena.highlighted3DObjects.push(obj3D)
|
if(this.kfArena.agents[aid]) {
|
||||||
this.fillAgentProperties(aid, this.kfArena.agents[aid].props, this.kfArena.agents[aid].values)
|
this.kfArena.highlighted3DObjects.push(obj3D)
|
||||||
this.notUserChange = true
|
this.fillAgentProperties(aid, this.kfArena.agents[aid].props, this.kfArena.agents[aid].values)
|
||||||
this.outputs.agentsSelector.value = this.kfArena.agents[aid].type
|
this.notUserChange = true
|
||||||
this.notUserChange = false
|
this.outputs.agentsSelector.value = this.kfArena.agents[aid].type
|
||||||
|
this.notUserChange = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.updateKfButtons()
|
this.updateKfButtons()
|
||||||
}
|
}
|
||||||
@@ -100,11 +123,18 @@ class KeyframeView extends WindozDomContent {
|
|||||||
else { this.outputs.btnSaveKF.disabled = true }
|
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 = {}){
|
fillAgentProperties(aid, agentProps, agentValues = {}){
|
||||||
this.outputs.agentProperties.innerHTML = `
|
this.outputs.agentProperties.innerHTML = `
|
||||||
<div data-output="agentId">ID: ${aid}</div>
|
<div data-output="agentId">ID: ${aid}</div>
|
||||||
`
|
`
|
||||||
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({
|
this.outputs.agentProperties.append(...this.fieldsFromJSON({
|
||||||
"position.x": {
|
"position.x": {
|
||||||
label: "Position X",
|
label: "Position X",
|
||||||
@@ -121,7 +151,7 @@ class KeyframeView extends WindozDomContent {
|
|||||||
type: "number",
|
type: "number",
|
||||||
default: "0"
|
default: "0"
|
||||||
},
|
},
|
||||||
}, agentValues, 'Coordinates'))
|
}, agentValues, 'Coordinates', this.onPropsChanged.bind(this)))
|
||||||
this.outputs.agentProperties.append(...this.fieldsFromJSON({
|
this.outputs.agentProperties.append(...this.fieldsFromJSON({
|
||||||
"speed.x": {
|
"speed.x": {
|
||||||
label: "Speed X",
|
label: "Speed X",
|
||||||
@@ -138,21 +168,26 @@ class KeyframeView extends WindozDomContent {
|
|||||||
type: "number",
|
type: "number",
|
||||||
default: "0"
|
default: "0"
|
||||||
},
|
},
|
||||||
}, agentValues, 'Speed vector'))
|
}, agentValues, 'Speed vector', this.onPropsChanged.bind(this)))
|
||||||
this.outputs.btnAddAgent.disabled = false
|
this.outputs.btnAddAgent.disabled = false
|
||||||
this.setupRefs()
|
this.setupRefs()
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSaveKF(evt){
|
async onSaveKF(evt){
|
||||||
|
let result = { success: true }
|
||||||
if(!this.currentKeyframe.kfId){ // Create first (and get new kfId)
|
if(!this.currentKeyframe.kfId){ // Create first (and get new kfId)
|
||||||
this.currentKeyframe.kfName = this.outputs.kfName.value
|
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
|
this.currentKeyframe.kfId = result.payload.kfId
|
||||||
} else if(this.currentKeyframe.kfName != this.outputs.kfName.value){ //rename
|
} else if(this.currentKeyframe.kfName != this.outputs.kfName.value){ //rename
|
||||||
this.currentKeyframe.kfName = this.outputs.kfName.value
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result.success){
|
||||||
|
await this.models.keyframes.save(this.currentKeyframe.kfId, this.kfArena.agents)
|
||||||
}
|
}
|
||||||
await this.models.keyframes.save(this.currentKeyframe.kfId, this.kfArena.agents)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
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)
|
const agentObj = this.agentFromJSON(aid, agentSprite.asp_3d)
|
||||||
|
|
||||||
agentObj.position.set(values.position.x, values.position.z, values.position.y )
|
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])
|
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(){
|
// getAllAgents(){
|
||||||
// const agents = []
|
// const agents = []
|
||||||
// scene.traverse(o => o.name && names.push(o.name))
|
// scene.traverse(o => o.name && names.push(o.name))
|
||||||
|
|||||||
Reference in New Issue
Block a user