agent def + windows fixes + 2d view + 3d view

This commit is contained in:
STEINNI
2025-09-26 21:02:32 +00:00
parent 73e2b5a762
commit dd860b45a9
5 changed files with 177 additions and 107 deletions
+11 -7
View File
@@ -37,7 +37,7 @@ body[eicapp] {
grid-template-columns: min-content auto; grid-template-columns: min-content auto;
min-height: 100vh; min-height: 100vh;
box-sizing: border-box; box-sizing: border-box;
background: repeating-linear-gradient( -45deg, #000, #555 10px, #000 10px, #555 20px ); background: repeating-linear-gradient( -45deg, #000, #333 10px, #000 10px, #333 20px );
} }
[eicapp] [eicapptoolbar] { [eicapp] [eicapptoolbar] {
@@ -95,17 +95,20 @@ body[eicapp] {
bottom: auto; bottom: auto;
overflow: hidden; overflow: hidden;
z-index: 2; z-index: 2;
display: block;
grid-template-rows: min-content 1fr; grid-template-rows: min-content 1fr;
max-height: 90vh; max-height: 90vh;
max-width: 90vw; max-width: 90vw;
display: flex;
flex-direction: column;
} }
[eicapp] .app-workspace .window.active { [eicapp] .app-workspace .window.active {
z-index: 3; z-index: 3;
background: var(--app-color-primary); background: var(--app-color-primary);
border-radius: .3rem; border-radius: .3rem;
} }
[eicapp] .app-workspace .window > header { display: grid; } [eicapp] .app-workspace .window > header {
flex: 0 0 auto;
}
[eicapp] .app-workspace .window > header h1 { [eicapp] .app-workspace .window > header h1 {
padding: var(--eicui-base-spacing-xs); padding: var(--eicui-base-spacing-xs);
color: var(--app-color-white); color: var(--app-color-white);
@@ -125,12 +128,13 @@ body[eicapp] {
[eicapp] .app-workspace .window > header .controls button.expand { display: inline-flex; } [eicapp] .app-workspace .window > header .controls button.expand { display: inline-flex; }
[eicapp] .app-workspace .window > header .controls button.shrink { display: none; } [eicapp] .app-workspace .window > header .controls button.shrink { display: none; }
[eicapp] .app-workspace .window > section { [eicapp] .app-workspace .window > section {
padding: var(--eicui-base-spacing-xs) var(--eicui-base-spacing-s); padding: var(--eicui-base-spacing-2xs) var(--eicui-base-spacing-2xs);
/*background: var(--app-bg-color);*/
cursor: default; cursor: default;
margin: 0; margin: 0;
overflow: auto; overflow: auto;
transition: all 0.5s; transition: all 0.5s;
flex: 1 1 auto;
} }
[eicapp] .app-workspace .window[device="tablet"] > section { [eicapp] .app-workspace .window[device="tablet"] > section {
padding: 0; padding: 0;
@@ -142,8 +146,8 @@ body[eicapp] {
box-shadow: none; box-shadow: none;
width: 100%; width: 100%;
max-width:none; max-width:none;
padding: 0 var(--eicui-base-spacing-2xs) var(--eicui-base-spacing-3xl) var(--eicui-base-spacing-2xs); padding: 0 var(--eicui-base-spacing-2xs) 0 var(--eicui-base-spacing-2xs);
background: repeating-linear-gradient( -45deg, #000, #555 10px, #000 10px, #555 20px ); background: repeating-linear-gradient( -45deg, #000, #333 10px, #000 10px, #333 20px );
cursor: default; cursor: default;
margin: 0; margin: 0;
overflow: visible; overflow: visible;
@@ -17,12 +17,37 @@ class DashboardsController extends EICController {
this.loadWindow( this.loadWindow(
'dashboards/MainDashboardView', 'dashboards/MainDashboardView',
{ {
title: 'Main dashboard', title: '3D view',
static: true, static: true,
expanded: true expanded: false,
windowStyle:{
width: '800px',
height: '600px',
left: '50px',
top: '100px',
}
}, },
{ {
models: models models: models,
camName: 'persp1'
}
)
this.loadWindow(
'dashboards/MainDashboardView',
{
title: '2D View',
static: true,
expanded: false,
windowStyle:{
width: '600px',
height: '450px',
right:'10px',
top:'100px',
}
},
{
models: models,
camName: 'cam2Dtop'
} }
) )
} }
+7 -1
View File
@@ -103,6 +103,11 @@ class EICController extends Controller {
<section></section> <section></section>
</div>`); </div>`);
if(options.expanded) content.setAttribute('expanded',''); if(options.expanded) content.setAttribute('expanded','');
if(options.windowStyle){
for(const k in options.windowStyle){
content.style[k] = options.windowStyle[k]
}
}
let container = content.querySelector('section'); let container = content.querySelector('section');
container.innerHTML = Controller.processTemplate(options.name, html, data); container.innerHTML = Controller.processTemplate(options.name, html, data);
@@ -291,7 +296,8 @@ class EICController extends Controller {
} }
attach(content) { attach(content) {
ui.show(content.view.el,!content.expanded ? 'grid': 'block'); //ui.show(content.view.el,!content.expanded ? 'grid': 'block');
ui.show(content.view.el, 'flex');
content.visible = true; content.visible = true;
} }
+62 -32
View File
@@ -5,49 +5,87 @@ export class Threetobus{
constructor(canvasEl){ constructor(canvasEl){
this.canvasEl = canvasEl this.canvasEl = canvasEl
this.cameras = {}
} }
init(){ initScene(){
// Scene // Scene
this.scene = new THREE.Scene() this.scene = new THREE.Scene()
//scene.background = new THREE.Color(0x202080)
// Camera // Cameras
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) this.cameras.persp1 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
this.camera.position.set(3, 3, 5) this.cameras.persp1.position.set(3, 3, 5)
const aspect = window.innerWidth / window.innerHeight
const frustumSize = 10
this.cameras.cam2Dtop = new THREE.OrthographicCamera(
-frustumSize * aspect / 2,
frustumSize * aspect / 2,
frustumSize / 2,
-frustumSize / 2,
0.1,
1000
)
this.cameras.cam2Dtop.position.set(0, 100, 0)
this.cameras.cam2Dtop.lookAt(0, 0, 0)
//this.camera = this.cameras.persp1
// Renderer // Lights
this.renderer = new THREE.WebGLRenderer({ antialias: true, canvas: this.canvasEl })
//renderer.setSize(window.innerWidth, window.innerHeight)
// Cube
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshStandardMaterial({ color: 'red' })
this.cube = new THREE.Mesh(geometry, material)
this.scene.add(this.cube)
this.cube.position.x+=2
// Light
const light = new THREE.DirectionalLight(0xffffff, 1) const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(5, 5, 5) light.position.set(5, 5, 5)
light.intensity = 2 light.intensity = 2
this.scene.add(light) this.scene.add(light)
this.scene.add(new THREE.AmbientLight(0xffffff, 0.4)) this.scene.add(new THREE.AmbientLight(0xffffff, 0.4))
// Renderer
this.renderer = new THREE.WebGLRenderer({ antialias: true, canvas: this.canvasEl })
}
startRendering(){
//controls
this.controls = new OrbitControls(this.camera, this.renderer.domElement) this.controls = new OrbitControls(this.camera, this.renderer.domElement)
this.renderer.render(this.scene, this.camera) //this.renderer.render(this.scene, this.camera)
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
this.camera.aspect = window.innerWidth / window.innerHeight this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix() this.camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight) renderer.setSize(window.innerWidth, window.innerHeight)
}) })
this.animate()
this._render() this.render()
}
changeCamera(camName){
if(camName in this.cameras){
this.camera = this.cameras[camName]
}
}
buildFromJSON(desc){
let obj
if(desc.type === 'Mesh') {
const geom = new THREE[desc.geometry.type](...(desc.geometry.args || []))
const mat = new THREE[desc.material.type]( desc.material.color ? { color: desc.material.color } : {} )
obj = new THREE.Mesh(geom, mat)
} else if(desc.type === 'Group') {
obj = new THREE.Group()
} else {
throw new Error("Unknown type: " + desc.type)
}
// Apply transforms
if(desc.position) obj.position.set(...desc.position)
if(desc.rotation) obj.rotation.set(...desc.rotation)
if(desc.scale) obj.scale.set(...desc.scale)
// Recursively add children
if(desc.children) {
desc.children.forEach(childDesc => {
obj.add(this.buildFromJSON(childDesc))
})
}
return obj
} }
_resizeRendererToDisplaySize() { _resizeRendererToDisplaySize() {
@@ -61,24 +99,16 @@ export class Threetobus{
return false return false
} }
_render() { render() {
if(this._resizeRendererToDisplaySize()) { if(this._resizeRendererToDisplaySize()) {
this.camera.aspect = this.renderer.domElement.clientWidth / this.renderer.domElement.clientHeight this.camera.aspect = this.renderer.domElement.clientWidth / this.renderer.domElement.clientHeight
this.camera.updateProjectionMatrix() this.camera.updateProjectionMatrix()
} }
this.renderer.render(this.scene, this.camera) this.renderer.render(this.scene, this.camera)
requestAnimationFrame(this._render.bind(this)) requestAnimationFrame(this.render.bind(this))
} }
animate() {
requestAnimationFrame(this.animate.bind(this))
this.cube.rotation.x += 0.01
this.cube.rotation.y += 0.01
this.controls.update()
this.renderer.render(this.scene, this.camera)
}
} }
+38 -33
View File
@@ -1,23 +1,33 @@
class MainDashboardView extends EICDomContent { class MainDashboardView extends EICDomContent {
//TODO should come from the API, from some sprites lib. (allow switching representations)
agentTypes = { agentTypes = {
molecule1:{ molecule1:{
type: 'circle', "type": "Mesh",
attrs: { "geometry": { "type": "BoxGeometry", "args": [1, 1, 1] },
r: 10, "material": { "type": "MeshStandardMaterial", "color": "orange" },
fill: '#BFB', "children": [
stroke: "#0A0", {
strokeWidth: 2, "type": "Mesh",
"geometry": { "type": "SphereGeometry", "args": [0.3, 16, 16] },
"material": { "type": "MeshStandardMaterial", "color": "blue" },
"position": [0, 0.5, 0]
} }
]
}, },
molecule2:{ molecule2:{
type: 'circle', "type": "Mesh",
attrs: { "geometry": { "type": "SphereGeometry", "args": [1, 1, 1] },
r: 10, "material": { "type": "MeshStandardMaterial", "color": "green" },
fill: '#BBF', "children": [
stroke: "#00A", {
strokeWidth: 2, "type": "Mesh",
"geometry": { "type": "SphereGeometry", "args": [0.3, 16, 16] },
"material": { "type": "MeshStandardMaterial", "color": "red" },
"position": [0, 1, 0]
} }
]
} }
} }
@@ -25,9 +35,18 @@ class MainDashboardView extends EICDomContent {
constructor() { constructor() {
super() super()
Object.assign(this, app.helpers.activeAttributes) Object.assign(this, app.helpers.activeAttributes)
//this.tileMarkup = app.Assets.Store.html['/app/assets/html/mailing/tile.html']
} }
DOMContentFocused(options) {
// Avoid 2nd refesh on DomContentLoaded
if(this.wasBlured){
//this.refreshyoustuff()
}
this.wasBlured = false
}
DOMContentBlured(options) { this.wasBlured = true }
DOMContentLoaded(options) { DOMContentLoaded(options) {
for(let model in options.models) this[model] = options.models[model] for(let model in options.models) this[model] = options.models[model]
const components = ui.eicfy(this.el) const components = ui.eicfy(this.el)
@@ -35,30 +54,16 @@ class MainDashboardView extends EICDomContent {
this.setupRefs(components) this.setupRefs(components)
this.ttb = new app.LoadedModules.Threetobus(this.outputs.paper43) this.ttb = new app.LoadedModules.Threetobus(this.outputs.paper43)
this.ttb.init() this.ttb.initScene()
this.ttb.changeCamera(options.camName)
this.ttb.startRendering()
const m1 = this.ttb.buildFromJSON(this.agentTypes.molecule1)
m1.name = 'toto'
this.ttb.scene.add(m1)
} }
DOMContentFocused(options) {
// Avoid 2nd refesh on DomContentLoaded
if(this.wasBlured){
//this.refreshSearch()
}
this.wasBlured = false
}
DOMContentBlured(options) { this.wasBlured = true }
createAgent(agentType, id, x, y){
if(!Object.keys(this.agentTypes).includes(agentType)) return
this.agentTypes[agentType]
const svgAgent = this.snaptobus.snap[this.agentTypes[agentType].type]().attr(this.agentTypes[agentType].attrs)
svgAgent.attr({
id: id,
cx: x,
cy:y,
})
}
} }