There are 4 tables related to the pokedex that I'm adding here:
* regional dex: for each pokemon, what is its regional dex index
* national dex: for each pokemon, what is its national dex index
* conversion: for each regional dex entry, what index is it in the national dex (can be computed automatically, so I added a QuickEdit item)
* dex info, such as the dex description
I also updated App.xaml and MainWindow.xaml.cs to make the QuickEditItems look better.
* table format feature: allow for recursive table definitions, simply because it's shorter.
* include expected locations of pointers to the Evolution table
* unit tests to show that we found the evolution table correctly
* model bugfix: when specifying to keep pointers, don't clear them during unusual loading situations
* model bugfix: when adding a format to a pointer in a table, if that location is already a table, give up and leave the table there.
The first move has no move description. So the move desciptions table should be the same length as the move names table, minus one. Added support for this kind of concept.
Previously, right-clicking on an actual anchor would let you clear the format of the anchor but keep the anchor, while right-clicking on the format without the anchor would let you clear both the anchor and the format. Not only is this backwards, but it's inconsistent.
Now, a much simpler system: if you use the right-click to clear the format, the app assumes that the entire anchor was in error, so the anchor and any pointers to it are all cleared, but no data is changed.
- Whenever I RefreshBackingData, do a lazy load of the view: don't load any cells until those cells are asked for.
- When cell (0,0) is requested, go ahead and load everything in an efficient manner, only getting each Run object once.
- Throughout ViewPort, always use this[x,y] to get a cell, since that will do the lazy-load.
when a character is matched, only check the string _after_ the current character for future characters. this makes searching for "mm" correctly filter out any words with only a single 'm'.
This also requires that the FieldArrayElementViewModel be able to ask the ViewPort to raise messages... which of course requires the FieldArrayElementViewModel to have access to the ViewPort.
old version:
Search linearly through all runs for any that are `ArrayRun`s
new version:
Search linearly through all anchors for any that are `ArrayRun`s
Getting a run from an anchor is O(log(n)), so this should be much faster when the number of runs is large.
Reuse existing ViewModels in the table where possible, as keeping the same DataContext and just changing a few properties massively speeds up the table tool layout.
Bug: when changing the struct type from "custom moves" to "custom moves & items", the first move got turned into an item. The test captures that bug, the code change fixes it.
Also, refresh the hex view when a change is made that could cause the table to update other rows automatically.
Also, when writing data, write IVs, Level, then Pokemon instead of Level, Pokemon, IVs.
- if the user changes the struct type, the pokemon team updates automatically, potentially adding default moves to the pokemon. This works both with inline hex updates and with tool changes. Other trainers that use the same team are also updated.
- if the user changes the pokemonCount, the pokemon team updates automatically. This works both with inline hex updates and with tool changes. Other trainers that use the same team are also updated.
- if the user updates the child run using the stream, the parent(s) change their struct type / pokemonCount to match.
- if the user updates the child run by using the table tool or changing the inline hex, the parent(s) update to match.
Passes all unit tests, but hasn't been hand-tested yet for edge cases.
In many fangames, the game contains an error where a pointer in a table points to something unexpected.
* I need to allow the pointer, because the table format requires that it be a pointer, and that's how the game reads it.
* I need to allow the destination to not be an anchor, because the destination may be being used for something else.
To make sure I'm handling this correctly for a wide variety of cases, I added `BasicLoadTests.CanLoad` for a wide variety of romhacks.
Also related, I added another section to `PokemonModel.ResolveConflicts` that validates pointers within tables, instead of only pointerruns.
For lists where multiple elements have the same text (example, the multiple 'picnicker' trainerclassname entries), loading the item with the table tool always selects the first element with that text in the combobox, even if that's not the index that was bound to. This is a binding issue.
To fix it, the ViewModel uses a slightly more complex data-type that wraps the string. The two options are now seen as different unequal objects, so no coercion happens.
The hex content normally jumps to a table when you select the table with the table tool. However, it doesn't jump if the table is already selected. The user experienced confusion, wanting to jump to the start of the table using the table drop-down, but they couldn't because they were already looking at that table.
despite adding the warning into the table, the next user still made the same mistake: they edited the existing pointer data in the table, which also edited other instances that pointed to that data. Hopefully doing this odd coloring will make it more clear.
- When the text being deserialized is bad, don't return a level of zero: just skip that line.
- When shrinking a PLMRun, clear out all extra bytes up to the original length. This is important in case the user removes multiple moves at once.
At some point, I'm going to implement what happens when you switch a pokemon from auto-moves to manual moves. When I do that, I need a reasonable default move list to assign to the pokemon as I'm swapping out the data type. Might as well write the default-move logic now.
When using a tool to edit the egg moves, only change the cells that are actually changing.
When using a tool to edit a bit array, only change the cells that are actually changing.
This makes the edit easier to see for the user.
change tracking was previously done in the model, but exposed in the ViewModel via a data format. The problem with this is that it meant that all changed formats were wrapped in a new format, which would require a lot of work to fully validate.
The new implementation is still in the model, but exposed in the ViewModel through a new property on the HexElement. The data formats are unchanged.
in some cases, auto-moving runs and then updating the selection was really slow. For example, updating pokenames (and related tables). This was due to a bug where the scroll value was being updated incorrectly, resulting in excessive horizontal panning to align the data.
As useful as this bug was, it's preventing people from noticing the panel on the left. As the editor grows, this panel will become more useful. I'm going to remove the bug, so that the tool panel no longer auto-opens. This requires more work from the user, but that work causes them to discover the panels existence (hopefully).
There are times where the table tool doesn't make sense but the text tool does, and vice-versa. In such situations, automatically switch from whichever of those tools is open to the other one.
Note that this will not automatically open a tool when none are open, nor will it mess with the code tool, nor will it change the tool in situations where both are applicable (such as the text portion of a table, or a run that is both a table and a stream). But it should reduce confusion and clicks in many common situations.