2018-08-05 18:19:48 +02:00
|
|
|
import Attributes from "./attributes";
|
2018-07-23 11:44:34 +00:00
|
|
|
import { macroName } from "./utils";
|
2018-08-05 18:19:48 +02:00
|
|
|
import Part from "./part";
|
|
|
|
import Point from "./point";
|
|
|
|
import Path from "./path";
|
|
|
|
import Snippet from "./snippet";
|
|
|
|
import Svg from "./svg";
|
|
|
|
import Hooks from "./hooks";
|
2018-08-01 18:18:29 +02:00
|
|
|
import pack from "bin-pack";
|
2018-08-05 18:19:48 +02:00
|
|
|
import Store from "./store";
|
2018-08-07 16:32:16 +02:00
|
|
|
import Debug from "./debug";
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
export default function Pattern(config = false) {
|
2018-08-05 14:04:15 +02:00
|
|
|
// width and height properties
|
2018-08-01 18:18:29 +02:00
|
|
|
this.width = false;
|
|
|
|
this.height = false;
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
// Hooks and Svg instance
|
|
|
|
this.hooks = new Hooks();
|
2018-08-07 15:23:37 +02:00
|
|
|
Svg.prototype.hooks = this.hooks;
|
2018-07-23 11:12:06 +00:00
|
|
|
|
|
|
|
// Data containers
|
2018-07-24 08:34:26 +02:00
|
|
|
this.settings = {};
|
2018-08-05 14:04:15 +02:00
|
|
|
this.options = {};
|
2018-08-05 18:19:48 +02:00
|
|
|
this.store = new Store();
|
2018-07-23 11:12:06 +00:00
|
|
|
this.parts = {};
|
2018-07-25 14:53:10 +00:00
|
|
|
|
2018-08-05 14:04:15 +02:00
|
|
|
// Merge config with defaults
|
|
|
|
let defaults = {
|
|
|
|
measurements: {},
|
|
|
|
options: {},
|
|
|
|
units: "metric"
|
|
|
|
};
|
|
|
|
this.config = { ...defaults, ...config };
|
2018-08-09 14:21:10 +02:00
|
|
|
for (let i in config.options) {
|
|
|
|
let option = config.options[i];
|
|
|
|
if (option.type === "%") this.options[i] = option.val / 100;
|
|
|
|
else this.options[i] = option.val;
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-08-09 14:21:10 +02:00
|
|
|
console.log(this.options);
|
2018-08-05 14:04:15 +02:00
|
|
|
|
|
|
|
// Constructors
|
2018-08-05 18:19:48 +02:00
|
|
|
this.Part = Part;
|
|
|
|
this.Point = Point;
|
|
|
|
this.Path = Path;
|
|
|
|
this.Snippet = Snippet;
|
2018-08-05 14:04:15 +02:00
|
|
|
|
|
|
|
// Context object to inject in part prototype
|
2018-07-23 11:12:06 +00:00
|
|
|
this.context = {
|
|
|
|
parts: this.parts,
|
2018-07-24 08:34:26 +02:00
|
|
|
config: this.config,
|
2018-07-25 14:53:10 +00:00
|
|
|
settings: this.settings,
|
|
|
|
options: this.options,
|
2018-08-05 16:32:38 +02:00
|
|
|
store: this.store
|
2018-07-23 11:44:34 +00:00
|
|
|
};
|
2018-08-05 18:19:48 +02:00
|
|
|
this.Part.prototype.context = this.context;
|
|
|
|
this.Part.prototype.macros = {};
|
2018-08-07 13:46:38 +02:00
|
|
|
this.Part.prototype.hooks = this.hooks;
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-07-23 20:14:32 +02:00
|
|
|
/**
|
|
|
|
* @throws Will throw an error when called
|
|
|
|
*/
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.draft = function() {
|
2018-07-23 20:14:32 +02:00
|
|
|
throw Error(
|
|
|
|
"You have to implement the draft() method in your Pattern instance."
|
|
|
|
);
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-07 15:23:37 +02:00
|
|
|
/** Debug method, exposes debug hook */
|
2018-08-07 16:32:16 +02:00
|
|
|
Pattern.prototype.debug = function(data) {
|
|
|
|
this.dbg.debug(data);
|
|
|
|
};
|
2018-08-01 18:18:29 +02:00
|
|
|
|
2018-08-07 15:23:37 +02:00
|
|
|
Pattern.prototype.render = function() {
|
|
|
|
this.svg = new Svg(this);
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-03 14:20:28 +02:00
|
|
|
return this.pack().svg.render(this);
|
2018-07-23 20:14:32 +02:00
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.on = function(hook, method) {
|
2018-07-23 20:14:32 +02:00
|
|
|
if (typeof this.hooks._hooks[hook] === "undefined") {
|
|
|
|
this.hooks._hooks[hook] = [];
|
|
|
|
}
|
|
|
|
this.hooks._hooks[hook].push(method);
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.with = function(plugin) {
|
2018-08-07 16:32:16 +02:00
|
|
|
this.dbg = new Debug(this.hooks);
|
|
|
|
|
|
|
|
this.debug(`Plugin: ${plugin.name} v${plugin.version}`);
|
2018-07-23 20:14:32 +02:00
|
|
|
if (plugin.hooks) this.loadPluginHooks(plugin);
|
|
|
|
if (plugin.macros) this.loadPluginMacros(plugin);
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-07-23 20:14:32 +02:00
|
|
|
return this;
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.loadPluginHooks = function(plugin) {
|
2018-07-23 20:14:32 +02:00
|
|
|
for (let hook of this.hooks.all) {
|
|
|
|
if (typeof plugin.hooks[hook] === "function") {
|
|
|
|
this.on(hook, plugin.hooks[hook]);
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
|
|
|
};
|
2018-07-23 11:12:06 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.loadPluginMacros = function(plugin) {
|
2018-07-23 20:14:32 +02:00
|
|
|
for (let macro in plugin.macros) {
|
|
|
|
if (typeof plugin.macros[macro] === "function") {
|
|
|
|
this.macro(macro, plugin.macros[macro]);
|
2018-07-23 11:12:06 +00:00
|
|
|
}
|
2018-07-23 20:14:32 +02:00
|
|
|
}
|
|
|
|
};
|
2018-07-24 14:38:03 +00:00
|
|
|
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.macro = function(key, method) {
|
|
|
|
this.Part.prototype[macroName(key)] = method;
|
2018-07-24 14:38:03 +00:00
|
|
|
};
|
2018-08-01 18:18:29 +02:00
|
|
|
|
|
|
|
/** Packs parts in a 2D space and sets pattern size */
|
2018-08-05 18:19:48 +02:00
|
|
|
Pattern.prototype.pack = function() {
|
2018-08-01 18:18:29 +02:00
|
|
|
let bins = [];
|
|
|
|
for (let key in this.parts) {
|
|
|
|
let part = this.parts[key];
|
|
|
|
if (part.render) {
|
|
|
|
part.stack();
|
|
|
|
bins.push({
|
2018-08-05 15:52:37 +02:00
|
|
|
id: key,
|
2018-08-01 18:18:29 +02:00
|
|
|
width: part.bottomRight.x - part.topLeft.x,
|
|
|
|
height: part.bottomRight.y - part.topLeft.y
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let size = pack(bins, { inPlace: true });
|
|
|
|
for (let bin of bins) {
|
|
|
|
let part = this.parts[bin.id];
|
|
|
|
if (bin.x !== 0 || bin.y !== 0)
|
|
|
|
part.attr("transform", `translate (${bin.x}, ${bin.y})`);
|
|
|
|
}
|
|
|
|
this.width = size.width;
|
|
|
|
this.height = size.height;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
};
|