Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt a new building viewmodel #149

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 21 additions & 22 deletions Dat/Objects/BuildingObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ public enum BuildingObjectFlags : uint8_t
public record BuildingObject(
[property: LocoStructOffset(0x00), LocoString, Browsable(false)] string_id Name,
[property: LocoStructOffset(0x02), Browsable(false)] image_id Image,
[property: LocoStructOffset(0x06)] uint8_t NumBuildingParts,
[property: LocoStructOffset(0x07)] uint8_t NumBuildingVariations,
[property: LocoStructOffset(0x08), LocoStructVariableLoad, LocoArrayLength(BuildingObject.BuildingHeightCount)] List<uint8_t> BuildingHeights,
[property: LocoStructOffset(0x0C), LocoStructVariableLoad, LocoArrayLength(BuildingObject.BuildingAnimationCount)] List<BuildingPartAnimation> BuildingAnimations,
[property: LocoStructOffset(0x10), LocoStructVariableLoad, LocoArrayLength(BuildingObject.BuildingVariationCount)] List<List<uint8_t>> BuildingVariations,
[property: LocoStructOffset(0x06)] uint8_t NumParts,
[property: LocoStructOffset(0x07)] uint8_t NumVariations,
[property: LocoStructOffset(0x08), LocoStructVariableLoad, LocoArrayLength(BuildingObject.MaxNumParts)] List<uint8_t> PartHeights,
[property: LocoStructOffset(0x0C), LocoStructVariableLoad, LocoArrayLength(BuildingObject.MaxNumParts)] List<BuildingPartAnimation> PartAnimations,
[property: LocoStructOffset(0x10), LocoStructVariableLoad, LocoArrayLength(BuildingObject.VariationPartCount)] List<List<uint8_t>> VariationParts,
[property: LocoStructOffset(0x90)] uint32_t Colours,
[property: LocoStructOffset(0x94)] uint16_t DesignedYear,
[property: LocoStructOffset(0x96)] uint16_t ObsoleteYear,
Expand All @@ -48,9 +48,8 @@ public record BuildingObject(
[property: LocoStructOffset(0xAE), LocoStructVariableLoad, LocoArrayLength(BuildingObject.MaxElevatorHeightSequences)] List<uint8_t[]> _ElevatorHeightSequences // 0xAE ->0xB2->0xB6->0xBA->0xBE (4 byte pointers)
) : ILocoStruct, ILocoStructVariableData
{
public const int BuildingVariationCount = 32;
public const int BuildingHeightCount = 4;
public const int BuildingAnimationCount = 2;
public const int MaxNumParts = 4;
public const int VariationPartCount = 32;
public const int MaxProducedCargoType = 2;
public const int MaxRequiredCargoType = 2;
public const int MaxElevatorHeightSequences = 4;
Expand All @@ -62,28 +61,28 @@ public record BuildingObject(
public ReadOnlySpan<byte> Load(ReadOnlySpan<byte> remainingData)
{
// variation heights
BuildingHeights.Clear();
BuildingHeights.AddRange(ByteReaderT.Read_Array<uint8_t>(remainingData[..(NumBuildingParts * 1)], NumBuildingParts));
remainingData = remainingData[(NumBuildingParts * 1)..]; // uint8_t*
PartHeights.Clear();
PartHeights.AddRange(ByteReaderT.Read_Array<uint8_t>(remainingData[..(NumParts * 1)], NumParts));
remainingData = remainingData[(NumParts * 1)..]; // uint8_t*

// variation animations
BuildingAnimations.Clear();
PartAnimations.Clear();
var buildingAnimationSize = ObjectAttributes.StructSize<BuildingPartAnimation>();
BuildingAnimations.AddRange(ByteReader.ReadLocoStructArray(remainingData[..(NumBuildingParts * buildingAnimationSize)], typeof(BuildingPartAnimation), NumBuildingParts, buildingAnimationSize)
PartAnimations.AddRange(ByteReader.ReadLocoStructArray(remainingData[..(NumParts * buildingAnimationSize)], typeof(BuildingPartAnimation), NumParts, buildingAnimationSize)
.Cast<BuildingPartAnimation>());
remainingData = remainingData[(NumBuildingParts * 2)..]; // uint16_t*
remainingData = remainingData[(NumParts * 2)..]; // uint16_t*

// variation parts
BuildingVariations.Clear();
for (var i = 0; i < NumBuildingVariations; ++i)
VariationParts.Clear();
for (var i = 0; i < NumVariations; ++i)
{
var ptr_10 = 0;
while (remainingData[++ptr_10] != 0xFF)
{
;
}

BuildingVariations.Add(remainingData[..ptr_10].ToArray().ToList());
VariationParts.Add(remainingData[..ptr_10].ToArray().ToList());
ptr_10++;
remainingData = remainingData[ptr_10..];
}
Expand Down Expand Up @@ -117,20 +116,20 @@ public ReadOnlySpan<byte> Save()
var ms = new MemoryStream();

// variation heights
foreach (var x in BuildingHeights)
foreach (var x in PartHeights)
{
ms.WriteByte(x);
}

// variation animations
foreach (var x in BuildingAnimations)
foreach (var x in PartAnimations)
{
ms.WriteByte(x.NumFrames);
ms.WriteByte(x.AnimationSpeed);
}

// variation parts
foreach (var x in BuildingVariations)
foreach (var x in VariationParts)
{
ms.Write(x.ToArray());
ms.WriteByte(0xFF);
Expand Down Expand Up @@ -161,7 +160,7 @@ public ReadOnlySpan<byte> Save()
}

public bool Validate()
=> NumBuildingParts is not 0 and not > 63
&& NumBuildingVariations is not 0 and <= 31;
=> NumParts is not 0 and not > 63
&& NumVariations is not 0 and <= 31;
}
}
26 changes: 12 additions & 14 deletions Dat/Objects/Industry/IndustryObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ public record IndustryObject(
[property: LocoStructOffset(0x1A), Browsable(false)] image_id _var_1A,
[property: LocoStructOffset(0x1E)] uint8_t NumBuildingParts,
[property: LocoStructOffset(0x1F)] uint8_t NumBuildingVariations,
[property: LocoStructOffset(0x20), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingHeightCount)] List<uint8_t> BuildingHeights, // This is the height of a building image
[property: LocoStructOffset(0x24), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingAnimationCount)] List<BuildingPartAnimation> BuildingAnimations,
[property: LocoStructOffset(0x20), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingHeightCount)] List<uint8_t> BuildingPartHeights, // This is the height of a building image
[property: LocoStructOffset(0x24), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingAnimationCount)] List<BuildingPartAnimation> BuildingPartAnimations,
[property: LocoStructOffset(0x28), LocoStructVariableLoad, LocoArrayLength(IndustryObject.AnimationSequencesCount)] List<List<uint8_t>> AnimationSequences, // Access with getAnimationSequence helper method
[property: LocoStructOffset(0x38), LocoStructVariableLoad] List<IndustryObjectUnk38> var_38, // Access with getUnk38 helper method
[property: LocoStructOffset(0x3C), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingVariationCount)] List<List<uint8_t>> BuildingVariations, // Access with getBuildingParts helper method
[property: LocoStructOffset(0x3C), LocoStructVariableLoad, LocoArrayLength(IndustryObject.BuildingVariationCount)] List<List<uint8_t>> BuildingVariationParts, // Access with getBuildingParts helper method
[property: LocoStructOffset(0xBC)] uint8_t MinNumBuildings,
[property: LocoStructOffset(0xBD)] uint8_t MaxNumBuildings,
[property: LocoStructOffset(0xBE), LocoStructVariableLoad] List<uint8_t> Buildings,
Expand Down Expand Up @@ -67,8 +67,6 @@ public record IndustryObject(
public const int MaxRequiredCargoType = 3;
public const int MaxWallTypeCount = 4;

//public List<IndustryObjectUnk38> UnkIndustry38 { get; set; } = [];

public S5Header? BuildingWall { get; set; }

public S5Header? BuildingWallEntrance { get; set; }
Expand All @@ -81,14 +79,14 @@ public record IndustryObject(
public ReadOnlySpan<byte> Load(ReadOnlySpan<byte> remainingData)
{
// part heights
BuildingHeights.Clear();
BuildingHeights.AddRange(ByteReaderT.Read_Array<uint8_t>(remainingData[..(NumBuildingParts * 1)], NumBuildingParts));
BuildingPartHeights.Clear();
BuildingPartHeights.AddRange(ByteReaderT.Read_Array<uint8_t>(remainingData[..(NumBuildingParts * 1)], NumBuildingParts));
remainingData = remainingData[(NumBuildingParts * 1)..]; // uint8_t*

// part animations
BuildingAnimations.Clear();
BuildingPartAnimations.Clear();
var buildingAnimationSize = ObjectAttributes.StructSize<BuildingPartAnimation>();
BuildingAnimations.AddRange(ByteReader.ReadLocoStructArray(remainingData[..(NumBuildingParts * buildingAnimationSize)], typeof(BuildingPartAnimation), NumBuildingParts, buildingAnimationSize)
BuildingPartAnimations.AddRange(ByteReader.ReadLocoStructArray(remainingData[..(NumBuildingParts * buildingAnimationSize)], typeof(BuildingPartAnimation), NumBuildingParts, buildingAnimationSize)
.Cast<BuildingPartAnimation>());
remainingData = remainingData[(NumBuildingParts * 2)..]; // uint16_t*

Expand Down Expand Up @@ -119,7 +117,7 @@ public ReadOnlySpan<byte> Load(ReadOnlySpan<byte> remainingData)
remainingData = remainingData[1..]; // skip final 0xFF byte

// variation parts
BuildingVariations.Clear();
BuildingVariationParts.Clear();
for (var i = 0; i < NumBuildingVariations; ++i)
{
var ptr_1F = 0;
Expand All @@ -128,7 +126,7 @@ public ReadOnlySpan<byte> Load(ReadOnlySpan<byte> remainingData)
;
}

BuildingVariations.Add(remainingData[..ptr_1F].ToArray().ToList());
BuildingVariationParts.Add(remainingData[..ptr_1F].ToArray().ToList());
ptr_1F++;
remainingData = remainingData[ptr_1F..];
}
Expand Down Expand Up @@ -188,13 +186,13 @@ public ReadOnlySpan<byte> Save()
using (var ms = new MemoryStream())
{
// part heights
foreach (var x in BuildingHeights)
foreach (var x in BuildingPartHeights)
{
ms.WriteByte(x);
}

// part animations
foreach (var x in BuildingAnimations)
foreach (var x in BuildingPartAnimations)
{
ms.WriteByte(x.NumFrames);
ms.WriteByte(x.AnimationSpeed);
Expand All @@ -217,7 +215,7 @@ public ReadOnlySpan<byte> Save()
ms.WriteByte(0xFF);

// variation parts
foreach (var x in BuildingVariations)
foreach (var x in BuildingVariationParts)
{
ms.Write(x.ToArray());
ms.WriteByte(0xFF);
Expand Down
1 change: 1 addition & 0 deletions Dat/Objects/TrackObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum TrackTraitFlags : uint16_t
Junction = 1 << 10,
}

[Flags]
public enum TrackObjectFlags : uint16_t
{
None = 0,
Expand Down
8 changes: 4 additions & 4 deletions Gui/Models/ObjectEditorModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,8 @@ public bool TryLoadObject(FileSystemItem filesystemItem, out UiDatLocoFile? uiLo
return true;
}

static Task? indexerTask;
static readonly SemaphoreSlim taskLock = new(1, 1);
static Task? _indexerTask;
static readonly SemaphoreSlim _taskLock = new(1, 1);

public async Task LoadObjDirectoryAsync(string directory, IProgress<float> progress, bool useExistingIndex)
{
Expand All @@ -277,10 +277,10 @@ public async Task LoadObjDirectoryAsync(string directory, IProgress<float> progr
}
finally
{
_ = taskLock.Release();
_ = _taskLock.Release();
}

await indexerTask;
await _indexerTask;
}

async Task LoadObjDirectoryAsyncCore(string directory, IProgress<float> progress, bool useExistingIndex)
Expand Down
50 changes: 50 additions & 0 deletions Gui/ViewModels/DatTypes/BaseLocoFileViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using OpenLoco.Common.Logging;
using OpenLoco.Gui.Models;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;

namespace OpenLoco.Gui.ViewModels
{
public abstract class BaseLocoFileViewModel : ReactiveObject, ILocoFileViewModel
{
protected BaseLocoFileViewModel(FileSystemItem currentFile, ObjectEditorModel model)
{
CurrentFile = currentFile;
Model = model;

ReloadCommand = ReactiveCommand.Create(Load);
SaveCommand = ReactiveCommand.Create(Save);
SaveAsCommand = ReactiveCommand.Create(SaveAs);
DeleteLocalFileCommand = ReactiveCommand.Create(Delete);
}

[Reactive]
public FileSystemItem CurrentFile { get; init; }
public ObjectEditorModel Model { get; init; }

protected ILogger Logger => Model.Logger;

public ReactiveCommand<Unit, Unit> ReloadCommand { get; init; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; init; }
public ReactiveCommand<Unit, Unit> SaveAsCommand { get; init; }
public ReactiveCommand<Unit, Unit> DeleteLocalFileCommand { get; init; }

public abstract void Load();

public abstract void Save();

public abstract void SaveAs();
public virtual void Delete() { }

public string ReloadText => CurrentFile.FileLocation == FileLocation.Local ? "Reload" : "Redownload";
public string SaveText => CurrentFile.FileLocation == FileLocation.Local ? "Save" : "Download";
public string SaveAsText => $"{SaveText} As";
public string DeleteLocalFileText => "Delete File";

public string ReloadIcon => CurrentFile.FileLocation == FileLocation.Local ? "DatabaseRefresh" : "FileSync";
public string SaveIcon => CurrentFile.FileLocation == FileLocation.Local ? "ContentSave" : "FileDownload";
public string SaveAsIcon => CurrentFile.FileLocation == FileLocation.Local ? "ContentSavePlus" : "FileDownloadOutline";
public string DeleteLocalFileIcon => "DeleteForever";
}
}
7 changes: 7 additions & 0 deletions Gui/ViewModels/DatTypes/DatObjectEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using OpenLoco.Dat.Objects.Sound;
using OpenLoco.Dat.Types;
using OpenLoco.Gui.Models;
using PropertyModels.Extensions;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
Expand Down Expand Up @@ -99,6 +100,12 @@ public override void Load()
if (CurrentObject?.LocoObject != null)
{
CurrentObjectViewModel = GetViewModelFromStruct(CurrentObject.LocoObject.Object);

//if (CurrentObjectViewModel is BuildingViewModel bvm)
//{
// bvm.Images = G1ImageConversion.CreateAvaloniaImages(CurrentObject.Images).Cast<Avalonia.Media.IImage>().ToBindingList();
//}

StringTableViewModel = new(CurrentObject.LocoObject.StringTable);

var imageNameProvider = (CurrentObject.LocoObject.Object is IImageTableNameProvider itnp)
Expand Down
53 changes: 0 additions & 53 deletions Gui/ViewModels/DatTypes/ILocoFileViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
using OpenLoco.Common.Logging;
using OpenLoco.Gui.Models;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;

namespace OpenLoco.Gui.ViewModels
{
public record FileViewButton(ReactiveCommand<Unit, Unit> Command, string Text, string Icon);

public interface ILocoFileViewModelControl
{
[Reactive]
public FileSystemItem CurrentFile { get; init; }

ListObservable<FileViewButton> Buttons { get; }
}

public interface ILocoFileViewModel
{
public ReactiveCommand<Unit, Unit> ReloadCommand { get; init; }
Expand All @@ -39,46 +28,4 @@ public interface ILocoFileViewModel
public string SaveAsIcon { get; }
public string DeleteLocalFileIcon { get; }
}

public abstract class BaseLocoFileViewModel : ReactiveObject, ILocoFileViewModel
{
protected BaseLocoFileViewModel(FileSystemItem currentFile, ObjectEditorModel model)
{
CurrentFile = currentFile;
Model = model;

ReloadCommand = ReactiveCommand.Create(Load);
SaveCommand = ReactiveCommand.Create(Save);
SaveAsCommand = ReactiveCommand.Create(SaveAs);
DeleteLocalFileCommand = ReactiveCommand.Create(Delete);
}

[Reactive]
public FileSystemItem CurrentFile { get; init; }
public ObjectEditorModel Model { get; init; }

protected ILogger Logger => Model.Logger;

public ReactiveCommand<Unit, Unit> ReloadCommand { get; init; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; init; }
public ReactiveCommand<Unit, Unit> SaveAsCommand { get; init; }
public ReactiveCommand<Unit, Unit> DeleteLocalFileCommand { get; init; }

public abstract void Load();

public abstract void Save();

public abstract void SaveAs();
public virtual void Delete() { }

public string ReloadText => CurrentFile.FileLocation == FileLocation.Local ? "Reload" : "Redownload";
public string SaveText => CurrentFile.FileLocation == FileLocation.Local ? "Save" : "Download";
public string SaveAsText => $"{SaveText} As";
public string DeleteLocalFileText => "Delete File";

public string ReloadIcon => CurrentFile.FileLocation == FileLocation.Local ? "DatabaseRefresh" : "FileSync";
public string SaveIcon => CurrentFile.FileLocation == FileLocation.Local ? "ContentSave" : "FileDownload";
public string SaveAsIcon => CurrentFile.FileLocation == FileLocation.Local ? "ContentSavePlus" : "FileDownloadOutline";
public string DeleteLocalFileIcon => "DeleteForever";
}
}
Loading