diff --git a/artworld/drawable.js b/artworld/drawable.js index 11337a2..42d0928 100644 --- a/artworld/drawable.js +++ b/artworld/drawable.js @@ -3,6 +3,12 @@ import { Vector2 } from "./math.js"; import { Color } from "./color.js"; import { Random } from "./random.js"; +function cloneObject(obj) { + for (let [k, v] of Object.entries(obj)) { + console.log(k, v); + } +} + export class Drawable { constructor(parent) { this._parent = parent; @@ -12,24 +18,18 @@ export class Drawable { this._strokeWeight = parent ? parent._strokeWeight : null; this._z_index = parent ? parent._z_index : null; this._posVec = new Vector2(0, 0); - this._register(); - } - - _register() { if (this._parent) { - this._parent._register(this); + this._parent.addChild(this); } artworld.register(this); } copy() { - let obj = Object.assign({}, this); - obj._register(); - return obj; + throw new Error("copy() must be implemented on child class"); } draw() { - // no-op, maybe log? + throw new Error("draw() must be implemented on child class"); } // setters @@ -73,6 +73,7 @@ export class Drawable { move(byVec) { this._posVec = this._posVec.add(byVec); + return this; } random() { @@ -110,18 +111,52 @@ export class Group extends Drawable { } copy() { - let newobj = super.copy(); + // new empty group + let newGroup = new Group(); + for (let child of this._children) { - let ccopy = Object.assign({}, child); - ccopy._parent = newobj; - ccopy._register(); + // make a copy of each child item + // use child class copy, with forced override of group + // this registers each one as a child of newGroup + // as part of the copy behavior + child.copy({ _parent: newGroup }); } - return newobj; + + // attach own parent if present + if (this._parent) { + newGroup._parent = this._parent; + newGroup._parent.addChild(newGroup); + } + + return newGroup; } - add(drawable) { + draw() {} + + addChild(drawable) { this._children.push(drawable); drawable._parent = this; return this; } + + fill(color) { + for (let child of this._children) { + child.fill(color); + } + return this; + } + + stroke(color) { + for (let child of this._children) { + child.stroke(color); + } + return this; + } + + strokeWeight(scalar) { + for (let child of this._children) { + child.strokeWeight(scalar); + } + return this; + } } diff --git a/artworld/shapes.js b/artworld/shapes.js index 888b8d8..2bf7efb 100644 --- a/artworld/shapes.js +++ b/artworld/shapes.js @@ -2,12 +2,28 @@ import { Vector2 } from "./math.js"; import { Drawable } from "./drawable.js"; import { Random } from "./random.js"; +function makeCopy(Cls, obj, override) { + // make new object, will be registered with world, but no _parent yet + let newObj = new Cls(); + // overwrite fields of newObj with obj + Object.assign(newObj, obj, override); + // attach to parent + if (newObj._parent) { + newObj._parent.addChild(newObj); + } + return newObj; +} + export class Line extends Drawable { constructor(parent) { super(parent); this._offsetVec = new Vector2(10, 0); } + copy(overrides) { + return makeCopy(Line, this, overrides); + } + draw() { artworld.setStrokeColor(this._stroke); artworld.setStrokeWeight(this._strokeWeight); @@ -32,6 +48,9 @@ export class Arc extends Drawable { this._startAngle = 0; this._endAngle = 180; } + copy(overrides) { + return makeCopy(Arc, this, overrides); + } draw() { artworld.prepareDraw(this); @@ -57,6 +76,9 @@ export class Circle extends Drawable { super(parent); this._r = 25; } + copy(overrides) { + return makeCopy(Circle, this, overrides); + } draw() { artworld.prepareDraw(this); @@ -82,6 +104,9 @@ export class Rect extends Drawable { this._height = Random.between(20, range); return this; } + copy(overrides) { + return makeCopy(Rect, this, overrides); + } draw() { artworld.prepareDraw(this); diff --git a/artworld/world.js b/artworld/world.js index 79a70b8..1b7323b 100644 --- a/artworld/world.js +++ b/artworld/world.js @@ -32,10 +32,10 @@ export class World { this._stroke = false; this._fill = false; if (drawable._stroke) { - this.ctx.lineWidth = drawable._strokeWidth; + this.ctx.lineWidth = drawable._strokeWeight; this.ctx.strokeStyle = drawable._stroke.toStr ? drawable._stroke.toStr() - : drawble._stroke; + : drawable._stroke; this._stroke = true; } else if (drawable._fill) { this.ctx.fillStyle = drawable._fill.toStr diff --git a/examples/copies.html b/examples/copies.html new file mode 100644 index 0000000..540349d --- /dev/null +++ b/examples/copies.html @@ -0,0 +1,28 @@ + +
+ + + + +