1
0
Fork 0
freesewing/src/pattern.js

137 lines
3.3 KiB
JavaScript
Raw Normal View History

import Attributes from "./attributes";
import { macroName } from "./utils";
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";
import Store from "./store";
2018-07-23 11:12:06 +00:00
export default function Pattern(config = false) {
// 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
// Hooks and Svg instance
this.hooks = new Hooks();
this.svg = new Svg(this);
2018-07-23 11:12:06 +00:00
// Data containers
this.settings = {};
this.options = {};
this.store = new Store();
2018-07-23 11:12:06 +00:00
this.parts = {};
2018-07-25 14:53:10 +00:00
// Merge config with defaults
let defaults = {
measurements: {},
options: {},
units: "metric"
};
this.config = { ...defaults, ...config };
if (config.options.length > 0) {
2018-07-23 11:12:06 +00:00
for (let conf of config.options) {
if (conf.type === "%") this.options[conf.id] = conf.val / 100;
2018-07-23 11:12:06 +00:00
else this.options[conf.id] = conf.val;
}
}
// Constructors
this.Part = Part;
this.Point = Point;
this.Path = Path;
this.Snippet = Snippet;
// Context object to inject in part prototype
2018-07-23 11:12:06 +00:00
this.context = {
parts: this.parts,
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
};
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
*/
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
Pattern.prototype.render = function() {
2018-08-07 13:46:38 +02:00
//this.hooks.attach("preRenderSvg", this.svg);
2018-08-01 18:18:29 +02:00
2018-08-07 13:46:38 +02:00
//this.hooks.attach("postRenderSvg", this.svg);
2018-07-23 20:14:32 +02:00
//this.hooks.attach('insertText', this.svg);
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
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
Pattern.prototype.with = function(plugin) {
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
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
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
}
};
Pattern.prototype.macro = function(key, method) {
this.Part.prototype[macroName(key)] = method;
};
2018-08-01 18:18:29 +02:00
/** Packs parts in a 2D space and sets pattern size */
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({
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;
};