mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-03-21 17:34:13 -05:00
feature requests
* choose unused var for map scripts * show block uses when a single block is selected
This commit is contained in:
parent
0f6ddb1abc
commit
ab6e688208
|
|
@ -526,7 +526,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
(LeftEdge, TopEdge) = (-PixelWidth / 2, -PixelHeight / 2);
|
||||
|
||||
mapScriptCollection = new(viewPort);
|
||||
mapScriptCollection = new(viewPort, eventTemplate);
|
||||
mapScriptCollection.NewMapScriptsCreated += (sender, e) => GetMapModel().SetAddress("mapscripts", e.Address);
|
||||
|
||||
mapRepointer = new MapRepointer(format, fileSystem, viewPort, viewPort.ChangeHistory, MapID, () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using HavenSoft.HexManiac.Core;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Code;
|
||||
using HavenSoft.HexManiac.Core.Models.Map;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
|
|
@ -980,7 +979,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
public bool ShowTutorContent {
|
||||
get {
|
||||
var content = tutorContent.Value;
|
||||
if (content != null && TutorOptions .AllOptions == null) {
|
||||
if (content != null && TutorOptions.AllOptions == null) {
|
||||
TutorOptions.Update(ComboOption.Convert(element.Model.GetOptions(HardcodeTablesModel.MoveTutors)), TutorNumber);
|
||||
TutorOptions.Bind(nameof(TutorOptions.SelectedIndex), (sender, e) => TutorNumber = TutorOptions.SelectedIndex);
|
||||
}
|
||||
|
|
@ -990,7 +989,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
private TextEditorViewModel tutorInfoEditor, tutorWhichPokemonEditor, tutorFailedEditor, tutorSuccessEditor;
|
||||
public TextEditorViewModel TutorInfoText => CreateTextEditor(ref tutorInfoEditor, () => tutorContent.Value?.InfoPointer);
|
||||
public TextEditorViewModel TutorWhichPokemonText => CreateTextEditor(ref tutorWhichPokemonEditor , () => tutorContent.Value?.WhichPokemonPointer);
|
||||
public TextEditorViewModel TutorWhichPokemonText => CreateTextEditor(ref tutorWhichPokemonEditor, () => tutorContent.Value?.WhichPokemonPointer);
|
||||
public TextEditorViewModel TutorFailedText => CreateTextEditor(ref tutorFailedEditor, () => tutorContent.Value?.FailedPointer);
|
||||
public TextEditorViewModel TutorSucessText => CreateTextEditor(ref tutorSuccessEditor, () => tutorContent.Value?.SuccessPointer);
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,24 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsSingleBlock => tilesToDraw is not null && tilesToDraw.GetLength(0) == 1 && tilesToDraw.GetLength(1) == 1;
|
||||
public int BlockUsageCount {
|
||||
get {
|
||||
if (preferredCollisionsPrimary == null) CountCollisionForBlocks();
|
||||
var layout = new LayoutModel(primaryMap?.GetLayout());
|
||||
if (layout.PrimaryBlockset?.Start is not int primaryAddress) return -1;
|
||||
if (layout.SecondaryBlockset?.Start is not int secondaryAddress) return -1;
|
||||
if (!IsSingleBlock) return -1;
|
||||
|
||||
var isPrimary = drawBlockIndex < PrimaryBlocks;
|
||||
if (isPrimary) {
|
||||
return blockUsageCount[primaryAddress][drawBlockIndex];
|
||||
} else {
|
||||
return blockUsageCount[secondaryAddress][drawBlockIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> CollisionOptions { get; } = new();
|
||||
|
||||
public bool BlockSelectionToggle { get; private set; }
|
||||
|
|
@ -1075,7 +1093,10 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
private bool drawMultipleTiles;
|
||||
public bool DrawMultipleTiles {
|
||||
get => drawMultipleTiles;
|
||||
private set => Set(ref drawMultipleTiles, value, old => NotifyPropertyChanged(nameof(BlockBagVisible)));
|
||||
private set {
|
||||
Set(ref drawMultipleTiles, value, old => NotifyPropertyChanged(nameof(BlockBagVisible)));
|
||||
NotifyPropertiesChanged(nameof(IsSingleBlock), nameof(BlockUsageCount));
|
||||
}
|
||||
}
|
||||
|
||||
private bool blockEditorVisible;
|
||||
|
|
@ -1708,9 +1729,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
});
|
||||
}
|
||||
public bool IsValid9GridSelection {
|
||||
get {
|
||||
return tilesToDraw != null && tilesToDraw.GetLength(0) == 3 && tilesToDraw.GetLength(1) == 3;
|
||||
}
|
||||
get => tilesToDraw != null && tilesToDraw.GetLength(0) == 3 && tilesToDraw.GetLength(1) == 3;
|
||||
}
|
||||
|
||||
public void SelectBlock(int x, int y) {
|
||||
|
|
@ -2078,9 +2097,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
private Dictionary<long, int[]> preferredCollisionsPrimary;
|
||||
private Dictionary<long, int[]> preferredCollisionsSecondary;
|
||||
private readonly AutoDictionary<long, AutoDictionary<int, int>> blockUsageCount = new(_ => new(_ => 0)); // for a tileset, for a block, the total number of times that block is used
|
||||
private void CountCollisionForBlocks() {
|
||||
preferredCollisionsPrimary = new Dictionary<long, int[]>();
|
||||
preferredCollisionsSecondary = new Dictionary<long, int[]>();
|
||||
blockUsageCount.Clear();
|
||||
|
||||
// step 1: count the usages of each collision for each block in each blockset
|
||||
var banksTable = model.GetTable(HardcodeTablesModel.MapBankTable);
|
||||
|
|
@ -2121,9 +2142,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
var tile = pair & 0x3FF;
|
||||
var isPrimary = tile < PrimaryTiles;
|
||||
if (isPrimary) {
|
||||
blockUsageCount[address1][tile] += 1;
|
||||
if (!blocks1[tile].TryGetValue(collision, out var value)) value = 0;
|
||||
blocks1[tile][collision] = value + 1;
|
||||
} else {
|
||||
blockUsageCount[address2][tile] += 1;
|
||||
if (!blocks2[tile].TryGetValue(collision, out var value)) value = 0;
|
||||
blocks2[tile][collision] = value + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
public class MapScriptCollection : ViewModelCore {
|
||||
private readonly IEditableViewPort viewPort;
|
||||
private readonly EventTemplate eventTemplate;
|
||||
private ModelArrayElement owner;
|
||||
private int address;
|
||||
|
||||
|
|
@ -22,7 +23,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
public event EventHandler<NewMapScriptsCreatedEventArgs> NewMapScriptsCreated;
|
||||
|
||||
public MapScriptCollection(IEditableViewPort viewPort) => this.viewPort = viewPort;
|
||||
public MapScriptCollection(IEditableViewPort viewPort, EventTemplate eventTemplate) => (this.viewPort, this.eventTemplate) = (viewPort, eventTemplate);
|
||||
|
||||
public void Load(ModelArrayElement owner) {
|
||||
foreach (var script in Scripts) script.DeleteMe -= HandleDelete;
|
||||
|
|
@ -36,11 +37,11 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
AllowAddMoreScripts = true;
|
||||
while (model[scriptStart] != 0) {
|
||||
if (Scripts.Count == 10) {
|
||||
Scripts.Add(new(viewPort, Pointer.NULL)); // 'UI is full' sentinel
|
||||
Scripts.Add(new(viewPort, eventTemplate, Pointer.NULL)); // 'UI is full' sentinel
|
||||
AllowAddMoreScripts = false;
|
||||
break;
|
||||
}
|
||||
Scripts.Add(new(viewPort, scriptStart));
|
||||
Scripts.Add(new(viewPort, eventTemplate, scriptStart));
|
||||
AddDeleteHandler(Scripts.Count - 1);
|
||||
scriptStart += 5;
|
||||
}
|
||||
|
|
@ -115,6 +116,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
public class MapScriptViewModel : ViewModelCore {
|
||||
private readonly IEditableViewPort viewPort;
|
||||
private readonly EventTemplate eventTemplate;
|
||||
private readonly int start;
|
||||
private int scriptType, address;
|
||||
private string displayAddress;
|
||||
|
|
@ -128,8 +130,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
public ObservableCollection<VisualOption> ScriptOptions { get; } = new();
|
||||
public ObservableCollection<MapSubScriptViewModel> SubScripts { get; } = new();
|
||||
|
||||
public MapScriptViewModel(IEditableViewPort viewPort, int start) {
|
||||
public MapScriptViewModel(IEditableViewPort viewPort, EventTemplate eventTemplate, int start) {
|
||||
this.viewPort = viewPort;
|
||||
this.eventTemplate = eventTemplate;
|
||||
var model = viewPort.Model;
|
||||
this.start = start;
|
||||
if (start == Pointer.NULL) {
|
||||
|
|
@ -193,7 +196,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
while (true) {
|
||||
var currentValue = model.ReadMultiByteValue(destination, 2);
|
||||
if (currentValue == 0 || currentValue == 0xFFFF) break;
|
||||
var child = new MapSubScriptViewModel(viewPort, destination);
|
||||
var child = new MapSubScriptViewModel(viewPort, eventTemplate, destination);
|
||||
child.DeleteMe += HandleDelete;
|
||||
SubScripts.Add(child);
|
||||
destination += 8;
|
||||
|
|
@ -292,7 +295,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
if (run.Start != tableRun.Start) {
|
||||
Load();
|
||||
} else {
|
||||
SubScripts.Append(new MapSubScriptViewModel(viewPort, tableRun.Start + tableRun.ElementCount * tableRun.ElementLength - 4));
|
||||
SubScripts.Append(new MapSubScriptViewModel(viewPort, eventTemplate, tableRun.Start + tableRun.ElementCount * tableRun.ElementLength - 4));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,6 +336,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
/// </summary>
|
||||
public class MapSubScriptViewModel : ViewModelCore {
|
||||
private readonly IEditableViewPort viewPort;
|
||||
private readonly EventTemplate eventTemplate;
|
||||
private int start, variable, val, address;
|
||||
private string variableText, valueText, addressText;
|
||||
|
||||
|
|
@ -340,8 +344,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
public event EventHandler<MapScriptDeleteEventArgs> DeleteMe;
|
||||
|
||||
public MapSubScriptViewModel(IEditableViewPort viewPort, int start) {
|
||||
(this.viewPort, this.start) = (viewPort, start);
|
||||
public MapSubScriptViewModel(IEditableViewPort viewPort, EventTemplate eventTemplate, int start) {
|
||||
(this.viewPort, this.eventTemplate, this.start) = (viewPort, eventTemplate, start);
|
||||
this.variable = viewPort.Model.ReadMultiByteValue(start, 2);
|
||||
this.val = viewPort.Model.ReadMultiByteValue(start + 2, 2);
|
||||
this.address = viewPort.Model.ReadPointer(start + 4);
|
||||
|
|
@ -356,6 +360,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
if (!variableText.TryParseHex(out int result)) return;
|
||||
variable = result;
|
||||
viewPort.Model.WriteMultiByteValue(start, 2, viewPort.ChangeHistory.CurrentChange, variable);
|
||||
NotifyPropertyChanged(nameof(CanGenerateNewVar));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -377,6 +382,12 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
});
|
||||
}
|
||||
|
||||
public bool CanGenerateNewVar => variable == 0;
|
||||
public void GenerateNewVar() {
|
||||
variable = eventTemplate.FindNextUnusedVariable();
|
||||
Variable = variable.ToString("X4");
|
||||
}
|
||||
|
||||
public void Delete() {
|
||||
var args = new MapScriptDeleteEventArgs();
|
||||
DeleteMe.Raise(this, args);
|
||||
|
|
|
|||
|
|
@ -134,6 +134,10 @@
|
|||
</Style>
|
||||
</Decorator.Style>
|
||||
</Decorator>
|
||||
<TextBlock Visibility="{Binding IsSingleBlock, Converter={StaticResource BoolToVisibility}}" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top">
|
||||
<Run Text="Usage Count:" />
|
||||
<Run Text="{Binding BlockUsageCount, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
<CheckBox IsChecked="{Binding Use9Grid}" Content="Draw 9-Grid" VerticalAlignment="Top" Grid.Row="1" HorizontalAlignment="Center"
|
||||
Visibility="{Binding IsValid9GridSelection, Converter={StaticResource BoolToVisibility}}">
|
||||
<CheckBox.ToolTip>
|
||||
|
|
@ -1324,7 +1328,19 @@
|
|||
<local:AngleTextBox Direction="Out" TextBinding="{Binding Address, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</DockPanel>
|
||||
<UniformGrid Columns="4" Margin="20,0">
|
||||
<local:AngleBorder Direction="Out" Content="Var:" />
|
||||
<Grid>
|
||||
<local:AngleBorder Direction="Out" Content="Var:" />
|
||||
<local:AngleButton HorizontalAlignment="Right" Direction="Right" Command="{res:MethodCommand GenerateNewVar}"
|
||||
Visibility="{Binding CanGenerateNewVar, Converter={StaticResource BoolToVisibility}}"
|
||||
Width="22" Height="18" IsTabStop="False" Padding="0,2" BorderBrush="{DynamicResource Backlight}">
|
||||
<local:AngleButton.ToolTip>
|
||||
<TextBlock>
|
||||
Automatically choose an unused var.
|
||||
</TextBlock>
|
||||
</local:AngleButton.ToolTip>
|
||||
<Path Data="{res:Icon Add}" Fill="{DynamicResource Secondary}" Stretch="Fill" />
|
||||
</local:AngleButton>
|
||||
</Grid>
|
||||
<local:AngleTextBox Direction="Right" TextBinding="{Binding Variable, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,2,0" />
|
||||
<local:AngleBorder Direction="Out" Content="Value:" Margin="2,0,0,0" />
|
||||
<local:AngleTextBox Direction="Right" TextBinding="{Binding Value, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user