1
0
Fork 0

refactor (core) reorganize method groupings in Pattern

This commit is contained in:
Enoch Riese 2023-04-18 00:00:25 -04:00
parent 8fea9a4beb
commit 13ec5e43e5
5 changed files with 198 additions and 201 deletions

View file

@ -1,13 +1,9 @@
import { Attributes } from '../attributes.mjs'
import { __addNonEnumProp, __macroName } from '../utils.mjs'
import { Part } from '../part.mjs'
import { Stack } from '../stack.mjs'
import { __addNonEnumProp } from '../utils.mjs'
import { Point } from '../point.mjs'
import { Path } from '../path.mjs'
import { Snippet } from '../snippet.mjs'
import { Svg } from '../svg.mjs'
import { Store } from '../store.mjs'
import { Hooks } from '../hooks.mjs'
import { version } from '../../data.mjs'
import { __loadPatternDefaults } from '../config.mjs'
import { PatternConfig } from './pattern-config.mjs'
@ -40,7 +36,6 @@ export function Pattern(designConfig = {}) {
__addNonEnumProp(this, 'height', 0)
__addNonEnumProp(this, 'autoLayout', { stacks: {} })
__addNonEnumProp(this, 'is', '')
__addNonEnumProp(this, 'hooks', new Hooks())
__addNonEnumProp(this, 'Point', Point)
__addNonEnumProp(this, 'Path', Path)
__addNonEnumProp(this, 'Snippet', Snippet)
@ -59,6 +54,10 @@ export function Pattern(designConfig = {}) {
// PUBLIC METHODS //
//////////////////////////////////////////////
///////////
// Setup //
///////////
/**
* Allows adding parts to the config at runtime
*
@ -83,6 +82,49 @@ Pattern.prototype.addPart = function (part, resolveImmediately = true) {
return this
}
/**
* Return the initialized configuration
*
* @return {object} config - The initialized config
*/
Pattern.prototype.getConfig = function () {
return this.__init().config
}
//////////////////////////////
// Plugin and Hook Handling //
//////////////////////////////
/**
* Adds a lifecycle hook method to the pattern
*
* @param {string} hook - Name of the lifecycle hook
* @param {function} method - The method to run
* @param {object} data - Any data to pass to the hook method
* @return {object} this - The Pattern instance
*/
Pattern.prototype.on = function (hook, method, data) {
this.plugins.on(hook, method, data)
return this
}
/**
* Loads a plugin
*
* @param {object} plugin - The plugin to load
* @param {object} data - Any data to pass to the plugin
* @return {object} this - The Pattern instance
*/
Pattern.prototype.use = function (plugin, data) {
this.plugins.use(plugin, data, this.settings)
return this
}
//////////////
// Drafting //
//////////////
/**
* Drafts this pattern, aka the raison d'etre of FreeSewing
*
@ -100,14 +142,9 @@ Pattern.prototype.draftPartForSet = function (partName, set) {
return new PatternDrafter(this).draftPartForSet(partName, set)
}
/**
* Return the initialized configuration
*
* @return {object} config - The initialized config
*/
Pattern.prototype.getConfig = function () {
return this.__init().config
}
///////////////
// Rendering //
///////////////
/**
* Renders the pattern to SVG
@ -127,13 +164,26 @@ Pattern.prototype.getRenderProps = function () {
return new PatternRenderer(this).getRenderProps()
}
//////////////
// Sampling //
//////////////
/**
* Handles pattern sampling
*
* @return {object} this - The Pattern instance
*/
Pattern.prototype.sample = function () {
return new PatternSampler(this).sample()
this.__init()
const sampleSetting = this.settings[0].sample
if (sampleSetting.type === 'option') {
return this.sampleOption(sampleSetting.option)
} else if (sampleSetting.type === 'measurement') {
return this.sampleMeasurement(sampleSetting.measurement)
} else if (sampleSetting.type === 'models') {
return this.sampleModels(sampleSetting.models, sampleSetting.focus || false)
}
return this.draft()
}
/**
@ -163,50 +213,13 @@ Pattern.prototype.sampleOption = function (optionName) {
return new PatternSampler(this).sampleOption(optionName)
}
/**
* Adds a lifecycle hook method to the pattern
*
* @param {string} hook - Name of the lifecycle hook
* @param {function} method - The method to run
* @param {object} data - Any data to pass to the hook method
* @return {object} this - The Pattern instance
*/
Pattern.prototype.on = function (hook, method, data) {
this.plugins.on(hook, method, data)
return this
}
/**
* Loads a plugin
*
* @param {object} plugin - The plugin to load
* @param {object} data - Any data to pass to the plugin
* @return {object} this - The Pattern instance
*/
Pattern.prototype.use = function (plugin, data) {
this.plugins.use(plugin, data, this.settings)
return this
}
//////////////////////////////////////////////
// PRIVATE METHODS //
//////////////////////////////////////////////
/**
* Creates a store for a set (of settings)
*
* @private
* @return {Store} store - A new store populated with relevant data/methods
*/
Pattern.prototype.__createSetStore = function () {
const store = new Store()
store.set('data', this.store.data)
store.extend([...this.plugins.__storeMethods])
return store
}
///////////
// Setup //
///////////
/**
* Merges (sets of) settings with the default settings
@ -237,6 +250,20 @@ Pattern.prototype.__applySettings = function (sets) {
return this
}
/**
* Creates a store for a set (of settings)
*
* @private
* @return {Store} store - A new store populated with relevant data/methods
*/
Pattern.prototype.__createSetStore = function () {
const store = new Store()
store.set('data', this.store.data)
store.extend([...this.plugins.__storeMethods])
return store
}
/**
* Initializes the pattern coniguration and settings
*
@ -258,67 +285,32 @@ Pattern.prototype.__init = function () {
* so we need to do the things we used to do in the contructor at a later stage.
* This methods does that, and resolves the design config + user settings
*/
this.__resolveParts() // Resolves parts
.__resolveConfig() // Gets the config from the resolver
.__loadConfigData() // Makes config data available in store
.__loadOptionDefaults() // Merges default options with user provided ones
// Resolve parts
this.designConfig.parts.forEach((p) => this.__configResolver.addPart(p))
this.plugins.loadConfigPlugins(this.config, this.settings) // Loads plugins
// Print final part distances.
this.__configResolver.logPartDistances()
// get the config from the resolver
this.config = this.__configResolver.asConfig()
// load resolved plugins
this.plugins.loadConfigPlugins(this.config, this.settings)
// Make config data available in store
if (this.designConfig.data) this.store.set('data', this.designConfig.data)
// Merges default options with user provided ones
this.__loadOptionDefaults()
this.store.log.info(`Pattern initialized. Draft order is: ${this.config.draftOrder.join(', ')}`)
this.__runHooks('postInit')
this.__initialized = true
return this
}
/**
* Checks whether a part is hidden in the config
*
* @private
* @param {string} partName - Name of the part to check
* @return {bool} hidden - true if the part is hidden, or false if not
*/
Pattern.prototype.__isPartHidden = function (partName) {
const partHidden = this.parts?.[this.activeSet]?.[partName]?.hidden || false
if (Array.isArray(this.settings[this.activeSet || 0].only)) {
if (this.settings[this.activeSet || 0].only.includes(partName)) return partHidden
}
if (this.config.partHide?.[partName]) return true
return partHidden
}
/**
* Checks whether a stack is hidden in the config
*
* @private
* @param {string} stackName - Name of the stack to check
* @return {bool} hidden - true if the part is hidden, or false if not
*/
Pattern.prototype.__isStackHidden = function (stackName) {
if (!this.stacks[stackName]) return true
const parts = this.stacks[stackName].getPartNames()
for (const partName of parts) {
if (!this.__isPartHidden(partName)) return false
}
return true
}
/**
* Loads data from the design config into the store
*
* @private
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__loadConfigData = function () {
if (this.designConfig.data) this.store.set('data', this.designConfig.data)
return this
}
/**
* Merges defaults for options with user-provided options
*
@ -353,6 +345,67 @@ Pattern.prototype.__loadOptionDefaults = function () {
return this
}
///////////
// Hooks //
///////////
/**
* Runs subscriptions to a given lifecycle hook
*
* @private
* @param {string} hookName - Name of the lifecycle hook
* @param {obhect} data - Any data to pass to the hook method
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__runHooks = function (hookName, data = false) {
if (data === false) data = this
let hooks = this.plugins.hooks[hookName]
if (hooks.length > 0) {
this.store.log.debug(`Running \`${hookName}\` hooks`)
for (let hook of hooks) {
hook.method(data, hook.data)
}
}
}
///////////////////////
// Config Evaluation //
///////////////////////
/**
* Checks whether a part is hidden in the config
*
* @private
* @param {string} partName - Name of the part to check
* @return {bool} hidden - true if the part is hidden, or false if not
*/
Pattern.prototype.__isPartHidden = function (partName) {
const partHidden = this.parts?.[this.activeSet]?.[partName]?.hidden || false
if (Array.isArray(this.settings[this.activeSet || 0].only)) {
if (this.settings[this.activeSet || 0].only.includes(partName)) return partHidden
}
if (this.config.partHide?.[partName]) return true
return partHidden
}
/**
* Checks whether a stack is hidden in the config
*
* @private
* @param {string} stackName - Name of the stack to check
* @return {bool} hidden - true if the part is hidden, or false if not
*/
Pattern.prototype.__isStackHidden = function (stackName) {
if (!this.stacks[stackName]) return true
const parts = this.stacks[stackName].getPartNames()
for (const partName of parts) {
if (!this.__isPartHidden(partName)) return false
}
return true
}
/**
* Determines whether a part is needed, depending on the 'only' setting and the configured dependencies
*
@ -385,50 +438,6 @@ Pattern.prototype.__needs = function (partName, set = 0) {
return false
}
/**
* Gets the configuration for the config resolver and sets it on the pattern
* @private
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__resolveConfig = function () {
this.config = this.__configResolver.asConfig()
return this
}
/**
* Resolves parts and their dependencies
*
* @private
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__resolveParts = function () {
this.designConfig.parts.forEach((p) => this.__configResolver.addPart(p))
// Print final part distances.
this.__configResolver.logPartDistances()
return this
}
/**
* Runs subscriptions to a given lifecycle hook
*
* @private
* @param {string} hookName - Name of the lifecycle hook
* @param {obhect} data - Any data to pass to the hook method
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__runHooks = function (hookName, data = false) {
if (data === false) data = this
let hooks = this.plugins.hooks[hookName]
if (hooks.length > 0) {
this.store.log.debug(`Running \`${hookName}\` hooks`)
for (let hook of hooks) {
hook.method(data, hook.data)
}
}
}
/**
* Determines whether a part is wanted, depending on the 'only' setting and the configured dependencies
*

View file

@ -66,7 +66,7 @@ export function PatternConfig(pattern) {
const DISTANCE_DEBUG = false
////////////////////
// PUBLIC METHODs //
// PUBLIC METHODS //
////////////////////
/**

View file

@ -121,11 +121,39 @@ PatternDrafter.prototype.__createPartForSet = function (partName, set = 0) {
}
}
PatternDrafter.prototype.__useSet = function (set = 0) {
this.activeSet = set
this.activeSettings = this.pattern.settings[set]
this.activeStore = this.pattern.setStores[set]
/**
* Instantiates a new Part instance and populates it with the pattern context
*
* @private
* @param {string} name - The name of the part
* @param {int} set - The index of the settings set in the list of sets
* @return {Part} part - The instantiated Part
*/
PatternDrafter.prototype.__createPartWithContext = function (name, set) {
// Context object to add to Part closure
const part = new Part()
part.name = name
part.set = set
part.stack = this.pattern.config.parts[name]?.stack || name
part.context = {
parts: this.pattern.parts[set],
config: this.pattern.config,
settings: this.pattern.settings[set],
store: this.pattern.setStores[set],
macros: this.pattern.plugins.macros,
}
if (this.pattern.settings[set]?.partClasses) {
part.attr('class', this.pattern.settings[set].partClasses)
}
for (const macro in this.pattern.plugins.macros) {
part[__macroName(macro)] = this.pattern.plugins.macros[macro]
}
return part
}
/**
* Generates an array of settings.absoluteOptions objects for sampling a list option
*
@ -193,35 +221,8 @@ PatternDrafter.prototype.__snappedPercentageOption = function (optionName, set)
return abs
}
/**
* Instantiates a new Part instance and populates it with the pattern context
*
* @private
* @param {string} name - The name of the part
* @param {int} set - The index of the settings set in the list of sets
* @return {Part} part - The instantiated Part
*/
PatternDrafter.prototype.__createPartWithContext = function (name, set) {
// Context object to add to Part closure
const part = new Part()
part.name = name
part.set = set
part.stack = this.pattern.config.parts[name]?.stack || name
part.context = {
parts: this.pattern.parts[set],
config: this.pattern.config,
settings: this.pattern.settings[set],
store: this.pattern.setStores[set],
macros: this.pattern.plugins.macros,
}
if (this.pattern.settings[set]?.partClasses) {
part.attr('class', this.pattern.settings[set].partClasses)
}
for (const macro in this.pattern.plugins.macros) {
part[__macroName(macro)] = this.pattern.plugins.macros[macro]
}
return part
PatternDrafter.prototype.__useSet = function (set = 0) {
this.activeSet = set
this.activeSettings = this.pattern.settings[set]
this.activeStore = this.pattern.setStores[set]
}

View file

@ -2,19 +2,6 @@ export function PatternSampler(pattern) {
this.pattern = pattern
}
PatternSampler.prototype.sample = function () {
this.pattern.__init()
const sampleSetting = this.pattern.settings[0].sample
if (sampleSetting.type === 'option') {
return this.sampleOption(sampleSetting.option)
} else if (sampleSetting.type === 'measurement') {
return this.sampleMeasurement(sampleSetting.measurement)
} else if (sampleSetting.type === 'models') {
return this.sampleModels(sampleSetting.models, sampleSetting.focus || false)
}
return this.pattern
}
/**
* Handles measurement sampling
*