mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-06-02 21:45:13 -05:00
refactor classes to new file
This commit is contained in:
parent
0cca2a6bad
commit
8e87ca99ac
|
|
@ -1215,394 +1215,6 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
*/
|
||||
}
|
||||
|
||||
public interface IEventModel : IEquatable<IEventModel>, INotifyPropertyChanged {
|
||||
event EventHandler EventVisualUpdated;
|
||||
public event EventHandler<EventCycleDirection> CycleEvent;
|
||||
string EventType { get; }
|
||||
string EventIndex { get; }
|
||||
int TopOffset { get; }
|
||||
int LeftOffset { get; }
|
||||
int X { get; set; }
|
||||
int Y { get; set; }
|
||||
int Elevation { get; set; }
|
||||
IPixelViewModel EventRender { get; }
|
||||
void Render(IDataModel model);
|
||||
void Delete();
|
||||
}
|
||||
|
||||
public enum EventCycleDirection { PreviousCategory, PreviousEvent, NextEvent, NextCategory }
|
||||
|
||||
public abstract class BaseEventModel : ViewModelCore, IEventModel, IEquatable<IEventModel> {
|
||||
public event EventHandler EventVisualUpdated;
|
||||
public event EventHandler<EventCycleDirection> CycleEvent;
|
||||
|
||||
private StubCommand cycleEventCommand;
|
||||
public ICommand CycleEventCommand => StubCommand<EventCycleDirection>(ref cycleEventCommand, direction => {
|
||||
CycleEvent?.Invoke(this, direction);
|
||||
});
|
||||
|
||||
protected readonly ModelArrayElement element;
|
||||
private readonly string parentLengthField;
|
||||
|
||||
public string EventType => GetType().Name.Replace("EventModel", string.Empty);
|
||||
public string EventIndex {
|
||||
get {
|
||||
var eventIndex = (element.Start - element.Table.Start) / element.Table.ElementLength + 1;
|
||||
return $"{eventIndex}/{element.Table.ElementCount}";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int TopOffset => 0;
|
||||
public virtual int LeftOffset => 0;
|
||||
|
||||
#region X/Y
|
||||
|
||||
public int X {
|
||||
get => element.GetValue("x");
|
||||
set {
|
||||
element.SetValue("x", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateXY) xy = null;
|
||||
NotifyPropertyChanged(nameof(XY));
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public int Y {
|
||||
get => element.GetValue("y");
|
||||
set {
|
||||
element.SetValue("y", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateXY) xy = null;
|
||||
NotifyPropertyChanged(nameof(XY));
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ignoreUpdateXY;
|
||||
private string xy;
|
||||
public string XY {
|
||||
get {
|
||||
if (xy == null) xy = $"({X}, {Y})";
|
||||
return xy;
|
||||
}
|
||||
set {
|
||||
xy = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
ignoreUpdateXY = true;
|
||||
if (parts[0].TryParseInt(out int x)) X = x;
|
||||
if (parts[1].TryParseInt(out int y)) Y = y;
|
||||
ignoreUpdateXY = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Elevation
|
||||
|
||||
public int Elevation {
|
||||
get => element.GetValue("elevation");
|
||||
set => element.SetValue("elevation", value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IPixelViewModel EventRender { get; protected set; }
|
||||
|
||||
public BaseEventModel(ModelArrayElement element, string parentLengthField) => (this.element, this.parentLengthField) = (element, parentLengthField);
|
||||
|
||||
public void Delete() => DeleteElement(parentLengthField);
|
||||
|
||||
public bool Equals(IEventModel other) {
|
||||
if (other is not BaseEventModel bem) return false;
|
||||
return bem.element.Start == element.Start;
|
||||
}
|
||||
|
||||
public abstract void Render(IDataModel model);
|
||||
|
||||
protected void RaiseEventVisualUpdated() => EventVisualUpdated.Raise(this);
|
||||
|
||||
protected void DeleteElement(string parentCountField) {
|
||||
var table = element.Table;
|
||||
var model = element.Model;
|
||||
var token = element.Token;
|
||||
var offset = table.ConvertByteOffsetToArrayOffset(element.Start);
|
||||
var editCount = table.ElementCount - offset.ElementIndex - 1;
|
||||
for (int i = 0; i < editCount; i++) {
|
||||
// TODO this edits pointers as well, we need to do pointer metadata update stuff
|
||||
token.ChangeData(model, element.Start + i * element.Length, element.Length.Range(j => model[element.Start + i * element.Length + j]).ToList());
|
||||
}
|
||||
if (table.ElementCount > 1) {
|
||||
var shorterTable = table.Append(token, -1);
|
||||
model.ObserveRunWritten(token, shorterTable);
|
||||
} else {
|
||||
foreach (var source in table.PointerSources) {
|
||||
model.ClearPointer(token, source, table.Start);
|
||||
model.WritePointer(token, source, Pointer.NULL);
|
||||
if(model.GetNextRun(source) is ITableRun parentTable) {
|
||||
var parent = new ModelArrayElement(model, parentTable.Start, 0, token, parentTable);
|
||||
parent.SetValue(parentCountField, 0);
|
||||
}
|
||||
}
|
||||
model.ClearData(token, table.Start, table.Length);
|
||||
}
|
||||
}
|
||||
|
||||
protected static IPixelViewModel BuildEventRender(short color) {
|
||||
var pixels = new short[256];
|
||||
for (int x = 1; x < 15; x++) {
|
||||
for (int y = 1; y < 15; y++) {
|
||||
if (((x + y) & 1) != 0) continue;
|
||||
pixels[y * 16 + x] = color;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 2, 2, default), pixels, transparent: 0);
|
||||
}
|
||||
}
|
||||
|
||||
public class ObjectEventModel : BaseEventModel {
|
||||
|
||||
public int ObjectID {
|
||||
get => element.GetValue("id");
|
||||
set => element.SetValue("id", value);
|
||||
}
|
||||
|
||||
public int Graphics {
|
||||
get => element.GetValue("graphics");
|
||||
set {
|
||||
element.SetValue("graphics", value);
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public int MoveType {
|
||||
get => element.GetValue("moveType");
|
||||
set => element.SetValue("moveType", value);
|
||||
}
|
||||
|
||||
#region Range
|
||||
|
||||
public int RangeX {
|
||||
get => element.GetValue("range") & 0xF;
|
||||
set {
|
||||
element.SetValue("range", (RangeY << 4) | value);
|
||||
rangeXY = null;
|
||||
NotifyPropertyChanged(nameof(RangeXY));
|
||||
}
|
||||
}
|
||||
|
||||
public int RangeY {
|
||||
get => element.GetValue("range") >> 4;
|
||||
set {
|
||||
element.SetValue("range", (value << 4) | RangeX);
|
||||
rangeXY = null;
|
||||
NotifyPropertyChanged(nameof(RangeXY));
|
||||
}
|
||||
}
|
||||
|
||||
private string rangeXY;
|
||||
public string RangeXY {
|
||||
get {
|
||||
if (rangeXY == null) rangeXY = $"({RangeX}, {RangeY})";
|
||||
return rangeXY;
|
||||
}
|
||||
set {
|
||||
rangeXY = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
if (parts[0].TryParseInt(out int x) && parts[1].TryParseInt(out int y)) element.SetValue("range", (y << 4) | x);
|
||||
NotifyPropertyChanged(nameof(RangeX));
|
||||
NotifyPropertyChanged(nameof(RangeY));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public int TrainerType {
|
||||
get => element.GetValue("trainerType");
|
||||
set => element.SetValue("trainerType", value);
|
||||
}
|
||||
|
||||
public int TrainerRangeOrBerryID {
|
||||
get => element.GetValue("trainerRangeOrBerryID");
|
||||
set => element.SetValue("trainerRangeOrBerryID", value);
|
||||
}
|
||||
|
||||
public int ScriptAddress {
|
||||
get => element.GetAddress("script");
|
||||
set => element.SetAddress("script", value);
|
||||
}
|
||||
|
||||
private string scriptAddressText;
|
||||
public string ScriptAddressText {
|
||||
get {
|
||||
if (scriptAddressText == null) scriptAddressText = element.GetAddress("script").ToAddress();
|
||||
return scriptAddressText;
|
||||
}
|
||||
set {
|
||||
scriptAddressText = value;
|
||||
element.SetAddress("script", value.TryParseHex(out int result) ? result : Pointer.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
public int Flag {
|
||||
get => element.GetValue("flag");
|
||||
set => element.SetValue("flag", value);
|
||||
}
|
||||
|
||||
public string FlagText {
|
||||
get => element.GetValue("flag").ToString("X4");
|
||||
set => element.SetValue("flag", value.TryParseHex(out int result) ? result : 0);
|
||||
}
|
||||
|
||||
public ObservableCollection<VisualComboOption> Options { get; } = new();
|
||||
|
||||
public ObjectEventModel(ModelArrayElement objectEvent, IList<IPixelViewModel> sprites) : base(objectEvent, "objectCount") {
|
||||
for (int i = 0; i < sprites.Count; i++) Options.Add(VisualComboOption.CreateFromSprite(i.ToString(), sprites[i].PixelData, sprites[i].PixelWidth, i));
|
||||
}
|
||||
|
||||
public override int TopOffset => 16 - EventRender.PixelHeight;
|
||||
public override int LeftOffset => (16 - EventRender.PixelWidth) / 2;
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
var owTable = new ModelTable(model, model.GetTable(HardcodeTablesModel.OverworldSprites).Start);
|
||||
EventRender = Render(model, owTable, Graphics);
|
||||
}
|
||||
|
||||
public static IPixelViewModel Render(IDataModel model, ModelTable owTable, int index) {
|
||||
if (index >= owTable.Count) {
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 2, 2, null), new short[256], 0);
|
||||
}
|
||||
var element = owTable[index];
|
||||
var data = element.GetSubTable("data")[0];
|
||||
var sprites = data.GetSubTable("sprites")[0];
|
||||
var graphicsAddress = sprites.GetAddress("sprite");
|
||||
var graphicsRun = model.GetNextRun(graphicsAddress) as ISpriteRun;
|
||||
if (graphicsRun == null) {
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 16, 16, null), new short[256], 0);
|
||||
}
|
||||
return ReadonlyPixelViewModel.Create(model, graphicsRun, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class WarpEventModel : BaseEventModel {
|
||||
public WarpEventModel(ModelArrayElement warpEvent) : base(warpEvent, "warpCount") { }
|
||||
|
||||
public int WarpID {
|
||||
get => element.GetValue("warpID");
|
||||
set => element.SetValue("warpID", value);
|
||||
}
|
||||
|
||||
#region Bank/Map
|
||||
|
||||
public int Bank {
|
||||
get => element.GetValue("bank");
|
||||
set {
|
||||
element.SetValue("bank", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateBankMap) bankMap = null;
|
||||
NotifyPropertyChanged(nameof(BankMap));
|
||||
NotifyPropertyChanged(nameof(TargetMapName));
|
||||
}
|
||||
}
|
||||
|
||||
public int Map {
|
||||
get => element.GetValue("map");
|
||||
set {
|
||||
element.SetValue("map", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateBankMap) bankMap = null;
|
||||
NotifyPropertyChanged(nameof(BankMap));
|
||||
NotifyPropertyChanged(nameof(TargetMapName));
|
||||
}
|
||||
}
|
||||
|
||||
private bool ignoreUpdateBankMap;
|
||||
private string bankMap;
|
||||
public string BankMap {
|
||||
get {
|
||||
if (bankMap == null) bankMap = $"({Bank}, {Map})";
|
||||
return bankMap;
|
||||
}
|
||||
set {
|
||||
bankMap = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
ignoreUpdateBankMap = true;
|
||||
if (parts[0].TryParseInt(out int bank)) Bank = bank;
|
||||
if (parts[1].TryParseInt(out int map)) Map = map;
|
||||
ignoreUpdateBankMap = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string TargetMapName => BlockMapViewModel.MapIDToText(element.Model, Bank * 1000 + Map);
|
||||
|
||||
#endregion
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(0, 0, 31));
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptEventModel : BaseEventModel {
|
||||
public ScriptEventModel(ModelArrayElement scriptEvent) : base(scriptEvent, "scriptCount") { }
|
||||
|
||||
public int Trigger {
|
||||
get => element.GetValue("trigger");
|
||||
set => element.SetValue("trigger", value);
|
||||
}
|
||||
|
||||
public int Index {
|
||||
get => element.GetValue("index");
|
||||
set => element.SetValue("index", value);
|
||||
}
|
||||
|
||||
public int ScriptAddress {
|
||||
get => element.GetAddress("script");
|
||||
set => element.SetAddress("script", value);
|
||||
}
|
||||
|
||||
private string scriptAddressText;
|
||||
public string ScriptAddressText {
|
||||
get {
|
||||
if (scriptAddressText == null) scriptAddressText = element.GetAddress("script").ToAddress();
|
||||
return scriptAddressText;
|
||||
}
|
||||
set {
|
||||
scriptAddressText = value;
|
||||
element.SetAddress("script", value.TryParseHex(out int result) ? result : Pointer.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(0, 31, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public class SignpostEventModel : BaseEventModel {
|
||||
// kind. arg::|h
|
||||
// kind = 5/6/7 => arg is itemID: hiddenItemID. attr|t|quantity:::.|isUnderFoot.
|
||||
// kind = other => arg is script<`xse`>
|
||||
|
||||
public SignpostEventModel(ModelArrayElement signpostEvent) : base(signpostEvent, "signpostCount") { }
|
||||
|
||||
public int Kind {
|
||||
get => element.GetValue("kind");
|
||||
set => element.SetValue("kind", value);
|
||||
}
|
||||
|
||||
public string Arg {
|
||||
get => element.GetValue("arg").ToString("X8");
|
||||
set => element.SetValue("arg", value.TryParseHex(out int result) ? result : 0);
|
||||
}
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(31, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public enum MapDirection {
|
||||
None = 0,
|
||||
Down = 1,
|
||||
|
|
|
|||
403
src/HexManiac.Core/ViewModels/Map/IEventViewModel.cs
Normal file
403
src/HexManiac.Core/ViewModels/Map/IEventViewModel.cs
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs.Sprites;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Tools;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
||||
|
||||
public interface IEventModel : IEquatable<IEventModel>, INotifyPropertyChanged {
|
||||
event EventHandler EventVisualUpdated;
|
||||
public event EventHandler<EventCycleDirection> CycleEvent;
|
||||
string EventType { get; }
|
||||
string EventIndex { get; }
|
||||
int TopOffset { get; }
|
||||
int LeftOffset { get; }
|
||||
int X { get; set; }
|
||||
int Y { get; set; }
|
||||
int Elevation { get; set; }
|
||||
IPixelViewModel EventRender { get; }
|
||||
void Render(IDataModel model);
|
||||
void Delete();
|
||||
}
|
||||
|
||||
public enum EventCycleDirection { PreviousCategory, PreviousEvent, NextEvent, NextCategory }
|
||||
|
||||
public abstract class BaseEventModel : ViewModelCore, IEventModel, IEquatable<IEventModel> {
|
||||
public event EventHandler EventVisualUpdated;
|
||||
public event EventHandler<EventCycleDirection> CycleEvent;
|
||||
|
||||
private StubCommand cycleEventCommand;
|
||||
public ICommand CycleEventCommand => StubCommand<EventCycleDirection>(ref cycleEventCommand, direction => {
|
||||
CycleEvent?.Invoke(this, direction);
|
||||
});
|
||||
|
||||
protected readonly ModelArrayElement element;
|
||||
private readonly string parentLengthField;
|
||||
|
||||
public string EventType => GetType().Name.Replace("EventModel", string.Empty);
|
||||
public string EventIndex {
|
||||
get {
|
||||
var eventIndex = (element.Start - element.Table.Start) / element.Table.ElementLength + 1;
|
||||
return $"{eventIndex}/{element.Table.ElementCount}";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int TopOffset => 0;
|
||||
public virtual int LeftOffset => 0;
|
||||
|
||||
#region X/Y
|
||||
|
||||
public int X {
|
||||
get => element.GetValue("x");
|
||||
set {
|
||||
element.SetValue("x", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateXY) xy = null;
|
||||
NotifyPropertyChanged(nameof(XY));
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public int Y {
|
||||
get => element.GetValue("y");
|
||||
set {
|
||||
element.SetValue("y", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateXY) xy = null;
|
||||
NotifyPropertyChanged(nameof(XY));
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
private bool ignoreUpdateXY;
|
||||
private string xy;
|
||||
public string XY {
|
||||
get {
|
||||
if (xy == null) xy = $"({X}, {Y})";
|
||||
return xy;
|
||||
}
|
||||
set {
|
||||
xy = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
ignoreUpdateXY = true;
|
||||
if (parts[0].TryParseInt(out int x)) X = x;
|
||||
if (parts[1].TryParseInt(out int y)) Y = y;
|
||||
ignoreUpdateXY = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Elevation
|
||||
|
||||
public int Elevation {
|
||||
get => element.GetValue("elevation");
|
||||
set => element.SetValue("elevation", value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IPixelViewModel EventRender { get; protected set; }
|
||||
|
||||
public BaseEventModel(ModelArrayElement element, string parentLengthField) => (this.element, this.parentLengthField) = (element, parentLengthField);
|
||||
|
||||
public void Delete() => DeleteElement(parentLengthField);
|
||||
|
||||
public bool Equals(IEventModel other) {
|
||||
if (other is not BaseEventModel bem) return false;
|
||||
return bem.element.Start == element.Start;
|
||||
}
|
||||
|
||||
public abstract void Render(IDataModel model);
|
||||
|
||||
protected void RaiseEventVisualUpdated() => EventVisualUpdated.Raise(this);
|
||||
|
||||
protected void DeleteElement(string parentCountField) {
|
||||
var table = element.Table;
|
||||
var model = element.Model;
|
||||
var token = element.Token;
|
||||
var offset = table.ConvertByteOffsetToArrayOffset(element.Start);
|
||||
var editCount = table.ElementCount - offset.ElementIndex - 1;
|
||||
for (int i = 0; i < editCount; i++) {
|
||||
// TODO this edits pointers as well, we need to do pointer metadata update stuff
|
||||
token.ChangeData(model, element.Start + i * element.Length, element.Length.Range(j => model[element.Start + i * element.Length + j]).ToList());
|
||||
}
|
||||
if (table.ElementCount > 1) {
|
||||
var shorterTable = table.Append(token, -1);
|
||||
model.ObserveRunWritten(token, shorterTable);
|
||||
} else {
|
||||
foreach (var source in table.PointerSources) {
|
||||
model.ClearPointer(token, source, table.Start);
|
||||
model.WritePointer(token, source, Pointer.NULL);
|
||||
if (model.GetNextRun(source) is ITableRun parentTable) {
|
||||
var parent = new ModelArrayElement(model, parentTable.Start, 0, token, parentTable);
|
||||
parent.SetValue(parentCountField, 0);
|
||||
}
|
||||
}
|
||||
model.ClearData(token, table.Start, table.Length);
|
||||
}
|
||||
}
|
||||
|
||||
protected static IPixelViewModel BuildEventRender(short color) {
|
||||
var pixels = new short[256];
|
||||
for (int x = 1; x < 15; x++) {
|
||||
for (int y = 1; y < 15; y++) {
|
||||
if (((x + y) & 1) != 0) continue;
|
||||
pixels[y * 16 + x] = color;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 2, 2, default), pixels, transparent: 0);
|
||||
}
|
||||
}
|
||||
|
||||
public class ObjectEventModel : BaseEventModel {
|
||||
|
||||
public int ObjectID {
|
||||
get => element.GetValue("id");
|
||||
set => element.SetValue("id", value);
|
||||
}
|
||||
|
||||
public int Graphics {
|
||||
get => element.GetValue("graphics");
|
||||
set {
|
||||
element.SetValue("graphics", value);
|
||||
RaiseEventVisualUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
public int MoveType {
|
||||
get => element.GetValue("moveType");
|
||||
set => element.SetValue("moveType", value);
|
||||
}
|
||||
|
||||
#region Range
|
||||
|
||||
public int RangeX {
|
||||
get => element.GetValue("range") & 0xF;
|
||||
set {
|
||||
element.SetValue("range", (RangeY << 4) | value);
|
||||
rangeXY = null;
|
||||
NotifyPropertyChanged(nameof(RangeXY));
|
||||
}
|
||||
}
|
||||
|
||||
public int RangeY {
|
||||
get => element.GetValue("range") >> 4;
|
||||
set {
|
||||
element.SetValue("range", (value << 4) | RangeX);
|
||||
rangeXY = null;
|
||||
NotifyPropertyChanged(nameof(RangeXY));
|
||||
}
|
||||
}
|
||||
|
||||
private string rangeXY;
|
||||
public string RangeXY {
|
||||
get {
|
||||
if (rangeXY == null) rangeXY = $"({RangeX}, {RangeY})";
|
||||
return rangeXY;
|
||||
}
|
||||
set {
|
||||
rangeXY = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
if (parts[0].TryParseInt(out int x) && parts[1].TryParseInt(out int y)) element.SetValue("range", (y << 4) | x);
|
||||
NotifyPropertyChanged(nameof(RangeX));
|
||||
NotifyPropertyChanged(nameof(RangeY));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public int TrainerType {
|
||||
get => element.GetValue("trainerType");
|
||||
set => element.SetValue("trainerType", value);
|
||||
}
|
||||
|
||||
public int TrainerRangeOrBerryID {
|
||||
get => element.GetValue("trainerRangeOrBerryID");
|
||||
set => element.SetValue("trainerRangeOrBerryID", value);
|
||||
}
|
||||
|
||||
public int ScriptAddress {
|
||||
get => element.GetAddress("script");
|
||||
set => element.SetAddress("script", value);
|
||||
}
|
||||
|
||||
private string scriptAddressText;
|
||||
public string ScriptAddressText {
|
||||
get {
|
||||
if (scriptAddressText == null) scriptAddressText = element.GetAddress("script").ToAddress();
|
||||
return scriptAddressText;
|
||||
}
|
||||
set {
|
||||
scriptAddressText = value;
|
||||
element.SetAddress("script", value.TryParseHex(out int result) ? result : Pointer.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
public int Flag {
|
||||
get => element.GetValue("flag");
|
||||
set => element.SetValue("flag", value);
|
||||
}
|
||||
|
||||
public string FlagText {
|
||||
get => element.GetValue("flag").ToString("X4");
|
||||
set => element.SetValue("flag", value.TryParseHex(out int result) ? result : 0);
|
||||
}
|
||||
|
||||
public ObservableCollection<VisualComboOption> Options { get; } = new();
|
||||
|
||||
public ObjectEventModel(ModelArrayElement objectEvent, IList<IPixelViewModel> sprites) : base(objectEvent, "objectCount") {
|
||||
for (int i = 0; i < sprites.Count; i++) Options.Add(VisualComboOption.CreateFromSprite(i.ToString(), sprites[i].PixelData, sprites[i].PixelWidth, i));
|
||||
}
|
||||
|
||||
public override int TopOffset => 16 - EventRender.PixelHeight;
|
||||
public override int LeftOffset => (16 - EventRender.PixelWidth) / 2;
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
var owTable = new ModelTable(model, model.GetTable(HardcodeTablesModel.OverworldSprites).Start);
|
||||
EventRender = Render(model, owTable, Graphics);
|
||||
}
|
||||
|
||||
public static IPixelViewModel Render(IDataModel model, ModelTable owTable, int index) {
|
||||
if (index >= owTable.Count) {
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 2, 2, null), new short[256], 0);
|
||||
}
|
||||
var element = owTable[index];
|
||||
var data = element.GetSubTable("data")[0];
|
||||
var sprites = data.GetSubTable("sprites")[0];
|
||||
var graphicsAddress = sprites.GetAddress("sprite");
|
||||
var graphicsRun = model.GetNextRun(graphicsAddress) as ISpriteRun;
|
||||
if (graphicsRun == null) {
|
||||
return new ReadonlyPixelViewModel(new SpriteFormat(4, 16, 16, null), new short[256], 0);
|
||||
}
|
||||
return ReadonlyPixelViewModel.Create(model, graphicsRun, true);
|
||||
}
|
||||
}
|
||||
|
||||
public class WarpEventModel : BaseEventModel {
|
||||
public WarpEventModel(ModelArrayElement warpEvent) : base(warpEvent, "warpCount") { }
|
||||
|
||||
public int WarpID {
|
||||
get => element.GetValue("warpID");
|
||||
set => element.SetValue("warpID", value);
|
||||
}
|
||||
|
||||
#region Bank/Map
|
||||
|
||||
public int Bank {
|
||||
get => element.GetValue("bank");
|
||||
set {
|
||||
element.SetValue("bank", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateBankMap) bankMap = null;
|
||||
NotifyPropertyChanged(nameof(BankMap));
|
||||
NotifyPropertyChanged(nameof(TargetMapName));
|
||||
}
|
||||
}
|
||||
|
||||
public int Map {
|
||||
get => element.GetValue("map");
|
||||
set {
|
||||
element.SetValue("map", value);
|
||||
NotifyPropertyChanged();
|
||||
if (!ignoreUpdateBankMap) bankMap = null;
|
||||
NotifyPropertyChanged(nameof(BankMap));
|
||||
NotifyPropertyChanged(nameof(TargetMapName));
|
||||
}
|
||||
}
|
||||
|
||||
private bool ignoreUpdateBankMap;
|
||||
private string bankMap;
|
||||
public string BankMap {
|
||||
get {
|
||||
if (bankMap == null) bankMap = $"({Bank}, {Map})";
|
||||
return bankMap;
|
||||
}
|
||||
set {
|
||||
bankMap = value;
|
||||
var parts = value.Split(new[] { ',', ' ', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length != 2) return;
|
||||
ignoreUpdateBankMap = true;
|
||||
if (parts[0].TryParseInt(out int bank)) Bank = bank;
|
||||
if (parts[1].TryParseInt(out int map)) Map = map;
|
||||
ignoreUpdateBankMap = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string TargetMapName => BlockMapViewModel.MapIDToText(element.Model, Bank * 1000 + Map);
|
||||
|
||||
#endregion
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(0, 0, 31));
|
||||
}
|
||||
}
|
||||
|
||||
public class ScriptEventModel : BaseEventModel {
|
||||
public ScriptEventModel(ModelArrayElement scriptEvent) : base(scriptEvent, "scriptCount") { }
|
||||
|
||||
public int Trigger {
|
||||
get => element.GetValue("trigger");
|
||||
set => element.SetValue("trigger", value);
|
||||
}
|
||||
|
||||
public int Index {
|
||||
get => element.GetValue("index");
|
||||
set => element.SetValue("index", value);
|
||||
}
|
||||
|
||||
public int ScriptAddress {
|
||||
get => element.GetAddress("script");
|
||||
set => element.SetAddress("script", value);
|
||||
}
|
||||
|
||||
private string scriptAddressText;
|
||||
public string ScriptAddressText {
|
||||
get {
|
||||
if (scriptAddressText == null) scriptAddressText = element.GetAddress("script").ToAddress();
|
||||
return scriptAddressText;
|
||||
}
|
||||
set {
|
||||
scriptAddressText = value;
|
||||
element.SetAddress("script", value.TryParseHex(out int result) ? result : Pointer.NULL);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(0, 31, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public class SignpostEventModel : BaseEventModel {
|
||||
// kind. arg::|h
|
||||
// kind = 5/6/7 => arg is itemID: hiddenItemID. attr|t|quantity:::.|isUnderFoot.
|
||||
// kind = other => arg is script<`xse`>
|
||||
|
||||
public SignpostEventModel(ModelArrayElement signpostEvent) : base(signpostEvent, "signpostCount") { }
|
||||
|
||||
public int Kind {
|
||||
get => element.GetValue("kind");
|
||||
set => element.SetValue("kind", value);
|
||||
}
|
||||
|
||||
public string Arg {
|
||||
get => element.GetValue("arg").ToString("X8");
|
||||
set => element.SetValue("arg", value.TryParseHex(out int result) ? result : 0);
|
||||
}
|
||||
|
||||
public override void Render(IDataModel model) {
|
||||
EventRender = BuildEventRender(UncompressedPaletteColor.Pack(31, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user