Commit Graph
100 Commits
Author SHA1 Message Date
Dav999 7404ea6178 Fix SDL_PLATFORM_UNI defines
Just did my first SDL3 compile and noticed the console messages didn't
have any color anymore... Because that was conditional to
SDL_PLATFORM_UNI. I saw this during the SDL3 PR and found it odd, but
it's on https://wiki.libsdl.org/SDL3/README-migration#sdl_platformh.
It turns out it actually doesn't exist, it's supposed to be
SDL_PLATFORM_UNIX.
2026-08-23 10:51:31 -04:00
Dav999 85dae94d2e Avoid compiler warning about signedness mismatch
This warning kept appearing for me:

Script.cpp:350:35: warning: comparison of integer expressions of
different signedness: ‘int’ and
‘std::__cxx11::basic_string<char>::size_type’
{aka ‘long unsigned int’} [-Wsign-compare]

  350 |                 for (int i = 0; i < words[1].size(); i++)
      |                                 ~~^~~~~~~~~~~~~~~~~

So I just made it a size_t instead.
2026-05-14 06:10:52 -04:00
Dav999 08aa7c9087 Remove nuisance Vorbis errors on blank music slots
When vvvvvvmusic.vvv files contain blank slots before the last valid
song, the following error message would be output for all of them:

[ERROR] Unable to create Vorbis handle, error 30

Now, this is very common: many levels, for example, ship a music file
where songs start at slot 16, or alternatively they used slots 0-15 but
didn't need every slot. Or IDs are skipped so that certain songs are
on their own page in the music editor. Either way, I've seen bursts of
this message appear in my console a lot when loading levels lol, so it
became time this was silenced by not bothering to load a <=1 byte song,
and giving a (silenced by default) debug message in that case instead.

(It checks for <= 1 byte, because in all these cases, the empty slots
have a single null byte in them. I looked up why that is again, and it
is because, in 2019, "Rumor goes that 0-byte tracks actually mess
things up in VVVVVV". We could probably verify if that's the case now,
but music files have been made this way for ages, and it's pretty clear
a 1-byte song is not usable.)
2026-05-14 06:10:52 -04:00
Dav999 65b024a9a3 Fix vertical position of Comms Relay textbox
Fixes #1242.

Turns out it was a really simple fix - the X positions were good, but
the Y positions were always at the top of the screen regardless of the
height of the textbox. Now they're vertically centered respective to
the speaker.
2025-06-15 21:15:00 -04:00
Dav999 d53861553e Update SheenBidi to 2.9.0
This fixes our problem with Valgrind reporting a jump based on an
uninitialized value; see https://github.com/Tehreer/SheenBidi/issues/19

Just to be sure nothing unexpected happens, I tested that this doesn't
cause any changes in behavior by outputting bidi-transformed versions
of all strings in strings.xml to a file for both our Arabic and Persian
localizations before and after the update, and confirming that the
files are the same.
2025-06-11 15:27:45 -04:00
Dav999 7dccc2d328 Apply translations for 2.5 strings
This includes translations for checkpoint saving and enemy speed in the
editor.
2025-06-08 17:05:32 -04:00
Dav999 26d27c7df5 Apply translations for 2.4 strings
This includes translations that were missing translations, with varying
extent between different languages, for the following things:
- "X mode is enabled" in-game warnings
- "Press {button} to freeze/unfreeze gameplay" for the level debugger
- Some credits strings for the post-2.4.0 extra Spanish options, the
  PT_BR proofread, and Persian
- The recent gamepad menu changes (#1229)

Furthermore:
- "TAB" (used in the level debugger string) is now a separate string
  instead of being hardcoded, because some languages needed it
  translated
- Added missing arrows to Arabic/Persian font (needed for the gamepad
  menu, and also a translator menu actually)
2025-06-08 17:05:32 -04:00
Dav999 1de2078014 Sync new gamepad strings into all language files
Also including all the localizations I already have right now.
2025-05-03 01:35:25 -04:00
Dav999 37b788c1c8 Add check for converting negative SDL_GameControllerButton to glyph
A SDL_GameControllerButton below 0 is out of array bounds, so that
should trip the assert and return GLYPH_UNKNOWN just like when the
value is too high.
2025-05-03 01:35:25 -04:00
Dav999 d730528118 Add confirmation and removal to bindings menu
This makes the following improvements to the gamepad bindings menu:

- The menu now shows a hint that you can press a button while any of
  the bind options are selected (or that you can navigate away from
  those options)
- Instead of button presses immediately setting a binding, they now
  ask for confirmation: press the same button a second time to confirm
- You can now remove a binding, the same way you add it (this has the
  same type of confirmation)
- This menu used to be inconsistent with pretty much every other menu
  in the game by showing a permanent title and description for the menu
  itself ("Game Pad", "Change controller options.") rather than showing
  a title and description for the currently selected option.
  This inconsistency is now fixed.
2025-05-03 01:35:25 -04:00
Dav999 75035047ad Update name of Arabic/Persian font
The level font menu now shows both names, since the font is used for
both Arabic and Persian.
2025-05-02 22:31:29 -04:00
Dav999 1a1bf2a4f9 Add new strings for Persian
New strings were delivered already today, so let's add them immediately
in this PR so we have a little less on our checklist later!
2025-05-02 22:31:29 -04:00
Dav999 48c3e175a3 Fix save summary sometimes getting misordered in Arabic
The Persian localizers noticed an issue where the translation for
"Dimension VVVVVV, 12:34:56" would become "VVVVVV, 12:34:56 noisnemiD",
rather than "12:34:56 ,VVVVVV noisnemiD" as expected. This was fixed
for Persian but the same issue also affected Arabic, so I added a
RIGHT-TO-LEFT MARK (U+200F) to fix it there as well.
2025-05-02 22:31:29 -04:00
Dav999 374ce11425 Sync language files
This adds "Persian" to all the languages, and brings the Persian files
up-to-date (mainly removing outdated strings and adding some late 2.4
stuff that we'll contact all translators for soon)
2025-05-02 22:31:29 -04:00
Dav999 0b00415ab3 Add Persian to credits screen 2025-05-02 22:31:29 -04:00
Dav999 3eb88e0ac0 Add files for Persian localization
A bit overdue since this was delivered a few weeks ago (oops),
but here it is!

Thanks to Amir Arzani and Masoud Varaste.
2025-05-02 22:31:29 -04:00
Dav999 343790f12b Change name of Silesian option (part 2)
Turns out there was a little miscommunication with the translator -
they said the option needed to say "Ślōnsko" but were only talking
about correcting the first word, where I thought the whole thing needed
to be replaced.
2025-02-18 09:51:40 -05:00
Dav999 e318df24bc Change name of Silesian option by request of translator
Our Silesian translator asked for "Ślonsko godka" to be changed to
"Ślōnsko".
2025-02-05 11:05:01 -05:00
Dav999 d709db4b45 Fix squeak and save spam in gamepad menu
If you push a button to set a controller binding, you may either hear
one Viridian squeak, two Viridian squeaks (a louder one), or Viridian
doesn't stop squeaking until you let go of the button. While you hear
the continuous squeaking, your save file is also repeatedly saved.

There are two small bugs at play here:
- the squeak is actually played in two different places at the same
  time (both in titleinput() whenever a button is pressed, and in
  updatebuttonmappings() when a mapping is succesfully changed)
- titleinput() doesn't register that a button is held down and applies
  the button (and saves to file) every frame for as long as the button
  is held

This commit fixes both these issues. Now a single button press always
causes one squeak, and only if the bindings actually changed. Your save
file is also no longer saved repeatedly from holding down the button.
2024-12-22 15:53:04 -05:00
Dav999 149f5fbebc Tweak IME selection background left bound
Just extending the selection background left by one pixel so there's
not one pixel of black background to the left of a selection that
starts at the beginning of the text, and so some characters being
selected show up better (particularly where there's a long vertical bar
at the first pixel). We shouldn't be overlapping any part of the
previous character, since every character normally has a pixel of
spacing on the right.
2024-08-06 18:16:46 -07:00
Dav999 9ec8d8b637 Add selection background to IME rendering
Decided to implement it anyway since the broken behavior (selection
length always being 0, at least on Windows) may get fixed later in SDL,
so let's do it right in one go.
2024-08-02 22:25:00 -07:00
Dav999 8b8f827b70 Add IME text rendering
This shows the uncommitted text in a box in the bottom left corner.
This doesn't show the selection (defined by the start and length fields
in the event) yet, but this is already much better than it was on its
own, and I don't know how urgent the selection is since it's broken on
Windows anyway.
2024-08-02 22:25:00 -07:00
Dav999 a9ca63b367 Add buffer for IME editing events
When inputting uncommitted text from an IME, this is now stored in a
std::string imebuffer, just like keybuffer. It also enables extended
editing events, so text longer than what fits in the standard editing
event is also supported. This commit does not yet display the text
onscreen.
2024-08-02 22:25:00 -07:00
Dav999 6df7d5df8a Fix font::print_wrap() name in README-programmers
lang/README-programmers.txt accidentally lists the name of the
font::print function twice, when the second one should've been
font::print_wrap instead. Oops.

[skip ci]
2024-06-28 08:03:55 -07:00
Dav999 a9d438968d Change reply scripting command to player color
This is just a small visual fix to an inconsistency with textbox
colors in simplified scripting. The `reply` command is meant to be
used for the player, and always correctly positions it above the
player, while the `say` command may be used to generate a cyan textbox
that's positioned above a cyan non-player crewmate. However, the color
for both textboxes is always `cyan`, so the `reply` command doesn't use
the (normally identical) `player` color even though all its other
behavior (squeak, position) does. Now that customized textbox colors
were added in 2.4 (#910), it's a shame that this distinction isn't
made between `cyan` and `player`, so this change addresses that (before
we're stuck with levels that change `cyan` but not `player`).
2024-03-29 19:47:46 -07:00
Dav999 99a1562d87 Only re-show language screen in default basedir
After some discussion about the previous commit, the usecase of
managing tons of basedirs and locking files in the filesystem might
mean it gets annoying to have the language screen show up again
whenever a new language is added, for a small group of people. The
solution to get the best of both worlds is to only re-ask for the
language in the default basedir. This means barely anyone will miss
their language having been newly added (especially since barely anyone
will use any custom basedirs, let alone ONLY custom ones).
2024-02-08 10:28:27 -08:00
Dav999 fbc3bd4d5a Make language screen show up once more
Now that two new variants of Spanish have been added, it would be
a shame that many players from Latin-America/Argentina may stay on
Castilian or English because they don't realize the new versions
were added for them. So now, if you've set your language in 2.4.0,
the language screen will show up once more in 2.4.1. This is done by
simply incrementing the lang_set flag to 2 - so that if it's 0 or 1,
your language setting is considered to be possibly outdated.

This shouldn't inconvenience players who don't need to select a new
language - their existing language will still be pre-selected, so they
can just hit ACTION once.

Terry confirms he did the same thing with Dicey Dungeons and says
it's a good idea (and that nobody minds).
2024-02-08 10:28:27 -08:00
Dav999 929aaebc84 Align stability generator in es_419 and es_AR 2024-02-05 18:03:08 -08:00
Dav999 d6ec4ae72a Change LATAM Spanish meta.xml Oprime to Pulsa
All of them were changed except for the one in meta.xml. I think it's
safe to assume this is correct, because everywhere else, the same
"Oprime {button} para" pattern always became "Pulsa {button} para" too.
2024-02-05 18:03:08 -08:00
Dav999 139612b319 Fix placeholders in Arabic strings_plural
For some reason all of us overlooked that all of them were {n_crew},
even those which required a different placeholder key...

https://steamcommunity.com/sharedfiles/filedetails/?id=3154670529
2024-02-05 18:03:08 -08:00
Dav999 a770f3e126 Add missing spaces to script editor title in Welsh 2024-02-02 19:03:52 -08:00
Dav999 18b532cd9f Translate the current 4 proxy strings into Dutch
These are the 3 variants of Spanish and "Editing and LQA".
2024-02-02 19:03:52 -08:00
Dav999 df5607959b Sync Spanish LATAM and Spanish ARG language files
They were missing the latest strings and also still had strings that
had been deleted.

(Whoever commits the upcoming delivery should also sync that version)
2024-02-02 19:03:52 -08:00
Dav999 448c4a5514 Apply updates to Arabic language files
This update was delivered earlier today!
2024-01-25 16:16:00 -08:00
Dav999 7cd1cae55a Rename capitalized no death mode in Dutch
Just like I changed the number één to be capitalized as Eén instead
of Één (due to this being a special case), I forgot to do the same
for the onelifemode.
2024-01-22 16:31:15 -08:00
Dav999 e7267c6eb6 Add missing blank lines in Irish congrats boxes
The three "Congratulations!" boxes which were supposed to have a blank
line in them didn't.
2024-01-22 16:31:15 -08:00
Dav999 5345d46c3d Fix a few spacing problems in Welsh
This involves a couple of dialog boxes ("Congratulations!" and the
jukebox) which were supposed to have blank lines, but they weren't
in the translation.
2024-01-22 16:31:15 -08:00
Dav999 1bc3e8e666 Fix Esperanto [button?] in Violet cutscene 2024-01-22 16:31:15 -08:00
Dav999 ebd4fa8ad8 Clean up outdated strings
These strings had been replaced over time and the original versions
marked ***OUTDATED*** to allow for the original wordings to be reused
by the translators who had only translated the original ones.
(See lang/README-programmers.txt.)

Now, these strings have all been updated in every language, so it's
time to clean them up!
2024-01-19 16:31:39 -08:00
Dav999 403136df46 Translate new strings to Dutch 2024-01-19 16:31:39 -08:00
Dav999 5a91d09a20 Add in-game mode indications (#1096) to language files
These were not in the English or any other language files. They should
be though, so that they can be translated and generally kept track of.
These aren't urgent either, since we have proxy strings that are used
if these are untranslated.
2024-01-19 16:31:39 -08:00
Dav999 3849ed7a24 Sync language files
This hasn't been done since before we got some deliveries for 2.4,
so there are a few languages which added apostrophes as ' instead of
&apos; in the XML (which is not wrong, but it gives diff noise whenever
there's a sync since VVVVVV writes them back as &apos;...)

Also, we never synced "[Press {button} to toggle gameplay]" across
language files (now two strings with unfreeze/freeze), but that was
also a pretty last-minute string as far as I remember. Arabic did have
it because that language was added after the string was added, so it
got copied from English. I don't think this one is that urgent to
translate into every language for 2.4.1 since it's pretty well hidden
for most people, and it's surrounded by things that have to be English,
so it's as if it's supposed to be like that. Let's just include these
with whatever the next batch of strings is.
2024-01-19 16:31:39 -08:00
Dav999 60fd0bc0c2 Replace [Press {button} to toggle gameplay] by freeze/unfreeze
This is both easier for translators ("toggle" can be an annoying word)
and is useful in general because you can tell if gameplay is frozen
without having to have anything in the room that should normally be
moving but isn't.

I didn't follow the rule in lang/README-programmers.txt to keep the
original string around as ***OUTDATED*** in this case, since I know
only Arabic has it translated - we can just tell the Arabic translators
on Discord that this string was replaced.
2024-01-19 16:31:39 -08:00
Dav999 d299b42ee8 Replace Chinese font
The original Chinese font (which we call "the Indienova font") was
received from the Chinese translators directly, and didn't come with
any license or copyright information other than that it was made by
Indienova. Questions have now been raised about the actual origin of
the characters in the font, and while we do have confirmation from the
translators that we're probably in the clear, they did suggest another
font for us to use, which we're switching to to be sure.

Some background information: the ideal font would probably be Ark Pixel
(https://github.com/TakWolf/ark-pixel-font/), but this font is not
finished yet. Therefore, the creators of Ark Pixel have made a font
that can be used as a placeholder to use in the meantime, Fusion Pixel
(https://github.com/TakWolf/fusion-pixel-font), which combines some
other fonts together in order to get full coverage. This is the font
we're now switching to.

It's not _that_ simple though - the ASCII part of Fusion Pixel is kinda
bad for us using it as a monospaced font. Normally I just replace the
ASCII set by the fullwidth characters, but in this font they were
almost entirely the same. So I instead picked the fullwidth characters
from Galmuri 12px, which is one of the "fusioned" fonts. Interestingly,
we happen to also use the 10px version of this as our Korean font, and
I like these Latin letters, so yay.

I also made the call to split the Chinese font into separate variants
for Simplified and Traditional Chinese. I was aware of the problem with
the Han Unification, but the Traditional Chinese translator said the
Indienova font also contains all the Traditional Chinese characters,
and they proofread the translation, so it was probably fine. Apparently
the difference between Simplified and Traditional Chinese variants of
the same characters are not that big, and it's acceptable. But
Fusion Pixel gives us separate versions of the font for Simplified and
Traditional Chinese, so this is a chance to get it right. Just kidding,
Fusion Pixel's Traditional variant switches out many characters that
were shared between Simplified and Traditional Chinese to Japanese
variants which are noticeably different. So it would be better to keep
using the SC font for TC, just like the Indienova font is SC only.
However:  Ark Pixel does have a version with correct characters for
Traditional Chinese! So for the TC version of our font, I just took all
Chinese characters from the TC version of Ark Pixel where available.
That way, all characters I checked have changed to TC variants
correctly.
2024-01-16 16:54:28 -08:00
Dav999 52b099f7d0 Replace U+2013 (–) by standard dash in Ukrainian
The Ukrainian strings.xml turns out to have two en-dashes which are
not in the font. This commit replaces them with standard dashes.
2024-01-16 16:46:24 -08:00
Dav999 48a71f4c22 Last update to Arabic font 2024-01-10 08:00:04 -08:00
Dav999 ff25e18945 Move author face to the right for RTL languages
This is quite a last-minute thing that was almost getting called off by
me discovering a critical segfault just now in testing this (whew) but
this shouldn't hurt.
2024-01-10 07:57:40 -08:00
Dav999 95c5bd80e1 Revert "Disable typing pipes in script names"
This reverts commit a806b072bd.

It causes an instant segfault if there's no entities or if you're not
editing terminals/script boxes or something, whatever it's not
crucial as a last-minute fix.
2024-01-10 16:42:01 +01:00
Dav999 ef13775456 Add Arabic language files
Here are all the language files for Arabic!
Thanks to Montassar and Seif for their hard work to localize the
entire game in such a short timespan.
2024-01-09 20:20:14 -08:00
Dav999 7b92e7af4d Update Arabic font 2024-01-09 20:20:14 -08:00
Dav999 ba92174c71 Use wordy2 in Dutch to capitalize één as Eén
The number "one" in Dutch is "één" (silly, I know :P). Capital letters
can have accents, but there's an exception where for this specific
word, the first accent is much more often left off than not. So I'm
now using wordy2 as the uppercase variants of all the numbers, and
using that instead of the |upper flag.
2024-01-09 18:05:15 -08:00
Dav999 060fe6938d Add support for right-aligned roomtext
This is mostly so people making levels in an RTL language have a more
pleasant and logical experience. If roomtext is placed in a level set
to RTL, it will get p1=1, which makes that roomtext right-aligned.
Because, imagine for English you click to place roomtext, and the text
runs left of where you clicked, which wouldn't be logical.

Since it's an entity-bound property, switching RTL on and off either in
the editor or via a script does not affect existing entities.
2024-01-09 13:13:04 -08:00
Dav999 7b46087077 Update README-translators.txt for some recent additions
These things hadn't been added to the documentation yet:
- <font> in a language's meta.xml
- <gamepad_hint>
- <rtl>
- wordy2/translation2
2024-01-09 12:12:54 -08:00
Dav999 f846ba5d59 Inverse centered text screen border for RTL
If text is set to be centered, but is so long that it starts running
offscreen on both sides, the print function instead makes the text
start no further left than the left border of the screen (x=0).
This is because text running offscreen at the end only is more readable
and looks less sloppy than running offscreen at both sides.

For RTL, the opposite applies, so it now also works oppositely for RTL
prints, where centered strings will only run offscreen on the left side
of the screen.
2024-01-08 19:17:44 -08:00
Dav999 d78338f9ef XFLIP prompts in the editor 2024-01-08 19:17:44 -08:00
Dav999 1b55c6501c Swap definitions of left and right textbox padding
Spaces on the left and right would end up on the other side in RTL,
which made the "You have rescued a crewmate!" text overlap with the
crewmate sprite, and makes the [C[C[C[C[Captain!] dialogs have spaces
on the left instead of on the right. So, best thing is to just swap
the directions so that they match.
2024-01-08 19:17:44 -08:00
Dav999 945f0edaae Ignore directional control chars in font::len()
They're invisible in font::print(), but they were still considered
characters with widths in the width function. This change made the
levels screen look better in RTL too - I was wondering why the level
options were too far left.
2024-01-08 19:17:44 -08:00
Dav999 18dfcff985 XFLIP cursor in roomname translator mode 2024-01-08 19:17:44 -08:00
Dav999 fd0aefe0ee XFLIP LOADING... screen 2024-01-08 19:17:44 -08:00
Dav999 96fa932a8a Don't pass newline characters to bidi algorithm
If you copy-paste a newline character where it's not interpreted, such
as in a level title, the print function wouldn't treat it any special.
font::print_wrap() would, but that's not used here.

However, now that bidi is involved, the newline is passed straight to
SheenBidi which interprets it as a new line (which would need a new
SBLine to be created, or maybe even a new SBParagraph if there's two).
All while we're still treating it as a single line. This means the text
would just stop being displayed after the first newline. This is now
fixed by treating all newlines as spaces.
2024-01-08 19:17:44 -08:00
Dav999 c8dbdc890e Flip Game Complete screen
Obvious "Key: value" things here, this one was easy.
2024-01-08 19:17:44 -08:00
Dav999 3d04d0acbc Mirror time trial results screen
This has a lot of reading-orientation stuff on it like "Key: value",
so easiest is to just flip the whole design of the screen rather than
trying to flip individual strings.
2024-01-08 19:17:44 -08:00
Dav999 79a0ad8493 XFLIP analog stick sensitivity slider properly
The slider itself was getting mirrored, but not the labels
(Low/Medium/High). This fixes that.
2024-01-08 19:17:44 -08:00
Dav999 5620edeb6b Fix orientation of levels list
I forgot to add the PR_RTL_XFLIP flag to these menu options, so they
were always left-aligned, no matter what.

What actually took me a bit to figure out was how to make the level
completion stars work regardless of the contents of the title - the
stars should always be to the left of the title in an LTR language, and
always to the right of the title in an RTL language. Level titles can
contain bidi characters regardless of the level's rtl flag being set,
so I just let bidi handle all the level menu options, with some control
characters to make sure everything always appears in the correct order.
2024-01-08 19:17:44 -08:00
Dav999 3f8333400f Base text box padding/centering on font width instead of codepoints
Stuff like centertext="1" and padtowidth="264" in cutscene translations
looked wrong in RTL mode, both with Arabic and English text. For Arabic
text, I could easily fix the problem by not counting the number of
codepoints (and assuming they all have the same glyph width), but by
instead taking the width of the string as reported for the font, and
dividing it by the glyph width. This leaves English text still looking
weird in RTL mode. But this shouldn't be a problem either: the Arabic
translations will probably be in Arabic (where the problem doesn't
happen), and I can get English text to show up fine by wrapping it in
U+2066 LEFT-TO-RIGHT ISOLATE and U+2069 POP DIRECTIONAL ISOLATE. So it
looks like an inherent quirk of bidi, that translators familiar with
bidi can easily grasp and fix.

This is main-game only functionality, so it shouldn't break existing
custom levels. We should just make sure textboxes in other languages
aren't broken, but from my testing, it's completely fine - in fact, it
should've improved if it was broken.
2024-01-08 19:17:44 -08:00
Dav999 25bdf0866a Make left/right key input correct for RTL menus
Instead of just up/down, you can also control menus with left/right.
Which is illogical in Arabic... No big deal, I imagined this code
to become much worse than it did. (And action sets is probably gonna
refactor the whole thing anyway)
2024-01-08 19:17:44 -08:00
Dav999 2b22f7cda2 Add PR_RTL_XFLIP to some important places
Okay, the "Font:" thing needed some local code after all, because both
the interface font as well as the level font are used there. But it's
good enough - all the other places can just use the flag.

Notably, I also used this for the menus, since the existing ones are
kinda LTR-oriented, and it's something that we don't *really* have to
do, but I think it shows we care!
2024-01-08 19:17:44 -08:00
Dav999 eac612c309 Add PR_RTL_XFLIP print flag
This lets you mirror the X axis specifically in RTL languages, so the
left border is 320 and the right border is 0, and invert the meaning of
PR_LEFT (0) and PR_RIGHT. Most of the time this is not necessary,
it's just for stuff where a label is followed by a different print,
like "Font: " followed by the font name, time trial time displays, etc
2024-01-08 19:17:44 -08:00
Dav999 3588168c4d Right-align textboxes in RTL languages
Most of this diff is just moving some existing code around, and
changing inline things to variables that could be changed more easily.
2024-01-08 19:17:44 -08:00
Dav999 27e83b6008 Add font::is_rtl(uint32_t flags)
This will return if the given flags indicate RTL properties
(such as textboxes being right-aligned).
2024-01-08 19:17:44 -08:00
Dav999 ed0c9b6b1f Add setrtl(on/off) scripting command
With the <font> tag (which doesn't indicate RTL-ness as explained),
we've had a setfont(font) scripting command. Now we have an <rtl>
tag, so we need a setrtl(on/off) command too to control that.
2024-01-08 19:17:44 -08:00
Dav999 29e2b19698 Add RTL level property and print flag
Again, the RTL property controls whether textboxes will be
right-aligned, and that kind of stuff. It can't be font-bound, since
Space Station supports Hebrew characters and we want to be able to
support, say, a Hebrew translation or Hebrew levels in the future
without having to make a dedicated (or duplicated) font for it.
Therefore it's a property of both the language pack as well as custom
levels - like custom levels already had a <font> tag, they now also
have an <rtl> tag that sets this property.

Right now, we'll have to hardcode it so the menu option for the Arabic
font sets the <rtl> property to 1, and all the other options set it to
0. But it's future-proof in that we can later decide to split the
option for Space Station into an LTR option and an RTL option (so both
"english/..." and "עברית" would select Space Station, but one sets the
RTL property to 0 and the other sets it to 1).
2024-01-08 19:17:44 -08:00
Dav999 37c4f76988 Add RTL language property
This doesn't have an effect yet, but it'll do things like
right-alignment in textboxes and other design-flipping.
2024-01-08 19:17:44 -08:00
Dav999 2003eed2a5 Hide unicode directional control characters
They shouldn't be looked up in the font and displayed under any
circumstances.
2024-01-08 19:17:44 -08:00
Dav999 45ec77973b Implement bidi_should_transform()
This now returns true if any of the characters in the text belong to
the Arabic or Hebrew alphabet, or are one of the Unicode directional
formatting characters. This is just so the bidi machinery doesn't have
to run 100% of the time for 100% of the languages. I will also make it
so the Arabic language pack, as well as custom levels, have an RTL
attribute that always enables bidi (and does things like
right-alignment in textboxes and other design-flipping)
2024-01-08 19:17:44 -08:00
Dav999 822755a75f Add Arabic ligature support
Montassar prepared a list of all the ligatures that needed to be
supported, which was a simple A+B->C table, so that one was not too
difficult either!
2024-01-08 19:17:44 -08:00
Dav999 30c68f70bd Add Arabic font
The Arabic part was made by Montassar Ghanmi, it didn't have its own
Latin part so I just copied 00-FF from Space Station.
2024-01-08 19:17:44 -08:00
Dav999 ef712f9f0c Add support for Arabic reshaping
This code can probably be polished a bit more, but the hard part is
over!

This part was written with guidance of this code:
https://github.com/TerryCavanagh/hx_arabic_shaper
2024-01-08 19:17:44 -08:00
Dav999 e011273eb3 Add Arabic reshaping lookup table
This adds the lookup table and an accompanying hashmap that will be
used for reshaping Arabic - it's not yet used though.
2024-01-08 19:17:44 -08:00
Dav999 59ccdbea00 Implement bidi reordering at display time
I'm now using SheenBidi to reorder RTL and bidirectional text properly
at text rendering time! For Arabic this is still missing reshaping, but
everything's looking really promising now!

The code changes are really non-invasive. The changes to Font.cpp are
absolutely minimal:

     1305+    if (bidi_should_transform(text))
     1306+    {
     1307+        text = bidi_transform(text);
     1308+    }

There's now a FontBidi.cpp, which implements these two functions,
notably bidi_transform(), which takes a UTF-8 encoded string and
returns another UTF-8 encoded string that has bidi reorderings and
reshapings applied.

In that function, SheenBidi gives us information about where in the
input string runs start and end, and on a basic level, all we need to
do there is to concatenate the parts together in the order that we're
given them, and to reverse the RTL runs (recognizable by odd levels).

As this is a proof-of-concept, bidi_should_transform() still always
returns true, applying the bidi algorithm to all languages and all
strings. I'm thinking of enabling bidi only when the language/font
metadata enables RTL (which could be for the interface or for a custom
level), or outside of that, at least when RTL characters are detected
(such as Arabic or Hebrew Unicode blocks).
2024-01-08 19:17:44 -08:00
Dav999 5766e6c426 Add SheenBidi to CMakeLists
Not much to see here, just making sure SheenBidi is compiled with the
game and we can include its headers.
2024-01-08 19:17:44 -08:00
Dav999 a9a1d7e1d6 Add SheenBidi submodule
I'm going to give it a shot to use this for bidi text support, it looks
like it's a pretty lightweight, compatible and low-dependency library
which is definitely a plus. We'll still need to do reshaping ourselves,
but that's the easy part compared to bidi.
2024-01-08 19:17:44 -08:00
Dav999 5f7cb46a35 Remove hair spaces from Japanese translation
I had added 1px spaces in some Japanese strings with buttons in them,
to avoid the button glyphs touching the rest of the text. However, the
Japanese translator later ended up putting full spaces in, not noticing
the hair spaces. So now the space was 1 pixel wider than it should've
been, and it's better to remove them.
2024-01-07 16:31:42 -08:00
Dav999 f4bdea7d6d Add a system for selecting between wordy/wordy2
Some languages have different spellings of wordy numbers based on the
gender of the things they're counting (uno crewmate versus una trinket)
or what a number's role is in the sentence (e.g. twenta out of twentu).
We've always had the idea we couldn't support such complex differences
though, because the game can't be adapted to know what gender each
object will have and what word classes might exist in other languages,
so translators would in those cases just have to forgo the wordy
numbers and just let the game use "20 out of 20".

A solution we came up semi-recently though (after all translations were
finished except for Arabic), was to allow the translator to define
however many classes of wordy numbers they need, and fill them all out.
This would not need the game to be *adapted* for every language's
specific grammar and word genders/classes. Instead, the translator
would just choose their correct self-defined class at the time they use
`wordy` in the VFormat placeholder. Something like
{n|wordy|class=feminine}, or {n|wordy_feminine}.

So this would benefit several languages, but we came up with the
solution a little late for all languages to benefit from it. The Arabic
translators asked for two separate classes of wordy numbers though, so
my plan is to first just have a second list of wordy numbers
(translation2 in numbers.xml), which can be accessed by passing the
`wordy2` flag to VFormat, instead of `wordy`.

Once 2.4 is released, we can take our time to do it properly. This
would involve the ability for translators to define however many
classes they need, to name them what they want, and this name would
then be useable in VFormat placeholders. We can convert all existing
translations to have one class defined by default, such as "wordy", or
"translation" depending on implementation, but there's not so much
concern for maintaining backwards compatibility here, so we can do a
mass-switchover for all language files. That said, it wouldn't be too
hard to add a special case for "translation" being "wordy" either.
We can then ask translators if they would like to change anything with
the new system in place.

For now, we can use this system for Arabic, maybe Spanish since there
were complaints about uno/una, and *maybe* Dutch (it has a thing where
the number "one" is often capitalized differently, but it's not
mandatory per se)
2024-01-06 14:11:40 -08:00
Dav999 ce1327f37a Enable SDL_HINT_IME_SHOW_UI to make typing CJK not guesswork
For some reason, the default behavior of SDL and/or Windows(?) (I only
tested this on Windows) seems to result in the fact that if any SDL app
doesn't account for it, there is no way for Japanese and Chinese
speakers to know what they're typing in.

How IMEs are supposed to work is that you can type words as sort of
WIP versions, and then select out of a list of candidates what the
final result should be. The app may display the WIP text and tell the
IME where the text field is so that the IME's menu can be displayed
around it. But if the app doesn't say where the text field is, then the
candidate list can also be displayed at the corner of the screen, which
is done in Minecraft.

By default, however, SDL apps don't get a candidate list at all, which
means you're basically flying blind as to what you're typing in, and
you would have to basically open notepad and copy-paste everything from
there - unless I'm missing something.

This commit sets the SDL_HINT_IME_SHOW_UI hint (added in SDL 2.0.18
apparently), so that the candidate list is at least shown in the corner.
We can probably deal with positioning and uncommitted text later.
2024-01-05 15:24:27 -08:00
Dav999 a97ba5e768 Fix minor [Press ACTION to save your game] overflow in German
Turns out the string I fixed in the previous commit was also never
noticed in German. For that one, I simply used the wording that was
used in the old hardcoded-ACTION string (with my German knowledge,
I'm confident that's still correct).
2023-12-23 10:50:12 -08:00
Dav999 1dc7ed4d65 Fix minor [Press ACTION to save your game] overflow in Turkish
When ACTION is filled in, the closing ] will go offscreen.
To fix it, I simply removed the square brackets.
2023-12-23 10:50:12 -08:00
Dav999 827417fec8 Restore gravity/warp lines sticking out a tile offscreen
I just discovered this: whereas 2.3 and older versions make gravity
and warp lines - when placed in the editor - stick out one tile
offscreen, the latest version stops the lines at the room border.

This change restores the old behavior, and it's a simple fix: the
refactored code was written to let tiles outside the room block
gravity/warp lines. Instead of all offscreen tiles blocking lines, now
there's a 1-tile padding around the room that will let them through.
2023-12-15 20:03:34 -08:00
Dav999 82aef30649 Minor indentation style fix in Render.cpp
This used 2-space indentation for one level, as well as }else{ on a
single line.
2023-12-15 20:00:05 -08:00
Dav999 e638544665 Add limits to the translator credits strings
Luckily, seems like no language has broken the limit when it is 40!
2023-12-15 20:00:05 -08:00
Dav999 bf85e10219 Try to prevent some lines in rolling credits going offscreen
The new localization-related credits are placed 5 characters from
the left border in the rolling credits (at x=40), which means the
limit was 35 8x8 characters. Which was broken by several languages.
So instead, move the string leftward a bit if it would run offscreen
otherwise.
2023-12-15 20:00:05 -08:00
Dav999 c1fea5f55a Fix current_credits_list_index not always being reset
If you go into the middle of the list of translators in the main menu
credits, then press Escape, and then go into the credits again, the
first page of the list may start at the wrong place, because while
game.translator_credits_pagenum was reset to 0,
game.current_credits_list_index wasn't. This is fixed now.
2023-12-15 20:00:05 -08:00
Dav999 f420b08a0b Fix translator credits headers being forced to 8x8 font
The header "Translators", as well as the language names, were using
PR_FONT_8X8, even though it was translatable text. This is now fixed.
(Also, the CJK spacing for the language names is now higher because
that looked nicer)
2023-12-15 20:00:05 -08:00
Dav999 abf12632bb Load plain font.png beyond U+007F
VVVVVV 2.2 only supported displaying characters 00-7F with its font
system. VVVVVV 2.3 added support for unicode, by supplying a font.txt
with all the characters that are in the font image. But 2.3 made
another change that I didn't immediately realize, even after reading
the code: if font.txt is not present, then the font is not assumed to
have _only_ 00-7F, but _all_ of unicode, as far as the image dimensions
allow.

However, an inconsistency I _did_ notice is how unknown characters
would be rendered in 2.3. If a font had a font.txt, then any unknown
characters would be shown as a '?'. If a font had no font.txt however,
then suddenly any unknown characters would just come out as a space.
I fixed this behavior with the new font system; but what was actually
happening for characters to come out blank is that characters up to
U+00FF, which _were_ technically in the font image but as fully
transparent, would be shown as they were in the image, and characters
beyond U+00FF wouldn't be shown since they were outside of the image.

I don't really want to show blank characters for any character between
80-FF if it is technically inside the image, because pretty much every
single ASCII-only font.png in existence (including the one in data.zip)
contains a blank lower half, just because the font in the game had
always had this specific resolution. (We didn't want to do things that
might crash the game because something was different from what it
expected...)

We have had some confusing occasions before with the old behavior where
the fonts weren't correctly packaged or something (like when the
Catalan translator was sent the first version of the translator pack,
or when people customize their fonts wrong) and special characters were
just blank spaces.

So, instead, for characters beyond 7F, I decided to consider them part
of the font, as long as they are not blank. That means, if a character
beyond the ASCII range has any (non-alpha-0) pixels, then it will be
added, otherwise it won't be. This is just to handle legacy fonts, and
the case where all fonts are missing and the one from data.zip is used;
new fonts should just use .fontmeta or .txt to define their characters.
2023-12-15 19:54:33 -08:00
Dav999 c2ad3d3b97 Clarify translators and programmers READMEs
The top of the programmers readme now says that you need the
translators readme to translate the game into a new language. Also,
since language file syncing now works to populate an empty language
folder, document that in the translators readme as well.
2023-12-15 19:48:55 -08:00
Dav999 6377fd5e73 Make language sync support creating blank language files
Two translators thus far have tried to populate initial language files
by creating a blank folder and then using the in-game sync option. For
example, see #1078.

That is not how the sync option was intended to be used, but it's
really close to getting everything, so I decided to just complete the
support by making sure numbers.xml is copied from English, and making
sure meta.xml is filled in with English text and not text from an
arbitrary language. Also, minor detail on plural form 1 being set to 1
by default if reset, so strings_plural.xml is fully consistent too.
2023-12-15 19:48:55 -08:00
Dav999 66ba557c4d Fix binding menu allowing you to lock yourself out of the game
Or well, lock yourself out if you don't have (easy) access to a
keyboard, like on Steam Deck.

In 2.3, this problem used to be much worse, since you could bind any
button to "menu" - which is actually also "return" in menus - and that
button could then no longer be bound to any other action, because
exiting the bindings menu had priority over assigning a different
binding. The result would be that people could have all their buttons
bound to "escape" with no way of undoing it or using their controllers
at all other than manually going into their config file to change it.

In 2.4, the most important bugs in the bindings menu are fixed, but
it's still possible to remove all your bindings from the "flip"
(confirm) action, meaning you can't navigate the menus anymore with a
controller to fix your bindings or even do anything.

There is one interesting part to all this: if an action has no buttons
bound to it at all when the game is started, then that action is
populated with the default button for that action. This is done for
each action separately, without accounting for the case where the
default button was already bound to another action which was not empty.
(This is something that the binding menu does try to prevent).
Therefore, having no buttons bound to "flip" while having A and B bound
to "menu", would result in A being bound to "flip" and A and B bound to
"menu".

That would still make you unable to enter the gamepad menu, since both
"confirm" and "return" are pressed in a row.

This commit fixes the specific situation where flip/confirm buttons are
also bound to menu/return, by removing all buttons that are in the flip
button list from the menu list. This means that, on Steam Deck, you can
still go to your bindings menu.
2023-12-15 19:44:51 -08:00
Dav999 8f7d0f4913 Make some minor refinements to Dutch translation
I put a main focus on the first cutscenes in the game, changing the
first "Uh oh..." from something like "Oh dear..." to "Oh no..." to make
sure it always sounds right. (The real translation of "Uh oh" is "O-o",
but that seemed too easy to read wrong for the first line in the game
that I wanted to avoid it altogether.)
2023-12-05 16:41:05 +01:00
Dav999 d745bf2e6c Restore correct LIES/TRUTH for Korean
This reverts the Korean sprites in commit
6a8db6a22d.

How many times did we accidentally flip these around now lol
2023-12-05 15:33:20 +01:00
Dav999 2533e144b6 Fix centering of game complete texts if level font != interface font
Textboxes created with graphics.createtextboxflipme() use PR_FONT_LEVEL
by default, but can be overridden with graphics.textboxprintflags() to,
for example, set PR_FONT_INTERFACE. This happens for the textboxes on
the Game Complete screen, which use interface text. The textboxes are
centered by setting the X position to -1 though, which means they're
solely centered based on the width of the first line, in the level
font (because the font hasn't been changed to the interface font yet).

Normally, this isn't a problem, because in the main game (where the
Game Complete screen usually appears), the level font is always equal
to the interface font. However, in custom levels you can still get it
(by calling gamestate 3500) and in that case some of the text may be
misaligned. This change fixes that by adding graphics.textboxcenterx()
to these textboxes.

As far as I can tell, these are the only textboxes that are centered
by just x=-1 despite changing the font afterwards.
2023-12-04 19:49:17 -08:00