diff --git a/Dat/FileParsing/LocoBinaryReader.cs b/Dat/FileParsing/LocoBinaryReader.cs
index e3012996..ef3ed0dd 100644
--- a/Dat/FileParsing/LocoBinaryReader.cs
+++ b/Dat/FileParsing/LocoBinaryReader.cs
@@ -283,7 +283,6 @@ public EmitterAnimation[] ReadEmitterAnimations(int count)
public FrictionSound ReadFrictionSound()
=> new()
{
- SoundObjectId = ReadByte(),
MinSpeed = ReadInt32(),
SpeedFreqFactor = ReadByte(),
BaseFrequency = ReadUInt16(),
@@ -295,7 +294,6 @@ public FrictionSound ReadFrictionSound()
public SimpleMotorSound ReadSimpleMotorSound()
=> new()
{
- SoundObjectId = ReadByte(),
IdleFrequency = ReadUInt16(),
IdleVolume = ReadByte(),
CoastingFrequency = ReadUInt16(),
@@ -312,7 +310,6 @@ public SimpleMotorSound ReadSimpleMotorSound()
public GearboxMotorSound ReadGearboxMotorSound()
=> new()
{
- SoundObjectId = ReadByte(),
IdleFrequency = ReadUInt16(),
IdleVolume = ReadByte(),
FirstGearFrequency = ReadUInt16(),
diff --git a/Dat/FileParsing/LocoBinaryWriter.cs b/Dat/FileParsing/LocoBinaryWriter.cs
index ebdbb309..1c70e857 100644
--- a/Dat/FileParsing/LocoBinaryWriter.cs
+++ b/Dat/FileParsing/LocoBinaryWriter.cs
@@ -167,7 +167,6 @@ public void Write(EmitterAnimation[] animations)
public void Write(FrictionSound sound)
{
- Write(sound.SoundObjectId);
Write(sound.MinSpeed);
Write(sound.SpeedFreqFactor);
Write(sound.BaseFrequency);
@@ -178,7 +177,6 @@ public void Write(FrictionSound sound)
public void Write(SimpleMotorSound sound)
{
- Write(sound.SoundObjectId);
Write(sound.IdleFrequency);
Write(sound.IdleVolume);
Write(sound.CoastingFrequency);
@@ -194,7 +192,6 @@ public void Write(SimpleMotorSound sound)
public void Write(GearboxMotorSound sound)
{
- Write(sound.SoundObjectId);
Write(sound.IdleFrequency);
Write(sound.IdleVolume);
Write(sound.FirstGearFrequency);
diff --git a/Dat/Loaders/Vehicle/VehicleObjectLoader.cs b/Dat/Loaders/Vehicle/VehicleObjectLoader.cs
index 5f4bf213..bb7f797b 100644
--- a/Dat/Loaders/Vehicle/VehicleObjectLoader.cs
+++ b/Dat/Loaders/Vehicle/VehicleObjectLoader.cs
@@ -73,7 +73,7 @@ private static void LoadVariable(LocoBinaryReader br, VehicleObject model, byte
// track type
if (!model.Flags.HasFlag(VehicleObjectFlags.AnyRoadType) && (model.Mode == TransportMode.Rail || model.Mode == TransportMode.Road))
{
- model.TrackType = br.ReadS5Header();
+ model.RoadOrTrackType = br.ReadS5Header();
}
// required track extra
@@ -187,14 +187,17 @@ private static void LoadFixed(LocoBinaryReader br, VehicleObject model, out byte
switch (model.DrivingSoundType)
{
case DrivingSoundType.Friction:
+ br.SkipByte(); // this is the object id which is the first byte of all of the sound union structs. it will be read from Sound property
model.FrictionSound = br.ReadFrictionSound();
br.SkipByte(StructSizes.SoundData - StructSizes.FrictionSound);
break;
case DrivingSoundType.SimpleMotor:
+ br.SkipByte(); // this is the object id which is the first byte of all of the sound union structs. it will be read from Sound property
model.SimpleMotorSound = br.ReadSimpleMotorSound();
br.SkipByte(StructSizes.SoundData - StructSizes.SimpleMotorSound);
break;
case DrivingSoundType.GearboxMotor:
+ br.SkipByte(); // this is the object id which is the first byte of all of the sound union structs. it will be read from Sound property
model.GearboxMotorSound = br.ReadGearboxMotorSound();
br.SkipByte(StructSizes.SoundData - StructSizes.GearboxMotorSound);
break;
@@ -256,16 +259,19 @@ public static void Save(Stream stream, LocoObject obj)
{
case DrivingSoundType.Friction:
ArgumentNullException.ThrowIfNull(model.FrictionSound);
+ bw.WriteEmptyBytes(1); // this is the object id which is the first byte of all of the sound union structs
bw.Write(model.FrictionSound);
bw.WriteEmptyBytes(StructSizes.SoundData - StructSizes.FrictionSound);
break;
case DrivingSoundType.SimpleMotor:
ArgumentNullException.ThrowIfNull(model.SimpleMotorSound);
+ bw.WriteEmptyBytes(1); // this is the object id which is the first byte of all of the sound union structs
bw.Write(model.SimpleMotorSound);
bw.WriteEmptyBytes(StructSizes.SoundData - StructSizes.SimpleMotorSound);
break;
case DrivingSoundType.GearboxMotor:
ArgumentNullException.ThrowIfNull(model.GearboxMotorSound);
+ bw.WriteEmptyBytes(1); // this is the object id which is the first byte of all of the sound union structs
bw.Write(model.GearboxMotorSound);
bw.WriteEmptyBytes(StructSizes.SoundData - StructSizes.GearboxMotorSound);
break;
@@ -299,7 +305,7 @@ private static void SaveVariable(VehicleObject model, LocoBinaryWriter bw)
// track type
if (!model.Flags.HasFlag(VehicleObjectFlags.AnyRoadType) && (model.Mode == TransportMode.Rail || model.Mode == TransportMode.Road))
{
- bw.WriteS5Header(model.TrackType);
+ bw.WriteS5Header(model.RoadOrTrackType);
}
// track extras
diff --git a/Definitions/ObjectModels/Objects/Vehicle/EmitterAnimation.cs b/Definitions/ObjectModels/Objects/Vehicle/EmitterAnimation.cs
index fb604e13..39c051ee 100644
--- a/Definitions/ObjectModels/Objects/Vehicle/EmitterAnimation.cs
+++ b/Definitions/ObjectModels/Objects/Vehicle/EmitterAnimation.cs
@@ -7,7 +7,7 @@ namespace Definitions.ObjectModels.Objects.Vehicle;
[TypeConverter(typeof(ExpandableObjectConverter))]
public class EmitterAnimation : ILocoStruct
{
- public ObjectModelHeader AnimationObject { get; set; } // will be SteamObject
+ public ObjectModelHeader AnimationObject { get; set; } // will be SteamObject
public uint8_t EmitterVerticalPos { get; set; }
public SimpleAnimationType Type { get; set; }
diff --git a/Definitions/ObjectModels/Objects/Vehicle/FrictionSound.cs b/Definitions/ObjectModels/Objects/Vehicle/FrictionSound.cs
index 6586e3ac..1cb378f7 100644
--- a/Definitions/ObjectModels/Objects/Vehicle/FrictionSound.cs
+++ b/Definitions/ObjectModels/Objects/Vehicle/FrictionSound.cs
@@ -1,3 +1,4 @@
+using Definitions.ObjectModels.Types;
using System.ComponentModel;
namespace Definitions.ObjectModels.Objects.Vehicle;
@@ -5,7 +6,7 @@ namespace Definitions.ObjectModels.Objects.Vehicle;
[TypeConverter(typeof(ExpandableObjectConverter))]
public class FrictionSound
{
- public uint8_t SoundObjectId { get; set; }
+ public ObjectModelHeader SoundObject { get; set; }
public int32_t MinSpeed { get; set; }
public uint8_t SpeedFreqFactor { get; set; }
public uint16_t BaseFrequency { get; set; }
diff --git a/Definitions/ObjectModels/Objects/Vehicle/GearboxMotorSound.cs b/Definitions/ObjectModels/Objects/Vehicle/GearboxMotorSound.cs
index 6876c950..55c72409 100644
--- a/Definitions/ObjectModels/Objects/Vehicle/GearboxMotorSound.cs
+++ b/Definitions/ObjectModels/Objects/Vehicle/GearboxMotorSound.cs
@@ -1,3 +1,4 @@
+using Definitions.ObjectModels.Types;
using System.ComponentModel;
namespace Definitions.ObjectModels.Objects.Vehicle;
@@ -5,7 +6,7 @@ namespace Definitions.ObjectModels.Objects.Vehicle;
[TypeConverter(typeof(ExpandableObjectConverter))]
public class GearboxMotorSound
{
- public uint8_t SoundObjectId { get; set; }
+ public ObjectModelHeader SoundObject { get; set; }
public uint16_t IdleFrequency { get; set; }
public uint8_t IdleVolume { get; set; }
public uint16_t FirstGearFrequency { get; set; } // All subsequent gears are based on this frequency
diff --git a/Definitions/ObjectModels/Objects/Vehicle/SimpleMotorSound.cs b/Definitions/ObjectModels/Objects/Vehicle/SimpleMotorSound.cs
index 867afa39..7e438189 100644
--- a/Definitions/ObjectModels/Objects/Vehicle/SimpleMotorSound.cs
+++ b/Definitions/ObjectModels/Objects/Vehicle/SimpleMotorSound.cs
@@ -1,3 +1,4 @@
+using Definitions.ObjectModels.Types;
using System.ComponentModel;
namespace Definitions.ObjectModels.Objects.Vehicle;
@@ -5,7 +6,7 @@ namespace Definitions.ObjectModels.Objects.Vehicle;
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SimpleMotorSound
{
- public uint8_t SoundObjectId { get; set; }
+ public ObjectModelHeader SoundObject { get; set; }
public uint16_t IdleFrequency { get; set; }
public uint8_t IdleVolume { get; set; }
public uint16_t CoastingFrequency { get; set; }
diff --git a/Definitions/ObjectModels/Objects/Vehicle/VehicleObject.cs b/Definitions/ObjectModels/Objects/Vehicle/VehicleObject.cs
index 28146626..ea29946e 100644
--- a/Definitions/ObjectModels/Objects/Vehicle/VehicleObject.cs
+++ b/Definitions/ObjectModels/Objects/Vehicle/VehicleObject.cs
@@ -9,7 +9,7 @@ public class VehicleObject : ILocoStruct
public TransportMode Mode { get; set; }
public VehicleType Type { get; set; }
public uint8_t NumCarComponents { get; set; }
- public ObjectModelHeader? TrackType { get; set; }
+ public ObjectModelHeader? RoadOrTrackType { get; set; }
public object_id TrackTypeId { get; set; }
public uint8_t CostIndex { get; set; }
public int16_t CostFactor { get; set; }
diff --git a/Definitions/ObjectModels/ColourSwatch.cs b/Definitions/ObjectModels/Types/ColourSwatch.cs
similarity index 85%
rename from Definitions/ObjectModels/ColourSwatch.cs
rename to Definitions/ObjectModels/Types/ColourSwatch.cs
index 0bc31010..5c59176e 100644
--- a/Definitions/ObjectModels/ColourSwatch.cs
+++ b/Definitions/ObjectModels/Types/ColourSwatch.cs
@@ -1,4 +1,4 @@
-namespace Definitions.ObjectModels;
+namespace Definitions.ObjectModels.Types;
public enum ColourSwatch
{
diff --git a/Definitions/ObjectModels/Types/ObjectModelHeader.cs b/Definitions/ObjectModels/Types/ObjectModelHeader.cs
index d6a9148d..d9fa0292 100644
--- a/Definitions/ObjectModels/Types/ObjectModelHeader.cs
+++ b/Definitions/ObjectModels/Types/ObjectModelHeader.cs
@@ -6,6 +6,10 @@ namespace Definitions.ObjectModels.Types;
[TypeConverter(typeof(ExpandableObjectConverter))]
public class ObjectModelHeader(string name, ObjectType objectType, ObjectSource objectSource, uint datchecksum) : ILocoStruct
{
+ public ObjectModelHeader()
+ : this(string.Empty, ObjectType.Airport, ObjectSource.Custom, 0)
+ { }
+
public string Name { get; set; } = name;
public ObjectType ObjectType { get; set; } = objectType;
public ObjectSource ObjectSource { get; set; } = objectSource;
diff --git a/Definitions/ObjectModels/Types/Pos.cs b/Definitions/ObjectModels/Types/Pos.cs
index bdc04946..1f098171 100644
--- a/Definitions/ObjectModels/Types/Pos.cs
+++ b/Definitions/ObjectModels/Types/Pos.cs
@@ -8,7 +8,7 @@ public class Pos2
public coord_t X { get; set; }
public coord_t Y { get; set; }
- public static Pos2 Zero => new Pos2 { X = 0, Y = 0 };
+ public static Pos2 Zero => new() { X = 0, Y = 0 };
}
[TypeConverter(typeof(ExpandableObjectConverter))]
@@ -18,5 +18,5 @@ public class Pos3
public coord_t Y { get; set; }
public coord_t Z { get; set; }
- public static Pos3 Zero => new Pos3 { X = 0, Y = 0, Z = 0 };
+ public static Pos3 Zero => new() { X = 0, Y = 0, Z = 0 };
}
diff --git a/Gui/App.axaml b/Gui/App.axaml
index 45a17c64..29d2584c 100644
--- a/Gui/App.axaml
+++ b/Gui/App.axaml
@@ -18,6 +18,8 @@
+
+
-
+
+
@@ -109,7 +118,7 @@
-
+
diff --git a/Gui/Gui.csproj b/Gui/Gui.csproj
index 69b63b17..b06e9855 100644
--- a/Gui/Gui.csproj
+++ b/Gui/Gui.csproj
@@ -81,5 +81,9 @@
ObjectEditorView.axaml
+
+ Pos3View.axaml
+ Code
+
diff --git a/Gui/ViewModels/Graphics/ColourRemapSwatchViewModel.cs b/Gui/ViewModels/Graphics/ColourRemapSwatchViewModel.cs
index 0e5477e8..36648ade 100644
--- a/Gui/ViewModels/Graphics/ColourRemapSwatchViewModel.cs
+++ b/Gui/ViewModels/Graphics/ColourRemapSwatchViewModel.cs
@@ -1,4 +1,4 @@
-using Definitions.ObjectModels;
+using Definitions.ObjectModels.Types;
using ReactiveUI.Fody.Helpers;
using AvaColour = Avalonia.Media.Color;
diff --git a/Gui/ViewModels/LocoTypes/Objects/AirportViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/AirportViewModel.cs
index 307426df..2e0d49db 100644
--- a/Gui/ViewModels/LocoTypes/Objects/AirportViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/AirportViewModel.cs
@@ -80,13 +80,16 @@ public int16_t SellCostFactor
set => Model.SellCostFactor = value;
}
- [Category("Building"), Length(1, AirportObjectLoader.Constants.BuildingVariationCount)]
+ [Category("Building")]
+ [Length(1, AirportObjectLoader.Constants.BuildingVariationCount)]
public BindingList> BuildingVariations { get; init; } = new(model.BuildingComponents.BuildingVariations.Select(x => x.ToBindingList()).ToBindingList());
- [Category("Building"), Length(1, AirportObjectLoader.Constants.BuildingHeightCount)]
+ [Category("Building")]
+ [Length(1, AirportObjectLoader.Constants.BuildingHeightCount)]
public BindingList BuildingHeights { get; init; } = model.BuildingComponents.BuildingHeights.ToBindingList();
- [Category("Building"), Length(1, AirportObjectLoader.Constants.BuildingAnimationCount)]
+ [Category("Building")]
+ [Length(1, AirportObjectLoader.Constants.BuildingAnimationCount)]
public BindingList BuildingAnimations { get; init; } = model.BuildingComponents.BuildingAnimations.ToBindingList();
[Category("Building")]
@@ -111,16 +114,4 @@ public uint32_t var_B6
get => Model.var_B6;
set => Model.var_B6 = value;
}
-
- //public AirportViewModel(AirportObject model)
- // : base(model)
- //{
- // BuildingHeights = new(model.BuildingComponents.BuildingHeights);
- // BuildingAnimations = new(model.BuildingComponents.BuildingAnimations);
- // BuildingVariations = new(model.BuildingComponents.BuildingVariations.Select(x => new BindingList(x)));
- // BuildingPositions = new(model.BuildingPositions);
- // MovementNodes = new(model.MovementNodes);
- // MovementEdges = new(model.MovementEdges);
- // var_B6 = new BindingList(model.var_B6);
- //}
}
diff --git a/Gui/ViewModels/LocoTypes/Objects/BridgeViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/BridgeViewModel.cs
index 897dca15..5a860eab 100644
--- a/Gui/ViewModels/LocoTypes/Objects/BridgeViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/BridgeViewModel.cs
@@ -92,9 +92,11 @@ public int16_t SellCostFactor
set => Model.SellCostFactor = value;
}
- [Category("Compatible")] public BindingList CompatibleTrackObjects { get; init; } = new(model.CompatibleTrackObjects);
+ [Category("Compatible")]
+ public BindingList CompatibleTrackObjects { get; init; } = new(model.CompatibleTrackObjects);
- [Category("Compatible")] public BindingList CompatibleRoadObjects { get; init; } = new(model.CompatibleRoadObjects);
+ [Category("Compatible")]
+ public BindingList CompatibleRoadObjects { get; init; } = new(model.CompatibleRoadObjects);
[Category("")]
public uint8_t var_03
diff --git a/Gui/ViewModels/LocoTypes/Objects/DockViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/DockViewModel.cs
index f8b187f0..9671277a 100644
--- a/Gui/ViewModels/LocoTypes/Objects/DockViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/DockViewModel.cs
@@ -59,13 +59,16 @@ public int16_t SellCostFactor
set => Model.SellCostFactor = value;
}
- [Category("Building"), Length(1, DockObjectLoader.Constants.BuildingVariationCount)]
+ [Category("Building")]
+ [Length(1, DockObjectLoader.Constants.BuildingVariationCount)]
public BindingList> BuildingVariations { get; init; } = new(model.BuildingComponents.BuildingVariations.Select(x => x.ToBindingList()).ToBindingList());
- [Category("Building"), Length(1, DockObjectLoader.Constants.BuildingHeightCount)]
+ [Category("Building")]
+ [Length(1, DockObjectLoader.Constants.BuildingHeightCount)]
public BindingList BuildingHeights { get; init; } = model.BuildingComponents.BuildingHeights.ToBindingList();
- [Category("Building"), Length(1, DockObjectLoader.Constants.BuildingAnimationCount)]
+ [Category("Building")]
+ [Length(1, DockObjectLoader.Constants.BuildingAnimationCount)]
public BindingList BuildingAnimations { get; init; } = model.BuildingComponents.BuildingAnimations.ToBindingList();
[Category("")]
diff --git a/Gui/ViewModels/LocoTypes/Objects/IndustryViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/IndustryViewModel.cs
index 50344a15..141b3ab5 100644
--- a/Gui/ViewModels/LocoTypes/Objects/IndustryViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/IndustryViewModel.cs
@@ -56,10 +56,12 @@ public uint32_t Colours
[Category("Production")]
public BindingList InitialProductionRate { get; init; } = new(model.InitialProductionRate);
- [Category("Production"), Length(0, IndustryObjectLoader.Constants.MaxProducedCargoType)]
+ [Category("Production")]
+ [Length(0, IndustryObjectLoader.Constants.MaxProducedCargoType)]
public BindingList ProducedCargo { get; init; } = new(model.ProducedCargo);
- [Category("Production"), Length(0, IndustryObjectLoader.Constants.MaxProducedCargoType)]
+ [Category("Production")]
+ [Length(0, IndustryObjectLoader.Constants.MaxProducedCargoType)]
public BindingList RequiredCargo { get; init; } = new(model.RequiredCargo);
[Category("Production")]
@@ -118,16 +120,20 @@ public uint8_t FarmNumStagesOfGrowth
set => Model.FarmNumStagesOfGrowth = value;
}
- [Category("Building"), Length(IndustryObjectLoader.Constants.AnimationSequencesCount, IndustryObjectLoader.Constants.AnimationSequencesCount)]
+ [Category("Building")]
+ [Length(IndustryObjectLoader.Constants.AnimationSequencesCount, IndustryObjectLoader.Constants.AnimationSequencesCount)]
public BindingList> AnimationSequences { get; init; } = model.AnimationSequences.Select(x => x.ToBindingList()).ToBindingList();
- [Category("Building"), Length(1, IndustryObjectLoader.Constants.BuildingVariationCount)]
+ [Category("Building")]
+ [Length(1, IndustryObjectLoader.Constants.BuildingVariationCount)]
public BindingList> BuildingVariations { get; init; } = new(model.BuildingComponents.BuildingVariations.Select(x => x.ToBindingList()).ToBindingList());
- [Category("Building"), Length(1, IndustryObjectLoader.Constants.BuildingHeightCount)]
+ [Category("Building")]
+ [Length(1, IndustryObjectLoader.Constants.BuildingHeightCount)]
public BindingList BuildingHeights { get; init; } = model.BuildingComponents.BuildingHeights.ToBindingList();
- [Category("Building"), Length(1, IndustryObjectLoader.Constants.BuildingAnimationCount)]
+ [Category("Building")]
+ [Length(1, IndustryObjectLoader.Constants.BuildingAnimationCount)]
public BindingList BuildingAnimations { get; init; } = model.BuildingComponents.BuildingAnimations.ToBindingList();
[Category("Building")]
@@ -168,7 +174,8 @@ public Colour ScaffoldingColour
set => Model.ScaffoldingColour = value;
}
- [Category("Building"), Length(0, IndustryObjectLoader.Constants.MaxWallTypeCount)]
+ [Category("Building")]
+ [Length(0, IndustryObjectLoader.Constants.MaxWallTypeCount)]
public BindingList WallTypes { get; init; } = model.WallTypes.ToBindingList();
[Category("Building")]
diff --git a/Gui/ViewModels/LocoTypes/Objects/RegionViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/RegionViewModel.cs
index 69ceeb64..dbc29001 100644
--- a/Gui/ViewModels/LocoTypes/Objects/RegionViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/RegionViewModel.cs
@@ -19,9 +19,11 @@ public uint8_t pad_07
set => Model.pad_07 = value;
}
- [Category("Cargo")] public BindingList CargoInfluenceObjects { get; init; } = new(model.CargoInfluenceObjects);
public BindingList DependentObjects { get; init; } = new(model.DependentObjects);
+ [Category("Cargo")]
+ public BindingList CargoInfluenceObjects { get; init; } = new(model.CargoInfluenceObjects);
+
[Category("Cargo")]
public BindingList CargoInfluenceTownFilter { get; init; } = new(model.CargoInfluenceTownFilter);
}
diff --git a/Gui/ViewModels/LocoTypes/Objects/RoadViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/RoadViewModel.cs
index 320518ff..517a5b9c 100644
--- a/Gui/ViewModels/LocoTypes/Objects/RoadViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/RoadViewModel.cs
@@ -81,8 +81,15 @@ public ObjectModelHeader Tunnel
set => Model.Tunnel = value;
}
- [Category("Compatible Objects")] public BindingList Bridges { get; set; } = new(model.Bridges);
- [Category("Compatible Objects")] public BindingList Stations { get; set; } = new(model.Stations);
- [Category("Compatible Objects")] public BindingList Mods { get; set; } = new(model.RoadMods);
- [Category("Compatible Objects")] public BindingList TracksAndRoads { get; set; } = new(model.TracksAndRoads);
+ [Category("Compatible Objects")]
+ public BindingList Bridges { get; set; } = new(model.Bridges);
+
+ [Category("Compatible Objects")]
+ public BindingList Stations { get; set; } = new(model.Stations);
+
+ [Category("Compatible Objects")]
+ public BindingList Mods { get; set; } = new(model.RoadMods);
+
+ [Category("Compatible Objects")]
+ public BindingList TracksAndRoads { get; set; } = new(model.TracksAndRoads);
}
diff --git a/Gui/ViewModels/LocoTypes/Objects/TownNamesViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/TownNamesViewModel.cs
index 76894ee4..0f72c819 100644
--- a/Gui/ViewModels/LocoTypes/Objects/TownNamesViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/TownNamesViewModel.cs
@@ -8,7 +8,8 @@ namespace Gui.ViewModels;
public class TownNamesViewModel(TownNamesObject model)
: LocoObjectViewModel(model)
{
- [Length(6, 6), Editable(false)]
+ [Length(6, 6)]
+ [Editable(false)]
public BindingList Categories { get; set; } = model.Categories.ToBindingList();
}
diff --git a/Gui/ViewModels/LocoTypes/Objects/TrackStationViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/TrackStationViewModel.cs
index adf4aa23..94104e04 100644
--- a/Gui/ViewModels/LocoTypes/Objects/TrackStationViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/TrackStationViewModel.cs
@@ -7,9 +7,9 @@
namespace Gui.ViewModels;
-public class TrackStationViewModel(TrackStationObject model) : LocoObjectViewModel(model)
+public class TrackStationViewModel(TrackStationObject model)
+ : LocoObjectViewModel(model)
{
-
public uint8_t PaintStyle
{
get => Model.PaintStyle;
diff --git a/Gui/ViewModels/LocoTypes/Objects/TrackViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/TrackViewModel.cs
index f6d8fdf1..f44f32e1 100644
--- a/Gui/ViewModels/LocoTypes/Objects/TrackViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/TrackViewModel.cs
@@ -84,9 +84,18 @@ public ObjectModelHeader Tunnel
set => Model.Tunnel = value;
}
- [Category("Compatible Objects")] public BindingList TracksAndRoads { get; init; } = new(model.TracksAndRoads);
- [Category("Compatible Objects")] public BindingList TrackExtras { get; init; } = new(model.TrackMods);
- [Category("Compatible Objects")] public BindingList Signals { get; init; } = new(model.Signals);
- [Category("Compatible Objects")] public BindingList Bridges { get; init; } = new(model.Bridges);
- [Category("Compatible Objects")] public BindingList Stations { get; init; } = new(model.Stations);
+ [Category("Compatible Objects")]
+ public BindingList TracksAndRoads { get; init; } = new(model.TracksAndRoads);
+
+ [Category("Compatible Objects")]
+ public BindingList TrackExtras { get; init; } = new(model.TrackMods);
+
+ [Category("Compatible Objects")]
+ public BindingList Signals { get; init; } = new(model.Signals);
+
+ [Category("Compatible Objects")]
+ public BindingList Bridges { get; init; } = new(model.Bridges);
+
+ [Category("Compatible Objects")]
+ public BindingList Stations { get; init; } = new(model.Stations);
}
diff --git a/Gui/ViewModels/LocoTypes/Objects/VehicleViewModel.cs b/Gui/ViewModels/LocoTypes/Objects/VehicleViewModel.cs
index 678930ea..08185998 100644
--- a/Gui/ViewModels/LocoTypes/Objects/VehicleViewModel.cs
+++ b/Gui/ViewModels/LocoTypes/Objects/VehicleViewModel.cs
@@ -2,6 +2,8 @@
using Definitions.ObjectModels.Objects.Cargo;
using Definitions.ObjectModels.Objects.Vehicle;
using Definitions.ObjectModels.Types;
+using DynamicData.Binding;
+using PropertyModels.ComponentModel;
using PropertyModels.ComponentModel.DataAnnotations;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
@@ -30,16 +32,59 @@ public VehicleViewModel(VehicleObject model) : base(model)
CargoTypeSpriteOffsets = new([.. model.CargoTypeSpriteOffsets.Select(x => new CargoTypeSpriteOffset(x.Key, x.Value))]);
StartSounds = new(model.StartSounds);
var_135 = new(model.var_135);
- TrackType = model.TrackType;
+ RoadOrTrackType = model.RoadOrTrackType;
RackRail = model.RackRail;
HasRackRail = model.Flags.HasFlag(VehicleObjectFlags.RackRail);
+ SimpleMotorSound = model.SimpleMotorSound ?? new SimpleMotorSound();
+ FrictionSound = model.FrictionSound ?? new FrictionSound();
+ GearboxMotorSound = model.GearboxMotorSound ?? new GearboxMotorSound();
+ Sound = model.Sound;
+
+ _ = this.WhenAnyValue(x => x.RackRail)
+ .Subscribe((_) => model.RackRail = RackRail);
+
+ #region Road/Track Type Binding
+
_ = this.WhenAnyValue(x => x.Mode, x => x.Flags)
.Subscribe((_) => this.RaisePropertyChanged(nameof(IsTrackTypeSettable)));
_ = this.WhenAnyValue(x => x.IsTrackTypeSettable)
- .Subscribe((_) => this.RaisePropertyChanged(nameof(TrackType)));
+ .Subscribe((_) => this.RaisePropertyChanged(nameof(RoadOrTrackType)));
+
+ _ = this.WhenAnyValue(x => x.RoadOrTrackType)
+ .Subscribe((_) => model.RoadOrTrackType = RoadOrTrackType);
+
+ #endregion
+
+ #region Sound Properties Binding
+ _ = this.WhenAnyValue(x => x.DrivingSoundType)
+ .Subscribe((_) =>
+ {
+ this.RaisePropertyChanged(nameof(SimpleMotorSound));
+ this.RaisePropertyChanged(nameof(FrictionSound));
+ this.RaisePropertyChanged(nameof(GearboxMotorSound));
+ });
+
+ _ = this.WhenAnyValue(x => x.Sound)
+ .Subscribe((_) => model.Sound = Sound);
+
+ _ = this.WhenAnyValue(x => x.SimpleMotorSound)
+ .Subscribe((_) => model.SimpleMotorSound = SimpleMotorSound);
+ _ = this.WhenAnyValue(x => x.FrictionSound)
+ .Subscribe((_) => model.FrictionSound = FrictionSound);
+ _ = this.WhenAnyValue(x => x.GearboxMotorSound)
+ .Subscribe((_) => model.GearboxMotorSound = GearboxMotorSound);
+
+ _ = this.WhenPropertyChanged(x => x.SimpleMotorSound)
+ .Subscribe((_) => model.SimpleMotorSound = SimpleMotorSound);
+ _ = this.WhenPropertyChanged(x => x.FrictionSound)
+ .Subscribe((_) => model.FrictionSound = FrictionSound);
+ _ = this.WhenPropertyChanged(x => x.GearboxMotorSound)
+ .Subscribe((_) => model.GearboxMotorSound = GearboxMotorSound);
+
+ #endregion
}
[Category("Stats")]
@@ -116,12 +161,16 @@ public VehicleObjectFlags Flags
}
}
+ [Browsable(false)]
bool IsTrackTypeSettable
- => (!model.Flags.HasFlag(VehicleObjectFlags.AnyRoadType) && (model.Mode == TransportMode.Rail || model.Mode == TransportMode.Road));
+ => !model.Flags.HasFlag(VehicleObjectFlags.AnyRoadType) && (model.Mode == TransportMode.Rail || model.Mode == TransportMode.Road);
- [Reactive, ConditionTarget, PropertyVisibilityCondition(nameof(IsTrackTypeSettable), true)]
- public ObjectModelHeader? TrackType { get; set; }
+ [Reactive]
+ [ConditionTarget]
+ [PropertyVisibilityCondition(nameof(IsTrackTypeSettable), true)]
+ public ObjectModelHeader? RoadOrTrackType { get; set; }
+ [ConditionTarget]
public bool HasRackRail
{
get => model.Flags.HasFlag(VehicleObjectFlags.RackRail);
@@ -134,7 +183,9 @@ public bool HasRackRail
}
}
- [Reactive, ConditionTarget, PropertyVisibilityCondition(nameof(HasRackRail), true)]
+ [Reactive]
+ [ConditionTarget]
+ [PropertyVisibilityCondition(nameof(HasRackRail), true)]
public ObjectModelHeader? RackRail { get; set; }
[Range(0, 4)]
@@ -157,28 +208,32 @@ public uint8_t ShipWakeSpacing
set => model.ShipWakeSpacing = value;
}
- [Category("Cost"), Range(0, 32)]
+ [Category("Cost")]
+ [Range(0, 32)]
public uint8_t CostIndex
{
get => model.CostIndex;
set => model.CostIndex = value;
}
- [Category("Cost"), Range(1, int16_t.MaxValue)]
+ [Category("Cost")]
+ [Range(1, int16_t.MaxValue)]
public int16_t CostFactor
{
get => model.CostFactor;
set => model.CostFactor = value;
}
- [Category("Cost"), Range(0, 32)]
+ [Category("Cost")]
+ [Range(0, 32)]
public uint8_t RunCostIndex
{
get => model.RunCostIndex;
set => model.RunCostIndex = value;
}
- [Category("Cost"), Range(0, int16_t.MaxValue)]
+ [Category("Cost")]
+ [Range(0, int16_t.MaxValue)]
public int16_t RunCostFactor
{
get => model.RunCostFactor;
@@ -192,10 +247,17 @@ public CompanyColourType SpecialColourSchemeIndex
set => model.CompanyColourSchemeIndex = value;
} // called "ColourType" in the loco codebase
- [Category("Sprites"), Editable(false)] public BindingList CarComponents { get; init; }
- [Category("Sprites"), Editable(false)] public BindingList BodySprites { get; init; }
- [Category("Sprites"), Editable(false)] public BindingList BogieSprites { get; init; }
- [Category("Sprites"), Editable(false)] public BindingList Animation { get; init; }
+ [Category("Sprites")]
+ public BindingList CarComponents { get; init; }
+
+ [Category("Sprites")]
+ public BindingList BodySprites { get; init; }
+
+ [Category("Sprites")]
+ public BindingList BogieSprites { get; init; }
+
+ [Category("Sprites")]
+ public BindingList Animation { get; init; }
[Category("Cargo")]
public CompatibleCargo CompatibleCargo1 { get; init; }
@@ -203,43 +265,46 @@ public CompanyColourType SpecialColourSchemeIndex
[Category("Cargo")]
public CompatibleCargo CompatibleCargo2 { get; init; }
- [Category("Cargo"), Length(0, 32), Description("This is a dictionary. For every cargo defined in both CompatibleCargoCategories, an entry must exist in this dictionary.")]
+ [Category("Cargo")]
+ [Length(0, 32)]
+ [Description("This is a dictionary. For every cargo defined in both CompatibleCargoCategories, an entry must exist in this dictionary.")]
public BindingList CargoTypeSpriteOffsets { get; init; }
[Category("Sound")]
- public ObjectModelHeader? Sound
- {
- get => model.Sound;
- set => model.Sound = value;
- }
-
- [Category("Sound")]
+ [ConditionTarget]
public DrivingSoundType DrivingSoundType
{
get => model.DrivingSoundType;
- set => model.DrivingSoundType = value;
+ set
+ {
+ model.DrivingSoundType = value;
+ this.RaisePropertyChanged(nameof(DrivingSoundType));
+ }
}
+ [Browsable(false)]
+ [DependsOnProperty(nameof(DrivingSoundType))]
+ [ConditionTarget]
+ bool IsDrivingSoundTypeSet
+ => model.DrivingSoundType != DrivingSoundType.None;
+
[Category("Sound")]
- public FrictionSound? FrictionSound
- {
- get => model.FrictionSound;
- set => model.FrictionSound = value;
- }
+ [Reactive]
+ [PropertyVisibilityCondition(nameof(IsDrivingSoundTypeSet), true)]
+ public ObjectModelHeader? Sound { get; set; }
[Category("Sound")]
- public SimpleMotorSound? SimpleMotorSound
- {
- get => model.SimpleMotorSound;
- set => model.SimpleMotorSound = value;
- }
+ [PropertyVisibilityCondition(nameof(DrivingSoundType), DrivingSoundType.Friction)]
+ public FrictionSound FrictionSound { get; set; }
[Category("Sound")]
- public GearboxMotorSound? GearboxMotorSound
- {
- get => model.GearboxMotorSound;
- set => model.GearboxMotorSound = value;
- }
+ [PropertyVisibilityCondition(nameof(DrivingSoundType), DrivingSoundType.SimpleMotor)]
+ public SimpleMotorSound SimpleMotorSound { get; set; }
+
+ [Category("Sound")]
+ [ConditionTarget]
+ [PropertyVisibilityCondition(nameof(DrivingSoundType), DrivingSoundType.GearboxMotor)]
+ public GearboxMotorSound GearboxMotorSound { get; set; }
[Category("Sound")]
public BindingList StartSounds { get; init; }
@@ -249,6 +314,7 @@ public GearboxMotorSound? GearboxMotorSound
public override void CopyBackToModel()
{
+ // this should be done with the reactive properties, but for now we'll leave it like this
Model.MaxCargo = [CompatibleCargo1.MaxCargo, CompatibleCargo2.MaxCargo];
Model.CompatibleCargoCategories =
[
diff --git a/Gui/ViewModels/Pos3ViewModel.cs b/Gui/ViewModels/Pos3ViewModel.cs
new file mode 100644
index 00000000..a994b5d9
--- /dev/null
+++ b/Gui/ViewModels/Pos3ViewModel.cs
@@ -0,0 +1,27 @@
+using Definitions.ObjectModels.Types;
+using PropertyModels.ComponentModel;
+
+namespace Gui.ViewModels;
+
+public class Pos3ViewModel : MiniReactiveObject
+{
+ public Pos3 Pos;
+
+ public coord_t X
+ {
+ get => Pos.X;
+ set => Pos.X = value;
+ }
+
+ public coord_t Y
+ {
+ get => Pos.Y;
+ set => Pos.Y = value;
+ }
+
+ public coord_t Z
+ {
+ get => Pos.Z;
+ set => Pos.Z = value;
+ }
+}
diff --git a/Gui/Views/ExtendedPropertyGrid.cs b/Gui/Views/ExtendedPropertyGrid.cs
new file mode 100644
index 00000000..10a12f8f
--- /dev/null
+++ b/Gui/Views/ExtendedPropertyGrid.cs
@@ -0,0 +1,63 @@
+using Avalonia.Controls;
+using Avalonia.PropertyGrid.Controls;
+using Avalonia.PropertyGrid.Controls.Factories;
+using Definitions.ObjectModels.Types;
+using Gui.ViewModels;
+
+namespace Gui.Views;
+
+public class ExtendedPropertyGrid : PropertyGrid
+{
+ public ExtendedPropertyGrid()
+ {
+ Factories.AddFactory(new Pos3CellEditFactory());
+ }
+}
+
+internal class Pos3CellEditFactory : AbstractCellEditFactory
+{
+ public override bool Accept(object accessToken) => accessToken is ExtendedPropertyGrid;
+
+ public override Control? HandleNewProperty(PropertyCellContext context)
+ {
+ var propertyDescriptor = context.Property;
+ _ = context.Target;
+
+ if (propertyDescriptor.PropertyType != typeof(Pos3))
+ {
+ return null;
+ }
+
+ var control = new Pos3View();
+
+ return control;
+ }
+
+ public override bool HandlePropertyChanged(PropertyCellContext context)
+ {
+ var propertyDescriptor = context.Property;
+ var target = context.Target;
+ var control = context.CellEdit!;
+
+ if (propertyDescriptor.PropertyType != typeof(Pos3))
+ {
+ return false;
+ }
+
+ ValidateProperty(control, propertyDescriptor, target);
+
+ if (control is Pos3View vv)
+ {
+ var pos = (Pos3)propertyDescriptor.GetValue(target)!;
+
+ var model = new Pos3ViewModel { Pos = pos };
+ vv.DataContext = model;
+
+ model.PropertyChanged += (s, e) => SetAndRaise(context, control, model.Pos);
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/Gui/Views/ImageView.axaml b/Gui/Views/ImageView.axaml
index f67379ba..74fce643 100644
--- a/Gui/Views/ImageView.axaml
+++ b/Gui/Views/ImageView.axaml
@@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vmg="using:Gui.ViewModels.Graphics"
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
- xmlns:pgc="clr-namespace:Avalonia.PropertyGrid.Controls;assembly=Avalonia.PropertyGrid"
+ xmlns:pgc="clr-namespace:Avalonia.PropertyGrid.Controls;assembly=Avalonia.PropertyGrid"
xmlns:amxc="using:Avalonia.Markup.Xaml.Converters"
xmlns:gmc="using:Gui.Models.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@@ -15,7 +15,7 @@
-
+
diff --git a/Gui/Views/Pos3View.axaml b/Gui/Views/Pos3View.axaml
new file mode 100644
index 00000000..f4772b4a
--- /dev/null
+++ b/Gui/Views/Pos3View.axaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/Gui/Views/Pos3View.cs b/Gui/Views/Pos3View.cs
new file mode 100644
index 00000000..da46ea30
--- /dev/null
+++ b/Gui/Views/Pos3View.cs
@@ -0,0 +1,5 @@
+using Avalonia.Controls.Primitives;
+
+namespace Gui.Views;
+
+public class Pos3View : TemplatedControl;
diff --git a/Tests/IdempotenceTests.cs b/Tests/IdempotenceTests.cs
index 3001878a..ffbeeade 100644
--- a/Tests/IdempotenceTests.cs
+++ b/Tests/IdempotenceTests.cs
@@ -1,6 +1,7 @@
using Dat.Converters;
using Dat.FileParsing;
using Definitions.ObjectModels;
+using Definitions.ObjectModels.Types;
using Gui.ViewModels;
using NUnit.Framework;
using NUnit.Framework.Internal;
diff --git a/Tests/ImagePaletteConversionTests.cs b/Tests/ImagePaletteConversionTests.cs
index b0c38a6d..5fdd8e08 100644
--- a/Tests/ImagePaletteConversionTests.cs
+++ b/Tests/ImagePaletteConversionTests.cs
@@ -4,6 +4,7 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using Definitions.ObjectModels;
+using Definitions.ObjectModels.Types;
namespace Dat.Tests;