migrate texture atlases to scoped ownership

- replace TextureAtlasManager and GlobalTextureAtlas with catalog-backed atlas ownership
  - make TextureAtlas and TextureRegion creation return explicit resource handles
  - let atlases retain their textures and regions through shared ownership
  - add atlas publication, lookup, removal, and enumeration to ResourceCatalog and ResourceScope
  - make TextureAtlasLoader publish atlases and regions into an explicit resource scope
  - move theme atlas ownership into each theme resource catalog
  - migrate maps, editors, examples, and tests away from the global atlas manager
  - add scope-aware Sprite pattern-loading overloads while preserving default-scope compatibility
  - fix re-entrant style-state invalidation when applying styles creates new widgets
  - add atlas ownership, scoped Sprite lookup, and style-state regression coverage
  - update the resource ownership plan and texture atlas editor launch configuration
This commit is contained in:
Martín Lucas Golini
2026-07-23 01:41:11 -03:00
parent 574b6b9014
commit 373bd40e59
39 changed files with 701 additions and 561 deletions
@@ -5,6 +5,7 @@
#include <eepp/scene/scenemanager.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/sys.hpp>
#include <eepp/ui/uifiledialog.hpp>
#include <eepp/ui/uiroot.hpp>
#include <eepp/ui/uiscenenode.hpp>
#include <eepp/ui/uithememanager.hpp>
@@ -364,3 +365,22 @@ UTEST( UISceneNode, NestedSceneInvalidationPropagatesToHostScene ) {
Engine::destroySingleton();
}
UTEST( UISceneNode, StyleStateUpdateAllowsWidgetCreation ) {
Engine::instance()->createWindow( WindowSettings( 1024, 768, "Style State Widget Creation Test",
WindowStyle::Default, WindowBackend::Default,
32, {}, 1, false, true ),
ContextSettings( false, 0, 0, GLv_default, true, false ) );
UISceneNode* sceneNode = init_test_scene_node();
UIFileDialog* dialog = UIFileDialog::New();
dialog->setParent( sceneNode->getRoot() );
// Applying the select-button state creates its UIImage icon. The new widget invalidates style
// state while the current dirty-state pass is still being processed.
sceneNode->flushDirtyStyleAndLayout();
EXPECT_TRUE( dialog->getButtonOpen() != nullptr );
Engine::destroySingleton();
}