mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-03-21 17:34:13 -05:00
new features
* squiggle errors for pokemon names / moves in trainer editor * filtering for block behaviors * image editor hover position and selection size displayed * name hints for blocksets in the map header
This commit is contained in:
parent
19df9c0e24
commit
47d5aa830d
|
|
@ -155,7 +155,7 @@ namespace HavenSoft.HexManiac.Core {
|
|||
foreach (var item in items) set.Add(item);
|
||||
}
|
||||
|
||||
public static bool All<T>(this ReadOnlySpan<T> span, Func<T,bool> predicate) {
|
||||
public static bool All<T>(this ReadOnlySpan<T> span, Func<T, bool> predicate) {
|
||||
var match = true;
|
||||
for (int i = 0; match && i < span.Length; i++) {
|
||||
match = predicate(span[i]);
|
||||
|
|
@ -212,6 +212,8 @@ namespace HavenSoft.HexManiac.Core {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void CombineTokens(this IList<string> tokens, string startToken, string endToken) => TableStreamRun.Recombine(tokens, startToken, endToken);
|
||||
|
||||
public static string CombineLines(this IReadOnlyList<string> lines) => lines.Aggregate((a, b) => a + Environment.NewLine + b);
|
||||
|
||||
public static string ReplaceOne(this string input, string search, string replacement) {
|
||||
|
|
|
|||
|
|
@ -839,6 +839,8 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
|
||||
public static IReadOnlyList<string> GetBitOptions(this IDataModel model, string tableName) => ModelCacheScope.GetCache(model).GetBitOptions(tableName);
|
||||
|
||||
public static bool TryMatch(this IReadOnlyList<string> list, string text, out int value) => ArrayRunEnumSegment.TryMatch(text, list, out value);
|
||||
|
||||
public static IEnumerable<ArrayRun> GetRelatedArrays(this IDataModel model, ArrayRun table) {
|
||||
yield return table; // a table is related to itself
|
||||
var basename = model.GetAnchorFromAddress(-1, table.Start);
|
||||
|
|
|
|||
|
|
@ -221,7 +221,11 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
public ModelTupleElement GetTuple(string fieldName) {
|
||||
var seg = table.ElementContent.Single(segment => segment.Name == fieldName);
|
||||
var segmentOffset = table.ElementContent.Until(s => s == seg).Sum(s => s.Length);
|
||||
return new ModelTupleElement(model, table, arrayIndex, segmentOffset, (ArrayRunTupleSegment)seg, tokenFactory);
|
||||
if (seg is ArrayRunBitArraySegment bitSeg) {
|
||||
return new ModelTupleElement(model, table, arrayIndex, segmentOffset, (ArrayRunBitArraySegment)seg, tokenFactory);
|
||||
} else {
|
||||
return new ModelTupleElement(model, table, arrayIndex, segmentOffset, (ArrayRunTupleSegment)seg, tokenFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public object __getindex__(string key) => this[key]; // for python
|
||||
|
|
@ -459,7 +463,7 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
SetValue(fieldName, (int)value);
|
||||
}
|
||||
}
|
||||
|
||||
public int FieldCount => tuple.Elements.Count;
|
||||
public bool HasField(string name) => tuple.Elements.Any(field => field.Name == name);
|
||||
|
||||
public int GetValue(string fieldName) {
|
||||
|
|
@ -618,6 +622,7 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
|
||||
public bool is_pokemon => eggRun.CreateDataFormat(model, address) is EggSection;
|
||||
public bool is_move => eggRun.CreateDataFormat(model, address) is EggItem;
|
||||
public int Address => address;
|
||||
|
||||
public EggElement(IDataModel model, int address, Func<ModelDelta> tokenFactory, EggMoveRun eggRun) => (this.model, this.address, this.tokenFactory, this.eggRun) = (model, address, tokenFactory, eggRun);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
|
@ -16,6 +17,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
public override string FormatString => "`asc`" + Length;
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => throw new System.NotImplementedException();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
|
||||
public AsciiRun(IDataModel model, int start, int length, SortedSpan<int> pointerSources = null) : base(start, pointerSources) => (this.model, Length) = (model, length.LimitToRange(1, 1000));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -55,6 +56,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
public override string FormatString => SharedFormatString;
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => null;
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
|
||||
public void AppendTo(IDataModel model, StringBuilder builder, int start, int length, int depth) {
|
||||
for (int i = 0; i < length - 1; i++) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -213,6 +214,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
public bool DependsOn(string anchorName) {
|
||||
return anchorName == PokemonNameTable || anchorName == MoveNamesTable;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
|
@ -66,6 +67,8 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
IReadOnlyList<AutocompleteItem> GetAutoCompleteOptions(string line, int caretLineIndex, int caretCharacterIndex);
|
||||
|
||||
IReadOnlyList<IPixelViewModel> Visualizations { get; }
|
||||
|
||||
ITextPreProcessor PreFormatter { get; }
|
||||
}
|
||||
|
||||
public class FormattedRunComparer : IComparer<IFormattedRun> {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,15 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
return results;
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<int, int> devolutions, minimumLevel;
|
||||
private IReadOnlyDictionary<int, IReadOnlyList<int>> eggMoves, levelupMoves, tutorMoves, tmMoves;
|
||||
public IReadOnlyDictionary<int, int> GetPokemonDevolutions() => devolutions ??= Flags.GetPokemonDevolutions(model);
|
||||
public IReadOnlyDictionary<int, int> GetPokemonMinimumLevels() => minimumLevel ??= Flags.GetMinimumLevelForPokemon(model);
|
||||
public IReadOnlyDictionary<int, IReadOnlyList<int>> GetPokemonEggMoves() => eggMoves ??= Flags.GetPokemonEggMoves(model);
|
||||
public IReadOnlyDictionary<int, IReadOnlyList<int>> GetLevelupMoves() => levelupMoves ??= Flags.GetPokemonLevelupMoves(model);
|
||||
public IReadOnlyDictionary<int, IReadOnlyList<int>> GetTutorMoves() => tutorMoves ??= Flags.GetPokemonTutorMoves(model);
|
||||
public IReadOnlyDictionary<int, IReadOnlyList<int>> GetTmMoves() => tmMoves ??= Flags.GetPokemonTmMoves(model);
|
||||
|
||||
#region Script Cache
|
||||
|
||||
// stores only the start and length
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -79,6 +80,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
public bool DependsOn(string anchorName) => false;
|
||||
|
||||
protected override BaseRun Clone(SortedSpan<int> newPointerSources) => new PCSRun(model, Start, Length, newPointerSources);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.Models.Runs.Factory;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
|
|
@ -146,7 +147,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
get => GetBit(Start + 5, 7);
|
||||
set => SetBit(Start + 5, 7, value);
|
||||
}
|
||||
public bool ChangeHappinessWhenBetween100And199{
|
||||
public bool ChangeHappinessWhenBetween100And199 {
|
||||
get => GetBit(Start + 5, 6);
|
||||
set => SetBit(Start + 5, 6, value);
|
||||
}
|
||||
|
|
@ -462,6 +463,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
public bool DependsOn(string anchorName) => false;
|
||||
|
||||
public void AppendTo(IDataModel model, StringBuilder builder, int start, int length, int depth) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -130,6 +131,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
public bool DependsOn(string anchorName) => anchorName == HardcodeTablesModel.MoveNamesTable;
|
||||
|
||||
public IEnumerable<(int, int)> Search(int index) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -218,6 +219,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs.Sprites {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
public bool DependsOn(string anchorName) => false;
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
return result;
|
||||
}
|
||||
|
||||
public TableStreamRun DeserializeRunFromZero(string content,ModelDelta token, out IReadOnlyList<int> changedOffsets, out List<int> movedChildren) {
|
||||
public TableStreamRun DeserializeRunFromZero(string content, ModelDelta token, out IReadOnlyList<int> changedOffsets, out List<int> movedChildren) {
|
||||
return DeserializeRun(content, token, 0, out changedOffsets, out movedChildren);
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +361,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
return tokens;
|
||||
}
|
||||
|
||||
public static void Recombine(List<string> tokens, string startToken, string endToken) {
|
||||
public static void Recombine(IList<string> tokens, string startToken, string endToken) {
|
||||
for (int i = 0; i < tokens.Count - 1; i++) {
|
||||
if (tokens[i].StartsWith(startToken) == tokens[i].EndsWith(endToken)) continue;
|
||||
tokens[i] += " " + tokens[i + 1];
|
||||
|
|
@ -493,6 +493,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
|
||||
public IReadOnlyList<IPixelViewModel> Visualizations => new List<IPixelViewModel>();
|
||||
public ITextPreProcessor PreFormatter { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using HavenSoft.HexManiac.Core.Models.Code;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs.Sprites;
|
||||
using HavenSoft.HexManiac.Core.ViewModels;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.DataFormats;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using Mono.Unix.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -36,6 +36,7 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
string IUpdateFromParentRun.RepointContentShortName => "Team";
|
||||
|
||||
private readonly bool showFullIVByteRange = false;
|
||||
private object minimumLevels;
|
||||
|
||||
#region Constructors
|
||||
|
||||
|
|
@ -377,6 +378,8 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
}
|
||||
}
|
||||
|
||||
public ITextPreProcessor PreFormatter => new TrainerTextFormatter(model);
|
||||
|
||||
public bool DependsOn(string anchorName) =>
|
||||
anchorName == HardcodeTablesModel.ItemsTableName ||
|
||||
anchorName == HardcodeTablesModel.MoveNamesTable ||
|
||||
|
|
@ -596,4 +599,70 @@ namespace HavenSoft.HexManiac.Core.Models.Runs {
|
|||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
public record TrainerTextFormatter(IDataModel Model) : ITextPreProcessor {
|
||||
public TextFormatting[] Format(string content) => new TextFormatting[0];
|
||||
|
||||
public IEnumerable<TextSegment> FindErrors(string content) {
|
||||
var errors = new List<TextSegment>();
|
||||
int species = 0;
|
||||
var lines = content.SplitLines();
|
||||
for (int i = 0; i < lines.Length; i++) {
|
||||
if (string.IsNullOrWhiteSpace(lines[i])) continue;
|
||||
if (lines[i].Trim().StartsWith("-")) {
|
||||
CheckMoveError(species, i, lines[i], errors);
|
||||
} else {
|
||||
species = CheckPokemonError(i, lines[i], errors);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
private int CheckPokemonError(int lineNumber, string line, IList<TextSegment> errors) {
|
||||
var tokens = line.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
tokens.CombineTokens("\"", "\"");
|
||||
if (tokens.Count < 2) return 0;
|
||||
if (!int.TryParse(tokens[0], out var level)) return 0;
|
||||
var cache = ModelCacheScope.GetCache(Model);
|
||||
var pokemonNames = cache.GetOptions(HardcodeTablesModel.PokemonNameTable);
|
||||
if (!pokemonNames.TryMatch(tokens[1], out var pokemon)) return 0;
|
||||
|
||||
// error: pokemon is too low of a level
|
||||
var minimumLevels = cache.GetPokemonMinimumLevels();
|
||||
if (minimumLevels is not null) {
|
||||
if (minimumLevels.TryGetValue(pokemon, out var minLevel) && minLevel > level) {
|
||||
errors.Add(new(lineNumber, line.IndexOf(tokens[1]), tokens[1].Length, SegmentType.Warning));
|
||||
} else if (cache.GetPokemonDevolutions()?.TryGetValue(pokemon, out var baby) ?? false) {
|
||||
// check that the lower evolution is also allowed. Important for stage 3 pokmeon that evolve via stone
|
||||
if (minimumLevels.TryGetValue(baby, out var babyLevel) && babyLevel > level) {
|
||||
errors.Add(new(lineNumber, line.IndexOf(tokens[1]), tokens[1].Length, SegmentType.Warning));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pokemon;
|
||||
}
|
||||
|
||||
private void CheckMoveError(int species, int lineNumber, string line, IList<TextSegment> errors) {
|
||||
var moveName = line.Substring(1).Trim();
|
||||
var cache = ModelCacheScope.GetCache(Model);
|
||||
var moveNames = cache.GetOptions(HardcodeTablesModel.MoveNamesTable);
|
||||
if (!moveNames.TryMatch(line, out var move)) return;
|
||||
|
||||
var allMoves = new HashSet<int>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (cache.GetLevelupMoves()?.TryGetValue(species, out var lvlMoves) ?? false) allMoves.AddRange(lvlMoves);
|
||||
if (cache.GetTutorMoves()?.TryGetValue(species, out var tutMoves) ?? false) allMoves.AddRange(tutMoves);
|
||||
if (cache.GetPokemonEggMoves()?.TryGetValue(species, out var eggMoves) ?? false) allMoves.AddRange(eggMoves);
|
||||
if (cache.GetTmMoves()?.TryGetValue(species, out var tmMoves) ?? false) allMoves.AddRange(tmMoves);
|
||||
if (!(cache.GetPokemonDevolutions()?.TryGetValue(species, out var baby) ?? false)) break;
|
||||
species = baby;
|
||||
}
|
||||
|
||||
// error: pokemon cannot learn move
|
||||
if (!allMoves.Contains(move) && line.Length > 2) {
|
||||
errors.Add(new(lineNumber, 2, line.Length - 2, SegmentType.Warning));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -399,6 +399,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
|
||||
/// <param name="toSelect">Points range from (0,0) to (PixelWidth, PixelHeight) </param>
|
||||
private void RaiseRefreshSelection(params Point[] toSelect) {
|
||||
SelectionSize = Point.Zero;
|
||||
selectedPixels = new bool[PixelWidth, PixelHeight];
|
||||
foreach (var s in toSelect) {
|
||||
if (WithinImage(s)) selectedPixels[s.X, s.Y] = true;
|
||||
|
|
@ -418,6 +419,10 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
private double spriteScale = 4;
|
||||
public double SpriteScale { get => spriteScale; set => Set(ref spriteScale, value, arg => NotifyPropertyChanged(nameof(FontSize))); }
|
||||
|
||||
private string quickInfo = string.Empty;
|
||||
public string QuickInfo { get => quickInfo; set => Set(ref quickInfo, value); }
|
||||
public Point SelectionSize { get; private set; }
|
||||
|
||||
public PaletteCollection Palette { get; }
|
||||
|
||||
public int SpritePointer { get; private set; }
|
||||
|
|
@ -595,6 +600,16 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
} else {
|
||||
toolStrategy.ToolDrag(point);
|
||||
}
|
||||
|
||||
QuickInfo = string.Empty;
|
||||
point = ToSpriteSpace(point);
|
||||
if (!point.X.InRange(0, PixelWidth)) return;
|
||||
if (!point.Y.InRange(0, PixelHeight)) return;
|
||||
var text = point.ToString();
|
||||
if (SelectionSize.X > 1 || SelectionSize.Y > 1) {
|
||||
text = $"[{SelectionSize}]";
|
||||
}
|
||||
QuickInfo = text;
|
||||
}
|
||||
|
||||
public void ToolUp(Point point) {
|
||||
|
|
@ -1048,6 +1063,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
var selectionPoints = new Point[width * height];
|
||||
for (int x = 0; x < width; x++) for (int y = 0; y < height; y++) selectionPoints[y * width + x] = start + new Point(x, y);
|
||||
parent.RaiseRefreshSelection(selectionPoints);
|
||||
parent.SelectionSize = new Point(width, height);
|
||||
}
|
||||
|
||||
public void ClearSelection() {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using HexManiac.Core.Models.Runs.Sprites;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
/*
|
||||
#define MB_NORMAL 0x00
|
||||
|
|
@ -431,7 +432,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
hasTerrainAndEncounter = blockAttributes[0].Length > 2;
|
||||
images = new CanvasPixelViewModel[8];
|
||||
indexForTileImage = new Dictionary<IPixelViewModel, int>();
|
||||
if (listSource.TryGetList("MapAttributeBehaviors", out var behaviors)) behaviors.ForEach(BehaviorOptions.Add);
|
||||
if (listSource.TryGetList("MapAttributeBehaviors", out var behaviors)) BehaviorOptions.Update(behaviors.Select((behavior, i) => new ComboOption(behavior, i)), behavior);
|
||||
BehaviorOptions.Bind(nameof(BehaviorOptions.SelectedIndex), (obj, e) => Behavior = BehaviorOptions.SelectedIndex);
|
||||
if (listSource.TryGetList("MapLayerOptions", out var layer)) layer.ForEach(LayerOptions.Add);
|
||||
if (listSource.TryGetList("MapTerrainOptions", out var terrain)) terrain.ForEach(TerrainOptions.Add);
|
||||
if (listSource.TryGetList("MapEncounterOptions", out var encounters)) encounters.ForEach(EncounterOptions.Add);
|
||||
|
|
@ -594,7 +596,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
public bool HasError => errorText != null;
|
||||
public string ErrorText => errorText;
|
||||
|
||||
public ObservableCollection<string> BehaviorOptions { get; } = new();
|
||||
public FilteringComboOptions BehaviorOptions { get; } = new();
|
||||
public ObservableCollection<string> LayerOptions { get; } = new();
|
||||
public ObservableCollection<string> TerrainOptions { get; } = new();
|
||||
public ObservableCollection<string> EncounterOptions { get; } = new();
|
||||
|
|
@ -612,6 +614,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
}
|
||||
errorText = attributes.ErrorInfo;
|
||||
NotifyPropertiesChanged(nameof(Behavior), nameof(Layer), nameof(Terrain), nameof(Encounter), nameof(HasError), nameof(ErrorText));
|
||||
BehaviorOptions.Update(BehaviorOptions.AllOptions, behavior);
|
||||
}
|
||||
|
||||
private void SaveAttributes(int arg = default) {
|
||||
|
|
|
|||
|
|
@ -267,6 +267,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
return trainerFlags;
|
||||
}
|
||||
|
||||
#region Derived Pokemon Data
|
||||
|
||||
public static IReadOnlyDictionary<int, int> GetMinimumLevelForPokemon(IDataModel model) {
|
||||
var evolutions = model.GetTableModel(HardcodeTablesModel.EvolutionTableName);
|
||||
var levelMethods = new[] { 4, 8, 9, 10, 11, 12, 13, 14 };
|
||||
|
|
@ -284,6 +286,101 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For a given pokemon, find what pokemon (if any evolves into it)
|
||||
/// </summary>
|
||||
public static IReadOnlyDictionary<int, int> GetPokemonDevolutions(IDataModel model) {
|
||||
var evolutions = model.GetTableModel(HardcodeTablesModel.EvolutionTableName);
|
||||
var levelMethods = new[] { 4, 8, 9, 10, 11, 12, 13, 14 };
|
||||
var results = new Dictionary<int, int>();
|
||||
foreach (var evo in evolutions) {
|
||||
// method1:evolutionmethods arg1:|s=method1(6=data.items.stats|7=data.items.stats) species1:data.pokemon.names unused1:
|
||||
for (int i = 0; i < evo.Length; i += 8) {
|
||||
var species = model.ReadMultiByteValue(evo.Start + i + 4, 2);
|
||||
results[species] = evo.ArrayIndex;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<int, IReadOnlyList<int>> GetPokemonEggMoves(IDataModel model) {
|
||||
var start = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, HardcodeTablesModel.EggMovesTableName);
|
||||
if (!start.InRange(0, model.Count)) return null;
|
||||
if (model.GetNextRun(start) is not EggMoveRun eggRun) return null;
|
||||
var table = new EggTable(model, null, eggRun);
|
||||
int currentPokemon = -1;
|
||||
var results = new AutoDictionary<int, List<int>>(i => new());
|
||||
foreach (var element in table) {
|
||||
var value = model.ReadMultiByteValue(element.Address, 2);
|
||||
if (element.is_pokemon) {
|
||||
value -= EggMoveRun.MagicNumber;
|
||||
currentPokemon = value;
|
||||
} else {
|
||||
results[currentPokemon].Add(value);
|
||||
}
|
||||
}
|
||||
return new Dictionary<int, IReadOnlyList<int>>(results.Select(kvp => new KeyValuePair<int, IReadOnlyList<int>>(kvp.Key, kvp.Value)));
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<int, IReadOnlyList<int>> GetPokemonLevelupMoves(IDataModel model) {
|
||||
var start = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, HardcodeTablesModel.LevelMovesTableName);
|
||||
if (!start.InRange(0, model.Count)) return null;
|
||||
if (model.GetNextRun(start) is not ArrayRun array) return null;
|
||||
var table = new ModelTable(model, array);
|
||||
var results = new AutoDictionary<int, List<int>>(i => new());
|
||||
foreach (var element in table) {
|
||||
var sub = element.GetSubTable("movesFromLevel");
|
||||
foreach (var move in sub) {
|
||||
if (sub.Run.ElementContent.Count == 1) {
|
||||
results[element.ArrayIndex].Add(model.ReadMultiByteValue(move.Start, 2) & 0x1FF);
|
||||
} else if (move.TryGetValue("move", out int moveIndex)) {
|
||||
results[element.ArrayIndex].Add(moveIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Dictionary<int, IReadOnlyList<int>>(results.Select(kvp => new KeyValuePair<int, IReadOnlyList<int>>(kvp.Key, kvp.Value)));
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<int, IReadOnlyList<int>> GetPokemonTutorMoves(IDataModel model) {
|
||||
var start = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, HardcodeTablesModel.TutorCompatibility);
|
||||
if (!start.InRange(0, model.Count)) return null;
|
||||
if (model.GetNextRun(start) is not ArrayRun array) return null;
|
||||
var table = new ModelTable(model, array);
|
||||
var options = model.GetTableModel(HardcodeTablesModel.MoveTutors);
|
||||
if (options == null) return null;
|
||||
var results = new AutoDictionary<int, List<int>>(i => new());
|
||||
foreach (var element in table) {
|
||||
if (!element.HasField("moves")) break;
|
||||
var move = element.GetTuple("moves");
|
||||
for (int i = 0; i < move.FieldCount; i++) {
|
||||
if ((model[element.Start + i / 8] & (1 << i)) == 0) continue;
|
||||
results[element.ArrayIndex].Add(options[i].GetValue(0));
|
||||
}
|
||||
}
|
||||
return new Dictionary<int, IReadOnlyList<int>>(results.Select(kvp => new KeyValuePair<int, IReadOnlyList<int>>(kvp.Key, kvp.Value)));
|
||||
}
|
||||
|
||||
public static IReadOnlyDictionary<int, IReadOnlyList<int>> GetPokemonTmMoves(IDataModel model) {
|
||||
var start = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, HardcodeTablesModel.TmCompatibility);
|
||||
if (!start.InRange(0, model.Count)) return null;
|
||||
if (model.GetNextRun(start) is not ArrayRun array) return null;
|
||||
var table = new ModelTable(model, array);
|
||||
var options = model.GetTableModel(HardcodeTablesModel.TmMoves);
|
||||
if (options == null) return null;
|
||||
var results = new AutoDictionary<int, List<int>>(i => new());
|
||||
foreach (var element in table) {
|
||||
if (!element.HasField("moves")) break;
|
||||
var move = element.GetTuple("moves");
|
||||
for (int i = 0; i < move.FieldCount; i++) {
|
||||
if ((model[element.Start + i / 8] & (1 << i)) == 0) continue;
|
||||
results[element.ArrayIndex].Add(options[i].GetValue(0));
|
||||
}
|
||||
}
|
||||
return new Dictionary<int, IReadOnlyList<int>>(results.Select(kvp => new KeyValuePair<int, IReadOnlyList<int>>(kvp.Key, kvp.Value)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static ISet<int> GetTrainerFlagUsages(IDataModel model, ScriptParser parser, int flag) {
|
||||
var flagUsages = new HashSet<int>();
|
||||
foreach (var spot in GetAllScriptSpots(model, parser, GetAllTopLevelScripts(model), 0x5C)) {
|
||||
|
|
|
|||
|
|
@ -885,6 +885,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
|
||||
public bool ShowTrainerContent => EventTemplate.GetTrainerContent(element.Model, this) != null && TrainerType != 0;
|
||||
|
||||
public TextEditorViewModel TrainerContent { get; } = new();
|
||||
|
||||
public int TrainerClass {
|
||||
get {
|
||||
var trainerContent = EventTemplate.GetTrainerContent(element.Model, this);
|
||||
|
|
@ -1400,6 +1402,10 @@ show:
|
|||
legendaryContent = new Lazy<LegendaryEventContent>(() => EventTemplate.GetLegendaryEventContent(element.Model, parser, this));
|
||||
|
||||
UpdateScriptError(ScriptAddress);
|
||||
|
||||
TrainerContent.PreFormatter = new TrainerTextFormatter(objectEvent.Model);
|
||||
TrainerContent.Content = TrainerTeam;
|
||||
TrainerContent.Bind(nameof(TextEditorViewModel.Content), (sender, e) => TrainerTeam = sender.Content);
|
||||
}
|
||||
|
||||
public override int TopOffset => 16 - (EventRender?.PixelHeight ?? 0);
|
||||
|
|
@ -1948,6 +1954,9 @@ show:
|
|||
public TrainerTeamViewModel(IDataModel model, int trainerID, Func<ModelDelta> tokenGenerator) {
|
||||
(this.model, this.trainerID) = (model, trainerID);
|
||||
this.tokenGenerator = tokenGenerator;
|
||||
TrainerContent.PreFormatter = new TrainerTextFormatter(model);
|
||||
TrainerContent.Content = TrainerTeam;
|
||||
TrainerContent.Bind(nameof(TextEditorViewModel.Content), (sender, e) => TrainerTeam = sender.Content);
|
||||
}
|
||||
|
||||
public string TrainerIDText {
|
||||
|
|
@ -1987,6 +1996,8 @@ show:
|
|||
}
|
||||
}
|
||||
|
||||
public TextEditorViewModel TrainerContent { get; } = new();
|
||||
|
||||
public ObservableCollection<IPixelViewModel> TeamVisualizations { get; } = new();
|
||||
|
||||
private void UpdateTeamVisualizations(TrainerPokemonTeamRun team) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using HavenSoft.HexManiac.Core.Models;
|
||||
using HavenSoft.HexManiac.Core.Models.Map;
|
||||
using HavenSoft.HexManiac.Core.Models.Runs;
|
||||
using HavenSoft.HexManiac.Core.ViewModels.Images;
|
||||
using HexManiac.Core.Models.Runs.Sprites;
|
||||
using System;
|
||||
|
|
@ -173,14 +174,14 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
public bool HasMapTypeOptions => MapTypeOptions.Count > 0;
|
||||
public ObservableCollection<string> MapTypeOptions { get; } = new();
|
||||
|
||||
private int GetValue([CallerMemberName]string name = null) {
|
||||
private int GetValue([CallerMemberName] string name = null) {
|
||||
name = char.ToLower(name[0]) + name.Substring(1);
|
||||
if (!map.HasField(name)) return -1;
|
||||
return map.GetValue(name);
|
||||
}
|
||||
|
||||
// when we call SetValue, get the latest token
|
||||
private void SetValue(int value, [CallerMemberName]string name = null) {
|
||||
private void SetValue(int value, [CallerMemberName] string name = null) {
|
||||
if (value == GetValue(name)) return;
|
||||
map = new(map.Model, map.Table.Start, (map.Start - map.Table.Start) / map.Table.ElementCount, tokenFactory, map.Table);
|
||||
var originalName = name;
|
||||
|
|
@ -189,7 +190,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
NotifyPropertyChanged(originalName);
|
||||
}
|
||||
|
||||
private bool GetBool([CallerMemberName]string name = null) {
|
||||
private bool GetBool([CallerMemberName] string name = null) {
|
||||
name = char.ToLower(name[0]) + name.Substring(1);
|
||||
if (map.HasField(name)) {
|
||||
return map.GetValue(name) != 0;
|
||||
|
|
@ -202,7 +203,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void SetBool(bool value, [CallerMemberName]string name = null) {
|
||||
private void SetBool(bool value, [CallerMemberName] string name = null) {
|
||||
var originalName = name;
|
||||
name = char.ToLower(name[0]) + name.Substring(1);
|
||||
if (map.HasField(name)) {
|
||||
|
|
@ -222,12 +223,22 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Map {
|
|||
private readonly Lazy<IPixelViewModel> render;
|
||||
public IDataModel Model { get; }
|
||||
public int Address { get; }
|
||||
public string NameHint { get; }
|
||||
public IPixelViewModel Render => render?.Value;
|
||||
public string AddressText => Address.ToAddress();
|
||||
public string AddressText => Address.ToAddress() + NameHint;
|
||||
|
||||
public BlocksetOption(IDataModel model, int address) {
|
||||
Model = model;
|
||||
Address = address;
|
||||
|
||||
var sources = model.GetNextRun(address)?.PointerSources ?? Enumerable.Empty<int>();
|
||||
var layoutRuns = sources.Select(source => model.GetNextRun(source)).Distinct();
|
||||
var layoutSources = layoutRuns.SelectMany(run => run?.PointerSources ?? Enumerable.Empty<int>());
|
||||
var mapRuns = layoutSources.Select(source => model.GetNextRun(source)).Where(run => model.GetAnchorFromAddress(-1, run.Start) != "data.maps.layouts" && run is ITableRun);
|
||||
var elements = mapRuns.Select(run => new ModelTable(model, (ITableRun)run)[0]).Where(element => element.HasField("regionSectionID"));
|
||||
NameHint = elements.Select(element => element.GetEnumValue("regionSectionID")).Distinct().OrderBy(s => s).FirstOrDefault() ?? string.Empty;
|
||||
if (NameHint != string.Empty) NameHint = $" (ex. {NameHint})";
|
||||
|
||||
if (!model.SpartanMode) render = new Lazy<IPixelViewModel>(() => new BlocksetModel(Model, Address).RenderBlockset(.5));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
public enum TextFormatting { None, Keyword, Constant, Numeric, Comment, Text }
|
||||
public interface ITextPreProcessor {
|
||||
TextFormatting[] Format(string content);
|
||||
IEnumerable<TextSegment> FindErrors(string content);
|
||||
}
|
||||
|
||||
public class TextEditorViewModel : ViewModelCore {
|
||||
|
|
@ -44,6 +45,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
public string Content {
|
||||
get => content;
|
||||
set {
|
||||
value ??= string.Empty;
|
||||
if (content == value) return;
|
||||
var oldContent = content;
|
||||
content = value;
|
||||
|
|
@ -78,6 +80,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
public void FocusKeyboard() => RequestKeyboardFocus.Raise(this);
|
||||
|
||||
private void UpdateLayers() {
|
||||
ErrorLocations.Clear();
|
||||
if (content.Length == 0) {
|
||||
if (PlainContent.Length != 0) {
|
||||
PlainContent = AccentContent =
|
||||
|
|
@ -113,6 +116,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
if (pre[i] == TextFormatting.Text) text.Replace(i, basic, i, 1);
|
||||
basic.Clear(i, 1);
|
||||
}
|
||||
foreach (var error in PreFormatter.FindErrors(Content)) ErrorLocations.Add(error);
|
||||
}
|
||||
|
||||
// comments
|
||||
|
|
@ -179,6 +183,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
NumericContent = numeric.ToString();
|
||||
CommentContent = comments.ToString();
|
||||
TextContent = text.ToString();
|
||||
|
||||
NotifyPropertiesChanged(
|
||||
nameof(PlainContent),
|
||||
nameof(AccentContent),
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
public IEnumerable<TextSegment> FindErrors(string content) { yield break; }
|
||||
}
|
||||
|
||||
public record HelpContext(string Line, int Index, int ContentBoundaryCount = 0, int ContentBoundaryIndex = -1, bool IsSelection = false);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using HavenSoft.HexManiac.Core.Models.Runs;
|
|||
using Microsoft.Scripting.Hosting;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Dynamic;
|
||||
|
||||
|
|
@ -150,6 +151,7 @@ clr.ImportExtensions(HavenSoft.HexManiac.Core.Models)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
public IEnumerable<TextSegment> FindErrors(string content) { yield break; }
|
||||
}
|
||||
|
||||
public record TableGetter(EditorViewModel Editor) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
|||
}
|
||||
}
|
||||
|
||||
public TextEditorViewModel ElementContent { get; } = new();
|
||||
|
||||
protected void HandleNewDataStream(IStreamRun oldRun, IStreamRun newRun, IReadOnlyList<int> changedOffsets, IReadOnlyList<int> changedRuns) {
|
||||
Model.ObserveRunWritten(ViewPort.CurrentChange, newRun);
|
||||
if (oldRun.Start != newRun.Start) {
|
||||
|
|
@ -33,7 +35,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
|||
}
|
||||
|
||||
if (Model.GetNextRun(newRun.Start) is ITableRun table) {
|
||||
foreach(var change in changedOffsets) {
|
||||
foreach (var change in changedOffsets) {
|
||||
var offsets = table.ConvertByteOffsetToArrayOffset(change);
|
||||
var info = table.NotifyChildren(Model, ViewPort.CurrentChange, offsets.ElementIndex, offsets.SegmentIndex);
|
||||
ViewPort.HandleErrorInfo(info);
|
||||
|
|
@ -72,6 +74,9 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
|||
} else {
|
||||
content = string.Empty;
|
||||
}
|
||||
|
||||
ElementContent.Content = content;
|
||||
ElementContent.Bind(nameof(ElementContent.Content), (sender, e) => Content = ElementContent.Content);
|
||||
}
|
||||
|
||||
protected override bool TryCopy(StreamElementViewModel other) {
|
||||
|
|
@ -79,6 +84,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels.Tools {
|
|||
if (!(other is TextStreamElementViewModel stream)) return false;
|
||||
Start = other.Start;
|
||||
TryUpdate(ref content, stream.content, nameof(Content));
|
||||
ElementContent.Content = Content;
|
||||
NotifyPropertyChanged(nameof(Visualizations));
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -527,6 +527,7 @@
|
|||
<local:SelectionRender x:Name="SelectionRender" Stretch="None" />
|
||||
</local:GridDecorator>
|
||||
</Canvas>
|
||||
<TextBlock Background="{DynamicResource Background}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Text="{Binding QuickInfo}" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
|
|
|
|||
|
|
@ -520,9 +520,8 @@
|
|||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Viewbox>
|
||||
<TextBox VerticalAlignment="Top" Text="{Binding TrainerTeam, UpdateSourceTrigger=PropertyChanged}"
|
||||
HorizontalAlignment="Right" AcceptsReturn="True" FontFamily="Consolas"
|
||||
Name="TrainerTeamBox" Background="Transparent" Width="230" CaretBrush="{DynamicResource Secondary}" />
|
||||
<local:TextEditor x:Name="TrainerTeamBox" DataContext="{Binding TrainerContent}" Width="230"
|
||||
Background="Transparent" VerticalAlignment="Top" Visibility="{Binding ShowContent, Converter={StaticResource BoolToVisibility}}" />
|
||||
<local:AutocompleteOverlay Target="{Binding ElementName=TrainerTeamBox}" />
|
||||
</Grid>
|
||||
<local:AngleBorder Direction="Right" HorizontalAlignment="Left" Margin="4,10,0,0">
|
||||
|
|
@ -569,9 +568,8 @@
|
|||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Viewbox>
|
||||
<TextBox VerticalAlignment="Top" Text="{Binding TrainerTeam, UpdateSourceTrigger=PropertyChanged}"
|
||||
HorizontalAlignment="Stretch" AcceptsReturn="True" FontFamily="Consolas"
|
||||
Name="TrainerTeamBox" Background="Transparent" CaretBrush="{DynamicResource Secondary}" />
|
||||
<local:TextEditor x:Name="TrainerTeamBox" DataContext="{Binding TrainerContent}"
|
||||
Background="Transparent" HorizontalAlignment="Stretch" Visibility="{Binding ShowContent, Converter={StaticResource BoolToVisibility}}" />
|
||||
<Button Command="{res:MethodCommand Refresh}" ToolTip="Refresh" BorderBrush="{DynamicResource Secondary}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Top" Width="20" Height="20">
|
||||
<Path Data="{res:Icon RotationArrow}" Fill="{DynamicResource Primary}" Stretch="Uniform" />
|
||||
|
|
@ -1030,8 +1028,7 @@
|
|||
|
||||
<local:AngleComboBox Grid.Column="1" Direction="Out" Margin="0,2,2,2" DisplayMemberPath="AddressText"
|
||||
ItemContainerStyle="{StaticResource BlocksetOptionsContainer}"
|
||||
ItemsSource="{Binding PrimaryOptions}" SelectedIndex="{Binding PrimaryIndex}">
|
||||
</local:AngleComboBox>
|
||||
ItemsSource="{Binding PrimaryOptions}" SelectedIndex="{Binding PrimaryIndex}" />
|
||||
<local:AngleComboBox Grid.Column="1" Direction="Out" Margin="0,2,2,2" Grid.Row="1" DisplayMemberPath="AddressText"
|
||||
ItemContainerStyle="{StaticResource BlocksetOptionsContainer}"
|
||||
ItemsSource="{Binding SecondaryOptions}" SelectedIndex="{Binding SecondaryIndex}" />
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<local:AngleBorder Direction="Left" Content="Behavior:" Margin="0,0,-2,0" />
|
||||
<local:AngleComboBox Direction="Out" Grid.Column="1" SelectedIndex="{Binding Behavior}" ItemsSource="{Binding BehaviorOptions}" Margin="2" />
|
||||
<local:AngleComboBox Direction="Out" Grid.Column="1" DataContext="{Binding BehaviorOptions}" Margin="2" />
|
||||
<local:AngleBorder Direction="Left" Content="Layer:" Grid.Row="1" Margin="0,0,-2,0" />
|
||||
<local:AngleComboBox Direction="Out" Grid.Row="1" Grid.Column="1" SelectedIndex="{Binding Layer}" ItemsSource="{Binding LayerOptions}" Margin="2" />
|
||||
|
||||
|
|
|
|||
|
|
@ -623,27 +623,18 @@
|
|||
<StackPanel ToolTip="{Binding ParentName}">
|
||||
<hsg3hv:CommonTableStreamControl />
|
||||
<Grid Margin="20,2,2,2" Background="{DynamicResource Backlight}">
|
||||
<Viewbox HorizontalAlignment="Right" Height="{Binding ActualHeight, ElementName=StreamTextBox}" Stretch="Uniform" IsHitTestVisible="False" Opacity=".5">
|
||||
<ItemsControl ItemsSource="{Binding Visualizations}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<hsg3hv:PixelImage TransparentBrush="{DynamicResource Backlight}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Viewbox>
|
||||
<TextBox Name="StreamTextBox" UndoLimit="0" Text="{Binding Content, UpdateSourceTrigger=PropertyChanged}"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Top"
|
||||
CaretBrush="{DynamicResource Secondary}"
|
||||
AcceptsReturn="True" FontFamily="Consolas"
|
||||
Visibility="{Binding ShowContent, Converter={StaticResource BoolToVisibility}}">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding Modifiers="Ctrl" Key="Z" Command="{Binding Undo}"/>
|
||||
<KeyBinding Modifiers="Ctrl" Key="Y" Command="{Binding Redo}"/>
|
||||
</TextBox.InputBindings>
|
||||
</TextBox>
|
||||
<hsg3hv:AutocompleteOverlay Target="{Binding ElementName=StreamTextBox}"/>
|
||||
<Viewbox HorizontalAlignment="Right" Height="{Binding ActualHeight, ElementName=StreamTextBox}" Stretch="Uniform" IsHitTestVisible="False" Opacity=".5">
|
||||
<ItemsControl ItemsSource="{Binding Visualizations}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<hsg3hv:PixelImage TransparentBrush="{DynamicResource Backlight}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Viewbox>
|
||||
<hsg3hv:TextEditor x:Name="StreamTextBox" DataContext="{Binding ElementContent}"
|
||||
Background="Transparent" VerticalAlignment="Top" Visibility="{Binding ShowContent, Converter={StaticResource BoolToVisibility}}" />
|
||||
<hsg3hv:AutocompleteOverlay Target="{Binding ElementName=StreamTextBox}"/>
|
||||
</Grid>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,2,0,0">
|
||||
<hsg3hv:AngleButton Command="{Binding SetDefaultMoves}" Margin="0,0,4,0" Content="Default Moves" Direction="Out">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:HavenSoft.HexManiac.WPF.Controls">
|
||||
<Grid Background="{DynamicResource Backlight}" TextBlock.FontFamily="Consolas" ClipToBounds="True">
|
||||
<Grid Name="Body" TextBlock.FontFamily="Consolas" ClipToBounds="True" Background="Transparent">
|
||||
<Canvas ClipToBounds="False" Width="0" HorizontalAlignment="Left">
|
||||
<TextBlock Name="BasicLayer" Foreground="{DynamicResource Primary}" Margin="2" Text="{Binding PlainContent}">
|
||||
<TextBlock.RenderTransform>
|
||||
|
|
|
|||
|
|
@ -1330,6 +1330,7 @@
|
|||
|
||||
<!-- Text Editor Style -->
|
||||
<Style TargetType="hsc:TextEditor">
|
||||
<Setter Property="Background" Value="{DynamicResource Backlight}" />
|
||||
<Setter Property="ContextMenuOverride">
|
||||
<Setter.Value>
|
||||
<ContextMenu>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user