Minor refactoring for pkmeditor GUI

Cleans up some interactions to be a little more obvious
This commit is contained in:
Kurt 2021-07-30 18:05:17 -07:00
parent de94876822
commit 4ec60916c1
8 changed files with 188 additions and 141 deletions

View file

@ -33,7 +33,6 @@ namespace PKHeX.WinForms.Controls
SaveMisc3(pk6); SaveMisc3(pk6);
SaveMisc4(pk6); SaveMisc4(pk6);
SaveMisc6(pk6); SaveMisc6(pk6);
CheckTransferPIDValid(pk6);
pk6.GroundTile = (GroundTileType)WinFormsUtil.GetIndex(CB_GroundTile); pk6.GroundTile = (GroundTileType)WinFormsUtil.GetIndex(CB_GroundTile);

View file

@ -30,14 +30,13 @@ namespace PKHeX.WinForms.Controls
SaveMisc3(pk7); SaveMisc3(pk7);
SaveMisc4(pk7); SaveMisc4(pk7);
SaveMisc6(pk7); SaveMisc6(pk7);
CheckTransferPIDValid(pk7);
// Toss in Party Stats // Toss in Party Stats
SavePartyStats(pk7); SavePartyStats(pk7);
// Unneeded Party Stats (Status, Flags, Unused) // Unneeded Party Stats (Status, Flags, Unused)
pk7.Data[0xE8] = pk7.Data[0xE9] = pk7.Data[0xEA] = pk7.Data[0xEB] = pk7.Status_Condition = pk7.DirtType = pk7.DirtLocation =
pk7.Data[0xED] = pk7.Data[0xEE] = pk7.Data[0xEF] = pk7.Data[0xEF] =
pk7.Data[0xFE] = pk7.Data[0xFF] = pk7.Data[0x100] = pk7.Data[0xFE] = pk7.Data[0xFF] = pk7.Data[0x100] =
pk7.Data[0x101] = pk7.Data[0x102] = pk7.Data[0x103] = 0; pk7.Data[0x101] = pk7.Data[0x102] = pk7.Data[0x103] = 0;

View file

@ -33,7 +33,6 @@ namespace PKHeX.WinForms.Controls
SaveMisc4(pk8); SaveMisc4(pk8);
SaveMisc6(pk8); SaveMisc6(pk8);
SaveMisc8(pk8); SaveMisc8(pk8);
CheckTransferPIDValid(pk8);
// Toss in Party Stats // Toss in Party Stats
SavePartyStats(pk8); SavePartyStats(pk8);

View file

@ -20,10 +20,13 @@ namespace PKHeX.WinForms.Controls
private void LoadSpeciesLevelEXP(PKM pk) private void LoadSpeciesLevelEXP(PKM pk)
{ {
// Do first if (!HaX)
pk.Stat_Level = Experience.GetLevel(pk.EXP, pk.PersonalInfo.EXPGrowth); {
if (pk.Stat_Level == 100 && !HaX) // Sanity check level and EXP
pk.EXP = Experience.GetEXP(pk.Stat_Level, pk.PersonalInfo.EXPGrowth); var current = pk.CurrentLevel;
if (current == 100) // clamp back to max EXP
pk.CurrentLevel = 100;
}
CB_Species.SelectedValue = pk.Species; CB_Species.SelectedValue = pk.Species;
TB_Level.Text = pk.Stat_Level.ToString(); TB_Level.Text = pk.Stat_Level.ToString();
@ -34,11 +37,12 @@ namespace PKHeX.WinForms.Controls
{ {
pk.Species = WinFormsUtil.GetIndex(CB_Species); pk.Species = WinFormsUtil.GetIndex(CB_Species);
pk.EXP = Util.ToUInt32(TB_EXP.Text); pk.EXP = Util.ToUInt32(TB_EXP.Text);
pk.Stat_Level = Util.ToInt32(TB_Level.Text);
} }
private void LoadOT(PKM pk) private void LoadOT(PKM pk)
{ {
GB_OT.BackgroundImage = null; GB_OT.BackgroundImage = null; // clear the Current Handler indicator just in case we switched formats.
TB_OT.Text = pk.OT_Name; TB_OT.Text = pk.OT_Name;
Label_OTGender.Text = gendersymbols[pk.OT_Gender]; Label_OTGender.Text = gendersymbols[pk.OT_Gender];
Label_OTGender.ForeColor = Draw.GetGenderColor(pk.OT_Gender); Label_OTGender.ForeColor = Draw.GetGenderColor(pk.OT_Gender);
@ -52,11 +56,10 @@ namespace PKHeX.WinForms.Controls
private void LoadPKRS(PKM pk) private void LoadPKRS(PKM pk)
{ {
Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked = pk.PKRS_Strain != 0; Label_PKRS.Visible = CB_PKRSStrain.Visible = CHK_Infected.Checked = Label_PKRSdays.Visible = CB_PKRSDays.Visible = pk.PKRS_Infected;
Label_PKRSdays.Visible = CB_PKRSDays.Visible = pk.PKRS_Days != 0;
CB_PKRSStrain.SelectedIndex = pk.PKRS_Strain; CB_PKRSStrain.SelectedIndex = pk.PKRS_Strain;
CHK_Cured.Checked = pk.PKRS_Strain > 0 && pk.PKRS_Days == 0; CHK_Cured.Checked = pk.PKRS_Cured;
CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, pk.PKRS_Days); // to strip out bad hacked 'rus CB_PKRSDays.SelectedIndex = Math.Min(CB_PKRSDays.Items.Count - 1, pk.PKRS_Days); // clamp to valid day values for the current strain
} }
private void SavePKRS(PKM pk) private void SavePKRS(PKM pk)
@ -67,7 +70,7 @@ namespace PKHeX.WinForms.Controls
private void LoadIVs(PKM pk) => Stats.LoadIVs(pk.IVs); private void LoadIVs(PKM pk) => Stats.LoadIVs(pk.IVs);
private void LoadEVs(PKM pk) => Stats.LoadEVs(pk.EVs); private void LoadEVs(PKM pk) => Stats.LoadEVs(pk.EVs);
private void LoadAVs(IAwakened a) => Stats.LoadAVs(a); private void LoadAVs(IAwakened pk) => Stats.LoadAVs(pk);
private void LoadMoves(PKM pk) private void LoadMoves(PKM pk)
{ {
@ -101,20 +104,20 @@ namespace PKHeX.WinForms.Controls
pk.Move4_PPUps = WinFormsUtil.GetIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0; pk.Move4_PPUps = WinFormsUtil.GetIndex(CB_Move4) > 0 ? CB_PPu4.SelectedIndex : 0;
} }
private void LoadShadow3(IShadowPKM ck3) private void LoadShadow3(IShadowPKM pk)
{ {
NUD_ShadowID.Value = ck3.ShadowID; NUD_ShadowID.Value = pk.ShadowID;
FLP_Purification.Visible = ck3.ShadowID > 0; FLP_Purification.Visible = pk.ShadowID > 0;
if (ck3.ShadowID > 0) if (pk.ShadowID > 0)
{ {
int value = ck3.Purification; int value = pk.Purification;
if (value < NUD_Purification.Minimum) if (value < NUD_Purification.Minimum)
value = (int)NUD_Purification.Minimum; value = (int)NUD_Purification.Minimum;
NUD_Purification.Value = value; NUD_Purification.Value = value;
CHK_Shadow.Checked = ck3.IsShadow; CHK_Shadow.Checked = pk.IsShadow;
NUD_ShadowID.Value = Math.Max(ck3.ShadowID, 0); NUD_ShadowID.Value = Math.Max(pk.ShadowID, 0);
} }
else else
{ {
@ -124,11 +127,11 @@ namespace PKHeX.WinForms.Controls
} }
} }
private void SaveShadow3(IShadowPKM ck3) private void SaveShadow3(IShadowPKM pk)
{ {
ck3.ShadowID = (int)NUD_ShadowID.Value; pk.ShadowID = (int)NUD_ShadowID.Value;
if (ck3.ShadowID > 0) if (pk.ShadowID > 0)
ck3.Purification = (int)NUD_Purification.Value; pk.Purification = (int)NUD_Purification.Value;
} }
private void LoadRelearnMoves(PKM pk) private void LoadRelearnMoves(PKM pk)
@ -139,12 +142,12 @@ namespace PKHeX.WinForms.Controls
CB_RelearnMove4.SelectedValue = pk.RelearnMove4; CB_RelearnMove4.SelectedValue = pk.RelearnMove4;
} }
private void SaveRelearnMoves(PKM pk7) private void SaveRelearnMoves(PKM pk)
{ {
pk7.RelearnMove1 = WinFormsUtil.GetIndex(CB_RelearnMove1); pk.RelearnMove1 = WinFormsUtil.GetIndex(CB_RelearnMove1);
pk7.RelearnMove2 = WinFormsUtil.GetIndex(CB_RelearnMove2); pk.RelearnMove2 = WinFormsUtil.GetIndex(CB_RelearnMove2);
pk7.RelearnMove3 = WinFormsUtil.GetIndex(CB_RelearnMove3); pk.RelearnMove3 = WinFormsUtil.GetIndex(CB_RelearnMove3);
pk7.RelearnMove4 = WinFormsUtil.GetIndex(CB_RelearnMove4); pk.RelearnMove4 = WinFormsUtil.GetIndex(CB_RelearnMove4);
} }
private void LoadMisc1(PKM pk) private void LoadMisc1(PKM pk)
@ -176,8 +179,8 @@ namespace PKHeX.WinForms.Controls
TB_Friendship.Text = pk.CurrentFriendship.ToString(); TB_Friendship.Text = pk.CurrentFriendship.ToString();
Label_HatchCounter.Visible = CHK_IsEgg.Checked && Entity.Format > 1; Label_HatchCounter.Visible = CHK_IsEgg.Checked;
Label_Friendship.Visible = !CHK_IsEgg.Checked && Entity.Format > 1; Label_Friendship.Visible = !CHK_IsEgg.Checked;
} }
private void SaveMisc2(PKM pk) private void SaveMisc2(PKM pk)
@ -210,7 +213,9 @@ namespace PKHeX.WinForms.Controls
TID_Trainer.LoadIDValues(pk); TID_Trainer.LoadIDValues(pk);
// Load Extrabyte Value // Load Extrabyte Value
TB_ExtraByte.Text = pk.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString(); var offset = Convert.ToInt32(CB_ExtraBytes.Text, 16);
var value = pk.Data[offset];
TB_ExtraByte.Text = value.ToString();
} }
private void SaveMisc3(PKM pk) private void SaveMisc3(PKM pk)
@ -274,12 +279,16 @@ namespace PKHeX.WinForms.Controls
private void LoadMisc6(PKM pk) private void LoadMisc6(PKM pk)
{ {
TB_EC.Text = $"{pk.EncryptionConstant:X8}"; TB_EC.Text = $"{pk.EncryptionConstant:X8}";
int abil = pk.AbilityNumber < 6 ? pk.AbilityNumber >> 1 : 0;
if (CB_Ability.Items.Count <= abil)
abil = CB_Ability.Items.Count - 1;
CB_Ability.SelectedIndex = abil; // with some simple error handling
DEV_Ability.SelectedValue = pk.Ability; DEV_Ability.SelectedValue = pk.Ability;
TB_AbilityNumber.Text = pk.AbilityNumber.ToString();
// with some simple error handling
var bitNumber = pk.AbilityNumber;
int abilityIndex = AbilityVerifier.IsValidAbilityBits(bitNumber) ? bitNumber >> 1 : 0;
if (abilityIndex >= CB_Ability.Items.Count) // sanity check ability count being possible
abilityIndex = CB_Ability.Items.Count - 1; // last possible index, if out of range
CB_Ability.SelectedIndex = abilityIndex;
TB_AbilityNumber.Text = bitNumber.ToString();
LoadRelearnMoves(pk); LoadRelearnMoves(pk);
LoadHandlingTrainer(pk); LoadHandlingTrainer(pk);
@ -291,6 +300,9 @@ namespace PKHeX.WinForms.Controls
private void SaveMisc6(PKM pk) private void SaveMisc6(PKM pk)
{ {
pk.EncryptionConstant = Util.GetHexValue(TB_EC.Text); pk.EncryptionConstant = Util.GetHexValue(TB_EC.Text);
if (PIDVerifier.GetTransferEC(pk, out var ec))
pk.EncryptionConstant = ec;
pk.AbilityNumber = Util.ToInt32(TB_AbilityNumber.Text); pk.AbilityNumber = Util.ToInt32(TB_AbilityNumber.Text);
SaveRelearnMoves(pk); SaveRelearnMoves(pk);
@ -316,26 +328,29 @@ namespace PKHeX.WinForms.Controls
private void LoadHandlingTrainer(PKM pk) private void LoadHandlingTrainer(PKM pk)
{ {
TB_OTt2.Text = pk.HT_Name; var handler = pk.HT_Name;
int gender = pk.HT_Gender & 1; int gender = pk.HT_Gender & 1;
TB_OTt2.Text = handler;
// Set CT Gender to None if no CT, else set to gender symbol. // Set CT Gender to None if no CT, else set to gender symbol.
Label_CTGender.Text = string.IsNullOrEmpty(pk.HT_Name) ? string.Empty : gendersymbols[gender]; Label_CTGender.Text = string.IsNullOrEmpty(handler) ? string.Empty : gendersymbols[gender];
Label_CTGender.ForeColor = Draw.GetGenderColor(gender); Label_CTGender.ForeColor = Draw.GetGenderColor(gender);
// Indicate who is currently in possession of the PKM // Indicate who is currently in possession of the PKM
UpadteHandlingTrainerBackground(pk); UpadteHandlingTrainerBackground(pk.CurrentHandler);
} }
private void UpadteHandlingTrainerBackground(PKM pk) private void UpadteHandlingTrainerBackground(int handler)
{ {
if (pk.CurrentHandler == 0) // OT var activeColor = ImageUtil.ChangeOpacity(SpriteUtil.Spriter.Set, 0.5);
if (handler == 0) // OT
{ {
GB_OT.BackgroundImage = ImageUtil.ChangeOpacity(SpriteUtil.Spriter.Set, 0.5); GB_OT.BackgroundImage = activeColor;
GB_nOT.BackgroundImage = null; GB_nOT.BackgroundImage = null;
} }
else // Handling Trainer else // Handling Trainer
{ {
GB_nOT.BackgroundImage = ImageUtil.ChangeOpacity(SpriteUtil.Spriter.Set, 0.5); GB_nOT.BackgroundImage = activeColor;
GB_OT.BackgroundImage = null; GB_OT.BackgroundImage = null;
} }
} }
@ -346,37 +361,6 @@ namespace PKHeX.WinForms.Controls
pk.HT_Gender = PKX.GetGenderFromString(Label_CTGender.Text) & 1; pk.HT_Gender = PKX.GetGenderFromString(Label_CTGender.Text) & 1;
} }
// Misc
private static void CheckTransferPIDValid(PKM pk)
{
var ver = pk.Version;
if (ver is 0 or >= (int)GameVersion.X) // Gen6+ ignored
return;
uint EC = pk.EncryptionConstant;
uint PID = pk.PID;
uint LID = PID & 0xFFFF;
uint HID = PID >> 16;
uint XOR = (uint)(pk.TID ^ LID ^ pk.SID ^ HID);
// Ensure we don't have a shiny.
if (XOR >> 3 == 1) // Illegal, fix. (not 16<XOR>=8)
{
// Keep as shiny, so we have to mod the EC
pk.EncryptionConstant = PID ^ 0x80000000;
}
else if ((XOR ^ 0x8000) >> 3 == 1 && PID != EC)
{
// Already anti-shiny, ensure the anti-shiny relationship is present.
pk.EncryptionConstant = PID ^ 0x80000000;
}
else
{
// Ensure the copy correlation is present.
pk.EncryptionConstant = PID;
}
}
private void LoadAbility4(PKM pk) private void LoadAbility4(PKM pk)
{ {
var index = GetAbilityIndex4(pk); var index = GetAbilityIndex4(pk);

View file

@ -21,14 +21,13 @@ namespace PKHeX.WinForms.Controls
InitializeComponent(); InitializeComponent();
// Groupbox doesn't show Click event in Designer... // Groupbox doesn't show Click event in Designer...
GB_OT.Click += (_, args) => ClickGT(GB_OT, args); GB_OT.Click += ClickGT;
GB_nOT.Click += (_, args) => ClickGT(GB_nOT, args); GB_nOT.Click += ClickGT;
GB_CurrentMoves.Click += (_, args) => ClickMoves(GB_CurrentMoves, args); GB_CurrentMoves.Click += ClickMoves;
GB_RelearnMoves.Click += (_, args) => ClickMoves(GB_RelearnMoves, args); GB_RelearnMoves.Click += ClickMoves;
TB_Nickname.Font = FontUtil.GetPKXFont(); var font = FontUtil.GetPKXFont();
TB_OT.Font = (Font)TB_Nickname.Font.Clone(); TB_Nickname.Font = TB_OT.Font = TB_OTt2.Font = font;
TB_OTt2.Font = (Font)TB_Nickname.Font.Clone();
// Commonly reused Control arrays // Commonly reused Control arrays
Moves = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 }; Moves = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 };
@ -36,21 +35,56 @@ namespace PKHeX.WinForms.Controls
PPUps = new[] { CB_PPu1, CB_PPu2, CB_PPu3, CB_PPu4 }; PPUps = new[] { CB_PPu1, CB_PPu2, CB_PPu3, CB_PPu4 };
MovePP = new[] { TB_PP1, TB_PP2, TB_PP3, TB_PP4 }; MovePP = new[] { TB_PP1, TB_PP2, TB_PP3, TB_PP4 };
Markings = new[] { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 }; Markings = new[] { PB_Mark1, PB_Mark2, PB_Mark3, PB_Mark4, PB_Mark5, PB_Mark6 };
ValidationRequired = Moves.Concat(Relearn).Concat(new[]
{ // Legality Indicators
CB_Species, CB_Nature, CB_HeldItem, CB_Ability, // Main Tab
CB_MetLocation, CB_EggLocation, CB_Ball, // Met Tab
CB_StatNature,
}).ToArray();
relearnPB = new[] { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 }; relearnPB = new[] { PB_WarnRelearn1, PB_WarnRelearn2, PB_WarnRelearn3, PB_WarnRelearn4 };
movePB = new[] { PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4 }; movePB = new[] { PB_WarnMove1, PB_WarnMove2, PB_WarnMove3, PB_WarnMove4 };
// Validation of incompletely entered data fields
bool Criteria(Control c) => c.BackColor == Draw.InvalidSelection && c is ComboBox x && x.Items.Count is not 0;
ValidatedControls = new ValidationRequiredSet[]
{
new(Moves, _ => true, Criteria),
new(new[] {CB_Species}, _ => true, Criteria),
new(new[] {CB_HeldItem}, pk => pk.Format >= 2, Criteria),
new(new[] {CB_Ability, CB_Nature, CB_MetLocation, CB_Ball}, pk => pk.Format >= 3, Criteria),
new(new[] {CB_EggLocation}, pk => pk.Format >= 4, Criteria),
new(new [] {CB_Country, CB_SubRegion}, pk => pk is PK6 or PK7, Criteria),
new(Relearn, pk => pk.Format >= 6, Criteria),
new(new[] {CB_StatNature}, pk => pk.Format >= 8, Criteria),
};
foreach (var c in WinFormsUtil.GetAllControlsOfType<ComboBox>(this)) foreach (var c in WinFormsUtil.GetAllControlsOfType<ComboBox>(this))
c.KeyDown += WinFormsUtil.RemoveDropCB; c.KeyDown += WinFormsUtil.RemoveDropCB;
Stats.MainEditor = this; Stats.MainEditor = this;
LoadShowdownSet = LoadShowdownSetDefault; LoadShowdownSet = LoadShowdownSetDefault;
TID_Trainer.UpdatedID += (_, args) => Update_ID(TID_Trainer, args); TID_Trainer.UpdatedID += Update_ID;
// Controls contained in a TabPage are not created until the tab page is shown
// Any data bindings in these controls are not activated until the tab page is shown.
FlickerInterface();
}
private class ValidationRequiredSet
{
private readonly Control[] Controls;
private readonly Func<PKM, bool> ShouldCheck;
private readonly Func<Control, bool> IsInvalidState;
public Control? IsNotValid(PKM pk)
{
if (!ShouldCheck(pk))
return null;
return Array.Find(Controls, z => IsInvalidState(z));
}
public ValidationRequiredSet(Control[] controls, Func<PKM, bool> shouldCheck, Func<Control, bool> state)
{
Controls = controls;
ShouldCheck = shouldCheck;
IsInvalidState = state;
}
} }
public void InitializeBinding() public void InitializeBinding()
@ -149,7 +183,8 @@ namespace PKHeX.WinForms.Controls
public SaveFile RequestSaveFile => SaveFileRequested.Invoke(this, EventArgs.Empty); public SaveFile RequestSaveFile => SaveFileRequested.Invoke(this, EventArgs.Empty);
public bool PKMIsUnsaved => FieldsLoaded && LastData.Any(b => b != 0) && !LastData.SequenceEqual(CurrentPKM.Data); public bool PKMIsUnsaved => FieldsLoaded && LastData.Any(b => b != 0) && !LastData.SequenceEqual(CurrentPKM.Data);
private readonly ComboBox[] Moves, Relearn, ValidationRequired, PPUps; private readonly ComboBox[] Moves, Relearn, PPUps;
private readonly ValidationRequiredSet[] ValidatedControls;
private readonly MaskedTextBox[] MovePP; private readonly MaskedTextBox[] MovePP;
private readonly PictureBox[] Markings; private readonly PictureBox[] Markings;
@ -176,12 +211,20 @@ namespace PKHeX.WinForms.Controls
if (ModifierKeys == (Keys.Control | Keys.Shift | Keys.Alt)) if (ModifierKeys == (Keys.Control | Keys.Shift | Keys.Alt))
return true; // Override return true; // Override
var cb = Array.Find(ValidationRequired, c => c.BackColor == Draw.InvalidSelection && c.Items.Count != 0); // If any controls are partially filled out, find the first one so we can indicate as such.
Control? cb = null;
foreach (var type in ValidatedControls)
{
cb = type.IsNotValid(Entity);
if (cb is not null)
break;
}
if (cb != null) if (cb != null)
tabMain.SelectedTab = WinFormsUtil.FindFirstControlOfType<TabPage>(cb); tabMain.SelectedTab = WinFormsUtil.FindFirstControlOfType<TabPage>(cb);
else if (!Stats.Valid) else if (!Stats.Valid)
tabMain.SelectedTab = Tab_Stats; tabMain.SelectedTab = Tab_Stats;
else if (WinFormsUtil.GetIndex(CB_Species) == 0) else if (WinFormsUtil.GetIndex(CB_Species) == 0 && !HaX) // can't set an empty slot...
tabMain.SelectedTab = Tab_Main; tabMain.SelectedTab = Tab_Main;
else else
return true; return true;
@ -278,7 +321,7 @@ namespace PKHeX.WinForms.Controls
Stats.UpdateIVs(this, EventArgs.Empty); Stats.UpdateIVs(this, EventArgs.Empty);
UpdatePKRSInfected(this, EventArgs.Empty); UpdatePKRSInfected(this, EventArgs.Empty);
UpdatePKRSCured(this, EventArgs.Empty); UpdatePKRSCured(this, EventArgs.Empty);
UpdateNatureModification(CB_StatNature, 1); UpdateNatureModification(CB_StatNature, Entity.StatNature);
if (HaX) // Load original values from pk not pkm if (HaX) // Load original values from pk not pkm
{ {
@ -323,8 +366,10 @@ namespace PKHeX.WinForms.Controls
img = Resources.hint; img = Resources.hint;
else else
img = null; img = null;
movePB[i].Visible = true;
movePB[i].Image = img; var pb = movePB[i];
pb.Visible = true;
pb.Image = img;
} }
if (Entity.Format >= 6) if (Entity.Format >= 6)
@ -677,7 +722,7 @@ namespace PKHeX.WinForms.Controls
UpdateLegality(); UpdateLegality();
} }
private void ClickGT(object sender, EventArgs e) private void ClickGT(object? sender, EventArgs e)
{ {
if (!GB_nOT.Visible) if (!GB_nOT.Visible)
return; return;
@ -686,7 +731,7 @@ namespace PKHeX.WinForms.Controls
Entity.CurrentHandler = 0; Entity.CurrentHandler = 0;
else if (TB_OTt2.Text.Length > 0) else if (TB_OTt2.Text.Length > 0)
Entity.CurrentHandler = 1; Entity.CurrentHandler = 1;
UpadteHandlingTrainerBackground(Entity); UpadteHandlingTrainerBackground(Entity.CurrentHandler);
TB_Friendship.Text = Entity.CurrentFriendship.ToString(); TB_Friendship.Text = Entity.CurrentFriendship.ToString();
} }
@ -701,7 +746,7 @@ namespace PKHeX.WinForms.Controls
CB_StatNature.SelectedIndex = CB_Nature.SelectedIndex; CB_StatNature.SelectedIndex = CB_Nature.SelectedIndex;
} }
private void ClickMoves(object sender, EventArgs e) private void ClickMoves(object? sender, EventArgs e)
{ {
UpdateLegality(skipMoveRepop: true); UpdateLegality(skipMoveRepop: true);
if (sender == GB_CurrentMoves) if (sender == GB_CurrentMoves)
@ -1259,10 +1304,13 @@ namespace PKHeX.WinForms.Controls
if (CB_ExtraBytes.Items.Count == 0 || sender is not MaskedTextBox mtb) if (CB_ExtraBytes.Items.Count == 0 || sender is not MaskedTextBox mtb)
return; return;
// Changed Extra Byte's Value // Changed Extra Byte's Value
if (Util.ToInt32(mtb.Text) > byte.MaxValue) var value = Util.ToInt32(mtb.Text);
if (value > byte.MaxValue)
{
mtb.Text = "255"; mtb.Text = "255";
return; // above statement triggers the event again.
}
int value = Util.ToInt32(mtb.Text);
int offset = Convert.ToInt32(CB_ExtraBytes.Text, 16); int offset = Convert.ToInt32(CB_ExtraBytes.Text, 16);
Entity.Data[offset] = (byte)value; Entity.Data[offset] = (byte)value;
} }
@ -1272,13 +1320,13 @@ namespace PKHeX.WinForms.Controls
if (CB_ExtraBytes.Items.Count == 0) if (CB_ExtraBytes.Items.Count == 0)
return; return;
// Byte changed, need to refresh the Text box for the byte's value. // Byte changed, need to refresh the Text box for the byte's value.
TB_ExtraByte.Text = Entity.Data[Convert.ToInt32(CB_ExtraBytes.Text, 16)].ToString(); var offset = Convert.ToInt32(CB_ExtraBytes.Text, 16);
TB_ExtraByte.Text = Entity.Data[offset].ToString();
} }
private void UpdateNatureModification(ComboBox cb, int type) private void UpdateNatureModification(ComboBox cb, int nature)
{ {
// 0 = Nature, 1 = Stat Nature string text = Stats.UpdateNatureModification(nature);
string text = Stats.UpdateNatureModification((type == 0) ? Entity.Nature : Entity.StatNature);
NatureTip.SetToolTip(cb, text); NatureTip.SetToolTip(cb, text);
} }
@ -1532,7 +1580,7 @@ namespace PKHeX.WinForms.Controls
Tip3.SetToolTip(TB_PID, tip); Tip3.SetToolTip(TB_PID, tip);
} }
private void Update_ID(object sender, EventArgs e) private void Update_ID(object? sender, EventArgs e)
{ {
if (!FieldsLoaded) if (!FieldsLoaded)
return; return;
@ -1632,14 +1680,14 @@ namespace PKHeX.WinForms.Controls
if (Entity.Format <= 4) if (Entity.Format <= 4)
UpdateRandomPID(sender, e); UpdateRandomPID(sender, e);
Entity.Nature = WinFormsUtil.GetIndex(CB_Nature); Entity.Nature = WinFormsUtil.GetIndex(CB_Nature);
UpdateNatureModification(CB_Nature, 0); UpdateNatureModification(CB_Nature, Entity.Nature);
Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well
UpdateLegality(); UpdateLegality();
} }
else if (sender == CB_StatNature) else if (sender == CB_StatNature)
{ {
Entity.StatNature = WinFormsUtil.GetIndex(CB_StatNature); Entity.StatNature = WinFormsUtil.GetIndex(CB_StatNature);
UpdateNatureModification(CB_StatNature, 1); UpdateNatureModification(CB_StatNature, Entity.StatNature);
Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well Stats.UpdateIVs(sender, EventArgs.Empty); // updating Nature will trigger stats to update as well
UpdateLegality(); UpdateLegality();
} }
@ -1654,13 +1702,23 @@ namespace PKHeX.WinForms.Controls
if (!FieldsLoaded) if (!FieldsLoaded)
return; return;
ValidateComboBox((ComboBox)sender); var cb = (ComboBox) sender;
if (Moves.Contains(sender)) // Move ValidateComboBox(cb);
if (Moves.Contains(cb)) // Move
UpdatePP(sender, e); UpdatePP(sender, e);
// Legality // Legality -- set all moves back (why all?)
Entity.Moves = Moves.Select(WinFormsUtil.GetIndex).ToArray(); Entity.Move1 = WinFormsUtil.GetIndex(CB_Move1);
Entity.RelearnMoves = Relearn.Select(WinFormsUtil.GetIndex).ToArray(); Entity.Move2 = WinFormsUtil.GetIndex(CB_Move2);
Entity.Move3 = WinFormsUtil.GetIndex(CB_Move3);
Entity.Move4 = WinFormsUtil.GetIndex(CB_Move4);
if (Entity.Format >= 6)
{
Entity.RelearnMove1 = WinFormsUtil.GetIndex(CB_RelearnMove1);
Entity.RelearnMove2 = WinFormsUtil.GetIndex(CB_RelearnMove2);
Entity.RelearnMove3 = WinFormsUtil.GetIndex(CB_RelearnMove3);
Entity.RelearnMove4 = WinFormsUtil.GetIndex(CB_RelearnMove4);
}
UpdateLegality(skipMoveRepop: true); UpdateLegality(skipMoveRepop: true);
} }
@ -1672,7 +1730,7 @@ namespace PKHeX.WinForms.Controls
var (text, value) = (ComboItem)((ComboBox)sender).Items[e.Index]; var (text, value) = (ComboItem)((ComboBox)sender).Items[e.Index];
var valid = LegalMoveSource.CanLearn(value) && !HaX; var valid = LegalMoveSource.CanLearn(value) && !HaX;
var current = (e.State & DrawItemState.Selected) == DrawItemState.Selected; var current = (e.State & DrawItemState.Selected) != 0;
var brush = Draw.Brushes.GetBackground(valid, current); var brush = Draw.Brushes.GetBackground(valid, current);
var textColor = Draw.GetText(current); var textColor = Draw.GetText(current);

View file

@ -50,7 +50,7 @@ namespace PKHeX.WinForms
} }
else if (showChangelog) else if (showChangelog)
{ {
ShowAboutDialog(1); ShowAboutDialog(AboutPage.Changelog);
} }
if (BAKprompt && !Directory.Exists(BackupPath)) if (BAKprompt && !Directory.Exists(BackupPath))
@ -355,9 +355,9 @@ namespace PKHeX.WinForms
Close(); Close();
} }
private void MainMenuAbout(object sender, EventArgs e) => ShowAboutDialog(0); private void MainMenuAbout(object sender, EventArgs e) => ShowAboutDialog(AboutPage.Shortcuts);
private static void ShowAboutDialog(int index = 0) private static void ShowAboutDialog(AboutPage index)
{ {
using var form = new About(index); using var form = new About(index);
form.ShowDialog(); form.ShowDialog();
@ -409,14 +409,13 @@ namespace PKHeX.WinForms
private static void ClosePopups() private static void ClosePopups()
{ {
var forms = Application.OpenForms.OfType<Form>() var forms = Application.OpenForms.OfType<Form>().Where(IsPopupFormType).ToArray();
.Where(z => z is not (Main or SplashScreen or SAV_FolderList))
.ToArray();
foreach (var f in forms) foreach (var f in forms)
f.Close(); f.Close();
} }
private static bool IsPopupFormType(Form z) => z is not (Main or SplashScreen or SAV_FolderList);
private void MainMenuSettings(object sender, EventArgs e) private void MainMenuSettings(object sender, EventArgs e)
{ {
var settings = Settings; var settings = Settings;
@ -687,7 +686,8 @@ namespace PKHeX.WinForms
private bool OpenPCBoxBin(IEnumerable<byte[]> pkms) private bool OpenPCBoxBin(IEnumerable<byte[]> pkms)
{ {
if (!C_SAV.OpenPCBoxBin(pkms.SelectMany(z => z).ToArray(), out string c)) var data = pkms.SelectMany(z => z).ToArray();
if (!C_SAV.OpenPCBoxBin(data, out string c))
{ {
WinFormsUtil.Alert(MsgFileLoadIncompatible, c); WinFormsUtil.Alert(MsgFileLoadIncompatible, c);
return true; return true;
@ -702,16 +702,21 @@ namespace PKHeX.WinForms
if (memCard.SaveGameCount == 1) if (memCard.SaveGameCount == 1)
return memCard.SelectedGameVersion; return memCard.SelectedGameVersion;
var games = new List<ComboItem>(); var games = GetMemoryCardGameSelectionList(memCard);
if (memCard.HasCOLO) games.Add(new ComboItem(MsgGameColosseum, (int)GameVersion.COLO));
if (memCard.HasXD) games.Add(new ComboItem(MsgGameXD, (int)GameVersion.XD));
if (memCard.HasRSBOX) games.Add(new ComboItem(MsgGameRSBOX, (int)GameVersion.RSBOX));
var dialog = new SAV_GameSelect(games, MsgFileLoadSaveMultiple, MsgFileLoadSaveSelectGame); var dialog = new SAV_GameSelect(games, MsgFileLoadSaveMultiple, MsgFileLoadSaveSelectGame);
dialog.ShowDialog(); dialog.ShowDialog();
return dialog.Result; return dialog.Result;
} }
private static List<ComboItem> GetMemoryCardGameSelectionList(SAV3GCMemoryCard memCard)
{
var games = new List<ComboItem>();
if (memCard.HasCOLO) games.Add(new ComboItem(MsgGameColosseum, (int) GameVersion.COLO));
if (memCard.HasXD) games.Add(new ComboItem(MsgGameXD, (int) GameVersion.XD));
if (memCard.HasRSBOX) games.Add(new ComboItem(MsgGameRSBOX, (int) GameVersion.RSBOX));
return games;
}
private static bool CheckGCMemoryCard(SAV3GCMemoryCard memCard, string path) private static bool CheckGCMemoryCard(SAV3GCMemoryCard memCard, string path)
{ {
var state = memCard.GetMemoryCardState(); var state = memCard.GetMemoryCardState();
@ -728,7 +733,7 @@ namespace PKHeX.WinForms
return false; return false;
case GCMemoryCardState.MultipleSaveGame: case GCMemoryCardState.MultipleSaveGame:
GameVersion game = SelectMemoryCardSaveGame(memCard); var game = SelectMemoryCardSaveGame(memCard);
if (game == GameVersion.Invalid) //Cancel if (game == GameVersion.Invalid) //Cancel
return false; return false;
memCard.SelectSaveGame(game); memCard.SelectSaveGame(game);
@ -803,7 +808,6 @@ namespace PKHeX.WinForms
private void ResetSAVPKMEditors(SaveFile sav) private void ResetSAVPKMEditors(SaveFile sav)
{ {
bool WindowToggleRequired = C_SAV.SAV.Generation < 3 && sav.Generation >= 3; // version combobox refresh hack
C_SAV.SetEditEnvironment(new SaveDataEditor<PictureBox>(sav, PKME_Tabs)); C_SAV.SetEditEnvironment(new SaveDataEditor<PictureBox>(sav, PKME_Tabs));
var pk = sav.LoadTemplate(TemplatePath); var pk = sav.LoadTemplate(TemplatePath);
@ -826,7 +830,7 @@ namespace PKHeX.WinForms
} }
// Initialize Overall Info // Initialize Overall Info
Menu_LoadBoxes.Enabled = Menu_DumpBoxes.Enabled = Menu_DumpBox.Enabled = Menu_Report.Enabled = C_SAV.SAV!.HasBox; Menu_LoadBoxes.Enabled = Menu_DumpBoxes.Enabled = Menu_DumpBox.Enabled = Menu_Report.Enabled = C_SAV.SAV.HasBox;
// Initialize Subviews // Initialize Subviews
bool WindowTranslationRequired = false; bool WindowTranslationRequired = false;
@ -836,11 +840,10 @@ namespace PKHeX.WinForms
WinFormsUtil.TranslateInterface(this, CurrentLanguage); WinFormsUtil.TranslateInterface(this, CurrentLanguage);
PKME_Tabs.PopulateFields(pk); PKME_Tabs.PopulateFields(pk);
if (WindowToggleRequired) // Version combobox selectedvalue needs a little help, only updates once it is visible
PKME_Tabs.FlickerInterface(); sav.State.Edited = false;
foreach (var p in Plugins) foreach (var p in Plugins)
p.NotifySaveLoaded(); p.NotifySaveLoaded();
sav.State.Edited = false;
} }
private static string GetProgramTitle() private static string GetProgramTitle()

View file

@ -42,12 +42,12 @@
// L_Thanks // L_Thanks
// //
this.L_Thanks.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.L_Thanks.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.L_Thanks.AutoSize = true;
this.L_Thanks.Location = new System.Drawing.Point(265, 4); this.L_Thanks.Location = new System.Drawing.Point(265, 4);
this.L_Thanks.Name = "L_Thanks"; this.L_Thanks.Name = "L_Thanks";
this.L_Thanks.Size = new System.Drawing.Size(147, 13); this.L_Thanks.Size = new System.Drawing.Size(225, 13);
this.L_Thanks.TabIndex = 2; this.L_Thanks.TabIndex = 2;
this.L_Thanks.Text = "Thanks to all the researchers!"; this.L_Thanks.Text = "Thanks to all the researchers!";
this.L_Thanks.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
// //
// TC_About // TC_About
// //
@ -122,7 +122,6 @@
this.Tab_Shortcuts.ResumeLayout(false); this.Tab_Shortcuts.ResumeLayout(false);
this.Tab_Changelog.ResumeLayout(false); this.Tab_Changelog.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout();
} }

View file

@ -4,13 +4,19 @@ namespace PKHeX.WinForms
{ {
public partial class About : Form public partial class About : Form
{ {
public About(int index = 0) public About(AboutPage index = AboutPage.Changelog)
{ {
InitializeComponent(); InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
RTB_Changelog.Text = Properties.Resources.changelog; RTB_Changelog.Text = Properties.Resources.changelog;
RTB_Shortcuts.Text = Properties.Resources.shortcuts; RTB_Shortcuts.Text = Properties.Resources.shortcuts;
TC_About.SelectedIndex = index; TC_About.SelectedIndex = (int)index;
} }
} }
public enum AboutPage
{
Shortcuts,
Changelog,
}
} }