Update the font alias regex pattern from:
(mono|sans)-(bold-|italic-)?(stroke-)?[0-9]{1,3}
to:
[a-z]+-(bold-|italic-)?(stroke-)?[0-9]{1,3}
Previously the pattern only allowed the `mono` and `sans` font families.
This change generalizes the pattern to accept any lowercase font family
name, making it compatible with the font alias convention described in:
https://gitea.wildfiregames.com/0ad/0ad/wiki/Adding_font_support
This allows new fonts to be registered through aliases without modifying
the regex each time a new family is introduced.
After 734386ce9f the new font system calculate height and cap height,
previously was having some magic number. Now we are using cap height
divide 2 to give a more nice space.
Remove an extra pixel in the buffer and improves background color for
better reading and eye care.
This also support the change console font option added in d549cbeeaaFixes: #8351
this commit fix and error in HWDetect when the libraries versions use
only MAJOR.MINOR like zlib in some linux os that is "1.3" that need
char[4] (1.3\0) conversion from Script::ToJSVal.
this commit create an overload template that matches "references to
array of uknown bound" and forward it to existing const char* / const
wchar_t* specializations.
this bug was reported by Vantha.
Now that size uses float when emulating positioning, it was getting a
different value, like 0.008. This commit fixed that issue by using
std::floor to remove small noise.
Symmetrical for LEFT with std::ceil.
The size is now float number, because of this code calculates the
required size, we should always ceiling the value to the next int to
remove any error or unwanted behavior in images or subpixel
calculations.
When scaling the GUI, GetCapHeight was incorrectly accounting for
m_Scale which caused text to be hidden due to improper clipping
calculations.
This commit corrects the CapHeight calculation by ensuring that the
division by m_Scale is applied, allowing text to be displayed correctly
at all GUI scale levels.
Remove manual memory management throughout the SoundManager subsystem
in favor of unorderedmap.
Key changes:
- Eliminate manual new/delete calls and potential memory leaks
- Update all sound item classes to use SoundManager factory
- Modernize resource management in OggData and related components
- Ensure exception-safe memory handling across the audio pipeline
This refactoring improves code maintainability, reduces crash risk from
memory errors, and aligns with modern C++ best practices.
Fix ERROR: JavaScript error where 'difficulty' is not defined on line
247 of config.js.
The bug was introduced in commit 062be89694 where two issues occurred:
this.difficulty was incorrectly set to the entire difficultyLevel module
instead of the difficulty parameter value.
Later comparisons used undefined difficulty variable instead of the
imported difficultyLevel module
New `[locale='xx']...[/locale]` markup lets GUI text sections render
with a locale-specific font (e.g. CJK) while the rest of the caption
keeps the current game font.
guiObject.caption = "Hello [locale='ja']世界[/locale], how do you
[locale='zh']感覺[/locale]" This is ideal for language pickers and
similar UI where you want the language name shown in its own script.
This commit unlocks richer, self-explanatory international UI while
keeping the legacy text behaviour unchanged.
Building the workspace with `--without-pch` fails on MSVC:
source/lib/sysdep/os/win/acpi.cpp(123): error C3861: 'isalpha':
identifier not found
The pre-compiled header normally brings in `<cctype>`, but when PCH
generation is disabled the translation unit must include the header
explicitly.
Add the missing `#include <cctype>` to
`source/lib/sysdep/os/win/acpi.cpp`.
No functional change; the code now compiles cleanly with or without PCH.
Modernized COggData::FetchDataIntoBuffer and OggStream
interface:
- Replaced raw buffer pointer with std::vector<u8> in COggData
- Updated GetNextChunk to use PS::span<u8>
- Removed manual new/delete and memset usage
- Replaced long with ALsizei for m_Frequency to match OpenAL API
- Simplified type usage with size_t where appropriate
- Eliminated unnecessary casting and improved code clarity
These changes improve safety, readability, and bring the
code closer to modern C++ standards.
Replaced the raw C array for m_Buffer with std::array
to improve bounds safety and code clarity.
- Used .data() and .at() for buffer access
- Added check for bufferCount exceeding OGG_MAX_BUFFER_COUNT
- Left FetchDataIntoBuffer unchanged to avoid breaking external usage
(e.g. CStreamItem)
This refactor improves safety while keeping external API stable.
OggData now manages its own buffer size and count directly,
instead of relying on SoundManager to provide those values.
- Removed unused GetBufferCount() and GetBufferSize()
- Use default values for buffer size and count in OggData
- Documented buffer settings for clarity
This change centralizes control in OggData and improves encapsulation.
The AddDataBuffer method was declared but never defined
in any implementation of CSoundData or its derived classes.
It is also not used anywhere in the codebase, so this
commit removes the dead declaration to clean up the
interface.
This commit renames ogg to m_OggStreamPtr for clarity and consistency
with naming conventions. Additionally, it moves the m_Format and
m_Frequency fields to the private section to ensure proper
encapsulation.
Local variables like pcmout have been renamed to PCMOut to match style
conventions, and all member fields now follow a consistent m_ prefix
style, placed at the end of the class definition for clarity.
These changes help improve code readability, enforce privacy, and align
with the rest of the codebase's naming standards.
This commit updates the OggData-related classes to use uniform brace
initialization ({}) for member variables where applicable. Brace
initialization improves clarity and prevents potential narrowing
conversions or unintended behavior caused by default constructor
ambiguity.
This change improves consistency and aligns with modern C++ best
practices, especially in C++11 and later where brace initialization is
recommended for safer initialization semantics.
The OggStream interface no longer needs the Close() method.
OpenOggNonstream returns a smart pointer (OggStreamPtr),
so resource cleanup is automatically handled by the destructor.
OggStreamImpl now calls ov_clear in its destructor, making
manual cleanup unnecessary. This commit removes the Close()
method from the interface and its implementation.
Why
Passing 0 as the width to `CGUIText` meant "no wrapping".
Buttons and text objects therefore treated every caption as a
single unbroken line, ignoring embedded new-line characters and
overflowing their allotted space.
What
`GetPreferredTextSize` in both `CButton` and `CText` now forwards
`m_pGUI.GetWindowSize().Width` instead of 0.
With a real width the underlying `CGUIText::GetSize()` can measure
the caption using normal word-wrap rules, restoring correct
multi-line behaviour and preventing layout glitches.
Fixes: #8193
FreeBSD could hang indefinitely when the debug-adapter process
terminated because we closed the TCP socket without first calling
`shutdown()`. On that platform (and similarly on Linux and macOS)
a peer that is still blocked in `recv` will not be woken up unless
a full‐duplex shutdown is performed.
This patch adds `shutdown(fd, SHUT_RDWR)` in `DapInterface.cpp`
for Linux, *BSD, and macOS builds, preventing the observed hang.
This commit enables proper property enumeration and inspection for GUI
proxy objects in debugging sessions using the SpiderMonkey Debugger API.
Interface (IGUIProxyObject):
- Added a pure virtual method getPropsNames() to expose cached property
names from the GUI object implementation.
Proxy handler (JSI_GUIProxy):
- Implemented ownPropertyKeys() to enumerate all visible properties of
the proxy, including: -- Built-in GUI fields: "name", "parent",
"children". -- Dynamic settings stored in m_Settings. -- Script event
handlers prefixed with "on" from m_ScriptHandlers. -- Function
properties returned by getPropsNames().
- Implemented getOwnPropertyDescriptor() to synthesize descriptors for
debugger queries: -- Returns undefined if the property is not defined.
-- Returns a read-only enumerable descriptor otherwise.
- Both methods are marked final and override SpiderMonkey's
BaseProxyHandler.
Why:
- SpiderMonkey’s Debugger API requires ownPropertyKeys and
getOwnPropertyDescriptor for proxy objects to be introspectable in dev
tools like VS Code.
- Without these, properties of GUI objects are hidden during debugging.
- This change improves the developer experience by making all meaningful
GUI object fields visible and explorable at runtime.
Adds initial support for the Debug Adapter Protocol (DAP) to
SpiderMonkey via debugger.js. This JavaScript-based implementation
enables external debuggers (e.g., VS Code) to interact with the JS
runtime using the DAP interface.
Implemented DAP requests and events:
- attach
- initialize (capabilities)
- stopped event
- threads
- scopes
- variables (globalThis pending)
- continue
- stepIn
- stepOut
- setBreakpoints
- Handling of debugger statements
This forms the foundation for interactive debugging of in-game scripts,
providing smoother integration with developer tools.
Spidermonkey provide a mechanics to debug all comportaments and real
from a different place with JS code this allow us to reuse the current
scriptinterface but addind the new Debugger object definition only for
debugging without change any code from other place like GUI &
simulation.
Debugger Adapter Interface is a protocol that commons IDE implement to
being able for debugging, the concept is to provide sockets connections
with c++ but the Dap implementation in JS that allow us to extend for
more Request / Events that DAP provide.
Because Dap Interface its implemented with JS we need to handle message
in the main thread so we are calling in the main loop before GUI
messages
Goal
----
Avoid corrupting the dynamic font-atlas on Vulkan by blocking any
re-uploads until the command buffer that created / last updated the
texture has actually been submitted.
What changed
------------
* **Queue-aware textures**
* Added `queueSubmitAware` flag to `IDevice::CreateTexture*` APIs.
* `Vulkan::CTexture` now stores two booleans:
- `m_QueueSubmitAware` – opt-in per texture.
- `m_PendingQueueSubmit` – set to *true* the moment an upload
is recorded, cleared once the submit scheduler has flushed.
* `CRingCommandContext::ScheduleUpload` marks the texture as
pending (`SetPendingQueueSubmit(true)`).
* **Device-side watcher**
* `Vulkan::CDevice` keeps a
`m_TextureUploadWatcherQueue`. Each frame it checks textures that
were uploaded ≥ `NUMBER_OF_FRAMES_IN_FLIGHT` frames ago and
clears their pending flag.
* New helpers
`ScheduleTextureUploadWatch `,
`ProcessTextureUploadWatchQueue()`.
* **Font code**
* Atlas texture is now created with
`queueSubmitAware = true`.
* `CFont::UploadTextureAtlasToGPU()` early-outs when
`IsPendingQueueSubmit()` returns *true*, instead of tracking a
submit-handle or the manual `m_IsLoadingTextureToGPU` flag
(removed).
Why this is better
------------------
The logic to wait for a flush is localised inside the rendering
backend, so `CFont` only needs to ask *“is my texture busy?”*.
This removes the fragile submit-handle bookkeeping and works even if
the scheduler issues multiple submits per frame in future.
Result
------
Atlas uploads are deferred until the previous submit completes,
eliminating the intermittent glyph corruption on the Vulkan backend
while leaving GL and the dummy backend unchanged.
Mods can add more resources than the summary screen’s fixed layout
handled, which crashed with:
ERROR: JavaScript error: gui/summary/layout.js:269 headerGUI is null
This patch doubles the column templates (9 → 18) and updates the
iteration logic so extra headers no longer resolve to null. It removes
the need for copy-paste XML edits when mods grow the resource list.
Known limitations
-----------------
* Column count is still static; a future change should generate the
layout from g_Resources at run-time.
* UI tested at 1080p and 4 K; very small resolutions might require a
horizontal scroll solution.
If a human player is set to “Removed” in Game Setup, leaves to the
main menu, and re-enters, they are auto-assigned back to the same
slot but still flagged as removed, triggering an instant defeat when
the match starts.
GameSettingsController::onLoad already reconciles **playerAI** against
current player assignments, but the analogous check for the new
**playerRemoved** setting was missing. The flag therefore survived
persisted-settings reloads.
This mirrors the existing AI-conflict logic and resets the flag
whenever a human player occupies the slot.
Bug reported by *elexis*.
Replace repeated LOGWARNING calls with ONCE(LOGWARNING) in
JSInterface_CGUISize.cpp and JSInterface_Main.cpp.
Why – The old behaviour printed a warning every time the deprecated
API was used, cluttering the log and annoying modders. We still want to
nudge them toward the new APIs (object.size = {...} and
guiObject.GetPreferedTextSize/getTextSize), but a single reminder is
enough.
What changed
CGUISimpleSetting<CGUISize>::DoFromJSVal now wraps the deprecation
message in ONCE(...).
Engine.GetTextSize warning is likewise wrapped.
Impact – Functionality is unchanged; only the frequency of the
warnings is throttled to one per session, making the transition less
intrusive and more user-friendly.
Fixes a typo introduced in fd847c2a23 where the code
incorrectly modified chatSubmitButton.size instead of
chatInput.size, effectively collapsing the input field's
width to zero.
This change ensures the chat input field resizes correctly
based on the button's position.
Thanks to Langbarg for noticing the issue.
Refs: #8138
Fixes a bug where chat overlay text wrapping changed
unexpectedly when earlier messages expired.
The issue was caused by Object.assign modifying the size
object in place, which did not trigger proper recalculation
for getTextSize in subsequent frames.
Replacing it with direct assignment ensures the size object
is recompute, allowing correct layout behavior.
Bisected to: fd847c2a23
Thanks to Langbarg for identifying the root cause.
Ref: #8043Fixes: #8138
Adds a runtime warning to `Engine.GetTextSize` indicating that the API
is deprecated and will be removed in a future version.
This API does not simulate GUI rendering accurately, as it treats markup
tags like [color], [font], or [icon] as visible characters. This leads
to incorrect size measurements in modern GUI layouts.
New recommended alternatives:
- Use `Engine.GetGUITextSize(...)` for accurate measurement of raw text
blocks, fully simulating GUI rendering.
- Use `guiObject.getTextSize()` when working within a specific GUI
object, as it accounts for maxWidth, padding (bufferZone), and object
constraints.
A warning is now emitted at runtime to guide developers toward these
updated APIs.
Updates GUI code to apply the correct usage of `guiObject.getTextSize()`
and `guiObject.GetPreferedTextSize()`.
- `guiObject.getPreferedTextSize()` is now used when the goal is to compute the
bounding box of a text string to dynamically resize or layout a GUI
object accordingly. It simulates how the text would be rendered,
accounting for markup and layout rules.
- `guiObject.getTextSize()` remains in use when text is being measured
within a fixed-size GUI element (e.g., a button or label). It respects
internal constraints like buffer zone and maxWidth, and is typically
used to align other elements based on its visual appearance.
These changes ensure more accurate text sizing and consistent layout
behavior across GUI components.
Introduces (CButton|CText).getPreferredTextSize, a new method for estimating
the natural width of a caption if the object had no width constraints.
Unlike .getTextSize, which reports the size after applying current
layout constraints (e.g., fixed width or anchors), getPreferredTextSize
answers the question: "How wide would this object need to be to display
the caption on a single line?"
This is particularly useful for modders and layout logic that wants to
dynamically size elements *before* assigning a fixed width or anchoring.
Replaces the for(;;) loop in GetNextChunk with a clearer while
(bytesRead < size) loop for better readability and intent.
Other improvements:
- Uses constexpr for constant audio format parameters
- Replaces C-style cast with reinterpret_cast
- Ensures consistent use of static_cast for type conversions
- Improves comment formatting
This refactor maintains the original logic while aligning with modern
C++ best practices.
Replaces a raw memcpy call with std::copy_n in VorbisBufferAdapter::Read
for improved type safety and readability. This ensures cleaner buffer
copying using standard C++ algorithms, avoiding manual pointer
arithmetic on void*.
The change is functionally equivalent but aligns better with modern
C++17 practices.
This commit updates the Ogg-related classes to use uniform brace
initialization ({}) for member variables where applicable. Brace
initialization improves clarity and prevents potential narrowing
conversions or unintended behavior caused by default constructor
ambiguity.
This change improves consistency and aligns with modern C++ best
practices, especially in C++11 and later where brace initialization is
recommended for safer initialization semantics.
Introduce a new `Open` method in `OggStreamImpl` that encapsulates the
logic for opening Ogg Vorbis files. This method replaces the previous
`Open` method and utilizes `std::runtime_error` for error reporting
instead of returning error codes. The constructor has been updated to
call this new method, ensuring files are opened upon instantiation. The
changes streamline the code and improve error handling.
OpenOggStream was previously used to stream Ogg files directly from the
file system. It operated on raw file paths (OsPath) and assumed
uncompressed, unarchived files, which made it unsuitable for working
with files inside archives or VFS layers.
However, its usage has been fully replaced by OpenOggNonstream, which:
- Reads the entire file into memory (non-streaming),
- Works with virtual file systems (VFS),
- Supports both archived and compressed assets,
Is already used consistently across debug and release builds.
There are no remaining references to OpenOggStream in the codebase, so
this commit removes the unused function and its associated logic.
This commit introduces support for std::optional<T> in
Script::FromJSVal. When a JavaScript value is undefined or null, the
resulting optional is set to std::nullopt; otherwise, the value is
converted and wrapped.
This change allows components to cleanly handle optional script values
without needing manual null checks or exception handling in C++.
As a direct application of this feature, the Identity component now uses
std::optional<std::wstring> for the return value of GetCiv(). This
resolves a bug where formation templates (e.g., those inheriting from
template_formation.xml) do not explicitly define a civ. After commit
03f7903fec, the code assumed GetCiv() would always return a valid
string, leading to undefined behavior when it was missing.
With this update:
- GetCiv() returning undefined results in an empty optional.
- The Identity component defaults to an empty civilization string ("")
when the civ is not defined.
- This avoids crashes or actor parsing errors for civ-less templates and
improves robustness in script-C++ interaction.
Closes: #8107Fixes: #8091
Previously, if a JavaScript function returned a value that failed to
convert to the requested C++ type (e.g., from JS undefined to
std::wstring), the ScriptInterface would fail silently, making debugging
difficult.
This commit improves the error reporting in the script system by logging
the name of the JavaScript function being called when a type conversion
failure occurs. This makes it easier to trace and fix issues arising
from script-side inconsistencies or missing return values.
The improved logging is particularly useful for debugging errors such as
undefined civ values from GetCiv() when used via m_Script.Call<T>().
Reported by wow on irc:
ERROR: JavaScript error:
gui/session/match_settings/MatchSettingsDialog.js line 55 undefined has
no properties
rebuild@gui/session/match_settings/MatchSettingsDialog.js:55:3
init@gui/session/session.js:320:3
reallyStartGame@gui/loading/loading.js:22:9 ERROR: GUI page
'page_session.xml': Failed to call init() function
Previously, modifying individual CGUISize properties (left, top, right,
bottom) via JavaScript had no effect unless the entire size object was
copied, modified, and reassigned—resulting in verbose and error-prone
code.
This update introduces proper JavaScript property accessors, enabling
direct reading and writing of CGUISize members. The result is a more
intuitive and scriptable API.
Key Changes:
- Implemented JavaScript get/set accessors for each CGUISize property,
directly interacting with the native object.
- Retained support for string assignments to CGUISize
- Maintained the GUISize JS object for backward compatibility, also
marked as deprecated.
- Improved CGUISimpleSetting<CGUISize> to allow partial updates via
direct property access.
- allow assigning size from object with pixel and percent values
You can now assign size using an object with properties like:
size = {
left: number, right: number, top: number, bottom: number,
rleft: number, rright: number, rtop: number, rbottom: number
}
- One or more properties can be specified, the missing properties with
fill as zero.
- Assignment triggers an immediate update event.
Delayed Setting Notifications:
- Introduced a mechanism for delayed setting notifications, currently
only used in CGUISimpleSetting<CGUISize>, to avoid redundant
recalculations.
- Ensured that getComputedSize triggers any pending delayed
notifications before returning the size.
This change significantly enhances the developer experience and brings
the behavior in line with typical expectations for direct property
manipulation in JavaScript.
Previously, the engine only loaded the last mod’s `config/mod.cfg` file,
causing earlier mods' configuration settings to be ignored. This broke
the expectation of stackable mod behavior and affected features relying
on custom config, such as font overrides.
This commit updates the mod mounting and configuration process to:
- Mount each mod's files before attempting to load its config.
- Reload each mod's `config/modname.cfg` via `g_ConfigDB.Reload(CFG_MOD)`
after mounting.
- Merge configuration keys into the CFG_MOD namespace:
- If a key exists, its value is updated.
- If not, the key is added.
This behavior now aligns with the VFS override system, where later mods
take precedence but earlier mods still contribute.
Also adds `_test.mods` for validation.
Fixes edge cases for mod authors who rely on consistent and layered
configuration overrides.
Related: #6383, #1810Fixes: #8060
Premake 5.0.0-alpha12 (released in August 2017) introduced the
`cppdialect` directive, which provides a cleaner and more portable way
to specify the C++ standard across compilers and platforms.
Previously, we used manual per-action buildoptions:
filter "action:vs*" buildoptions { "/std:c++17" }
filter "action:not vs*" buildoptions { "-std=c++17" }
This workaround was necessary due to the limitations of older Premake
versions (particularly Premake 4), which lacked built-in support for
setting the C++ language standard.
Now that we're using a newer version of Premake 5, we can simplify this
setup by using:
cppdialect "C++17"
This results in cleaner, more maintainable build scripts with consistent
behavior across toolchains.
To improve visual consistency during dynamic font rendering, especially
on lower-end machines or during low FPS moments, we now preload a set of
common Latin letters, digits, and punctuation glyphs immediately after a
font is loaded by the FontManager.
This reduces the likelihood of users seeing empty or missing characters
on the first frame after a font is used, minimizing visual glitches
during simulation.
The preloaded characters include:
- Uppercase and lowercase Latin letters (A–Z, a–z)
- Digits (0–9)
- Common punctuation and symbols (e.g., .,;:!?()[]{}<> etc.)
This change helps smooth the user experience and avoids blank spaces
during the initial rendering of text in performance-constrained
scenarios.
After FreeType integration in dfb4598186 font height and line spacing
were incorrectly applied. That caused UI elements like capture, health,
and resource stats to appear misaligned or invisible.
Commit c2d529b975 standardized font height usage, removed lineSpace, and
introduced GetCapHeight + Descender for better vertical alignment.
However, affected texts used a font-stroke-12 with a GUI size of 12,
which now renders lower in the container due to stroke and metric
offset. Increasing the size to 14 ensures the text is properly visible
and aligned.
This adjusts for the actual space font-stroke-12 occupies in rendering.
Fixes: #7962
This reverts commit dc156c3f24.
The original commit addressed incorrect UI alignment caused by improper
handling of font height and linespacing after FreeType integration
(introduced in 734386ce9f).
However, commit c2d529b975 corrected the root issue by standardizing
font metrics:
- Proper use of FreeType's height
- Removal of lineSpace
- Introduction of getCapHeight and Descender for accurate vertical
alignment
As a result, the UI offset workaround is now obsolete and must be
reverted to reflect the correct baseline behavior.
This reverts commit 52ee6ad470.
The original commit addressed incorrect UI alignment caused by improper
handling of font height and linespacing after FreeType integration
(introduced in 734386ce9f).
However, commit c2d529b975 corrected the root issue by standardizing
font metrics:
- Proper use of FreeType's height
- Removal of lineSpace
- Introduction of getCapHeight and Descender for accurate vertical
alignment
As a result, the UI offset workaround is now obsolete and must be
reverted to reflect the correct baseline behavior.
Previously, `height` was derived from a manually chosen glyph (typically
"I", Standard Cap Height) using FontBuilder, and `lineSpacing` was used
inconsistently for layout logic as a height.
Now, with the FreeType-based system:
- `height` uses `face->size->metrics.height`, which includes the
recommended line height with internal leading/line gap as defined by
the font designer.
- `lineSpacing` was removed
- `GetCapHeight` uses the standard cap height + ascender to have a
visual virtual alignment
This change standardizes font metric usage:
- Use `height` for vertical layout and line progression.
- Use `GetCapheight` in layout engines like `CGUIText` or `CGUIString`,
This ensures better alignment across fonts and consistent spacing in
multiline text rendering.
Fixes: #7962
This commit primarily corrects an inaccurate comment and resolves a
hidden bug in the VisualActor shadow logic, while preserving the current
behavior.
Previously, the DisableShadows option removed both casting and receiving
shadows. However, the internal logic ignored this setting in some cases,
causing shadows to appear even when explicitly disabled in XML
templates.
This change introduces the ability to control CastShadows and
ReceiveShadows independently via template settings, defaulting both to
true unless explicitly specified.
In addition, previews are updated to receive shadows but not cast them,
improving visual volume effects without affecting lighting behavior.
The FreeType font loader was directly passing filesystem-style paths
(e.g., mod.zip/...) to FT_New_Face, which does not support paths inside
ZIP archives. As a result, FreeType failed to open the font, triggering
a crash when the engine attempted to use an invalid face object.
This patch changes the font loading logic to:
Use the VFS to read the .ttf font file into memory (shared_ptr<u8> and
size).
Load the font using FT_New_Memory_Face with the in-memory buffer,
ensuring compatibility with zipped mods.
Previously, opening a map that referenced a deleted or missing terrain
caused a severe crash with multiple error dialogs, forcing users to kill
the process. This change restores the previous behavior where missing
terrains are gracefully handled: a warning is logged and the terrain is
substituted with a fallback placeholder (ErrorTexture from
TextureManager).
This significantly improves UX for developers and modders working with
outdated or broken maps, aligning behavior with expectations from
earlier versions of the editor.
This commit introduces optional debugging visuals for font glyph
rendering. When enabled, each glyph is drawn with a surrounding debug
box to aid in visual inspection of glyph layout, spacing, and atlas
behavior.
Usage examples (via console):
// Enable debug box rendering
Engine.ConfigDB_CreateValue("user","fonts.debugBox", true);
// Set debug box color (R G B)
Engine.ConfigDB_CreateValue("user","fonts.debugBoxColor", "35 0 35");
This feature is intended for developers working on font layout or atlas
generation logic, and has no effect on normal gameplay or UI rendering
when disabled.
Text rendering appeared blurry due to subpixel positioning when using
LINEAR filtering. Replaced glyph position calculation with std::ceilf()
to ensure integer-aligned drawing coordinates and crisper text.
This commit enhances text rendering by leveraging FreeType and a dynamic
font atlas. Previously, GUI scaling relied on bitmap fonts, which led to
blurry and distorted text when scaling up. Now, we scale the font size
directly using FreeType, resulting in much sharper and more readable
text at any GUI scale.
Key improvements:
- Replaced bitmap font scaling with true font size scaling via FreeType.
- Reduced glyph cache dependency on fixed positions, relying on shader
scaling instead.
- Switched to float-based glyph positioning for more accurate rendering
and scaling.
These changes ensure clean and consistent text appearance across
different GUI scales.
After 734386ce9f, CJK fonts are included in mods/mod folder, removing the
need for CJK mods. This commit enables those languages in the release
and the installer.
FreeType’s FT_Glyph_To_Bitmap mutates the FT_Glyph by allocating a new
glyph object and overwriting the input pointer. This creates a risk of
memory leaks if the old glyph isn’t released or if ownership is unclear.
To avoid this, we now store the glyph in a UniqueFTGlyph and explicitly
pass it by reference to FT_Glyph_To_Bitmap. After the mutation,
ownership continues to reside in the smart pointer, and cleanup is
guaranteed even in error branches.
For temporary glyphs (e.g., strokes), we still manually call
FT_Done_Glyph, since they are not managed by UniqueFTGlyph. These
changes ensure all glyph memory is correctly released and reduce the
need for repetitive error-path cleanup code.
Replace premade bitmap fonts with FreeType2 and dynamic texture atlas.
Switched from static, premade bitmap fonts to runtime-generated glyphs using FreeType2.
Glyphs are rendered on demand into a dynamic texture atlas, improving scalability,
font quality, and support for internationalization.
Currently using RGBA format for compatibility across all render
paths while initial support for R8_UNORM is being added.
This prepares for future optimizations in VRAM and performance
Includes groundwork for gamma-corrected blending and future swizzling support.
Propagation mousewheel event was introduce to have the opportunity to
parent handle this event if an only if the child doenst handle and the
parent set a handler for that event.
The error foundedd by elexis inside a game relay on the message waw
propagated outsie IGUIObjects to CGUI.cpp that shouldnt be at the
beggin. I forget to stop the propagation when all objects in the tree
was validated, because of that the message was propagate to CGUI.cpp
andd then hanle by camera.
the fix suggest to only propagate the event in the GUI tree, not outside
the GUI tree
Now that we are propagating mousewheel events to parent we need to
explicitly mark that the event was handle in JS and shouldnt be handle
by parent.
this error was informed by Elexis
This PR introduces a new ScrollPanel component with the following
capabilities:
- Scroll Orientation Support: Allows scrolling in horizontal, vertical,
or both directions, providing flexibility for different use cases.
- Partial Object Rendering: Supports partial rendering of objects that
are only partially visible within the scroll boundaries, improving
visual accuracy and performance.
- Boundary-Constrained Mouse Interaction: Handles mouse events strictly
within the panel's visible boundaries, preventing interaction with
objects outside the scrollable area.
- Minimum Internal Size (min_width, min_height): Introduces support for
virtual space management, allowing the panel to maintain a minimum
internal size independent of its actual on-screen dimensions. Even
when the panel is resized, this ensures that the content respects a
defined virtual space (with min_width and min_height), effectively
simulating a larger internal canvas. This is particularly useful for
large content or scenarios where a more extensive scrollable area is
required than the current visible panel.
Tooltip shouldnt receive any mouse event direct, there is a edge case
when you have a big tooltip and the object that need that tooltip is in
the bottom left, at this moment tooltip is in the same position of the
mouse, current code was returning the tooltip, and the code hide the
tooltip, and find again there is another object that needs the tooltip
and show again. To fix this is just than simple to set a tooltip like
ghost because shouldnt receive any mouse event.
Fixed a bug where hotkeys were not being reset properly, ensuring that
all hotkeys are now cleared when expected.
Corrected improper use of forEach with string character access,
replacing it with a valid iteration method over characters.
Removed unnecessary and dead code to improve code cleanliness and
maintainability.