include the idea of escape characters, so we can type the anchor character, type spaces (or not if it's the start of the run), and type the escape character \ itself.
When showing a sprite in the table tool, we check to see what table index it is so we can use that index to find the palette. We need to do the same thing with tilesets. This means that GetPixels() needs a new parameter, the tableIndex, which can be passed in from any context that cares about it. Most of the time, getting the pixels doesn't care what the table index is. But now tilemaps can use this to figure out which tileset to use.
If a sprite uses the same color for both the transparent slot and another slot and HMA intends to render the first color as transparent, HMA will now adjust the color in the transparent color so that it knows which pixels to make transparent and which pixels to keep.
Visibility mode changes the coloring of bytes to help certain bytes stick out more clearly. Previously, it only worked with a single byte. Now it's been more fully integrated into the model, and can work with any number of bytes. Note that it only cares about bytes that are on screen, so it won't find byte chunks where part of the chunk is off screen.
* When exactly an entire run is selected, treat backspace like delete: just clear the whole thing.
* When running DataClear on an LzCompressed token, set it to FFFF, not FF.
* When doing backspace on any DataFormatInstance, use ConvertCellToText to control how the element gets edited.
* Change various LZ formats so that they use DataFormatInstance.
During paste operations, we don't actually need autocomplete. It's important to keep the options in mind, but we can delay evaluation until they're actually used.
Change autocomplete related methods to return lazy IEnumerable objects instead of returning a pre-populated read-only list. Add a LazyList<T> class that can handle the once-time evaluation logic. If no element of the list is ever checked, then the auto-complete code never runs.
Change ViewPort's UpdateToolsFromSelection tha happens when the selection changes. Only evaluate it after the edit operation is complete.
* Allow pasting tuple elements with spaces
* Improve how tuples treat leading space / +
* Allow typing [] to truncate a tuple run
* Include a [] at the end of a stream during deep copy
Initialization happens on a background thread. We want to be able to run commands when initialization is complete. The way this was done before wasn't very thread safe. The new version will always run the command.
* If initialization is complete, it runs the command right away.
* If initialization is not complete, it defers execution until initialization is done.
* Initialization is measured in scopes. An inner scope will not run initialization work when it's done, since there's still more initialization work that needs to be completed.
* Things like "goto" will now defer execution until initialization is complete. For most users, this won't matter. For speed users, it means that goto will now work the way they expect.
Streams now have the ability to express a "visualization" of the stream, which is a list of PixelViewModels. The table tool will display those in the background of the textbox, over to the right.
SpriteDecorator wraps other formats, providing the extra behavior of having a sprite background. This can be used to draw a sprite behind a single cell or behind a group of cells.
To get the z-ordering right, the info from SpriteDecorator is read during a new RenderBackground method, which happens before RenderData.
Change the paradigm: instead of saying "final write + offset = destination", say "destination + offset = final write". This means that you can write things like <data.moves.stats.battle+4>, which will resolve in bytes to the pointer + 4, while resolving as a pointer to the move stats.
when rendering a sprite, include an offset for which page of the sprite is being rendered. For a multi-page sprite with single page palettes or single-page sprites with multi-page palettes, this changes nothing. But for a multi-page sprite with multiple palettes, this allows the pages to correlate 1-to-1 as expected.
This test was failing (intentionally) in the previous version. Added logic to read the modified run after a data change via ViewPort interaction, and calculate the next compressed length. The code should also handle repointing in the case of extension, but that's not tested yet. It does, however, clear unused bytes to `FF` if the new compressed length is shorter.
I also separated the idea of a IDataFormatInstance from a IDataFormatStreamInstance.
* a `IDataFormatInstance` represents a single format that is multiple cells long. The entire format should be selected at once. Examples include a level-up token (2 cells) or a pointer token (4 cells).
* a `IDataFormatStreamInstance` represents a single-cell format that is part of a 'stream' that is multiple cells long. The format includes a reference to the start of the stream and the data format's index within the stream for the Text Tool. Examples include ASCII and PCS data. The user can freely type to edit the stream, but each format is only a single-cell long.
This isn't actually used yet, but the separation of the concepts should allow me to simplify ViewPort cell selection group logic in the future.
LZData isn't too complex, but it does involve many types of tokens, and thus many formats.
(1) the magic 1-byte header
(2) the 2-byte compressed token
(3) the 1-byte uncompressed token. This is really just raw data, but isn't the same as `None` because it can't be freely converted to a pointer or a length-token and shouldn't have the "this is text" right-click menu items
(4) the 1-byte section header. This is also similar to raw data, but we probably want to display it in a different color to make it obvious that it's a section header and not just an uncompressed byte.
Adding this new data format required that we define its behaviors for lots of things. For now, we'll assume that the only valid thing the user can do with an end token is to extend the table.
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.
WordRuns, like PointerRuns, can live anywhere in the file and don't require anchors to them. Instead of needing an anchor to them, they specify the name of a table that they are matched to. Whenever that table's length changes, the WordRun's value is automatically updated to match the table length.
The Egg Move stream has 2 types of data in it, each of which is 2 bytes long. Either it's a pokemon, or it's a move. (There's also the end, FF FF). This is the initial test to show that we can read an egg move stream from a format.