started sims section & axes&grid settings for KFEditor

This commit is contained in:
STEINNI
2026-06-05 15:45:27 +00:00
parent ce9e73ac41
commit 5207a3b18e
13 changed files with 309 additions and 7 deletions
+20
View File
@@ -1,4 +1,24 @@
[ [
{
"label": "Simulations Management",
"icon": "icon-lab2",
"collapsed": true,
"access": ["*"],
"items": [
{
"label": "Create a simulation",
"icon": "icon-new",
"route": "/sims/create",
"access": ["*"]
},
{
"label": "Play / Pause a simulation",
"icon": "icon-file-play",
"route": "/sims/manage",
"access": ["*"]
}
]
},
{ {
"label": "Live Arena", "label": "Live Arena",
"icon": "icon-bolt", "icon": "icon-bolt",
+59 -6
View File
@@ -27,6 +27,7 @@
--app-menu-collapsed-width: 50px; --app-menu-collapsed-width: 50px;
--app-menu-expanded-width: 160px; --app-menu-expanded-width: 160px;
--app-menu-hover-max-width: 400px;
--app-menu-width: var(--app-menu-expanded-width); --app-menu-width: var(--app-menu-expanded-width);
@@ -80,6 +81,53 @@ menu[eicmenu] [menuitem] > a > i, menu[eicmenu] [menuitem] > .nolink > i{
menu[eicmenu] [menuitem] > a > button, menu[eicmenu] [menuitem] > .nolink button { menu[eicmenu] [menuitem] > a > button, menu[eicmenu] [menuitem] > .nolink button {
background: var(--app-color-primary); background: var(--app-color-primary);
} }
/* Submenu vertical expand/collapse (overrides EICUI height:0 which breaks transitions) */
menu[eicmenu].app-menu > [menuitem] > ul {
max-height: 30rem;
height: auto !important;
overflow: hidden;
transition: max-height 0.6s ease-in-out, opacity 0.3s ease-in-out, padding 0.3s ease-in-out;
}
menu[eicmenu].app-menu > [menuitem] > ul[collapsed] {
max-height: 0;
height: auto !important;
padding-top: 0;
padding-bottom: 0;
}
/* Collapsed app menu: show main section icons, hide sub-entries */
menu[eicmenu].app-menu[collapsed] {
width: max-content;
transition: max-width 0.3s ease-in-out;
}
menu[eicmenu].app-menu[collapsed]:not(:hover) {
max-width: var(--app-menu-collapsed-width);
overflow-x: hidden;
}
menu[eicmenu].app-menu[collapsed]:hover {
max-width: var(--app-menu-hover-max-width);
overflow-x: hidden;
}
menu[eicmenu].app-menu[collapsed]:not(:hover) > [menuitem] > .nolink {
display: flex;
justify-content: center;
padding: var(--eicui-base-spacing-xs);
}
menu[eicmenu].app-menu[collapsed]:not(:hover) > [menuitem] > .nolink > label,
menu[eicmenu].app-menu[collapsed]:not(:hover) > [menuitem] > .nolink > button {
display: none;
}
menu[eicmenu].app-menu[collapsed]:not(:hover) > [menuitem] > .nolink > i {
font-size: larger;
margin: 0;
}
menu[eicmenu].app-menu[collapsed]:not(:hover) > [menuitem] > ul {
max-height: 0 !important;
opacity: 0;
padding: 0;
}
[eicapp] .app-workspace { [eicapp] .app-workspace {
display: grid; display: grid;
/* /*
@@ -366,7 +414,7 @@ input{
padding-left: 1em; padding-left: 1em;
box-sizing: border-box; box-sizing: border-box;
height: 2em; height: 2em;
background-color: #6B5; background-color: #CFC;
border: none; border: none;
} }
@@ -382,14 +430,19 @@ bz-select > button{
color:#EEE; color:#EEE;
} }
bz-select > button::after{ color:#EEE; } bz-select > button::after{ color:#EEE; }
bz-select option{ bz-select option,
div.options-container.portaled option{
background-color: #676; background-color: #676;
color: #EEE; color: #EEE;
} }
bz-select option i{ margin-right:0.3em; } bz-select option i,
bz-select option i.icon-atom1{ color:#FF4; } div.options-container.portaled option i{ margin-right:0.3em; }
bz-select option i.icon-bug{ color:#4DF; } bz-select option i.icon-atom1,
bz-select > div.options-container.open { max-height: 20em; } div.options-container.portaled option i.icon-atom1{ color:#FF4; }
bz-select option i.icon-bug,
div.options-container.portaled option i.icon-bug{ color:#4DF; }
bz-select > div.options-container.open,
div.options-container.portaled.open { max-height: 20em; }
bz-toggler div.toggle-switch span.toggle-bar { background-color: #473; } bz-toggler div.toggle-switch span.toggle-bar { background-color: #473; }
bz-toggler div.toggle-switch span.toggle-thumb { background-color:#9D8; } bz-toggler div.toggle-switch span.toggle-thumb { background-color:#9D8; }
+5
View File
@@ -20,6 +20,11 @@
"url": "/editors", "url": "/editors",
"role": [ "*" ], "role": [ "*" ],
"controller" : "/editors/EditorsController" "controller" : "/editors/EditorsController"
},
{
"url": "/sims",
"role": [ "*" ],
"controller" : "/sims/SimsController"
}, },
{ {
"url": "/system", "url": "/system",
+51
View File
@@ -0,0 +1,51 @@
class SimsController extends WindozController {
constructor(params) {
super(params)
}
async create() {
const models = {
sims: new SimsModel('/sims'),
keyframes: new KeyframesModel('/keyframes')
}
this.loadWindow(
'sims/CreateSimView',
{
title: '<i class="icon-new"></i> Create a simulation',
static: true,
expanded: false,
withSettings: false,
windowStyle: WindozDomContent.boxFromPrefs('sims.createsimview', { x: 50, y: 50, w: 800, h: 600 }),
},
{
models: models,
}
)
}
async manage() {
const models = {
sims: new SimsModel('/sims')
}
this.loadWindow(
'sims/ManageSimView',
{
title: '<i class="icon-file-play"></i> Play / Pause a simulation',
static: true,
expanded: false,
withSettings: false,
windowStyle: WindozDomContent.boxFromPrefs('sims.managesimview', { x: 50, y: 50, w: 800, h: 600 }),
},
{
models: models,
}
)
}
}
app.registerClass('SimsController', SimsController)
+36
View File
@@ -0,0 +1,36 @@
{
"routes": [
{
"url": "/create",
"role": [ "*" ],
"controller" : "/sims/SimsController",
"method": "create"
},
{
"url": "/manage",
"role": [ "*" ],
"controller" : "/sims/SimsController",
"method": "manage"
}
],
"models": [
"SimsModel",
"KeyframesModel"
],
"views": [
"sims/CreateSimView",
"sims/ManageSimView"
],
"controllerDependencies": [
"/helpers/basicDialogs",
"/helpers/activeAttributes"
],
"assets": {
"styles": [
],
"html": [
],
"json": [
]
}
}
+34
View File
@@ -0,0 +1,34 @@
class SimsModel extends WindozModel {
constructor() {
super()
this.ressource = '/sims'
}
async list() {
// TODO: implement
return([])
}
async get(simId) {
// TODO: implement
return(null)
}
async create(simData) {
// TODO: implement
return(null)
}
async start(simId) {
// TODO: implement
return(null)
}
async pause(simId) {
// TODO: implement
return(null)
}
}
app.registerClass('SimsModel', SimsModel)
+20
View File
@@ -68,6 +68,15 @@ class KeyframeView extends WindozDomContent {
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()
this.output('settingsMenu', app.Assets.Store.html.spaceViewSetting)
this.outputs.settingsMenu.querySelectorAll('input[type="toggler"]').forEach(el => {
const tog = new InputToggler(el)
if(this.kfArena[tog._el.name]?.layers){
tog.value = this.kfArena.camera.layers.test(this.kfArena[tog._el.name].layers) ? 'yes' : 'no'
}
tog.onToggle = this.settingsToggle.bind(this)
})
this.outputs.btnAddAgent.disabled = true this.outputs.btnAddAgent.disabled = true
this.outputs.btnRemoveAgent.disabled = true this.outputs.btnRemoveAgent.disabled = true
@@ -77,6 +86,17 @@ class KeyframeView extends WindozDomContent {
this.currentlySelectedAid = null this.currentlySelectedAid = null
} }
settingsToggle(value, object){
if(['grid','axes'].includes(object._el.name)){
const layerId = {'grid':1,'axes':2}[object._el.name]
if(value=='yes'){
this.kfArena.camera.layers.enable(layerId)
} else {
this.kfArena.camera.layers.disable(layerId)
}
}
}
deselectSceneAgent(){ deselectSceneAgent(){
if(!this.currentlySelectedAid) return if(!this.currentlySelectedAid) return
const obj3D = this.kfArena.scene.getObjectByName(this.currentlySelectedAid) const obj3D = this.kfArena.scene.getObjectByName(this.currentlySelectedAid)
+25
View File
@@ -0,0 +1,25 @@
<style>
.create-sim section {
padding: 1em;
}
.create-sim bz-select[data-output="keyframesSelector"] {
margin-top: 1em;
}
.create-sim .cols-2 { align-items: baseline; }
</style>
<article eiccard class="create-sim">
<header>
<h1>Create a simulation</h1>
</header>
<section>
<div class="cols-2">
<label>Simulation first keyframe:</label>
<bz-select label="Existing keyframes..." data-output="keyframesSelector"></bz-select>
</div>
<div class="cols-2">
<label>Simulation Name:</label>
<input type="text" data-output="simName" placeholder="(min 5 chars)"/>
</div>
<button eicbutton rounded data-output="btnCreateSim" data-trigger="onCreateSim">Create Simulation</button>
</section>
</article>
+30
View File
@@ -0,0 +1,30 @@
class CreateSimView extends WindozDomContent {
constructor() {
super()
Object.assign(this, app.helpers.activeAttributes, app.helpers.basicDialogs)
}
async DOMContentLoaded(options) {
this.models = options.models
const components = ui.eicfy(this.el)
this.setupRefs(components)
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))
}
onChangeKeyframe(event) {
if(!this.outputs.keyframesSelector.value) return
// TODO: use selected keyframe for simulation creation
}
}
app.registerClass('CreateSimView', CreateSimView)
+8
View File
@@ -0,0 +1,8 @@
<article eiccard class="manage-sim">
<header>
<h1>Play / Pause a simulation</h1>
</header>
<section>
<p>TODO: simulation play / pause controls</p>
</section>
</article>
+15
View File
@@ -0,0 +1,15 @@
class ManageSimView extends WindozDomContent {
constructor() {
super()
Object.assign(this, app.helpers.basicDialogs)
}
async DOMContentLoaded(options) {
this.models = options.models
ui.eicfy(this.el)
// TODO: implement
}
}
app.registerClass('ManageSimView', ManageSimView)
+5
View File
@@ -0,0 +1,5 @@
In SPARC, the app menu is created from app/assets/json/global/app-menu-map.json
Each entry defines a route.
A "high level" route is then configured in app/config/baseRoutes.json that delegates a group of URLs to a controller.
Then, a controller, in its associated .json file defines in its "routes" section the sub-route managed by the controller,
and the method to be called inside that controller.