From 0cca2a6badfa596e061d3fe4e1cc3064ce4d4f4b Mon Sep 17 00:00:00 2001 From: Haven1433 Date: Tue, 13 Sep 2022 22:49:38 -0500 Subject: [PATCH] add next/prev buttons --- .../ViewModels/Map/BlockMapViewModel.cs | 83 +++- .../ViewModels/Map/MapEditorViewModel.cs | 11 + src/HexManiac.WPF/Controls/MapTab.xaml | 363 ++++++++++-------- 3 files changed, 283 insertions(+), 174 deletions(-) diff --git a/src/HexManiac.Core/ViewModels/Map/BlockMapViewModel.cs b/src/HexManiac.Core/ViewModels/Map/BlockMapViewModel.cs index 230c9a5d..5f84ab41 100644 --- a/src/HexManiac.Core/ViewModels/Map/BlockMapViewModel.cs +++ b/src/HexManiac.Core/ViewModels/Map/BlockMapViewModel.cs @@ -36,6 +36,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { set { var oldValue = selectedEvent; selectedEvent = value; + NotifyPropertyChanged(); HandleSelectedEventChanged(oldValue); } } @@ -44,15 +45,66 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { if (old == selectedEvent) return; if (old != null) { old.EventVisualUpdated -= RefreshFromEventChange; + old.CycleEvent -= CycleActiveEvent; } if (selectedEvent != null) { selectedEvent.EventVisualUpdated += RefreshFromEventChange; + selectedEvent.CycleEvent += CycleActiveEvent; } RedrawEvents(); } private void RefreshFromEventChange(object sender, EventArgs e) => RedrawEvents(); + private void CycleActiveEvent(object sender, EventCycleDirection direction) { + // organize events into categories + var events = GetEvents(tokenFactory()); + var categories = new List> { new(), new(), new(), new() }; + int selectionIndex = -1, selectedCategory = -1; + for (int i = 0; i < events.Count; i++) { + int currentCategory = + events[i] is ObjectEventModel ? 0 : + events[i] is WarpEventModel ? 1 : + events[i] is ScriptEventModel ? 2 : + events[i] is SignpostEventModel ? 3 : + -1; + categories[currentCategory].Add(events[i]); + + if (events[i].Equals(selectedEvent)) { + selectionIndex = categories[currentCategory].Count - 1; + selectedCategory = currentCategory; + }; + } + + // remove unused categories + for (int i = 0; i < categories.Count; i++) { + if (categories[i].Count != 0) continue; + categories.RemoveAt(i); + if (selectedCategory > i) selectedCategory--; + i--; + } + + // cycle + if (direction == EventCycleDirection.PreviousCategory) { + selectedCategory += categories.Count - 1; + selectionIndex = 0; + } else if (direction == EventCycleDirection.NextCategory) { + selectedCategory += 1; + selectionIndex = 0; + } else if (direction == EventCycleDirection.PreviousEvent) { + selectionIndex += categories[selectedCategory].Count - 1; + } else if (direction == EventCycleDirection.NextEvent) { + selectionIndex += 1; + } else { + throw new NotImplementedException(); + } + selectedCategory %= categories.Count; + selectionIndex %= categories[selectedCategory].Count; + + // update selection + SelectedEvent = categories[selectedCategory][selectionIndex]; + } + #endregion private static int MapSizeLimit => 0x2800; // (x+15)*(y+14) must be less that 0x2800 (5*2048). This can lead to limits like 113x66 or 497x6 @@ -1163,8 +1215,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { */ } - public interface IEventModel : INotifyPropertyChanged { + public interface IEventModel : IEquatable, INotifyPropertyChanged { event EventHandler EventVisualUpdated; + public event EventHandler CycleEvent; + string EventType { get; } + string EventIndex { get; } int TopOffset { get; } int LeftOffset { get; } int X { get; set; } @@ -1175,14 +1230,28 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { void Delete(); } - public abstract class BaseEventModel : ViewModelCore, IEventModel { - // TODO text for event number / event count (1/4, 2/4, 3/4, 4/4, etc) - // TODO commands for switching selection to another event/group + public enum EventCycleDirection { PreviousCategory, PreviousEvent, NextEvent, NextCategory } + + public abstract class BaseEventModel : ViewModelCore, IEventModel, IEquatable { public event EventHandler EventVisualUpdated; + public event EventHandler CycleEvent; + + private StubCommand cycleEventCommand; + public ICommand CycleEventCommand => StubCommand(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; @@ -1245,6 +1314,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { 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); @@ -1473,7 +1547,6 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { } public class ScriptEventModel : BaseEventModel { - // trigger: index:: script<`xse`> public ScriptEventModel(ModelArrayElement scriptEvent) : base(scriptEvent, "scriptCount") { } public int Trigger { diff --git a/src/HexManiac.Core/ViewModels/Map/MapEditorViewModel.cs b/src/HexManiac.Core/ViewModels/Map/MapEditorViewModel.cs index d7d6802d..9ca348e3 100644 --- a/src/HexManiac.Core/ViewModels/Map/MapEditorViewModel.cs +++ b/src/HexManiac.Core/ViewModels/Map/MapEditorViewModel.cs @@ -185,11 +185,13 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { if (primaryMap != map) { if (primaryMap != null) { primaryMap.NeighborsChanged -= PrimaryMapNeighborsChanged; + primaryMap.PropertyChanged -= PrimaryMapPropertyChanged; primaryMap.CollisionHighlight = -1; } PrimaryMap = map; if (primaryMap != null) { primaryMap.NeighborsChanged += PrimaryMapNeighborsChanged; + primaryMap.PropertyChanged += PrimaryMapPropertyChanged; primaryMap.CollisionHighlight = collisionIndex; } NotifyPropertyChanged(nameof(Blocks)); @@ -232,6 +234,15 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map { UpdatePrimaryMap(primaryMap); } + private void PrimaryMapPropertyChanged(object sender, PropertyChangedEventArgs e) { + var map = (BlockMapViewModel)sender; + if (e.PropertyName == nameof(BlockMapViewModel.SelectedEvent)) { + if (map.SelectedEvent != selectedEvent) { + SelectedEvent = map.SelectedEvent; + } + } + } + private IEnumerable GetMapNeighbors(BlockMapViewModel map, int recursionLevel) { if (recursionLevel < 1) yield break; var directions = new List { diff --git a/src/HexManiac.WPF/Controls/MapTab.xaml b/src/HexManiac.WPF/Controls/MapTab.xaml index a9f41a1b..04afd914 100644 --- a/src/HexManiac.WPF/Controls/MapTab.xaml +++ b/src/HexManiac.WPF/Controls/MapTab.xaml @@ -42,199 +42,224 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + +