From b6ff6514485d11240ec3063a255c7482015d8c6a Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Thu, 22 May 2025 09:40:55 +0200 Subject: [PATCH 01/21] add configurable selection of vehicles on train as a target --- src/services/vehicleCopier.ts | 23 ++++++++++- src/ui/mainWindow.ts | 56 ++++++++++++++++++++++++--- src/viewmodels/vehicleViewModel.ts | 5 ++- tests/services/vehicleCopier.tests.ts | 2 +- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 1527b99..334d50f 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -18,6 +18,7 @@ export const enum CopyOptions AllVehiclesOnTrain, PrecedingVehiclesOnTrain, FollowingVehiclesOnTrain, + CustomSelectionOfVehiclesOnTrain, AllVehiclesOnAllTrains, PrecedingVehiclesOnAllTrains, FollowingVehiclesOnAllTrains, @@ -31,6 +32,7 @@ export const copyOptions = [ "All vehicles on this train", "Preceding vehicles on this train", "Following vehicles on this train", + "Custom selection of vehicles on this train", "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", @@ -62,7 +64,7 @@ export const enum CopyFilter * Gets the targeted vehicles based on the selected copy option, in the following * format; [[ car id, amount of following cars (inclusive) ], ...]. */ -export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null): [number, number | null][] +export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null, sequence: number, lastVehicle: number): [number, number | null][] { if (ride && train && vehicle) { @@ -80,6 +82,11 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n { return [[ vehicle[0]._id, null ]]; } + case CopyOptions.CustomSelectionOfVehiclesOnTrain: + { + const index = vehicle[1]; + return vehicleSequence(ride, index, lastVehicle, sequence, v => [ v._id, 1 ]); + } case CopyOptions.AllVehiclesOnAllTrains: { return getTargetsOnAllTrains(ride, t => [ t._carId, null ]); @@ -241,3 +248,17 @@ function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideT { return ride[0]._trains().map(callback); } + +export function vehicleSequence(ride: [ParkRide, number], index: number, lastVehicle: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] +{ + const train = ride[0]._trains()[0]; + const vehicles = train._vehicles(); + let idxArr = vehicles.slice(index, lastVehicle); + let newArr: RideVehicle[] = []; + idxArr.forEach((e, i) => { + if (i % sequence === 0) { + newArr.push(e); + } + }); + return newArr.map(callback); +} \ No newline at end of file diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index a086db2..e2c5e00 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -1,10 +1,10 @@ -import { button, checkbox, CheckboxParams, colourPicker, compute, dropdown, dropdownSpinner, DropdownSpinnerParams, FlexiblePosition, groupbox, horizontal, label, SpinnerParams, toggle, twoway, vertical, viewport, WidgetCreator, window } from "openrct2-flexui"; +import { button, checkbox, CheckboxParams, colourPicker, compute, dropdown, dropdownSpinner, DropdownSpinnerParams, FlexiblePosition, groupbox, horizontal, label, spinner, SpinnerParams, toggle, twoway, vertical, viewport, WidgetCreator, window } from "openrct2-flexui"; import { isDevelopment, pluginVersion } from "../environment"; import { RideType } from "../objects/rideType"; import { RideVehicleVariant, VehicleVisibility } from "../objects/rideVehicleVariant"; import { invoke, refreshRide } from "../services/events"; import { getDistanceFromProgress } from "../services/spacingEditor"; -import { applyToTargets, CopyFilter, getTargets, getVehicleSettings } from "../services/vehicleCopier"; +import { applyToTargets, CopyFilter, CopyOptions, getTargets, getVehicleSettings } from "../services/vehicleCopier"; import { changeSpacing, changeTrackProgress, setMass, setPositionX, setPositionY, setPositionZ, setPoweredAcceleration, setPoweredMaximumSpeed, setPrimaryColour, setReversed, setRideType, setSeatCount, setSecondaryColour, setSpin, setTertiaryColour, setVariant } from "../services/vehicleEditor"; import { VehicleSpan } from "../services/vehicleSpan"; import { isValidGameVersion } from "../services/versionChecker"; @@ -55,7 +55,7 @@ model._selectedRide.subscribe(r => const mainWindow = window({ title, width: { value: 515, min: 515, max: 560 }, - height: 415, + height: 430, spacing: 5, onOpen: () => model._open(), onClose: () => @@ -244,6 +244,7 @@ const mainWindow = window({ "All vehicles on this train", "Preceding vehicles on this train", "Following vehicles on this train", + "Custom selection of vehicles on this train", "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", @@ -251,7 +252,52 @@ const mainWindow = window({ ], tooltip: applyOptionsTip, selectedIndex: model._copyTargetOption, - onChange: idx => model._copyTargetOption.set(idx) + onChange: idx => { + idx === CopyOptions.CustomSelectionOfVehiclesOnTrain ? model._isSequence.set(true) : model._isSequence.set(false); + model._copyTargetOption.set(idx); + } + }), + horizontal({ + padding: { top: -4, right: 1 }, + content: [ + label({ + text: "Apply to every # vehicle(s):", + tooltip: "Applies settings to every selected number of vehicles", + width: 180, + visibility: compute(model._isSequence, s => s ? "visible" : "none") + }), + spinner({ + tooltip: "Applies settings to every selected number of vehicles", + width: 60, + value: 1, + minimum: 1, + maximum: compute(model._vehicles, c => c.length || 1), + step: model._multiplier, + visibility: compute(model._isSequence, s => s ? "visible" : "none"), + onChange: v => model._sequenceValue.set(v) + }) + ] + }), + horizontal({ + padding: { top: -4, right: 1 }, + content: [ + label({ + text: "Last vehicle of train to modify", + tooltip: "Selects which vehicle of the train is the last to modify", + width: 180, + visibility: compute(model._isSequence, s => s ? "visible" : "none") + }), + spinner({ + tooltip: "Selects which vehicle of the train is the last to modify", + width: 60, + value: compute(model._vehicles, c => c.length || 1), + minimum: 1, + maximum: compute(model._vehicles, c => c.length || 1), + step: model._multiplier, + visibility: compute(model._isSequence, s => s ? "visible" : "none"), + onChange: v => model._lastVehicle.set(v) + }) + ] }), horizontal([ button({ @@ -479,7 +525,7 @@ function applySelectedSettingsToRide(): void { applyToTargets( getVehicleSettings(vehicle[0], model._copyFilters.get()), - getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle) + getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle, model._sequenceValue.get(), model._lastVehicle.get()) ); } } diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 369be30..65518cb 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -29,6 +29,7 @@ export class VehicleViewModel readonly _rides = store([]); readonly _trains = compute(this._selectedRide, r => (r) ? r[0]._trains() : []); readonly _vehicles = compute(this._selectedTrain, t => (t) ? t[0]._vehicles() : []); + readonly _lastVehicle = store(0); readonly _type = store<[RideType, number] | null>(null); readonly _variants = compute(this._type, t => (t) ? t[0]._variants() : []); @@ -55,16 +56,18 @@ export class VehicleViewModel readonly _isUnpowered = compute(this._selectedVehicle, this._type, this._variant, v => !v || !v[0]._isPowered()); readonly _isPicking = store(false); readonly _isDragging = store(false); + readonly _isSequence = store(false); readonly _isEditDisabled = compute(this._selectedVehicle, v => !v); readonly _isSpinDisabled = compute(this._spinFrames, v => !v); readonly _isPositionDisabled = compute(this._isMoving, this._isEditDisabled, (m, e) => m || e); readonly _formatPosition = (pos: number): string => (this._isEditDisabled.get() ? "Not available" : pos.toString()); readonly _multiplierIndex = store(0); readonly _multiplier = compute(this._multiplierIndex, idx => (10 ** idx)); + readonly _sequenceValue = store(1); readonly _copyFilters = store(CopyFilter.Default); readonly _copyTargetOption = store(0); - readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, (o, v) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v)); + readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, this._sequenceValue, this._lastVehicle, (o, v, s, l) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v, s, l )); readonly _synchronizeTargets = store(false); readonly _clipboard = store(null); diff --git a/tests/services/vehicleCopier.tests.ts b/tests/services/vehicleCopier.tests.ts index 15089e1..a2913a5 100644 --- a/tests/services/vehicleCopier.tests.ts +++ b/tests/services/vehicleCopier.tests.ts @@ -32,7 +32,7 @@ const getTargetsMacro = test.macro((t, option: CopyOptions, trainIndex: number, const train = ride._trains()[trainIndex]; const vehicle = train._at(vehicleIndex); - const targets = getTargets(option, [ride, 25], [train, trainIndex], [vehicle, vehicleIndex]); + const targets = getTargets(option, [ride, 25], [train, trainIndex], [vehicle, vehicleIndex], 1, 1); t.deepEqual(targets, expectedTargets); }); From c873fc2867feaa5567fbe3742f752d22f722b196 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Thu, 22 May 2025 10:11:18 +0200 Subject: [PATCH 02/21] changed `let` to `const` --- src/services/vehicleCopier.ts | 4 ++-- src/ui/mainWindow.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 334d50f..0e944cd 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -253,8 +253,8 @@ export function vehicleSequence(ride: [ParkRide, number], index: number, lastVeh { const train = ride[0]._trains()[0]; const vehicles = train._vehicles(); - let idxArr = vehicles.slice(index, lastVehicle); - let newArr: RideVehicle[] = []; + const idxArr = vehicles.slice(index, lastVehicle); + const newArr: RideVehicle[] = []; idxArr.forEach((e, i) => { if (i % sequence === 0) { newArr.push(e); diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index e2c5e00..4b22ce1 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -252,7 +252,7 @@ const mainWindow = window({ ], tooltip: applyOptionsTip, selectedIndex: model._copyTargetOption, - onChange: idx => { + onChange: idx =>{ idx === CopyOptions.CustomSelectionOfVehiclesOnTrain ? model._isSequence.set(true) : model._isSequence.set(false); model._copyTargetOption.set(idx); } From 82367ec37101a8b1464e4a26074c5b2561aa5212 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Thu, 22 May 2025 10:14:07 +0200 Subject: [PATCH 03/21] fix: multiple `Opening curly brace appears on the same line as controlling statement` --- src/services/vehicleCopier.ts | 6 ++++-- src/ui/mainWindow.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 0e944cd..9e2f78d 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -255,8 +255,10 @@ export function vehicleSequence(ride: [ParkRide, number], index: number, lastVeh const vehicles = train._vehicles(); const idxArr = vehicles.slice(index, lastVehicle); const newArr: RideVehicle[] = []; - idxArr.forEach((e, i) => { - if (i % sequence === 0) { + idxArr.forEach((e, i) => + { + if (i % sequence === 0) + { newArr.push(e); } }); diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 4b22ce1..547ca3e 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -252,7 +252,8 @@ const mainWindow = window({ ], tooltip: applyOptionsTip, selectedIndex: model._copyTargetOption, - onChange: idx =>{ + onChange: idx => + { idx === CopyOptions.CustomSelectionOfVehiclesOnTrain ? model._isSequence.set(true) : model._isSequence.set(false); model._copyTargetOption.set(idx); } From 337d15dc94cfd2e4fe635c1ba3de13ac19779183 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Thu, 22 May 2025 10:24:29 +0200 Subject: [PATCH 04/21] fix: edited expression to function call --- src/ui/mainWindow.ts | 4 ++-- src/viewmodels/vehicleViewModel.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 547ca3e..307f34f 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -4,7 +4,7 @@ import { RideType } from "../objects/rideType"; import { RideVehicleVariant, VehicleVisibility } from "../objects/rideVehicleVariant"; import { invoke, refreshRide } from "../services/events"; import { getDistanceFromProgress } from "../services/spacingEditor"; -import { applyToTargets, CopyFilter, CopyOptions, getTargets, getVehicleSettings } from "../services/vehicleCopier"; +import { applyToTargets, CopyFilter, getTargets, getVehicleSettings } from "../services/vehicleCopier"; import { changeSpacing, changeTrackProgress, setMass, setPositionX, setPositionY, setPositionZ, setPoweredAcceleration, setPoweredMaximumSpeed, setPrimaryColour, setReversed, setRideType, setSeatCount, setSecondaryColour, setSpin, setTertiaryColour, setVariant } from "../services/vehicleEditor"; import { VehicleSpan } from "../services/vehicleSpan"; import { isValidGameVersion } from "../services/versionChecker"; @@ -254,7 +254,7 @@ const mainWindow = window({ selectedIndex: model._copyTargetOption, onChange: idx => { - idx === CopyOptions.CustomSelectionOfVehiclesOnTrain ? model._isSequence.set(true) : model._isSequence.set(false); + model._setSequence(idx); model._copyTargetOption.set(idx); } }), diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 65518cb..f897e74 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -360,6 +360,18 @@ export class VehicleViewModel } } + /** + * Toggle the visibilty of custom set of vehicles options. + */ + _setSequence(index: number): void + { + if (index === CopyOptions.CustomSelectionOfVehiclesOnTrain) + { + this._isSequence.set(true); + } + this._isSequence.set(false); + } + /** * Copies the currently selected vehicle to the clipboard, or clears clipboard. */ From f250fc940de224da4c40a4bdb7ecc064e79b11cf Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Thu, 22 May 2025 18:45:52 +0200 Subject: [PATCH 05/21] changed `Custom selection of vehicles` to `Specific vehicles` --- src/services/vehicleCopier.ts | 6 +++--- src/ui/mainWindow.ts | 2 +- src/viewmodels/vehicleViewModel.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 9e2f78d..617c391 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -18,7 +18,7 @@ export const enum CopyOptions AllVehiclesOnTrain, PrecedingVehiclesOnTrain, FollowingVehiclesOnTrain, - CustomSelectionOfVehiclesOnTrain, + SpecificVehiclesOnTrain, AllVehiclesOnAllTrains, PrecedingVehiclesOnAllTrains, FollowingVehiclesOnAllTrains, @@ -32,7 +32,7 @@ export const copyOptions = [ "All vehicles on this train", "Preceding vehicles on this train", "Following vehicles on this train", - "Custom selection of vehicles on this train", + "Specific vehicles on this train", "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", @@ -82,7 +82,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n { return [[ vehicle[0]._id, null ]]; } - case CopyOptions.CustomSelectionOfVehiclesOnTrain: + case CopyOptions.SpecificVehiclesOnTrain: { const index = vehicle[1]; return vehicleSequence(ride, index, lastVehicle, sequence, v => [ v._id, 1 ]); diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 307f34f..f741b12 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -244,7 +244,7 @@ const mainWindow = window({ "All vehicles on this train", "Preceding vehicles on this train", "Following vehicles on this train", - "Custom selection of vehicles on this train", + "Specific vehicles on this train", "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index f897e74..77aa372 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -361,11 +361,11 @@ export class VehicleViewModel } /** - * Toggle the visibilty of custom set of vehicles options. + * Toggle the visibilty of specific vehicles options. */ _setSequence(index: number): void { - if (index === CopyOptions.CustomSelectionOfVehiclesOnTrain) + if (index === CopyOptions.SpecificVehiclesOnTrain) { this._isSequence.set(true); } From 41de90e140c11cadc4d603d725c0e75a053c8a9b Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 13:33:17 +0200 Subject: [PATCH 06/21] fixed `setSequence` function --- src/viewmodels/vehicleViewModel.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 77aa372..e3e5472 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -363,13 +363,8 @@ export class VehicleViewModel /** * Toggle the visibilty of specific vehicles options. */ - _setSequence(index: number): void - { - if (index === CopyOptions.SpecificVehiclesOnTrain) - { - this._isSequence.set(true); - } - this._isSequence.set(false); + _setSequence(index: number): void { + this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain); } /** From 3e41c697121d196e7432f904eee3724548d1f403 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 13:36:16 +0200 Subject: [PATCH 07/21] fixed opening curly brace --- src/viewmodels/vehicleViewModel.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index e3e5472..df88773 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -363,7 +363,8 @@ export class VehicleViewModel /** * Toggle the visibilty of specific vehicles options. */ - _setSequence(index: number): void { + _setSequence(index: number): void + { this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain); } From 9742eb96cb1506ddc4436906e28038ca7c9052d9 Mon Sep 17 00:00:00 2001 From: Arjan van Dijk <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 16:45:04 +0200 Subject: [PATCH 08/21] removed export from function export was a leftover which is unnecessary. --- src/services/vehicleCopier.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 617c391..2d00011 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -249,7 +249,7 @@ function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideT return ride[0]._trains().map(callback); } -export function vehicleSequence(ride: [ParkRide, number], index: number, lastVehicle: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] +function vehicleSequence(ride: [ParkRide, number], index: number, lastVehicle: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] { const train = ride[0]._trains()[0]; const vehicles = train._vehicles(); @@ -263,4 +263,4 @@ export function vehicleSequence(ride: [ParkRide, number], index: number, lastVeh } }); return newArr.map(callback); -} \ No newline at end of file +} From d7eff6382abc344438a13c4eb039b05357b96cd7 Mon Sep 17 00:00:00 2001 From: Arjan van Dijk <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 18:13:16 +0200 Subject: [PATCH 09/21] fixed lastVehicle variable --- src/viewmodels/vehicleViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index df88773..63a3f83 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -29,7 +29,7 @@ export class VehicleViewModel readonly _rides = store([]); readonly _trains = compute(this._selectedRide, r => (r) ? r[0]._trains() : []); readonly _vehicles = compute(this._selectedTrain, t => (t) ? t[0]._vehicles() : []); - readonly _lastVehicle = store(0); + readonly _lastVehicle = compute(this.vehicles, v => v.length); readonly _type = store<[RideType, number] | null>(null); readonly _variants = compute(this._type, t => (t) ? t[0]._variants() : []); From 192f02efcbbc9d063a6570963f83741419ddaafa Mon Sep 17 00:00:00 2001 From: Arjan van Dijk <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 18:58:38 +0200 Subject: [PATCH 10/21] changed "last vehicle" to "amount of vehicles" --- src/ui/mainWindow.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index f741b12..855aeba 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -283,13 +283,13 @@ const mainWindow = window({ padding: { top: -4, right: 1 }, content: [ label({ - text: "Last vehicle of train to modify", + text: "Amount of vehicles to modify", tooltip: "Selects which vehicle of the train is the last to modify", width: 180, visibility: compute(model._isSequence, s => s ? "visible" : "none") }), spinner({ - tooltip: "Selects which vehicle of the train is the last to modify", + tooltip: "Sets the amount of vehicles to modify", width: 60, value: compute(model._vehicles, c => c.length || 1), minimum: 1, From 10e005efaeeb87be946eea34fe35f866c72a697b Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 19:20:23 +0200 Subject: [PATCH 11/21] Forgot an underscore --- src/viewmodels/vehicleViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 63a3f83..ccccf1b 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -29,7 +29,7 @@ export class VehicleViewModel readonly _rides = store([]); readonly _trains = compute(this._selectedRide, r => (r) ? r[0]._trains() : []); readonly _vehicles = compute(this._selectedTrain, t => (t) ? t[0]._vehicles() : []); - readonly _lastVehicle = compute(this.vehicles, v => v.length); + readonly _lastVehicle = compute(this._vehicles, v => v.length); readonly _type = store<[RideType, number] | null>(null); readonly _variants = compute(this._type, t => (t) ? t[0]._variants() : []); From ac9a50b91495b3f67587524ea7cd9b096bfee923 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 21:32:47 +0200 Subject: [PATCH 12/21] fixed values for "amount of vehicles" spinner --- src/services/vehicleCopier.ts | 8 ++++---- src/ui/mainWindow.ts | 10 +++++----- src/viewmodels/vehicleViewModel.ts | 7 ++++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 2d00011..d6c3cef 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -64,7 +64,7 @@ export const enum CopyFilter * Gets the targeted vehicles based on the selected copy option, in the following * format; [[ car id, amount of following cars (inclusive) ], ...]. */ -export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null, sequence: number, lastVehicle: number): [number, number | null][] +export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null, sequence: number, amount: number): [number, number | null][] { if (ride && train && vehicle) { @@ -85,7 +85,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n case CopyOptions.SpecificVehiclesOnTrain: { const index = vehicle[1]; - return vehicleSequence(ride, index, lastVehicle, sequence, v => [ v._id, 1 ]); + return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); } case CopyOptions.AllVehiclesOnAllTrains: { @@ -249,11 +249,11 @@ function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideT return ride[0]._trains().map(callback); } -function vehicleSequence(ride: [ParkRide, number], index: number, lastVehicle: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] +function vehicleSequence(ride: [ParkRide, number], index: number, amount: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] { const train = ride[0]._trains()[0]; const vehicles = train._vehicles(); - const idxArr = vehicles.slice(index, lastVehicle); + const idxArr = vehicles.slice(index, index + amount); const newArr: RideVehicle[] = []; idxArr.forEach((e, i) => { diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 855aeba..6913289 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -275,7 +275,7 @@ const mainWindow = window({ maximum: compute(model._vehicles, c => c.length || 1), step: model._multiplier, visibility: compute(model._isSequence, s => s ? "visible" : "none"), - onChange: v => model._sequenceValue.set(v) + onChange: v => model._sequence.set(v) }) ] }), @@ -291,12 +291,12 @@ const mainWindow = window({ spinner({ tooltip: "Sets the amount of vehicles to modify", width: 60, - value: compute(model._vehicles, c => c.length || 1), + value: compute(model._vehicles, c => c.length), minimum: 1, - maximum: compute(model._vehicles, c => c.length || 1), + maximum: compute(model._vehicles, model._selectedVehicle, (c, s) => (s) ? c.length - s[1] : 1), step: model._multiplier, visibility: compute(model._isSequence, s => s ? "visible" : "none"), - onChange: v => model._lastVehicle.set(v) + onChange: v => model._amount.set(v) }) ] }), @@ -526,7 +526,7 @@ function applySelectedSettingsToRide(): void { applyToTargets( getVehicleSettings(vehicle[0], model._copyFilters.get()), - getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle, model._sequenceValue.get(), model._lastVehicle.get()) + getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle, model._sequence.get(), model._amount.get()) ); } } diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index ccccf1b..0b22f5f 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -29,7 +29,6 @@ export class VehicleViewModel readonly _rides = store([]); readonly _trains = compute(this._selectedRide, r => (r) ? r[0]._trains() : []); readonly _vehicles = compute(this._selectedTrain, t => (t) ? t[0]._vehicles() : []); - readonly _lastVehicle = compute(this._vehicles, v => v.length); readonly _type = store<[RideType, number] | null>(null); readonly _variants = compute(this._type, t => (t) ? t[0]._variants() : []); @@ -63,11 +62,13 @@ export class VehicleViewModel readonly _formatPosition = (pos: number): string => (this._isEditDisabled.get() ? "Not available" : pos.toString()); readonly _multiplierIndex = store(0); readonly _multiplier = compute(this._multiplierIndex, idx => (10 ** idx)); - readonly _sequenceValue = store(1); + + readonly _sequence = store(1); + readonly _amount = compute(this._vehicles, c => c.length); readonly _copyFilters = store(CopyFilter.Default); readonly _copyTargetOption = store(0); - readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, this._sequenceValue, this._lastVehicle, (o, v, s, l) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v, s, l )); + readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, this._sequence, this._amount, (o, v, s, a) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v, s, a )); readonly _synchronizeTargets = store(false); readonly _clipboard = store(null); From bbeb56ef122c3c27a3fc4f637302842ea2031a40 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 13:26:39 +0200 Subject: [PATCH 13/21] Menus for Specific vehicles on all trains --- src/services/vehicleCopier.ts | 11 +++++++++-- src/ui/mainWindow.ts | 4 +++- src/viewmodels/vehicleViewModel.ts | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index d6c3cef..4c88cf2 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -22,7 +22,8 @@ export const enum CopyOptions AllVehiclesOnAllTrains, PrecedingVehiclesOnAllTrains, FollowingVehiclesOnAllTrains, - SameVehicleOnAllTrains + SameVehicleOnAllTrains, + SpecificVehiclesOnAllTrains } /** @@ -36,7 +37,8 @@ export const copyOptions = [ "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", - "Same vehicle number on all trains" + "Same vehicle number on all trains", + "Specific vehicles on all trains" ]; @@ -106,6 +108,11 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n const index = vehicle[1]; return getTargetsOnAllTrains(ride, t => [ t._at(index)._id, 1 ]); } + case CopyOptions.SpecificVehiclesOnAllTrains: + { + const index = vehicle[1]; + return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + } } } Log.assert(true, "getTargets(), selected copy option out of range:", copyOption, ", or vehicle not selected:", vehicle); diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 6913289..8c219f3 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -248,12 +248,14 @@ const mainWindow = window({ "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", - "Same vehicle number on all trains" + "Same vehicle number on all trains", + "Specific vehicles on all trains" ], tooltip: applyOptionsTip, selectedIndex: model._copyTargetOption, onChange: idx => { + console.log(idx); model._setSequence(idx); model._copyTargetOption.set(idx); } diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 0b22f5f..f493bb8 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -366,7 +366,7 @@ export class VehicleViewModel */ _setSequence(index: number): void { - this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain); + this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain || index === CopyOptions.SpecificVehiclesOnAllTrains); } /** From aa5b16f84728d6e14c949f17893880243b7ed891 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 19:14:02 +0200 Subject: [PATCH 14/21] add configurable selection of vehicles on all trains as a target --- src/services/vehicleCopier.ts | 28 ++++++++++++++++------------ src/ui/mainWindow.ts | 1 - 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 4c88cf2..dc67e6d 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -256,18 +256,22 @@ function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideT return ride[0]._trains().map(callback); } -function vehicleSequence(ride: [ParkRide, number], index: number, amount: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] -{ - const train = ride[0]._trains()[0]; - const vehicles = train._vehicles(); - const idxArr = vehicles.slice(index, index + amount); +function vehicleSequence(ride: [ParkRide, number], index: number, amount: number, sequence: number, allTrainsSelected: boolean, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] { const newArr: RideVehicle[] = []; - idxArr.forEach((e, i) => - { - if (i % sequence === 0) - { - newArr.push(e); - } - }); + const train = ride[0]._trains()[0]; + const allTrains = ride[0]._trains(); + if (allTrainsSelected) { + allTrains.map(test); + } + else { test(train) } + function test(train: RideTrain) { + const vehicles = train._vehicles(); + const idxArr = vehicles.slice(index, index + amount); + idxArr.forEach((e, i) => { + if (i % sequence === 0) { + newArr.push(e); + } + }); + } return newArr.map(callback); } diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 8c219f3..db48855 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -255,7 +255,6 @@ const mainWindow = window({ selectedIndex: model._copyTargetOption, onChange: idx => { - console.log(idx); model._setSequence(idx); model._copyTargetOption.set(idx); } From 5d21d88ef8d984e4d8696992bdd8a6a9585455b4 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 22:35:50 +0200 Subject: [PATCH 15/21] added all trains check --- src/services/vehicleCopier.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index dc67e6d..bb408e7 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -87,7 +87,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n case CopyOptions.SpecificVehiclesOnTrain: { const index = vehicle[1]; - return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + return vehicleSequence(ride, index, amount, sequence, false, v => [ v._id, 1 ]); } case CopyOptions.AllVehiclesOnAllTrains: { @@ -111,7 +111,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n case CopyOptions.SpecificVehiclesOnAllTrains: { const index = vehicle[1]; - return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + return vehicleSequence(ride, index, amount, sequence, true, v => [ v._id, 1 ]); } } } From 650a71711513feaf6984999faeb83fd051fe0fb1 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Sat, 24 May 2025 09:34:07 +0200 Subject: [PATCH 16/21] renamed function --- src/services/vehicleCopier.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index bb408e7..551fe9a 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -261,10 +261,10 @@ function vehicleSequence(ride: [ParkRide, number], index: number, amount: number const train = ride[0]._trains()[0]; const allTrains = ride[0]._trains(); if (allTrainsSelected) { - allTrains.map(test); + allTrains.map(createSequence); } - else { test(train) } - function test(train: RideTrain) { + else { createSequence(train) } + function createSequence(train: RideTrain) { const vehicles = train._vehicles(); const idxArr = vehicles.slice(index, index + amount); idxArr.forEach((e, i) => { From 74320478d7abc3f5eaf83404d6490507156aea2d Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Sat, 24 May 2025 16:53:55 +0200 Subject: [PATCH 17/21] Fixed the code so every key including `spacing` works --- src/services/vehicleCopier.ts | 28 +++-------- src/services/vehicleEditor.ts | 71 ++++++++++++++------------- src/services/vehicleSpan.ts | 9 ++-- src/ui/mainWindow.ts | 5 +- src/viewmodels/vehicleViewModel.ts | 10 ++-- tests/services/vehicleCopier.tests.ts | 10 ++-- tests/services/vehicleEditor.tests.ts | 54 ++++++++++---------- 7 files changed, 87 insertions(+), 100 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index d6c3cef..e4ed7c2 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -64,7 +64,7 @@ export const enum CopyFilter * Gets the targeted vehicles based on the selected copy option, in the following * format; [[ car id, amount of following cars (inclusive) ], ...]. */ -export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null, sequence: number, amount: number): [number, number | null][] +export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | null, train: [RideTrain, number] | null, vehicle: [RideVehicle, number] | null, amount: number): [number, number | null][] { if (ride && train && vehicle) { @@ -84,8 +84,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n } case CopyOptions.SpecificVehiclesOnTrain: { - const index = vehicle[1]; - return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + return [[ vehicle[0]._id, amount ]]; } case CopyOptions.AllVehiclesOnAllTrains: { @@ -164,9 +163,9 @@ export function getVehicleSettings(source: RideVehicle, filters: CopyFilter): Ve /** * Applies the set of vehicle settings to the specified targets. */ -export function applyToTargets(settings: VehicleSettings, targets: [number, number | null][]): void +export function applyToTargets(settings: VehicleSettings, targets: [number, number | null][], sequence: number): void { - execute({ settings, targets }); + execute({ settings, targets, sequence }); } @@ -199,6 +198,7 @@ interface PasteVehicleSettingsArgs { settings: VehicleSettings; targets: VehicleSpan[]; + sequence: number; } @@ -207,7 +207,7 @@ interface PasteVehicleSettingsArgs */ function pasteVehicleSettings(args: PasteVehicleSettingsArgs): void { - forEachVehicle(args.targets, car => applyVehicleSettings(car, args.settings)); + forEachVehicle(args.targets, args.sequence, car => applyVehicleSettings(car, args.settings)); } @@ -248,19 +248,3 @@ function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideT { return ride[0]._trains().map(callback); } - -function vehicleSequence(ride: [ParkRide, number], index: number, amount: number, sequence: number, callback: (vehicle: RideVehicle) => [number, number | null]): [number, number | null][] -{ - const train = ride[0]._trains()[0]; - const vehicles = train._vehicles(); - const idxArr = vehicles.slice(index, index + amount); - const newArr: RideVehicle[] = []; - idxArr.forEach((e, i) => - { - if (i % sequence === 0) - { - newArr.push(e); - } - }); - return newArr.map(callback); -} diff --git a/src/services/vehicleEditor.ts b/src/services/vehicleEditor.ts index 0240fae..e78ceba 100644 --- a/src/services/vehicleEditor.ts +++ b/src/services/vehicleEditor.ts @@ -36,129 +36,129 @@ const * Sets the ride type for this vehicle. Resets all other properties * to their default values for that type. */ -export function setRideType(vehicles: VehicleSpan[], type: RideType): void +export function setRideType(vehicles: VehicleSpan[], type: RideType, sequence: number): void { - updateValue(vehicles, rideTypeKey, type._id); + updateValue(vehicles, rideTypeKey, type._id, sequence); } /** * Sets the vehicle sprite variant. (e.g. locomotive, tender or passenger car) */ -export function setVariant(vehicles: VehicleSpan[], variant: number): void +export function setVariant(vehicles: VehicleSpan[], variant: number, sequence: number): void { - updateValue(vehicles, variantKey, variant); + updateValue(vehicles, variantKey, variant, sequence); } /** * Sets whether the vehicle should be reversed on the track or not. */ -export function setReversed(vehicles: VehicleSpan[], reversed: boolean): void +export function setReversed(vehicles: VehicleSpan[], reversed: boolean, sequence: number): void { - updateValue(vehicles, reversedKey, reversed); + updateValue(vehicles, reversedKey, reversed, sequence); } /** * Moves the vehicle a relative distance along the track. */ -export function changeTrackProgress(vehicles: VehicleSpan[], trackProgress: number): void +export function changeTrackProgress(vehicles: VehicleSpan[], trackProgress: number, sequence: number): void { - updateValue(vehicles, trackProgressKey, trackProgress); + updateValue(vehicles, trackProgressKey, trackProgress, sequence); } /** * Moves the vehicle a relative distance away from the vehicle before it. */ -export function changeSpacing(vehicles: VehicleSpan[], trackProgress: number): void +export function changeSpacing(vehicles: VehicleSpan[], trackProgress: number, sequence: number): void { - updateValue(vehicles, spacingKey, trackProgress); + updateValue(vehicles, spacingKey, trackProgress, sequence); } /** * Sets the maximum number of seats for this vehicle. */ -export function setSeatCount(vehicles: VehicleSpan[], seats: number): void +export function setSeatCount(vehicles: VehicleSpan[], seats: number, sequence: number): void { - updateValue(vehicles, seatsKey, seats); + updateValue(vehicles, seatsKey, seats, sequence); } /** * Sets the mass for this vehicle. */ -export function setMass(vehicles: VehicleSpan[], mass: number): void +export function setMass(vehicles: VehicleSpan[], mass: number, sequence: number): void { - updateValue(vehicles, massKey, mass); + updateValue(vehicles, massKey, mass, sequence); } /** * Sets the powered acceleration for this vehicle. */ -export function setPoweredAcceleration(vehicles: VehicleSpan[], power: number): void +export function setPoweredAcceleration(vehicles: VehicleSpan[], power: number, sequence: number): void { - updateValue(vehicles, poweredAccelerationKey, power); + updateValue(vehicles, poweredAccelerationKey, power, sequence); } /** * Sets the powered acceleration for this vehicle. */ -export function setPoweredMaximumSpeed(vehicles: VehicleSpan[], maximumSpeed: number): void +export function setPoweredMaximumSpeed(vehicles: VehicleSpan[], maximumSpeed: number, sequence: number): void { - updateValue(vehicles, poweredMaxSpeedKey, maximumSpeed); + updateValue(vehicles, poweredMaxSpeedKey, maximumSpeed, sequence); } /** * Sets the primary colour for this vehicle. */ -export function setPrimaryColour(vehicles: VehicleSpan[], colour: Colour): void +export function setPrimaryColour(vehicles: VehicleSpan[], colour: Colour, sequence: number): void { - updateValue(vehicles, primaryColour, colour); + updateValue(vehicles, primaryColour, colour, sequence); } /** * Sets the secondary colour for this vehicle. */ -export function setSecondaryColour(vehicles: VehicleSpan[], colour: Colour): void +export function setSecondaryColour(vehicles: VehicleSpan[], colour: Colour, sequence: number): void { - updateValue(vehicles, secondaryColour, colour); + updateValue(vehicles, secondaryColour, colour, sequence); } /** * Sets the tertiary colour for this vehicle. */ -export function setTertiaryColour(vehicles: VehicleSpan[], colour: Colour): void +export function setTertiaryColour(vehicles: VehicleSpan[], colour: Colour, sequence: number): void { - updateValue(vehicles, tertiaryColour, colour); + updateValue(vehicles, tertiaryColour, colour, sequence); } /** * Sets the x position for this vehicle. */ -export function setPositionX(vehicles: VehicleSpan[], x: number): void +export function setPositionX(vehicles: VehicleSpan[], x: number, sequence: number): void { - updateValue(vehicles, xPosition, x); + updateValue(vehicles, xPosition, x, sequence); } /** * Sets the y position for this vehicle. */ -export function setPositionY(vehicles: VehicleSpan[], y: number): void +export function setPositionY(vehicles: VehicleSpan[], y: number, sequence: number): void { - updateValue(vehicles, yPosition, y); + updateValue(vehicles, yPosition, y, sequence); } /** * Sets the z position for this vehicle. */ -export function setPositionZ(vehicles: VehicleSpan[], z: number): void +export function setPositionZ(vehicles: VehicleSpan[], z: number, sequence: number): void { - updateValue(vehicles, zPosition, z); + updateValue(vehicles, zPosition, z, sequence); } /** * Sets the z position for this vehicle. */ -export function setSpin(vehicles: VehicleSpan[], spin: number): void +export function setSpin(vehicles: VehicleSpan[], spin: number, sequence: number): void { - updateValue(vehicles, spinKey, spin); + updateValue(vehicles, spinKey, spin, sequence); } @@ -170,14 +170,15 @@ interface UpdateVehicleSettingArgs targets: VehicleSpan[]; key: VehicleUpdateKeys; value: number; + sequence: number; } /** * Dispatches an update game action to other clients to update the specified key. */ -function updateValue(vehicles: VehicleSpan[], key: VehicleUpdateKeys, value: number): void +function updateValue(vehicles: VehicleSpan[], key: VehicleUpdateKeys, value: number, sequence: number): void { - execute({ targets: vehicles, key, value }); + execute({ targets: vehicles, key, value, sequence }); } /** @@ -293,7 +294,7 @@ function updateVehicleSetting(args: UpdateVehicleSettingArgs): void } } - forEachVehicle(targets, callback); + forEachVehicle(targets, args.sequence, callback); } /** diff --git a/src/services/vehicleSpan.ts b/src/services/vehicleSpan.ts index 6703190..4568a55 100644 --- a/src/services/vehicleSpan.ts +++ b/src/services/vehicleSpan.ts @@ -15,7 +15,7 @@ export type VehicleSpan = [number, number | null]; /** * Applies a specific callback for each vehicle in the specified list of vehicle spans. */ -export function forEachVehicle(vehicles: VehicleSpan[], action: (car: Car, index: number) => void): void +export function forEachVehicle(vehicles: VehicleSpan[], sequence: number, action: (car: Car, index: number) => void): void { for (let s = 0, sl = vehicles.length; s < sl; s++) { @@ -29,10 +29,11 @@ export function forEachVehicle(vehicles: VehicleSpan[], action: (car: Car, index const car = getCarById(currentId); if (!car) break; - - action(car, count); + if (count % sequence === 0) + { + action(car, count); + } invoke(refreshVehicle, currentId); - const nextId = car.nextCarOnTrain; if (isNull(nextId)) break; diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 6913289..f15b8cf 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -526,7 +526,8 @@ function applySelectedSettingsToRide(): void { applyToTargets( getVehicleSettings(vehicle[0], model._copyFilters.get()), - getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle, model._sequence.get(), model._amount.get()) + getTargets(model._copyTargetOption.get(), model._selectedRide.get(), model._selectedTrain.get(), vehicle, model._amount.get()), + model._sequence.get() ); } } @@ -534,7 +535,7 @@ function applySelectedSettingsToRide(): void /** * Apply the same amount of track progress to all selected vehicles based on the currently selected car. */ -function applyTrackProgressChange(action: (vehicles: VehicleSpan[], value: number) => void, increment: number, filter: CopyFilter): void +function applyTrackProgressChange(action: (vehicles: VehicleSpan[], value: number, sequence: number) => void, increment: number, filter: CopyFilter): void { const selectedVehicle = model._selectedVehicle.get(); if (selectedVehicle) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 0b22f5f..1fc05e9 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -68,7 +68,7 @@ export class VehicleViewModel readonly _copyFilters = store(CopyFilter.Default); readonly _copyTargetOption = store(0); - readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, this._sequence, this._amount, (o, v, s, a) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v, s, a )); + readonly _copyTargets = compute(this._copyTargetOption, this._selectedVehicle, this._amount, (o, v, a) => getTargets(o, this._selectedRide.get(), this._selectedTrain.get(), v, a )); readonly _synchronizeTargets = store(false); readonly _clipboard = store(null); @@ -289,7 +289,7 @@ export class VehicleViewModel /** * Attempt to modify the vehicle with the specified action, if a vehicle is selected. */ - _modifyVehicle(action: (vehicles: VehicleSpan[], value: T) => void, value: T, filter: CopyFilter): void + _modifyVehicle(action: (vehicles: VehicleSpan[], value: T, sequence: number) => void, value: T, filter: CopyFilter): void { if (this._isRefreshing) { @@ -302,11 +302,11 @@ export class VehicleViewModel // Only apply if action matches filter. if (this._synchronizeTargets.get() && (!filter || ((this._copyFilters.get() || CopyFilter.All) & filter))) { - action(this._copyTargets.get(), value); + action(this._copyTargets.get(), value, this._sequence.get()); } else { - action([[ vehicle[0]._id, 1 ]], value); + action([[ vehicle[0]._id, 1 ]], value, this._sequence.get()); } } else @@ -395,7 +395,7 @@ export class VehicleViewModel const settings = this._clipboard.get(); if (vehicle && settings) { - applyToTargets(settings, [[ vehicle[0]._id, 1 ]]); + applyToTargets(settings, [[ vehicle[0]._id, 1 ]], this._sequence.get()); } } diff --git a/tests/services/vehicleCopier.tests.ts b/tests/services/vehicleCopier.tests.ts index a2913a5..da22d7b 100644 --- a/tests/services/vehicleCopier.tests.ts +++ b/tests/services/vehicleCopier.tests.ts @@ -32,7 +32,7 @@ const getTargetsMacro = test.macro((t, option: CopyOptions, trainIndex: number, const train = ride._trains()[trainIndex]; const vehicle = train._at(vehicleIndex); - const targets = getTargets(option, [ride, 25], [train, trainIndex], [vehicle, vehicleIndex], 1, 1); + const targets = getTargets(option, [ride, 25], [train, trainIndex], [vehicle, vehicleIndex], 1); t.deepEqual(targets, expectedTargets); }); @@ -226,7 +226,7 @@ test("Paste all vehicle settings on single car", t => colours: [ 13, 15, 18 ] }; - applyToTargets(settings, [[ 99, 1 ]]); + applyToTargets(settings, [[ 99, 1]], 1); const targetCar = map.getEntity(99); t.is(targetCar.rideObject, 21); @@ -260,7 +260,7 @@ test("Paste all vehicle settings on a car does not affect other cars", t => colours: [ 13, 15, 18 ] }; - applyToTargets(settings, [[ 99, 3 ], [ 99, null ]]); + applyToTargets(settings, [[ 99, 3 ], [ 99, null ]], 1); function testUnaffectedCar(carId: number): void { @@ -291,7 +291,7 @@ test("Paste empty vehicle settings on single car does not do anything", t => const settings: VehicleSettings = {}; - applyToTargets(settings, [[ 99, 1 ]]); + applyToTargets(settings, [[ 99, 1]], 1); const targetCar = map.getEntity(99); t.is(targetCar.rideObject, 2); @@ -323,7 +323,7 @@ test("Paste all vehicle settings on multiple trains car affects all", t => colours: [ 8, 6, 5 ] }; - applyToTargets(settings, [[ 98, 4 ], [ 97, null ]]); + applyToTargets(settings, [[ 98, 4 ], [ 97, null ]], 1); function testAffectedCar(carId: number): void { diff --git a/tests/services/vehicleEditor.tests.ts b/tests/services/vehicleEditor.tests.ts index 8a862a2..a542a45 100644 --- a/tests/services/vehicleEditor.tests.ts +++ b/tests/services/vehicleEditor.tests.ts @@ -44,7 +44,7 @@ test("Set ride type", t => { const car = setupCarMock(99); - setRideType([[ 99, 1 ]], new RideType(Mock.rideObject({ index: 23 }))); + setRideType([[ 99, 1]], new RideType(Mock.rideObject({ index: 23 })), 1); t.is(car.rideObject, 23); // Reset other properties @@ -54,7 +54,7 @@ test("Set ride type", t => t.is(car.poweredAcceleration, 40); t.is(car.poweredMaxSpeed, 35); - setRideType([[ 99, 1 ]], new RideType(Mock.rideObject({ index: 55 }))); + setRideType([[ 99, 1]], new RideType(Mock.rideObject({ index: 55 })), 1); t.is(car.rideObject, 55); // Reset other properties @@ -70,7 +70,7 @@ test("Set variant", t => { const car = setupCarMock(56); - setVariant([[ 56, 1 ]], 3); + setVariant([[ 56, 1]], 3, 1); t.is(car.vehicleObject, 3); // Reset other properties @@ -80,7 +80,7 @@ test("Set variant", t => t.is(car.poweredAcceleration, 11); t.is(car.poweredMaxSpeed, 12); - setVariant([[ 56, 1 ]], 1); + setVariant([[ 56, 1]], 1, 1); t.is(car.vehicleObject, 1); // Reset other properties @@ -96,10 +96,10 @@ test("Set seat count", t => { const car = setupCarMock(58); - setSeatCount([[ 58, 1 ]], 26); + setSeatCount([[ 58, 1]], 26, 1); t.is(car.numSeats, 26); - setSeatCount([[ 58, 1 ]], 10); + setSeatCount([[ 58, 1]], 10, 1); t.is(car.numSeats, 10); }); @@ -108,10 +108,10 @@ test("Set mass", t => { const car = setupCarMock(58); - setMass([[ 58, 1 ]], 260); + setMass([[ 58, 1]], 260, 1); t.is(car.mass, 260); - setMass([[ 58, 1 ]], 9800); + setMass([[ 58, 1]], 9800, 1); t.is(car.mass, 9800); }); @@ -120,10 +120,10 @@ test("Set powered acceleration", t => { const car = setupCarMock(42); - setPoweredAcceleration([[ 42, 1 ]], 120); + setPoweredAcceleration([[ 42, 1]], 120, 1); t.is(car.poweredAcceleration, 120); - setPoweredAcceleration([[ 42, 1 ]], 5); + setPoweredAcceleration([[ 42, 1]], 5, 1); t.is(car.poweredAcceleration, 5); }); @@ -132,10 +132,10 @@ test("Set powered max speed", t => { const car = setupCarMock(9); - setPoweredMaximumSpeed([[ 9, 1 ]], 65); + setPoweredMaximumSpeed([[ 9, 1]], 65, 1); t.is(car.poweredMaxSpeed, 65); - setPoweredMaximumSpeed([[ 9, 1 ]], 30); + setPoweredMaximumSpeed([[ 9, 1]], 30, 1); t.is(car.poweredMaxSpeed, 30); }); @@ -144,10 +144,10 @@ test("Set primary colour", t => { const car = setupCarMock(9); - setPrimaryColour([[ 9, 1 ]], 5); + setPrimaryColour([[ 9, 1]], 5, 1); t.is(car.colours.body, 5); - setPrimaryColour([[ 9, 1 ]], 31); + setPrimaryColour([[ 9, 1]], 31, 1); t.is(car.colours.body, 31); }); @@ -156,10 +156,10 @@ test("Set secondary colour", t => { const car = setupCarMock(19); - setSecondaryColour([[ 19, 1 ]], 12); + setSecondaryColour([[ 19, 1]], 12, 1); t.is(car.colours.trim, 12); - setSecondaryColour([[ 19, 1 ]], 0); + setSecondaryColour([[ 19, 1]], 0, 1); t.is(car.colours.trim, 0); }); @@ -168,10 +168,10 @@ test("Set tertiary colour", t => { const car = setupCarMock(23); - setTertiaryColour([[ 23, 1 ]], 25); + setTertiaryColour([[ 23, 1]], 25, 1); t.is(car.colours.tertiary, 25); - setTertiaryColour([[ 23, 1 ]], 2); + setTertiaryColour([[ 23, 1]], 2, 1); t.is(car.colours.tertiary, 2); }); @@ -180,13 +180,13 @@ test("Set x position", t => { const car = setupCarMock(29); - setPositionX([[ 29, 1 ]], 10); + setPositionX([[ 29, 1]], 10, 1); t.is(car.x, 10); - setPositionX([[ 29, 1 ]], 10_090); + setPositionX([[ 29, 1]], 10_090, 1); t.is(car.x, 10 + 10_090); - setPositionX([[ 29, 1 ]], -3); + setPositionX([[ 29, 1]], -3, 1); t.is(car.x, 10 + 10_090 - 3); }); @@ -195,13 +195,13 @@ test("Set y position", t => { const car = setupCarMock(10); - setPositionY([[ 10, 1 ]], 5020); + setPositionY([[ 10, 1]], 5020, 1); t.is(car.y, 5020); - setPositionY([[ 10, 1 ]], -302_010); + setPositionY([[ 10, 1]], -302_010, 1); t.is(car.y, 5020 - 302_010); - setPositionY([[ 10, 1 ]], 15); + setPositionY([[ 10, 1]], 15, 1); t.is(car.y, 5020 - 302_010 + 15); }); @@ -210,12 +210,12 @@ test("Set z position", t => { const car = setupCarMock(101); - setPositionZ([[ 101, 1 ]], -698); + setPositionZ([[ 101, 1]], -698, 1); t.is(car.z, -698); - setPositionZ([[ 101, 1 ]], 653); + setPositionZ([[ 101, 1]], 653, 1); t.is(car.z, -698 + 653); - setPositionZ([[ 101, 1 ]], -10); + setPositionZ([[ 101, 1]], -10, 1); t.is(car.z, -698 + 653 - 10); }); From c9cc11e2acaa73fe5eecb37d3fa056601d017cc1 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Sat, 24 May 2025 17:05:23 +0200 Subject: [PATCH 18/21] fixed amount of vehicles after closing and reopening plugin --- src/viewmodels/vehicleViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 1fc05e9..eeb9b3d 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -64,7 +64,7 @@ export class VehicleViewModel readonly _multiplier = compute(this._multiplierIndex, idx => (10 ** idx)); readonly _sequence = store(1); - readonly _amount = compute(this._vehicles, c => c.length); + readonly _amount = store(this._vehicles.get().length); readonly _copyFilters = store(CopyFilter.Default); readonly _copyTargetOption = store(0); From ab74f51cb3e4e693abb89660b46b60b90d529eff Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 13:26:39 +0200 Subject: [PATCH 19/21] Menus for Specific vehicles on all trains --- src/services/vehicleCopier.ts | 11 +++++++++-- src/ui/mainWindow.ts | 4 +++- src/viewmodels/vehicleViewModel.ts | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index e4ed7c2..3fbf449 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -22,7 +22,8 @@ export const enum CopyOptions AllVehiclesOnAllTrains, PrecedingVehiclesOnAllTrains, FollowingVehiclesOnAllTrains, - SameVehicleOnAllTrains + SameVehicleOnAllTrains, + SpecificVehiclesOnAllTrains } /** @@ -36,7 +37,8 @@ export const copyOptions = [ "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", - "Same vehicle number on all trains" + "Same vehicle number on all trains", + "Specific vehicles on all trains" ]; @@ -105,6 +107,11 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n const index = vehicle[1]; return getTargetsOnAllTrains(ride, t => [ t._at(index)._id, 1 ]); } + case CopyOptions.SpecificVehiclesOnAllTrains: + { + const index = vehicle[1]; + return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + } } } Log.assert(true, "getTargets(), selected copy option out of range:", copyOption, ", or vehicle not selected:", vehicle); diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index f15b8cf..22d44d4 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -248,12 +248,14 @@ const mainWindow = window({ "All vehicles on all trains", "Preceding vehicles on all trains", "Following vehicles on all trains", - "Same vehicle number on all trains" + "Same vehicle number on all trains", + "Specific vehicles on all trains" ], tooltip: applyOptionsTip, selectedIndex: model._copyTargetOption, onChange: idx => { + console.log(idx); model._setSequence(idx); model._copyTargetOption.set(idx); } diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index eeb9b3d..4e0af1d 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -366,7 +366,7 @@ export class VehicleViewModel */ _setSequence(index: number): void { - this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain); + this._isSequence.set(index === CopyOptions.SpecificVehiclesOnTrain || index === CopyOptions.SpecificVehiclesOnAllTrains); } /** From 6dd297fd2fe0f9797923cf99fb1d9503285bc765 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Fri, 23 May 2025 19:14:02 +0200 Subject: [PATCH 20/21] add configurable selection of vehicles on all trains as a target --- src/services/vehicleCopier.ts | 4 ++-- src/ui/mainWindow.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/vehicleCopier.ts b/src/services/vehicleCopier.ts index 3fbf449..1c910e4 100644 --- a/src/services/vehicleCopier.ts +++ b/src/services/vehicleCopier.ts @@ -110,7 +110,7 @@ export function getTargets(copyOption: CopyOptions, ride: [ParkRide, number] | n case CopyOptions.SpecificVehiclesOnAllTrains: { const index = vehicle[1]; - return vehicleSequence(ride, index, amount, sequence, v => [ v._id, 1 ]); + return getTargetsOnAllTrains(ride, t => [ t._at(index)._id, amount ]); } } } @@ -254,4 +254,4 @@ function applyVehicleSettings(car: Car, settings: VehicleSettings): void function getTargetsOnAllTrains(ride: [ParkRide, number], callback: (train: RideTrain) => [number, number | null]): [number, number | null][] { return ride[0]._trains().map(callback); -} +} \ No newline at end of file diff --git a/src/ui/mainWindow.ts b/src/ui/mainWindow.ts index 22d44d4..6d4e7d0 100644 --- a/src/ui/mainWindow.ts +++ b/src/ui/mainWindow.ts @@ -255,7 +255,6 @@ const mainWindow = window({ selectedIndex: model._copyTargetOption, onChange: idx => { - console.log(idx); model._setSequence(idx); model._copyTargetOption.set(idx); } From 2a14aa00cbc17cce910cefb358cb037225206094 Mon Sep 17 00:00:00 2001 From: Manticore-007 <71702374+Manticore-007@users.noreply.github.com> Date: Sat, 24 May 2025 17:34:05 +0200 Subject: [PATCH 21/21] dropdowns visible for specific vehicles on all trains --- src/viewmodels/vehicleViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/viewmodels/vehicleViewModel.ts b/src/viewmodels/vehicleViewModel.ts index 4e0af1d..c6658db 100644 --- a/src/viewmodels/vehicleViewModel.ts +++ b/src/viewmodels/vehicleViewModel.ts @@ -64,7 +64,7 @@ export class VehicleViewModel readonly _multiplier = compute(this._multiplierIndex, idx => (10 ** idx)); readonly _sequence = store(1); - readonly _amount = store(this._vehicles.get().length); + readonly _amount = compute(this._vehicles, c => c.length); readonly _copyFilters = store(CopyFilter.Default); readonly _copyTargetOption = store(0);