mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-27 06:20:25 +00:00
Extract metadata-reflection class to PKHeX.Core
separate GUI logic from non-gui logic :)
This commit is contained in:
parent
94eee74e5c
commit
9b6a10df46
2 changed files with 126 additions and 100 deletions
120
PKHeX.Core/Saves/MemeCrypto/SCBlockMetadata.cs
Normal file
120
PKHeX.Core/Saves/MemeCrypto/SCBlockMetadata.cs
Normal file
|
@ -0,0 +1,120 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides reflection utility for manipulating blocks, providing block names and value wrapping.
|
||||
/// </summary>
|
||||
public class SCBlockMetadata
|
||||
{
|
||||
private readonly Dictionary<SaveBlock, string> BlockList;
|
||||
private readonly Dictionary<uint, string> ValueList;
|
||||
private readonly SCBlockAccessor Accessor;
|
||||
|
||||
public SCBlockMetadata(SCBlockAccessor accessor)
|
||||
{
|
||||
var aType = accessor.GetType();
|
||||
|
||||
BlockList = aType.GetAllPropertiesOfType<SaveBlock>(accessor);
|
||||
ValueList = aType.GetAllConstantsOfType<uint>();
|
||||
Accessor = accessor;
|
||||
}
|
||||
|
||||
public IEnumerable<ComboItem> GetSortedBlockKeyList()
|
||||
{
|
||||
var list = Accessor.BlockInfo
|
||||
.Select((z, i) => new ComboItem(GetBlockHint(z, i), (int)z.Key))
|
||||
.OrderBy(z => !z.Text.StartsWith("*"))
|
||||
.ThenBy(z => GetSortKey(z));
|
||||
return list;
|
||||
}
|
||||
|
||||
private static string GetSortKey(in ComboItem item)
|
||||
{
|
||||
var text = item.Text;
|
||||
if (text.StartsWith("*"))
|
||||
return text;
|
||||
// key:X8, " - ", "####", " ", type
|
||||
return text.Substring(8 + 3 + 4 + 1);
|
||||
}
|
||||
|
||||
private string GetBlockHint(SCBlock z, int i)
|
||||
{
|
||||
var blockName = GetBlockName(z, out _);
|
||||
var type = (z.Type.IsBoolean() ? "Bool" : z.Type.ToString());
|
||||
if (blockName != null)
|
||||
return $"*{type} {blockName}";
|
||||
return $"{z.Key:X8} - {i:0000} {type}";
|
||||
}
|
||||
|
||||
public string? GetBlockName(SCBlock block, out SaveBlock? saveBlock)
|
||||
{
|
||||
// See if we have a Block object for this block
|
||||
var obj = BlockList.FirstOrDefault(z => ReferenceEquals(z.Key.Data, block.Data));
|
||||
if (obj.Key != null)
|
||||
{
|
||||
saveBlock = obj.Key;
|
||||
return obj.Value;
|
||||
}
|
||||
|
||||
// See if it's a single-value declaration
|
||||
if (ValueList.TryGetValue(block.Key, out var blockName))
|
||||
{
|
||||
saveBlock = null;
|
||||
return blockName;
|
||||
}
|
||||
saveBlock = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an object that wraps the block with a Value property to get/set via a PropertyGrid/etc control.
|
||||
/// </summary>
|
||||
/// <returns>Returns null if no wrapping is supported.</returns>
|
||||
public static object? GetEditableBlockObject(SCBlock block)
|
||||
{
|
||||
return block.Type switch
|
||||
{
|
||||
SCTypeCode.Byte => new WrappedValueView<byte>(block, block.GetValue()),
|
||||
SCTypeCode.UInt16 => new WrappedValueView<ushort>(block, block.GetValue()),
|
||||
SCTypeCode.UInt32 => new WrappedValueView<uint>(block, block.GetValue()),
|
||||
SCTypeCode.UInt64 => new WrappedValueView<ulong>(block, block.GetValue()),
|
||||
|
||||
SCTypeCode.SByte => new WrappedValueView<sbyte>(block, block.GetValue()),
|
||||
SCTypeCode.Int16 => new WrappedValueView<short>(block, block.GetValue()),
|
||||
SCTypeCode.Int32 => new WrappedValueView<int>(block, block.GetValue()),
|
||||
SCTypeCode.Int64 => new WrappedValueView<long>(block, block.GetValue()),
|
||||
|
||||
SCTypeCode.Single => new WrappedValueView<float>(block, block.GetValue()),
|
||||
SCTypeCode.Double => new WrappedValueView<double>(block, block.GetValue()),
|
||||
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private class WrappedValueView<T> where T : struct
|
||||
{
|
||||
private readonly SCBlock Parent;
|
||||
private T _value;
|
||||
|
||||
[Description("Stored Value for this Block")]
|
||||
public T Value
|
||||
{
|
||||
get => _value;
|
||||
set => Parent.SetValue(_value = value);
|
||||
}
|
||||
|
||||
[Description("Type of Value this Block stores")]
|
||||
public string ValueType => typeof(T).Name;
|
||||
|
||||
public WrappedValueView(SCBlock block, object currentValue)
|
||||
{
|
||||
Parent = block;
|
||||
_value = (T)Convert.ChangeType(currentValue, typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -13,10 +12,9 @@ namespace PKHeX.WinForms
|
|||
public partial class SAV_BlockDump8 : Form
|
||||
{
|
||||
private readonly SAV8SWSH SAV;
|
||||
private SCBlock CurrentBlock;
|
||||
private readonly SCBlockMetadata Metadata;
|
||||
|
||||
private readonly Dictionary<SaveBlock, string> BlockList;
|
||||
private readonly Dictionary<uint, string> ValueList;
|
||||
private SCBlock CurrentBlock;
|
||||
|
||||
public SAV_BlockDump8(SaveFile sav)
|
||||
{
|
||||
|
@ -26,18 +24,10 @@ namespace PKHeX.WinForms
|
|||
|
||||
PG_BlockView.Size = RTB_Hex.Size;
|
||||
|
||||
var accessor = SAV.Blocks;
|
||||
var aType = accessor.GetType();
|
||||
BlockList = aType.GetAllPropertiesOfType<SaveBlock>(SAV.Blocks);
|
||||
ValueList = aType.GetAllConstantsOfType<uint>();
|
||||
|
||||
var blocks = SAV.AllBlocks
|
||||
.Select((z, i) => new ComboItem(GetBlockHint(z, i), (int)z.Key))
|
||||
.OrderBy(z => !z.Text.StartsWith("*"))
|
||||
.ThenBy(z => GetSortKey(z));
|
||||
Metadata = new SCBlockMetadata(SAV.Blocks);
|
||||
|
||||
CB_Key.InitializeBinding();
|
||||
CB_Key.DataSource = blocks.ToArray();
|
||||
CB_Key.DataSource = Metadata.GetSortedBlockKeyList().ToArray();
|
||||
|
||||
var boolToggle = new[]
|
||||
{
|
||||
|
@ -49,24 +39,6 @@ namespace PKHeX.WinForms
|
|||
CB_TypeToggle.DataSource = boolToggle;
|
||||
}
|
||||
|
||||
private static string GetSortKey(in ComboItem item)
|
||||
{
|
||||
var text = item.Text;
|
||||
if (text.StartsWith("*"))
|
||||
return text;
|
||||
// key:X8, " - ", "####", " ", type
|
||||
return text.Substring(8 + 3 + 4 + 1);
|
||||
}
|
||||
|
||||
private string GetBlockHint(SCBlock z, int i)
|
||||
{
|
||||
var blockName = GetBlockName(z, out _);
|
||||
var type = (z.Type.IsBoolean() ? "Bool" : z.Type.ToString());
|
||||
if (blockName != null)
|
||||
return $"*{type} {blockName}";
|
||||
return $"{z.Key:X8} - {i:0000} {type}";
|
||||
}
|
||||
|
||||
private void CB_Key_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
var key = (uint)WinFormsUtil.GetIndex(CB_Key);
|
||||
|
@ -89,7 +61,7 @@ namespace PKHeX.WinForms
|
|||
L_Detail_R.Text = GetBlockSummary(block);
|
||||
RTB_Hex.Text = string.Join(" ", block.Data.Select(z => $"{z:X2}"));
|
||||
|
||||
string blockName = GetBlockName(block, out SaveBlock obj);
|
||||
string blockName = Metadata.GetBlockName(block, out SaveBlock obj);
|
||||
if (blockName != null)
|
||||
{
|
||||
L_BlockName.Visible = true;
|
||||
|
@ -114,7 +86,7 @@ namespace PKHeX.WinForms
|
|||
}
|
||||
}
|
||||
|
||||
var o = WrapUtil.GetWrapped(block);
|
||||
var o = SCBlockMetadata.GetEditableBlockObject(block);
|
||||
if (o != null)
|
||||
{
|
||||
PG_BlockView.Visible = true;
|
||||
|
@ -125,26 +97,6 @@ namespace PKHeX.WinForms
|
|||
PG_BlockView.Visible = false;
|
||||
}
|
||||
|
||||
private string GetBlockName(SCBlock block, out SaveBlock saveBlock)
|
||||
{
|
||||
// See if we have a Block object for this block
|
||||
var obj = BlockList.FirstOrDefault(z => ReferenceEquals(z.Key.Data, block.Data));
|
||||
if (obj.Key != null)
|
||||
{
|
||||
saveBlock = obj.Key;
|
||||
return obj.Value;
|
||||
}
|
||||
|
||||
// See if it's a single-value declaration
|
||||
if (ValueList.TryGetValue(block.Key, out var blockName))
|
||||
{
|
||||
saveBlock = null;
|
||||
return blockName;
|
||||
}
|
||||
saveBlock = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void CB_TypeToggle_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
var cType = CurrentBlock.Type;
|
||||
|
@ -269,52 +221,6 @@ namespace PKHeX.WinForms
|
|||
bytes.CopyTo(data, 0);
|
||||
}
|
||||
|
||||
private class WrappedValueView<T>
|
||||
{
|
||||
private readonly SCBlock Parent;
|
||||
private T _value;
|
||||
|
||||
[Description("Stored Value for this Block")]
|
||||
public T Value
|
||||
{
|
||||
get => _value;
|
||||
set => Parent.SetValue(_value = value);
|
||||
}
|
||||
|
||||
[Description("Type of Value this Block stores")]
|
||||
public string ValueType => typeof(T).Name;
|
||||
|
||||
public WrappedValueView(SCBlock block, object currentValue)
|
||||
{
|
||||
Parent = block;
|
||||
_value = (T)Convert.ChangeType(currentValue, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
private static class WrapUtil
|
||||
{
|
||||
public static object GetWrapped(SCBlock block)
|
||||
{
|
||||
return block.Type switch
|
||||
{
|
||||
SCTypeCode.Byte => new WrappedValueView<byte>(block, block.GetValue()),
|
||||
SCTypeCode.UInt16 => new WrappedValueView<ushort>(block, block.GetValue()),
|
||||
SCTypeCode.UInt32 => new WrappedValueView<uint>(block, block.GetValue()),
|
||||
SCTypeCode.UInt64 => new WrappedValueView<ulong>(block, block.GetValue()),
|
||||
|
||||
SCTypeCode.SByte => new WrappedValueView<sbyte>(block, block.GetValue()),
|
||||
SCTypeCode.Int16 => new WrappedValueView<short>(block, block.GetValue()),
|
||||
SCTypeCode.Int32 => new WrappedValueView<int>(block, block.GetValue()),
|
||||
SCTypeCode.Int64 => new WrappedValueView<long>(block, block.GetValue()),
|
||||
|
||||
SCTypeCode.Single => new WrappedValueView<float>(block, block.GetValue()),
|
||||
SCTypeCode.Double => new WrappedValueView<double>(block, block.GetValue()),
|
||||
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void PG_BlockView_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
|
||||
{
|
||||
Debug.WriteLine($"ChangedItem = {e.ChangedItem.Label}, OldValue = {e.OldValue}, NewValue = {e.ChangedItem.Value}");
|
||||
|
|
Loading…
Reference in a new issue