diff --git a/CHANGELOG.md b/CHANGELOG.md index 33db2f4d..8a09a9bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 3.2.0 (unreleased) * Feature: Display hardness and chroma alongside the MOS pattern in Rank 2 modal [#379](https://github.com/xenharmonic-devs/scale-workshop/issues/379) + * Feature: Add a button for calculating more MOS sizes in Rank 2 modal [#832](https://github.com/xenharmonic-devs/scale-workshop/issues/832) ## 3.1.0 * Feature: Implement the missing size inequality operator `~<>` (i.e. the negation of `~=`) diff --git a/src/components/modals/generation/RankTwo.vue b/src/components/modals/generation/RankTwo.vue index 5433b7ee..8989fe0a 100644 --- a/src/components/modals/generation/RankTwo.vue +++ b/src/components/modals/generation/RankTwo.vue @@ -423,6 +423,7 @@ function generate(expand = true) { > {{ mosInfo.size }} + diff --git a/src/stores/tempering.ts b/src/stores/tempering.ts index 7d7e1e42..5ddd85bc 100644 --- a/src/stores/tempering.ts +++ b/src/stores/tempering.ts @@ -122,8 +122,8 @@ function makeState(defaultMethod: T, rank2 = false) { } export const useRank2Store = defineStore('rank2', () => { - const MAX_SIZE = 128 - const MAX_LENGTH = 12 + const MAX_SIZE_UNIT = 100 + const MAX_LENGTH_UNIT = 10 // === Component state === const state = makeState<'generator' | 'vals' | 'commas' | 'circle'>('generator', true) @@ -139,6 +139,8 @@ export const useRank2Store = defineStore('rank2', () => { // method: "circle" const periodStretch = ref('0') const generatorFineCents = ref('0') + // MOS pattern buttons / more + const mosPatternAmount = ref(1) // Footer preview const previewMosPattern = ref('') // State for key colors @@ -165,27 +167,40 @@ export const useRank2Store = defineStore('rank2', () => { ) const [mosPatterns, mosPatternsError] = computedAndError(() => { + const m = mosPatternAmount.value + const maxSize = m * MAX_SIZE_UNIT + const maxLength = m * MAX_LENGTH_UNIT if (method.value === 'generator') { // Don't show error in the default configuration if (!generatorString.value.length) { return [] } - return getMosPatterns(generatorPerPeriod.value, safeNumPeriods.value, MAX_SIZE, MAX_LENGTH) + return getMosPatterns(generatorPerPeriod.value, safeNumPeriods.value, maxSize, maxLength) } else if (method.value === 'vals') { // TODO: Interactivity guards using MAX_INTERACTIVE_SUBGROUP_SIZE. const temp = state.valsTemperament.value const [period, gen] = temp.generators - return getMosPatterns(gen / period, temp.numberOfPeriods, MAX_SIZE, MAX_LENGTH) + return getMosPatterns(gen / period, temp.numberOfPeriods, maxSize, maxLength) } else if (method.value === 'commas') { // TODO: Interactivity guards using MAX_INTERACTIVE_SUBGROUP_SIZE. const temp = state.commasTemperament.value const [period, gen] = temp.generators - return getMosPatterns(gen / period, temp.numberOfPeriods, MAX_SIZE, MAX_LENGTH) + return getMosPatterns(gen / period, temp.numberOfPeriods, maxSize, maxLength) } else { return [] } }, []) + const morePatterns = computed(() => { + const m = mosPatternAmount.value + const maxSize = m * MAX_SIZE_UNIT + const maxLength = m * MAX_LENGTH_UNIT + if (mosPatterns.value.length >= maxLength) { + return mosPatterns.value[mosPatterns.value.length - 1].size + 1 + } + return maxSize + 1 + }) + const error = computed(() => mosPatternsError.value || state.error.value) const circlePeriodCents = computed(() => { @@ -245,6 +260,10 @@ export const useRank2Store = defineStore('rank2', () => { up.value = Math.min(up.value, newValue) }) + watch([generatorPerPeriod, numPeriods, state.valsTemperament, state.commasTemperament], () => { + mosPatternAmount.value = 1 + }) + return { ...state, error, @@ -258,6 +277,7 @@ export const useRank2Store = defineStore('rank2', () => { safeNumPeriods, periodStretch, generatorFineCents, + mosPatternAmount, previewMosPattern, colorMethod, colorAccidentals, @@ -267,6 +287,7 @@ export const useRank2Store = defineStore('rank2', () => { opposite, mosPatterns, mosPatternsError, + morePatterns, circlePeriodCents, circleGeneratorCents, generatorsPerPeriod,