logs in console, caching in getAgentProps, console createAgent independent of GUI
This commit is contained in:
@@ -1,32 +1,77 @@
|
||||
if(!app.helpers) app.helpers = {}
|
||||
/**
|
||||
* Mixing add-in methods to your view instance.
|
||||
* All of this should not be a helper, but inherited this from WindozDomContent, but not my framework anymore.
|
||||
* All of this should not be a helper, but inherited this from EICDomContent, but not my framework anymore.
|
||||
* @category MyEic
|
||||
*/
|
||||
app.helpers.activeAttributes = {
|
||||
|
||||
/**
|
||||
* setupTriggers adds all click (data-trigger) and change (data-change) handlers.
|
||||
* handlers should have the signatue : onXyz(component, event), will spit a warning if the handler doesn't exist.
|
||||
* setupTriggers is re-entrant: it can be called again after refreshing part of the view
|
||||
* @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) )
|
||||
*/
|
||||
setupTriggers(components){ // Should inherit this from WindozDomContent, but not my framework anymore.
|
||||
for(let component of components.filter(component => component.el.hasAttribute('data-trigger'))) {
|
||||
_triggersRegister: { 'click': new WeakMap(), 'change': new WeakMap()},
|
||||
setupTriggers(components = []){ // Should inherit this from EICDomContent, but not my framework anymore.
|
||||
for(let component of components.filter(component => component.el.hasAttribute('data-trigger'))) { //components with or without click property
|
||||
if(typeof this[component.el.dataset.trigger] !== 'function') {
|
||||
console.warn(`data-trigger without corresponding method : ${component.el.dataset.trigger}`)
|
||||
continue
|
||||
}
|
||||
component.click = this[component.el.dataset.trigger].bind(this, component)
|
||||
if(component.click) component.click = this[component.el.dataset.trigger].bind(this, component)
|
||||
else {
|
||||
const oldTrigger = this._triggersRegister.click.get(component.el)
|
||||
if(oldTrigger) component.el.removeEventListener('click', oldTrigger)
|
||||
const newTrigger = this[component.el.dataset.trigger].bind(this, component)
|
||||
this._triggersRegister.click.set(component.el, newTrigger)
|
||||
component.el.addEventListener('click', newTrigger)
|
||||
}
|
||||
}
|
||||
for(let component of components.filter(component => component.el.hasAttribute('data-change'))) {
|
||||
if(this.el){ // for views and other content-based classes, add triggers on simple non-component elements
|
||||
for(const el of this.el.querySelectorAll('[data-trigger]:not([data-eicui-id])')){
|
||||
if(typeof this[el.dataset.trigger] !== 'function') {
|
||||
console.warn(`data-trigger without corresponding method : ${el.dataset.trigger}`)
|
||||
continue
|
||||
}
|
||||
const oldTrigger = this._triggersRegister.click.get(el)
|
||||
if(oldTrigger) el.removeEventListener('click', oldTrigger)
|
||||
const newTrigger = this[el.dataset.trigger].bind(this)
|
||||
this._triggersRegister.click.set(el, newTrigger)
|
||||
el.addEventListener('click', newTrigger)
|
||||
}
|
||||
}
|
||||
|
||||
for(let component of components.filter(component => component.el.hasAttribute('data-change'))) { //components with or without click property
|
||||
if(typeof this[component.el.dataset.change] !== 'function') {
|
||||
console.warn(`data-change without corresponding method : ${component.el.dataset.trigger}`)
|
||||
console.warn(`data-change without corresponding method : ${component.el.dataset.change}`)
|
||||
continue
|
||||
}
|
||||
component.el.addEventListener("change",this[component.el.dataset.change].bind(this, component))
|
||||
if(component.el.type=='text') component.el.addEventListener("keyup",this[component.el.dataset.change].bind(this, component))
|
||||
const oldTrigger = this._triggersRegister.change.get(component.el)
|
||||
if(oldTrigger) {
|
||||
component.el.removeEventListener('change', oldTrigger)
|
||||
component.el.removeEventListener('keyup', oldTrigger)
|
||||
}
|
||||
const newTrigger = this[component.el.dataset.change].bind(this, component)
|
||||
this._triggersRegister.change.set(component.el, newTrigger)
|
||||
component.el.addEventListener("change", newTrigger)
|
||||
if(component.el.type=='text') component.el.addEventListener("keyup", newTrigger)
|
||||
}
|
||||
if(this.el){ // for views and other content-based classes, add triggers on simple non-component elements
|
||||
for(const el of this.el.querySelectorAll('[data-change]:not([data-eicui-id])')){
|
||||
if(typeof this[el.dataset.change] !== 'function') {
|
||||
console.warn(`data-change without corresponding method : ${el.dataset.change}`)
|
||||
continue
|
||||
}
|
||||
const oldTrigger = this._triggersRegister.change.get(el)
|
||||
if(oldTrigger) {
|
||||
el.removeEventListener('change', oldTrigger)
|
||||
el.removeEventListener('keyup', oldTrigger)
|
||||
}
|
||||
const newTrigger = this[el.dataset.change].bind(this)
|
||||
this._triggersRegister.change.set(el, newTrigger)
|
||||
el.addEventListener('change', newTrigger)
|
||||
if(el.type=='text') el.addEventListener('keyup', newTrigger)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -39,7 +84,7 @@ app.helpers.activeAttributes = {
|
||||
* setupRefs is re-entrant: it can be called again after refreshing part of the view
|
||||
* @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) )
|
||||
*/
|
||||
setupRefs(components = []){
|
||||
setupRefs(components=[]){
|
||||
if(!this.components) this.components = {}
|
||||
for(let component of components.filter(component => component.el.hasAttribute('data-ref'))) {
|
||||
this.components[component.el.dataset.ref] = component
|
||||
@@ -61,7 +106,6 @@ app.helpers.activeAttributes = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* output (singular) : this.output('mydiv', '<p>Some markup</p>') places markup in a data-output node
|
||||
* @param {*} name
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { PDBLoader } from 'three/examples/jsm/loaders/PDBLoader.js'
|
||||
|
||||
async function loadMolecule(url) {
|
||||
const loader = new PDBLoader()
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
loader.load(
|
||||
url,
|
||||
pdb => {
|
||||
// pdb contient:
|
||||
// pdb.geometryAtoms : BufferGeometry des atomes
|
||||
// pdb.geometryBonds : BufferGeometry des liaisons
|
||||
// pdb.json : infos (numéro atomique, couleurs…)
|
||||
|
||||
const group = new THREE.Group()
|
||||
|
||||
// --- Atomes ---
|
||||
const atomsGeo = pdb.geometryAtoms
|
||||
const atomsInfo = pdb.json.atoms
|
||||
|
||||
for (let i = 0; i < atomsInfo.length; i++) {
|
||||
const atom = atomsInfo[i]
|
||||
|
||||
const position = new THREE.Vector3(
|
||||
atomsGeo.attributes.position.getX(i),
|
||||
atomsGeo.attributes.position.getY(i),
|
||||
atomsGeo.attributes.position.getZ(i)
|
||||
)
|
||||
|
||||
const color = new THREE.Color(atom.color)
|
||||
const radius = atom.radius
|
||||
|
||||
const sphere = new THREE.Mesh(
|
||||
new THREE.SphereGeometry(radius, 32, 16),
|
||||
new THREE.MeshPhongMaterial({ color })
|
||||
)
|
||||
|
||||
sphere.position.copy(position)
|
||||
group.add(sphere)
|
||||
}
|
||||
|
||||
// --- Liaisons ---
|
||||
const bondsGeo = pdb.geometryBonds
|
||||
|
||||
for (let i = 0; i < bondsGeo.attributes.position.count; i += 2) {
|
||||
const start = new THREE.Vector3().fromBufferAttribute(bondsGeo.attributes.position, i)
|
||||
const end = new THREE.Vector3().fromBufferAttribute(bondsGeo.attributes.position, i + 1)
|
||||
|
||||
const bondLength = start.distanceTo(end)
|
||||
|
||||
const cyl = new THREE.Mesh(
|
||||
new THREE.CylinderGeometry(0.1, 0.1, bondLength, 16),
|
||||
new THREE.MeshPhongMaterial({ color: 0xffffff })
|
||||
)
|
||||
|
||||
// Orienter et positionner le cylindre
|
||||
cyl.position.copy(start).lerp(end, 0.5)
|
||||
cyl.lookAt(end)
|
||||
cyl.rotateX(Math.PI / 2)
|
||||
|
||||
group.add(cyl)
|
||||
}
|
||||
|
||||
resolve(group)
|
||||
},
|
||||
undefined,
|
||||
reject
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
if(!app.helpers) app.helpers = {}
|
||||
app.helpers.kfConsole = {
|
||||
|
||||
async execCommand(event){
|
||||
if(this.outputs.commands.value.trim()=='\\help'){
|
||||
this.outputs.commands.value = ''
|
||||
this.outputs.results.innerHTML += await app.Assets.loadHtml({ name: 'help/KFconsoleHelp.html' })
|
||||
this.setupTriggers()
|
||||
} else if(this.outputs.commands.value.trim()=='\\clear'){
|
||||
this.outputs.commands.value = ''
|
||||
this.outputs.results.innerHTML = ''
|
||||
} else {
|
||||
this.outputs.results.innerHTML += await this.evalCmd(this.outputs.commands.value)
|
||||
}
|
||||
const lines = this.outputs.results.querySelectorAll('div.line')
|
||||
if(lines.length > 100) {
|
||||
for(let i=0; i<(lines.length-100); i++) lines[i].remove()
|
||||
}
|
||||
this.outputs.results.scrollTo({ top: this.outputs.results.scrollHeight, behavior: 'smooth' })
|
||||
},
|
||||
|
||||
onSnippet(evt){
|
||||
const snippetName = evt.target.dataset.snippet
|
||||
const codeDiv = this.outputs.results.querySelector(`div.snippet[data-snippet="${snippetName}"]`)
|
||||
if(codeDiv){ this.outputs.commands.value = codeDiv.textContent }
|
||||
},
|
||||
|
||||
async evalCmd(code){
|
||||
const api = {
|
||||
log: (...args) => {
|
||||
const res=[]
|
||||
for(const arg of args){
|
||||
if(typeof(arg)=='string') res.push(arg)
|
||||
else res.push(JSON.stringify(arg))
|
||||
}
|
||||
return(res)
|
||||
},
|
||||
createAgent: async (type, properties) => {
|
||||
if(Array.from(this.outputs.agentsSelector.options).find(item => item.value==type)){
|
||||
const defaultValues = await this.models.agents.getDefaultProps(type)
|
||||
console.log('==deflt===>', defaultValues,)
|
||||
return(await this.newAgent(type, { ...defaultValues, ...properties })) //TODO: deepMerge
|
||||
} else {
|
||||
throw(`Invalid agent type: ${type}`)
|
||||
}
|
||||
},
|
||||
removeAgent: (aid) => {
|
||||
|
||||
},
|
||||
updateAgent: (aid, properties) => {
|
||||
|
||||
},
|
||||
listagentTypes: () => {
|
||||
|
||||
},
|
||||
}
|
||||
try {
|
||||
const fn = new Function(...Object.keys(api), `
|
||||
return(
|
||||
(async () => {
|
||||
const logs = []
|
||||
const log = (...args) => {
|
||||
for(const arg of args){
|
||||
if(typeof(arg)=='string') logs.push(arg)
|
||||
else logs.push(JSON.stringify(arg))
|
||||
}
|
||||
}
|
||||
${code}
|
||||
return(logs)
|
||||
})()
|
||||
)
|
||||
`)
|
||||
|
||||
const res = await fn(...Object.values(api))
|
||||
return(
|
||||
'<div class="line">'+
|
||||
res.map(item => {
|
||||
if(typeof(item) == 'object') return(JSON.stringify(item))
|
||||
return(item)
|
||||
}).join('</div><div class="line">')
|
||||
+'</div>'
|
||||
)
|
||||
} catch (err) {
|
||||
return(`<div class="error">${err.name}: ${err.message}</div>`)
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user