UNPKG

agentscript

Version:

AgentScript Model in Model/View architecture

301 lines (262 loc) 9.59 kB
import * as util from './utils.js' import TwoView from '../src/TwoView.js' import ColorMap from '../src/ColorMap.js' /** * Basic 2D view. * */ class TwoDraw extends TwoView { static defaultOptions(model) { return { patchesColor: 'random', initPatches: null, turtles: model.turtles, turtlesColor: 'random', turtlesStrokeColor: 'random', turtlesShape: 'dart', turtlesSize: 1, turtlesRotate: true, links: model.links, linksColor: 'random', linksWidth: 1, textProperty: null, textSize: 0.5, textColor: 'black', patchesMap: 'DarkGray', turtlesMap: 'Basic16', } } static drawKeys() { const defaults = this.defaultOptions({}) return Object.keys(defaults) } static separateDrawOptions(viewOptions, drawOptions) { if (viewOptions.drawOptions) { // drawOptions = viewOptions.drawOptions Object.assign(drawOptions, viewOptions.drawOptions) delete viewOptions.drawOptions } const keys = TwoDraw.drawKeys() keys.forEach(k => { if (viewOptions[k]) { drawOptions[k] = viewOptions[k] delete viewOptions[k] } }) return drawOptions // return [viewOptions, drawOptions] } static fullScreenOptions(patchSize, background = 'black', margin = 10) { document.body.style.backgroundColor = background document.body.style.margin = `${margin}px` const width = window.innerWidth - 2 * margin // - 2 const height = window.innerHeight - 2 * margin // - 2 const maxX = Math.floor(width / (2 * patchSize)) const maxY = Math.floor(height / (2 * patchSize)) const maxZ = 1 return { maxX: maxX, maxY: maxY, maxZ: maxZ, minX: -maxX, minY: -maxY, minZ: -maxZ, } } // ====================== constructor(model, viewOptions = {}, drawOptions = {}) { // if (viewOptions.drawOptions) { // drawOptions = viewOptions.drawOptions // delete viewOptions.drawOptions // } // ;[viewOptions, drawOptions] = drawOptions = TwoDraw.separateDrawOptions(viewOptions, drawOptions) drawOptions = Object.assign(TwoDraw.defaultOptions(model), drawOptions) super(model, viewOptions) // TwoView this.model = model this.checkOptions(drawOptions) this.drawOptions = drawOptions } // The parameters are easily mistaken: check they are all in the defaults. checkOptions(drawOptions) { const keys = Object.keys(drawOptions) const defaults = TwoDraw.defaultOptions(this.model) keys.forEach(k => { if (defaults[k] === undefined) { console.log( 'Legal TwoDraw parameters', Object.keys(TwoDraw.defaultOptions(this.model)) ) throw Error('Unknown TwoDraw parameter: ' + k) } }) if (typeof drawOptions.patchesMap === 'string') { drawOptions.patchesMap = ColorMap[drawOptions.patchesMap] if (!drawOptions.patchesMap) Error('Unknown patchMap: ' + drawOptions.patchesMap) } if (typeof drawOptions.turtlesMap === 'string') { drawOptions.turtlesMap = ColorMap[drawOptions.turtlesMap] if (!drawOptions.turtlesMap) Error('Unknown turtlesMap: ' + drawOptions.turtlesMap) } } resetOptions(drawOptions = this.drawOptions) { // if (drawOptions !== this.drawOptions) // drawOptions = Object.assign( // {}, // TwoDraw.defaultOptions(), // drawOptions // ) // drawOptions = Object.assign({}, TwoDraw.defaultOptions(), drawOptions) this.checkOptions(drawOptions) this.drawOptions = drawOptions this.ticks = 0 this.draw() // this.view.ticks = 0 // return drawOptions } // reset(drawOptions = this.drawOptions) { // // this.resetOptions(drawOptions) // // this.patchesView = new PatchesView(this.world.numX, this.world.numY) // // this.turtlesView = new TurtlesView(this.ctx, this.world, options) // // super.reset() // super.initView() // this.ticks = 0 // // this.clear() // // super.reset(this.viewOptions.patchSize) // // this.draw() // } // reset(redraw = true) { // this.ticks = 0 // if (redraw) this.draw() // super.reset() // } reset(patchesSize) { this.ticks = 0 super.reset(patchesSize) this.draw() } setValue(key, val) { if (key === 'patchesSize') { this.reset(val) return } // const keys = TwoDraw.drawKeys() // keys.unshift('patchesSize') const keys = ['patchesSize'].concat(TwoDraw.drawKeys()) if (!keys.includes(key)) { throw new Error(`setValue: ${key} not a valid TwoDraw key. Valid keys: ${keys.join()}`) } this.drawOptions[key] = val this.draw() } draw() { // params = Object.assign({}, TwoDraw.defaultOptions(), params) const model = this.model const view = this let { // data, patchesColor, initPatches, turtles, turtlesColor, turtlesStrokeColor, turtlesShape, turtlesSize, turtlesRotate, links, linksColor, linksWidth, textProperty, textSize, textColor, patchesMap, turtlesMap, } = this.drawOptions // const { model, view } = this if (view.ticks === 0) { if (textProperty) view.setTextProperties(textSize) if (initPatches) { // colors is an array of typedColors or pixels: const colors = initPatches(model, view) view.createPatchPixels(i => colors[i]) // console.log(colors) } else if (patchesColor === 'random') { // NOTE: random colors only done once for patches. view.createPatchPixels(i => patchesMap.randomColor()) } } // if (patchesColor === 'random' || initPatches) { // view.clear() // patch transparent pixels do not clear the canvas! // view.drawPatches() // redraw cached patches colors onto our view canvas // } else if (typeof patchesColor === 'function') { // view.drawPatches(model.patches, p => patchesColor(p)) // } else if (util.isImageable(patchesColor)) { // view.drawPatchesImage(patchesColor) // } else { // view.clear(patchesColor) // } if (util.isImageable(patchesColor)) { view.drawPatchesImage(patchesColor) } else { if (patchesColor === 'random' || initPatches) { view.clear() // patch transparent pixels do not clear the canvas! view.drawPatches() // redraw cached patches colors onto our view canvas } else if (util.isFunction(patchesColor)) { view.clear() view.drawPatches(model.patches, p => patchesColor(p)) } else { view.clear(patchesColor) } } const checkColor = (agent, color) => color === 'random' ? turtlesMap.atIndex(agent.id).css : color view.drawLinks(links, l => ({ color: linksColor === 'random' ? turtlesMap.atIndex(l.id) : typeof linksColor === 'function' ? checkColor(l, linksColor(l)) : linksColor, // width: linksWidth, width: typeof linksWidth === 'function' ? linksWidth(l) : linksWidth, })) view.drawTurtles(turtles, t => ({ shape: typeof turtlesShape === 'function' ? turtlesShape(t) : turtlesShape, color: turtlesColor === 'random' ? turtlesMap.atIndex(t.id).css : typeof turtlesColor === 'function' ? checkColor(t, turtlesColor(t)) : turtlesColor, strokeColor: turtlesStrokeColor === 'random' ? turtlesMap.atIndex(t.id + 4).css : typeof turtlesColor === 'function' ? checkColor(t, turtlesColor(t)) : turtlesColor, size: typeof turtlesSize === 'function' ? turtlesSize(t) : turtlesSize, noRotate: typeof turtlesRotate === 'function' ? !turtlesRotate(t) : !turtlesRotate, })) if (textProperty) { turtles.ask(t => { if (t[textProperty] != null) view.drawText(t[textProperty], t.x, t.y, textColor) }) } view.tick() } } export default TwoDraw