Player icon indicating copy to clipboard operation
Player copied to clipboard

Maniacs text rendering smaller updates

Open jetrotal opened this issue 2 months ago • 2 comments

Support For some missing maniacs text rendering tags:

  • more colors: colors limit can go beyond \c[19]
  • index mode for exFont icons: $[n] or $[\v[n]]
  • array tags for both color and exfont: you can pick up with tags such as \c[x,y] or $[x,y]
image
//TPC SYNTAX:
v[1] = 31
@msg.show "\c[19]AAA\c[\v[1]]AAA\c[3,3]AAA 
$a $[A] $[1] $[\v[1]] $[1,4]
"
System exfont

I noticed some duplicated code when formating strings in game_message and game_windows... But I won't mess with those, because every time I propose structural changes my PR goes to limbo to never be aproved.

jetrotal avatar Oct 10 '25 23:10 jetrotal

Thanks. Could you document e.g. inside this PR how the parsing of invalid data behaves?

Such as \c[3, 100], \c[3,a], \c[3, a], \c[3, 0003]. $?, $[], $[a], $[3 and whatever you can come up with ;).

Ghabry avatar Oct 12 '25 14:10 Ghabry

Analysis of Color Command \C[...]

This command is handled by Window_Message::UpdateMessage. When the Maniacs patch is active, it uses ParseArray.

Input String How It's Parsed (ParseArray) Resulting text_color Index Visual Output
\C[3] values={3}, is_array=false 3 Text becomes color #3.
\C[3,1] values={3, 1}, is_array=true 1 * 10 + 3 = 13 Text becomes color #13.
\C[3, 100] values={3, 100}, is_array=true 100 * 10 + 3 = 1003 Out of Bounds. The renderer will try to read from an invalid area of the System graphic. This results in a black, transparent, or garbage-colored pixel being used as the text color.
\C[3,a] parse_one_number for y reads nothing, gets 0. Returns values={3, 0}, is_array=true. 0 * 10 + 3 = 3 The text becomes color #3. The a and everything after it until the ] is ignored for that parameter.
\C[3, a] parse_one_number for y encounters a space, stops, and returns 0. Returns values={3, 0}, is_array=true. 0 * 10 + 3 = 3 The text becomes color #3. The spaces and the a are ignored.
\C[3, 0003] parse_one_number handles leading zeros correctly. Parsed as values={3, 3}, is_array=true. 3 * 10 + 3 = 33 The text becomes color #33 (valid only with Maniacs). Without the patch, it would be clamped to 0.
\C[3 ParseArray never finds the closing ]. It reads to the end of the string. The command is considered malformed (dialog skips itself) for some reason the dialog skips to the next comment right after hitting '3'
\C[] ParseArray returns values={}. The if (!pres.values.empty()) check fails. (no change) The text color does not change.
\C[3,] ParseArray returns values={3, 0}, is_array=true. 0 * 10 + 3 = 3 The text becomes color #3.

Analysis of ExFont Command $[...]

This command is handled by Utils::ExFontNext. It has more complex internal logic.

Input String How It's Parsed (ExFontNext) Renderer Action Visual Output
$? The character after $ is not [ or an alphabet character. The parser fails. The $ is treated as a literal character, and ? is parsed next. The literal text $? is printed.
$[ ] ParseArray is called on [ ]. It finds no numbers and returns an empty values vector. The if conditions in ExFontNext fail. The parser fails to identify a valid ExFont command. The literal text $[ ] is printed.
$a Standard (non-Maniacs) syntax. The parser returns the character code for 'a'. The renderer looks up the 'a' icon (index 0) and draws it. Icon 'a' (top-left icon).
$[a] Maniacs AZ Mode. The parser finds [a], identifies the single letter, and returns the character code for 'a'. The renderer looks up the 'a' icon (index 0) and draws it. Icon 'a' (top-left icon).
$[1] Maniacs Index Mode. ParseArray returns values={1}, is_array=false. The parser calculates coordinates x=1, y=0. The renderer receives (x=1, y=0) and draws the icon at that grid position. Icon 'b' (the second icon on the first row).
$[4,1] Maniacs XY Mode. ParseArray returns values={4, 1}, is_array=true. The renderer receives (x=4, y=1) and draws the icon at that grid position. The icon at the 5th column, 2nd row.
$[1000] Maniacs Index Mode. ParseArray returns values={1000}. Parser calculates x = 1000 % 13 = 12, y = 1000 / 13 = 76. The renderer receives (x=12, y=76). ExFont::vRender then performs a bounds check against the ExFont sheet's dimensions. Since y=76 is far beyond the typical height, this check fails. A blank space the size of one icon.
$[1,a] ParseArray on the second argument (a) returns 0. Parsed as $[1,0]. The renderer receives (x=1, y=0). Icon 'b'. The ,a part is effectively ignored and treated as ,0.
$[3 ExFontNext finds [ but never finds the closing ]. It fails to match any bracketed syntax. It also fails the standard $A-Z check. The parser fails completely. The literal text $[3 is printed.
$[\V[1]] Maniacs Index Mode with a variable. ParseArray's internal helper resolves \V[1]. If Variable #1 contains 27, it's parsed as $[27]. The parser calculates coordinates for index 27 (x=1, y=2). The renderer draws the icon at that position. The icon corresponding to index 27.

syntax used:

@sys.skin "System" .stretch .gothic
@comment "--- Color Command Tests (\\C) ---"
@comment "These tests assume the Maniacs patch is enabled."
@msg.show "\c[0]First, some valid examples."
@msg.show "This is default color \c[0]0."
@msg.show "This is standard color \c[2]2."
@msg.show "This is a Maniacs patch extended color \c[25]25."
@msg.show "\c[0]This uses XY coordinates: \c[3,1](3,1)."
@comment "---"
@comment "Now testing with variables."
v[500] = 13
@msg.show "Color is from V[500]: \c[\v[500]]Hello!"
v[500] = 5
v[501] = 1
@msg.show "Color from XY V[500],V[501]: \c[\v[500],\v[501]]Hello!"
@comment "---"
@comment "Now for problematic and invalid examples."
@comment "The parser should treat non-numeric parts as 0."
@msg.show "\c[3,a] becomes \c[3,0]Color 3."
@msg.show "\c[3,    a] spaces are ignored, also \c[3,0]Color 3."
@comment "---"
@comment "The parser should handle leading zeros correctly."
@msg.show "\c[3,0003] becomes \c[3,3]Color 33."
@comment "---"
@comment "Out of bounds values result in garbage/black colors."
@msg.show "\c[3,100] is color 1003 (out of bounds)."
@msg.show "\c[9999999999] will likely overflow."
@comment "---"
@comment "Malformed syntax is rendered as literal text."
@msg.show "Unterminated bracket: \c[3"
@msg.show "Empty bracket: \c[]No color change."
@msg.show "Trailing comma: \c[3,]becomes \c[3,0]Color 3."
@comment " "
@comment "--- ExFont Icon Tests ($) ---"
@comment "These tests assume the Maniacs patch is enabled."
@comment "And that you have a valid ExFont.png file."
@msg.show "Standard: $A, Maniacs AZ: $[A]"
@comment "Icon at index 1 is 'B'"
@msg.show "Maniacs Index: $[1]"
@comment "Icon at X=4, Y=1"
@msg.show "Maniacs XY: $[4,1]"
@comment "---"
@comment "Now testing with variables."
v[500] = 2
@msg.show "Icon index from V[500]: $[\v[500]]"
v[500] = 2
v[501] = 2
@msg.show "Icon XY from variables: $[\v[500],\v[501]]"
@comment "---"
@comment "Now for problematic and invalid examples."
@comment "Invalid char after '$' is rendered literally."
@msg.show "Invalid syntax: $?"
@comment "---"
@comment "The parser treats non-numeric parts as 0."
@msg.show "$[1,a] should become $[1,0]"
@comment "---"
@comment "Out of bounds coordinates will result in a blank icon."
@msg.show "Out of bounds index: $[1000]"
@msg.show "Out of bounds XY: $[1,1000]"
@comment "---"
@comment "Malformed syntax is rendered as literal text."
@msg.show "Unterminated bracket: $[3"
@msg.show "Empty bracket: $[ ]"
@comment " "
@comment "--- End of Tests ---"
@msg.show "All tests complete."

jetrotal avatar Oct 12 '25 16:10 jetrotal

@jetrotal I reworked some of the code. Can you test if it still works? At least the unit tests say that it should :sweat_smile: (it was mostly fine, removed some code duplication and got rid of this XY_FLAG)

Ghabry avatar Dec 14 '25 14:12 Ghabry