Merge branch 'feature/resource-shared-ownership' into develop

This commit is contained in:
Martín Lucas Golini
2026-07-25 01:36:21 -03:00
286 changed files with 8731 additions and 4581 deletions

View File

@@ -0,0 +1,61 @@
# Resource ownership follow-up plan
Status: proposed follow-up after Stage 7 completion, 2026-07-24.
The shared-resource ownership migration is complete. This plan is intentionally limited to
validation, documentation, diagnostics, and compatibility-era naming cleanup. It must not reopen
the established `ResourceScope` / `ResourceCatalog` ownership model without a concrete defect.
## 1. Scene lifetime coverage
- Add focused tests proving resources published only into a scene scope are released when its
`UISceneNode` and `ResourceScope` are destroyed.
- Cover textures, drawables, fonts, themes, icons, and shader programs where practical.
- Verify explicitly imported catalogs remain alive only through their actual external owners.
- Assert against registry/catalog contents and retained handles, not only destructor side effects.
## 2. Public ownership documentation
- Audit public resource APIs and consistently document whether parameters and return values are:
owning, retaining, borrowing, or observing.
- Document the required lifetime for borrowed raw pointers returned by UI and GPU APIs.
- Keep hot-path raw pointers where ownership is established elsewhere; do not imply ownership by
converting those APIs to shared handles.
- Add short ownership examples to `ResourceScope`, `ResourceCatalog`, and family-specific services.
## 3. Compatibility-era naming cleanup
- Rename non-owning `ShaderProgramManager`, `VertexBufferManager`, and `FrameBufferManager`
concepts to `ShaderProgramRegistry`, `VertexBufferRegistry`, and `FrameBufferRegistry` throughout
filenames, includes, build files, and documentation.
- Review other `*Manager` names only when their current role is genuinely a registry or service.
- Keep this as an isolated public API cleanup so downstream include breakage is easy to review.
## 4. GPU borrowed-lifetime diagnostics
- Add debug-only validation that borrowed frame buffers, vertex buffers, shaders, and programs are
not used after their owning OpenGL context or renderer has been destroyed.
- Prefer cheap generation/context identity checks at API boundaries over reference counting in hot
rendering paths.
- Do not add OpenGL context-loss recreation support; current supported platforms do not require it.
## 5. Static initialization audit
- Build a Clang diagnostic configuration with `-Wglobal-constructors` and
`-Wexit-time-destructors` to identify C++ work performed before `main()` and after its return.
- Produce a linker-level inventory of `.init_array` entries for representative executables to find
constructors hidden in libraries or translation units excluded from Clang diagnostics.
- Prioritize globals that allocate memory, register callbacks/resources, depend on singleton order,
or retain graphics objects. Constant-initialized POD data is not a migration target.
- Move executable state into `main()` scopes and callback lambdas. Replace necessary library
globals with function-local statics only when process lifetime is intentional and documented.
- Track the baseline count and prevent new non-trivial global constructors in CI once existing
cases have been classified.
## Validation
- Run the complete unit-test suite and all normal platform CI jobs after each focused change.
- Keep `git diff --check` clean and run examples affected by shutdown-order changes under ASan.
- Confirm GPU/resource handles are destroyed before `Engine::destroySingleton()` in examples and
tools that own them locally.

View File

@@ -1,7 +1,6 @@
# eepp shared-resource ownership architecture
Status: active implementation baseline; Stage 0, prerequisite fixes, and Stage 1 complete;
Stage 2 is next, 2026-07-15.
Status: implementation complete through Stage 7, 2026-07-24.
This document freezes the contracts that must be true before the public texture API is changed. The
implementation may refine names and small mechanics, but changing an invariant below requires an
@@ -19,9 +18,9 @@ The final model is:
reporting. It is never searched for semantic names.
- Catalogs define names and persistence.
- Scopes define which catalogs and typed caches are visible.
- GPU resources remain graphics-thread-affine. The project contract requires final owning releases
and destruction to run through the graphics/update lifecycle rather than supporting arbitrary
last-release threads.
- GPU resources remain graphics-thread-affine. A final owning release may happen on a worker, but
the texture deleter only performs a thread-safe handoff to TextureFactory. Actual destruction runs
through the graphics/display lifecycle.
- UI drawable resolution is layered over Graphics resource lookup; browser caching and navigation
remain outside Graphics.
- A UISceneNode can own a scope and resolver, but neither texture lifetime nor pure Graphics usage
@@ -105,10 +104,10 @@ Factories use an equivalent private helper for protected constructors. `std::mak
used for tracked eepp resources unless the memory manager is redesigned to understand its combined
allocation. No second control block may be created from `handle.get()`.
Texture is the deliberate exception to immediate `eeDelete`: its factory-controlled deleter queues
the final raw object for graphics-thread destruction. `TextureFactory::collectReleasedTextures()`
performs the eventual `eeDelete` after queued rendering has been flushed. This is the same deferred
destruction contract used by scene nodes; it is not a general arbitrary-thread GPU disposal system.
Texture is the deliberate exception to immediate `eeDelete`: its factory-controlled deleter may
queue the final raw object from any thread. `TextureFactory::collectReleasedTextures()` performs the
eventual `eeDelete` on the graphics thread after queued rendering has been flushed. This is the same
deferred destruction contract used by scene nodes; it is not a general GPU disposal system.
### 3.3 Identity, keys, and labels
@@ -234,9 +233,11 @@ Frozen lookup rules:
- Never search the live registry.
- Never implicitly search a parent, host scene, sibling scene, or every live resource.
- The default Graphics scope imports the global catalog explicitly.
- A UI/application scene receives only the catalogs deliberately imported into it.
- A Web document does not inherit host/global resources unless the host exports and imports them
intentionally.
- A UI/application scene imports the default resource catalog automatically for the common case;
callers can disable this at construction for strict isolation and then import only the catalogs
they deliberately expose.
- A Web document receives the same default-catalog baseline unless created with automatic import
disabled. It never implicitly inherits host, sibling, or other document-local catalogs.
- Scopes import catalogs, not arbitrary scopes. This avoids recursive lookup and import cycles.
Pure `EE::Graphics` users may use TextureFactory for unpinned creation or Engine's default Graphics
@@ -270,14 +271,14 @@ performs the same collection explicitly because no later display is guaranteed.
### 5.1 Graphics-thread lifetime contract
GPU resources are graphics-thread-affine. Creating, mutating and finally releasing owning handles
must follow the engine's graphics/update lifecycle. `std::shared_ptr` provides ownership safety; it
does not expand eepp's supported threading contract. Async CPU decoding may run elsewhere, but
ownership handoff and final release are marshalled to the main/scene update path unless an existing
API explicitly acquires a shared GL context.
GPU operations remain graphics-context-affine and follow the existing graphics/update or explicitly
shared-context rules. Releasing the final `TexturePtr` is different: it performs no GPU operation and
may enqueue the raw texture from any thread. Only collection and actual destruction require the
graphics thread and a current context.
Debug builds should assert this contract at factory release and collection boundaries. The design
does not add a generic device state, epoch or arbitrary-thread disposal queue for unsupported usage.
Debug builds assert the collection boundary. The design does not add a generic device state, epoch,
or disposal mechanism for other GPU resource families; TextureFactory's small deferred-release queue
is the texture-specific lifetime boundary already required by batched rendering.
### 5.2 Texture deferred destruction
@@ -344,34 +345,75 @@ fixed:
Shared lifetime and shareable instance state are separate concerns. `isStateful()` is not a sharing
contract and will not be used as one.
### 7.1 Frozen source/instance split
### 7.1 Source/instance split
Resource resolution caches immutable source data. UI consumers own per-consumer drawable instances:
```cpp
using DrawableSourcePtr = ResourcePtr<const DrawableSource>;
using DrawablePtr = ResourcePtr<Drawable>;
DrawableSourcePtr DrawableResolver::findSource( const DrawableRequest& request );
DrawablePtr Drawable::clone() const;
DrawablePtr DrawableResolver::createDrawable( const DrawableRequest& request );
```
Stage 4 established this contract without introducing a parallel `DrawableSource` class hierarchy.
Existing drawable resource types serve as source prototypes while retained by an atlas, theme,
icon, catalog, or resolver. A prototype is never handed directly to an unrelated consumer:
`clone()` returns independently mutable presentation state while sharing underlying
texture/resource handles. This is simpler than duplicating every drawable type into source and
instance classes and remains compatible with introducing immutable source-only types later when a
concrete resource requires one.
eepp continues to use `Drawable::Type` for runtime drawable dispatch. Generic handle conversion
checks that tag and then uses `static_pointer_cast`; cloning code for a statically known concrete
type also uses `static_pointer_cast`. The ownership migration does not introduce RTTI casts.
Representative split:
- `Texture` is shared GPU/resource data, not a globally shared mutable drawable instance.
- `TextureRegionSource` contains a TexturePtr, immutable source rectangle, offset, and intrinsic size.
- `NinePatchSource` contains immutable region and border data.
- `TextureDrawable`/`TextureRegionDrawable` hold per-consumer destination size, tint, alpha, position,
and other presentation state while retaining their source.
- `TextureRegion` prototypes and instances retain a TexturePtr; instances copy rectangle, offset,
intrinsic size, destination size, tint, and position.
- `NinePatch` instances clone their nine mutable region children while sharing the textures.
- `TextureDrawable` holds per-consumer destination size, tint, alpha, and position while retaining
the shared TexturePtr.
- `StateListDrawable`, `DrawableGroup`, and `Sprite` are per-consumer state machines/instances that
refer to source handles or private child instances.
`DrawableImageParser::createDrawable()` always returns a fresh consumer instance for CSS-generated
or resolved content, even when its immutable source came from a cache.
The migration will remove draw-time mutation of shared child/source objects. Rendering APIs may use
external draw parameters where that simplifies an implementation, but no shared source can be
temporarily recolored, resized, repositioned, or advanced by a consumer.
`UIIcon`, `UIGlyphIcon`, and `UISVGIcon` expose the split directly:
```cpp
const DrawablePtr& UIIcon::getSource( int size ) const;
DrawablePtr UIIcon::createDrawable( int size ) const;
```
`getSource()` supports lookup, measurement, and immediate rendering without cloning an existing
prototype. Glyph and SVG icons may materialize and cache a missing size source once.
`createDrawable()` is the explicit consumer-instance boundary for callers that retain the drawable
or need persistent independent state.
Immediate, single-threaded render paths may borrow an icon source and temporarily change
presentation state when they restore every changed value before returning and never retain the raw
pointer. Retained widget, menu, model, animated, or otherwise independently stateful consumers must
create and own an instance. Shared child mutation remains forbidden where drawing can be reentrant
or where the complete state cannot be restored locally.
No rendering callback may call `clone()`, `UIIcon::createDrawable()`, or an API that performs either
operation internally. It must render either a previously retained instance or a borrowed source
under the temporary-state contract above. The Stage 4 call-site audit classifies all remaining
direct `clone()` calls as:
- implementations recursively cloning their private child state;
- constructors and setters adopting a private region/sprite/map instance;
- theme, skin, icon, CSS, and name-resolution source-to-instance boundaries;
- widget deserialization and one-time assignment; or
- focused ownership tests.
The code editor lock icon and ecode debugger, linter, LSP breadcrumb, and autocomplete icon paths
borrow their per-size icon sources at the point of immediate rendering and restore temporary color
changes before returning. Icons assigned to widgets, menus, or models still use owned instances.
### 7.2 Consumer API
@@ -526,7 +568,7 @@ focused regression coverage while preserving current raw factory ownership:
- Externally executed HTTP tasks cannot retain a dangling raw Http after Pool destruction.
- TextureAtlasLoader joins/stops ResourceLoader work before callback-visible loader state is
destroyed.
- Engine destroys ShaderProgramManager before Renderer and clears TextLayout before FontManager.
- Engine clears TextLayout before destroying the default ResourceScope and its FontService.
- Engine stops asynchronous resource producers before resource consumers and GPU managers.
- UISceneNode's static async delivery queue has an explicit shutdown purge/rejection boundary.
- Obsolete FrameBuffer context-loss reload APIs were removed.
@@ -571,11 +613,22 @@ Exit tests:
- Pending batches flush before texture collection.
- Engine teardown leaves no pending released textures or unexpected live registry entries.
- Repeated test-only Engine create/destroy cycles start with empty resource state.
- Wrong-thread final release triggers the documented debug contract assertion.
- Worker-thread final release only queues the texture; it does not run GL or destruction work.
- `EE_MEMORY_MANAGER` accurately removes texture allocations through the factory-controlled deleter.
### Stage 2: one complete TexturePtr ownership cut
Status: complete, 2026-07-19. TextureFactory creation and acquisition APIs now return TexturePtr,
and TextureLoader exposes handle-based state with `reset()` replacing destructive `unload()`
semantics. TextureRegion, atlases/loaders, framebuffers, font pages and glyphs, nine-patches,
sprites, particle systems, SVG caches, UI image/background paths, maps, tools, tests, ecode, and
eeiv now retain texture handles. Atlas worker loads store their returned handles directly instead
of depending on later global lookup. BatchRenderer retains handle-aware submissions until flush;
its raw overload is limited to Texture's immediate draw path, whose queued object lifetime is
protected by display-time deferred destruction. Sprite's obsolete texture-owner flag and public
factory texture-removal APIs are removed. Factory-wide strong retention remains only as the
planned temporary bridge to Stage 3.
Change creation/acquisition APIs to return TexturePtr and migrate every required holder in the same
repository-wide cut. During conversion, TextureFactory temporarily retains strong handles so an
unclassified ignored result cannot silently expire.
@@ -608,6 +661,15 @@ Exit criteria:
### Stage 3: catalog and scope ownership cutover
Status: complete, 2026-07-19. Engine now owns the global catalog and default Graphics scope;
UISceneNode owns an isolated scope that can be shared explicitly. TextureFactory is an unpinned
creator and weak live registry with no semantic name/hash lookup. Atlas, map, UI image/background,
DrawableSearcher, ecode, tests, and other name-based consumers publish to and resolve through their
explicit scope. Catalog aliases and imports provide intentional persistence and deterministic
sharing. Worker-thread final TexturePtr release is handed to the factory's thread-safe queue and
actual deletion remains display/shutdown-bound. The full cut also corrected TextureLoader's decoder
pixel allocator provenance, which asynchronous scoped loading exposed.
Implement the global catalog, default Graphics scope, application/scene catalogs, explicit imports,
immutable keys, and aliases. Move intended persistent resources from temporary factory retention into
catalogs/caches. Remove factory-wide strong retention and activate final unpinned creation.
@@ -625,6 +687,31 @@ Exit criteria:
### Stage 4: drawable source/instance conversion
Status: complete, 2026-07-20. Drawable ownership
now uses `DrawablePtr`; textures create private
`TextureDrawable` wrappers; mutable prototypes implement `clone()`; sprites, state lists,
skins, groups, nine-patches, regions, glyphs, gradients, and primitive drawables clone their
presentation state. UIImage, UINodeDrawable, menus/icons/themes, parsers, editor/tool consumers,
maps, physics, ecode, and eeiv were migrated in the same API cut.
`DrawableResource::Unload` and callback IDs were replaced by Change-only RAII connections.
Callback state is allocated lazily on the first connection, so ordinary drawable resources carry
no callback allocation. Callback storage and notification snapshots use small inline buffers;
snapshotting preserves safe self-disconnection and reentrant mutation during notification without
allocating in the common case.
`Variant` stores DrawablePtr outside its scalar union. UITextureRegion and ScrollParallax render
with local geometry rather than temporarily resizing shared source regions; region-based map
objects retain private instances. `DrawableSearcher` already returns fresh instances as a safe
bridge, but its replacement by the layered UI resolver remains Stage 5.
`UIIcon::getSource()` now returns a cached source/prototype for lookup, measurement, and immediate
single-threaded rendering under the temporary-state restoration contract, while
`UIIcon::createDrawable()` explicitly creates one private consumer instance. `UIGlyphIcon` and
`UISVGIcon` cache their lazily materialized sources under the same contract. The complete `clone()`
call-site audit found no remaining render-loop cloning. The code editor, debugger, linter, LSP
breadcrumb, and autocomplete draw-only paths borrow sources directly; retained widget and menu
icons continue to own instances.
Introduce source types and per-consumer instances, remove shared draw-state mutation, replace manual
ownership with DrawablePtr, remove Unload lifetime callbacks, add RAII change connections, and
migrate Variant's storage.
@@ -642,6 +729,18 @@ Exit criteria:
### Stage 5: layered UI resolution
Status: complete, 2026-07-21. `DrawableSearcher` was removed from Graphics. `ResourceScope` now
provides scoped drawable lookup for textures, atlas regions, nine-patches, and sprites, preserving a
pure Graphics entry point with no UI dependency. Each `UISceneNode` owns an allocation-free
`UI::DrawableResolver` that reads the scene's current scope and referer when resolving file, data,
HTTP, and named drawable references. UI images, sprites, menus, CSS parsing, and tests use the scene
resolver; callers without a scene explicitly construct one over `defaultResourceScope()`.
CSS icon resolution now uses the requesting node's scene instead of the process-global scene.
Texture names remain isolated by local/imported catalogs and become visible across scenes only when
their scopes or catalogs are shared intentionally. Atlas, nine-patch, and sprite manager migration
to scoped catalogs remains Stage 7 work for those resource families.
Implement UI::DrawableResolver and replace DrawableSearcher. Scene resolvers delegate Graphics work
to their explicit scope. Keep CSS/icon/glyph interpretation in UI and cookie/navigation concerns in
Web services.
@@ -655,6 +754,29 @@ Exit criteria:
### Stage 6: WebResourceCache and document leases
Status: complete, 2026-07-21. Each UISceneNode now owns a WebResourceCache document session with
an explicit cache partition and navigation generation. UIWebView advances that session when the
replacement document is installed, after the previous document has been detached. Document,
stylesheet, remote font, image, and CSS background image
requests share canonical fragment-free keys that include the partition, request method/body and
headers, resource kind, and image decode options.
Concurrent requests coalesce into one fetch and one image decode/upload. Subscribers retain their
own document generation, so navigation or destruction removes stale delivery without cancelling a
request needed by another session. Applications can install one cache and explicit partition into
multiple WebViews to share eligible public resources; distinct partitions and content-affecting
headers remain isolated. Scene ResourceScope entries remain an explicit override but fetched Web
resources are retained only by consumers, document leases, and the cache.
Completed entries use monotonic TTL and LRU timestamps plus a configurable byte budget. Active
document leases are not evicted; the TTL starts when the final document lease is released, allowing
Back/Forward navigation to reuse resources regardless of how long the previous document remained
open. Navigation releases only that session's previous leases, and UIWebView performs throttled
cache maintenance so expired unleased entries are collected even when no new requests complete. Failed loads
retry, redirect/final cookies are delivered only to current subscribers, and image upload is
dispatched through the scene's guarded main-thread resource queue. Common lease lists use inline
small vectors, and completed entries release starter request bodies, headers, and dispatchers.
Implement cache partitions, canonical keys/origins, per-document sessions and leases, in-flight
coalescing, per-subscriber generation guards, retries, TTL/LRU, and byte budgets. Integrate WebView
navigation at its existing document replacement boundary.
@@ -670,12 +792,44 @@ Exit criteria:
### Stage 7: remaining resource families
Migrate fonts, font faces/fallback caches, themes, shader programs/shaders, nine-patch catalogs,
atlas managers, and every remaining raw-owning ResourceManager subclass one family at a time. Their
self-contained GPU objects retain the established graphics-thread destruction contract unless a
concrete migration requires otherwise.
Status: complete, 2026-07-24. Nine-patches and texture atlases are migrated. `NinePatch::New()`,
`TextureRegion::New()`, and `TextureAtlas::New()` return handles. Atlases retain region and texture
handles; loaders retain and publish atlas handles; theme-owned catalogs retain their named atlas
sources; and scene `ResourceScope` imports make those sources visible intentionally.
`NinePatchManager`, `TextureAtlasManager`, and `GlobalTextureAtlas` were removed. Removing a catalog
entry releases only catalog ownership and leaves separately retained consumers valid.
Remove raw-owning `ResourceManager<T>` only when no subclass or consumer depends on it.
This is the required pattern for the remaining process-wide singleton resource managers. A
singleton must not be modernized into another process-global semantic namespace. Each family moves
to ordinary catalogs owned by its application, scene, theme, document, or other natural lifetime
boundary. `globalResourceCatalog()` is reserved for resources deliberately published process-wide;
scene scopes see non-global resources only through their local catalog or explicit imports.
Migrate fonts, font faces/fallback caches, themes/icons, shader programs/shaders, and every remaining
raw-owning ResourceManager subclass one family at a time. Their self-contained GPU objects retain
the established graphics-thread destruction contract unless a concrete migration requires
otherwise.
For fonts, ownership is separate from rendering policy. Font handles and semantic lookup live in
naturally owned catalogs: application defaults use the default scope, while author `@font-face`
resources are owned by their document scene. Every `ResourceScope` owns an inline `FontService` for
its rendering configuration, emoji fonts, configured fallbacks, and system fallback cache. Fonts
retain only a borrowed service pointer while published in that scope and are detached when removed
or when the scope is destroyed. Raw `Font*` values in text/layout/style structures remain borrowed
views whose enclosing application, scene, theme, or fallback service retains the corresponding
handle. The former process-wide `FontManager` singleton and compatibility namespace were removed.
Publishing a font with an existing local key replaces that catalog binding; the legacy manager
behavior that silently suffixed duplicate font names is intentionally not preserved.
Themes, skins, icon themes, and icons now use shared resource handles. Each scene's
`UIThemeManager` owns its themes and imports their catalogs into that scene's scope; it is not a
process-wide semantic namespace. Shader and shader-program factories return handles, programs own
their constituent shaders, and catalogs/scopes can publish shader programs under semantic keys.
`ShaderProgramRegistry`, `VertexBufferRegistry`, and `FrameBufferRegistry` remain process-wide only
as non-owning inventories of live OpenGL-context objects used for reload and diagnostics.
The raw-owning `ResourceManager<T>` and `ResourceManagerMulti<T>` templates were removed after their
last consumers migrated.
## 11. Required validation matrix
@@ -692,7 +846,7 @@ Remove raw-owning `ResourceManager<T>` only when no subclass or consumer depends
### GPU/thread lifetime
- Final texture release on the graphics thread queues rather than immediately deleting.
- Wrong-thread final release is detected as a project-contract violation in debug builds.
- Worker-thread final release safely queues; display performs the destruction with a current context.
- Display flushes batches before collecting released textures under the current context.
- Engine shutdown performs a final collection before TextureFactory/Renderer/context destruction.
- No deletion/callback occurs while registry/cache locks are held.
@@ -740,8 +894,8 @@ Remove raw-owning `ResourceManager<T>` only when no subclass or consumer depends
## 12. Next implementation deliverable
Stage 1 is complete, including removal of the obsolete context-recovery APIs and TextureLoader
callback registry, weak UITextureViewer observation, and display/shutdown texture collection. The
next coding deliverable is the complete Stage 2 TexturePtr ownership cut described above: change
the public APIs and migrate every texture holder while temporary factory retention keeps the
repository behavior stable.
The ownership migration is complete through Stage 7. Follow-up work is validation and API polish:
expand scene-lifetime and repeated-Engine coverage, audit public ownership documentation, add
debug-only borrowed GPU lifetime checks, audit non-trivial static initialization, and rename
compatibility-era manager filenames when the public include transition is scheduled. OpenGL
context-loss recreation is explicitly outside the supported lifecycle contract.

View File

@@ -387,6 +387,18 @@
"command": "${project_root}/bin/eepp-ui-font-picker-debug",
"name": "eepp-ui-font-picker-debug",
"working_dir": "${project_root}/bin"
},
{
"args": "",
"command": "${project_root}/bin/eepp-TextureAtlasEditor-debug",
"name": "eepp-TextureAtlasEditor-debug",
"working_dir": "${project_root}/bin"
},
{
"args": "",
"command": "${project_root}/bin/eepp-sprites-debug",
"name": "eepp-sprites-debug",
"working_dir": "${project_root}/bin"
}
],
"var": {

View File

@@ -0,0 +1,37 @@
name: Emscripten
on: [push, pull_request]
env:
EM_VERSION: 4.0.1
EM_CACHE_FOLDER: emsdk-cache
jobs:
Emscripten:
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
ref: ${{ github.ref }}
fetch-depth: 2
- name: Checkout submodules
run: |
git submodule update --init --recursive
- name: Install Premake
run: |
wget https://cdn.ensoft.dev/eepp-assets/premake-5.0.0-beta6-linux.tar.gz
tar xvzf premake-5.0.0-beta6-linux.tar.gz
- name: Cache Emscripten system libraries
uses: actions/cache@v5
with:
path: ${{ env.EM_CACHE_FOLDER }}
key: emscripten-${{ env.EM_VERSION }}-${{ runner.os }}
- name: Setup Emscripten
uses: emscripten-core/setup-emsdk@v15
with:
version: ${{ env.EM_VERSION }}
actions-cache-folder: ${{ env.EM_CACHE_FOLDER }}
- name: Build
run: |
projects/emscripten/make.sh config=release_wasm32

View File

@@ -9,6 +9,7 @@ framework heavily focused on the development of rich graphical user interfaces.
[![macOS status](https://img.shields.io/github/actions/workflow/status/SpartanJ/eepp/eepp-macos-build-check.yml?branch=develop&label=macOS)](https://github.com/SpartanJ/eepp/actions?query=workflow%3AmacOS)
[![iOS status](https://img.shields.io/github/actions/workflow/status/SpartanJ/eepp/eepp-ios-build-check.yml?branch=develop&label=iOS)](https://github.com/SpartanJ/eepp/actions?query=workflow%3AiOS)
[![Android status](https://img.shields.io/github/actions/workflow/status/SpartanJ/eepp/eepp-android-build-check.yml?branch=develop&label=Android)](https://github.com/SpartanJ/eepp/actions?query=workflow%3AAndroid)
[![emscripten status](https://img.shields.io/github/actions/workflow/status/SpartanJ/eepp/eepp-emscripten-build-check.yml?branch=develop&label=emscripten)](https://github.com/SpartanJ/eepp/actions?query=workflow%3Aemscripten)
## Features

View File

@@ -56,14 +56,11 @@ TabWidget {
}
MarkdownView {
color: var(--font);
background-color: var(--list-back);
padding: 4dp;
}
MarkdownView body {
color: var(--font);
}
MarkdownView p,
MarkdownView ol,
MarkdownView ul,

View File

@@ -68,6 +68,17 @@ class DynamicLRU {
mCacheMap.clear();
}
template <typename Predicate> void eraseIf( Predicate predicate ) {
for ( auto it = mCacheList.begin(); it != mCacheList.end(); ) {
if ( predicate( it->first, it->second ) ) {
mCacheMap.erase( it->first );
it = mCacheList.erase( it );
} else {
++it;
}
}
}
[[nodiscard]] std::size_t size() const { return mCacheList.size(); }
};
@@ -166,6 +177,19 @@ class StaticLRU {
used_ = 0;
}
template <typename Predicate> void eraseIf( Predicate predicate ) {
std::vector<std::pair<KeyT, ValueT>> retained;
retained.reserve( used_ );
for ( std::uint16_t idx = head_; idx < N; idx = next_[idx] ) {
if ( !predicate( keys_[idx], vals_[idx] ) )
retained.emplace_back( std::move( keys_[idx] ), std::move( vals_[idx] ) );
}
clear();
for ( auto it = retained.rbegin(); it != retained.rend(); ++it )
put( std::move( it->first ), std::move( it->second ) );
}
[[nodiscard]] std::size_t size() const noexcept { return used_; }
private:
@@ -283,6 +307,9 @@ class LRUCache {
std::optional<ValueT> get( KeyParamT key ) { return impl_.get( key ); }
void put( KeyT key, ValueT value ) { impl_.put( std::move( key ), std::move( value ) ); }
void clear() { impl_.clear(); }
template <typename Predicate> void eraseIf( Predicate predicate ) {
impl_.eraseIf( std::move( predicate ) );
}
static constexpr std::size_t capacity() { return Capacity; }
[[nodiscard]] std::size_t size() const { return impl_.size(); }

View File

@@ -10,23 +10,20 @@
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/drawablegroup.hpp>
#include <eepp/graphics/drawableresource.hpp>
#include <eepp/graphics/drawablesearcher.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontbmfont.hpp>
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fontsprite.hpp>
#include <eepp/graphics/fontstyleconfig.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/framebuffer.hpp>
#include <eepp/graphics/framebuffermanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/globaltextureatlas.hpp>
#include <eepp/graphics/glyphdrawable.hpp>
#include <eepp/graphics/image.hpp>
#include <eepp/graphics/linewrap.hpp>
#include <eepp/graphics/ninepatch.hpp>
#include <eepp/graphics/ninepatchmanager.hpp>
#include <eepp/graphics/packerhelper.hpp>
#include <eepp/graphics/particle.hpp>
#include <eepp/graphics/particlesystem.hpp>
@@ -46,6 +43,8 @@
#include <eepp/graphics/renderer/rendererglshader.hpp>
#include <eepp/graphics/renderer/rendererhelper.hpp>
#include <eepp/graphics/rendermode.hpp>
#include <eepp/graphics/resourcecatalog.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/richtext.hpp>
#include <eepp/graphics/scopedtexture.hpp>
#include <eepp/graphics/scrollparallax.hpp>
@@ -65,7 +64,7 @@
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/graphics/textureatlasloader.hpp>
#include <eepp/graphics/textureatlasmanager.hpp>
#include <eepp/graphics/texturedrawable.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/textureloader.hpp>
#include <eepp/graphics/texturepacker.hpp>

View File

@@ -30,6 +30,8 @@ class EE_API ArcDrawable : public PrimitiveDrawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
Float getRadius() const;
void setRadius( const Float& radius );

View File

@@ -43,6 +43,10 @@ class EE_API BatchRenderer {
void setTexture( const Texture* texture,
Texture::CoordinateType coordinateType = Texture::CoordinateType::Normalized );
/** Retains the texture until the currently queued batch has been rendered. */
void setTexture( const TexturePtr& texture,
Texture::CoordinateType coordinateType = Texture::CoordinateType::Normalized );
/** Set the predefined blending function to use on the batch */
void setBlendMode( const BlendMode& blend );
@@ -315,7 +319,10 @@ class EE_API BatchRenderer {
VertexData* mTVertex{ nullptr };
unsigned int mNumVertex{ 0 };
// Borrowed draw view. Handle-aware submissions retain mTextureOwner; Texture::draw() borrows
// under the contract that released textures are collected only after this batch is flushed.
const Texture* mTexture{ nullptr };
TexturePtr mTextureOwner;
BlendMode mBlend{ BlendMode::Alpha() };
Vector2f mTexCoord[4]{ Vector2f::Zero, Vector2f::Zero, Vector2f::Zero, Vector2f::Zero };

View File

@@ -14,6 +14,8 @@ class EE_API CircleDrawable : public ArcDrawable {
CircleDrawable();
CircleDrawable( const Float& radius, const Uint32& segmentsCount );
DrawablePtr clone() const;
};
}} // namespace EE::Graphics

View File

@@ -24,6 +24,8 @@ class EE_API ConvexShapeDrawable : public PrimitiveDrawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
void setPolygon( const Polygon2f& polygon );
void addPoint( const Vector2f& point );

View File

@@ -2,6 +2,7 @@
#define EE_GRAPHICS_DRAWABLE_HPP
#include <eepp/graphics/blendmode.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/rendermode.hpp>
#include <eepp/math/size.hpp>
#include <eepp/system/color.hpp>
@@ -10,12 +11,17 @@ using namespace EE::System;
namespace EE { namespace Graphics {
class Drawable;
class StatefulDrawable;
using DrawablePtr = ResourcePtr<Drawable>;
using DrawableWeakPtr = ResourceWeakPtr<Drawable>;
class EE_API Drawable {
public:
enum Type {
TEXTURE,
TEXTUREDRAWABLE,
TEXTUREREGION,
SPRITE,
ARC,
@@ -57,6 +63,10 @@ class EE_API Drawable {
virtual bool isStateful() = 0;
/** Creates an independently mutable instance backed by the same immutable resource data.
* This is an ownership/setup operation; rendering loops must retain and reuse the result. */
virtual DrawablePtr clone() const;
void setAlpha( Uint8 alpha );
const Uint8& getAlpha();

View File

@@ -8,7 +8,7 @@ namespace EE { namespace Graphics {
class EE_API DrawableGroup : public Drawable {
public:
static DrawableGroup* New();
static ResourcePtr<DrawableGroup> New();
DrawableGroup();
@@ -26,9 +26,11 @@ class EE_API DrawableGroup : public Drawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
void clearDrawables();
Drawable* addDrawable( Drawable* drawable );
DrawablePtr addDrawable( DrawablePtr drawable );
Uint32 getDrawableCount() const;
@@ -36,19 +38,14 @@ class EE_API DrawableGroup : public Drawable {
void setClipEnabled( bool clipEnabled );
bool isDrawableOwner() const;
void setDrawableOwner( bool drawableOwner );
std::vector<Drawable*>& getGroup();
std::vector<DrawablePtr>& getGroup();
protected:
std::vector<Drawable*> mGroup;
std::vector<DrawablePtr> mGroup;
std::vector<Vector2f> mPos;
Sizef mSize;
bool mNeedsUpdate;
bool mClipEnabled;
bool mDrawableOwner;
virtual void onPositionChange();

View File

@@ -2,17 +2,45 @@
#define EE_GRAPHICS_DRAWABLERESOURCE_HPP
#include <eepp/core.hpp>
#include <eepp/core/small_vector.hpp>
#include <eepp/graphics/drawable.hpp>
#include <memory>
namespace EE { namespace Graphics {
class DrawableResource;
struct DrawableResourceCallbackState {
using Callback = std::function<void( DrawableResource& )>;
Uint32 nextId{ 0 };
SmallVector<std::pair<Uint32, Callback>, 2> callbacks;
};
class EE_API DrawableResourceConnection {
public:
DrawableResourceConnection() = default;
~DrawableResourceConnection();
DrawableResourceConnection( DrawableResourceConnection&& other ) noexcept;
DrawableResourceConnection& operator=( DrawableResourceConnection&& other ) noexcept;
DrawableResourceConnection( const DrawableResourceConnection& ) = delete;
DrawableResourceConnection& operator=( const DrawableResourceConnection& ) = delete;
void disconnect();
explicit operator bool() const;
private:
friend class DrawableResource;
DrawableResourceConnection( std::weak_ptr<DrawableResourceCallbackState> state, Uint32 id );
std::weak_ptr<DrawableResourceCallbackState> mState;
Uint32 mId{ 0 };
};
class EE_API DrawableResource : public Drawable {
public:
enum Event { Change, Unload };
virtual ~DrawableResource();
typedef std::function<void( Uint32, Event, DrawableResource* )> OnResourceChangeCallback;
using OnResourceChangeCallback = DrawableResourceCallbackState::Callback;
/** @return The DrawableResource Id. The Id is the String::hash of the name. */
const String::HashType& getId() const;
@@ -26,19 +54,13 @@ class EE_API DrawableResource : public Drawable {
/** Always true */
bool isDrawableResource() const;
/** Push a new on resource change callback.
* @return The Callback Id
*/
Uint32 pushResourceChangeCallback( const OnResourceChangeCallback& cb );
/** Pop the on resource change callback id indicated. */
bool popResourceChangeCallback( const Uint32& callbackId );
/** Connects a callback for mutable resource data changes. */
DrawableResourceConnection connectResourceChange( OnResourceChangeCallback cb );
protected:
std::string mName;
String::HashType mId;
Uint32 mNumCallBacks;
UnorderedMap<Uint32, OnResourceChangeCallback> mCallbacks;
std::shared_ptr<DrawableResourceCallbackState> mCallbackState;
explicit DrawableResource( Type drawableType );
@@ -48,7 +70,7 @@ class EE_API DrawableResource : public Drawable {
virtual void onResourceChange();
void sendEvent( const Event& event );
void sendResourceChanged();
};
}} // namespace EE::Graphics

View File

@@ -1,27 +0,0 @@
#ifndef EE_GRAPHICS_DRAWABLEMANAGER_HPP
#define EE_GRAPHICS_DRAWABLEMANAGER_HPP
#include <eepp/core/core.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/network/uri.hpp>
namespace EE { namespace Graphics {
class EE_API DrawableSearcher {
public:
static Drawable* searchByName( const std::string& name, bool firstSearchSprite = false,
Network::URI referer = "" );
static Drawable* searchById( const Uint32& id );
static void setPrintWarnings( const bool& print );
static bool getPrintWarnings();
protected:
static bool sPrintWarnings;
};
}} // namespace EE::Graphics
#endif

View File

@@ -11,6 +11,8 @@ using namespace std::literals;
namespace EE { namespace Graphics {
class Font;
using FontPtr = ResourcePtr<Font>;
using FontWeakPtr = ResourceWeakPtr<Font>;
struct EE_API Glyph {
Float advance{ 0 }; ///< Offset to move horizontally to the next character
@@ -135,6 +137,10 @@ class EE_API Font {
virtual Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const = 0;
/** Returns the horizontal advance without requiring a renderable glyph texture. */
virtual Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
/** @return The glyph drawable that represents the glyph in a texture. The glyph drawable
* allocation is managed by the font. */
virtual GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
@@ -156,7 +162,7 @@ class EE_API Font {
virtual Float getUnderlineThickness( unsigned int characterSize ) const = 0;
virtual Texture* getTexture( unsigned int characterSize ) const = 0;
virtual const TexturePtr& getTexture( unsigned int characterSize ) const = 0;
virtual Uint32 getFontStyle() const;

View File

@@ -12,12 +12,20 @@ class IOStream;
namespace EE { namespace Graphics {
class FontBMFont;
class ResourceScope;
using FontBMFontPtr = ResourcePtr<FontBMFont>;
using FontBMFontWeakPtr = ResourceWeakPtr<FontBMFont>;
/** @brief Implementation of AngelCode BMFont fonts. */
class EE_API FontBMFont : public Font {
public:
static FontBMFont* New( const std::string fontName );
static FontBMFontPtr New( const std::string fontName );
static FontBMFontPtr New( const std::string fontName, ResourceScope& resourceScope );
static FontBMFont* New( const std::string fontName, const std::string& filename );
static FontBMFontPtr New( const std::string fontName, const std::string& filename );
static FontBMFontPtr New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope );
~FontBMFont();
@@ -37,7 +45,10 @@ class EE_API FontBMFont : public Font {
const Font::Info& getInfo() const;
Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
Float outlineThickness = 0 ) const;
Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
bool bold = false, bool italic = false,
@@ -54,7 +65,7 @@ class EE_API FontBMFont : public Font {
Float getUnderlineThickness( unsigned int characterSize ) const;
Texture* getTexture( unsigned int characterSize ) const;
const TexturePtr& getTexture( unsigned int characterSize ) const;
bool loaded() const;
@@ -71,8 +82,8 @@ class EE_API FontBMFont : public Font {
GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph
GlyphDrawableTable
drawables; ///> Table mapping code points to their corresponding glyph drawables.
Texture* texture; ///< Texture containing the pixels of the glyphs
drawables; ///> Table mapping code points to their corresponding glyph drawables.
TexturePtr texture; ///< Texture containing the pixels of the glyphs
};
void cleanup();

View File

@@ -14,8 +14,8 @@ class EE_API FontFamily {
const std::string& ext,
const std::vector<std::string_view>& names );
static FontTrueType* setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType );
static void setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType );
};
}} // namespace EE::Graphics

View File

@@ -1,70 +0,0 @@
#ifndef EE_GRAPHICSCFONTMANAGER_HPP
#define EE_GRAPHICSCFONTMANAGER_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/system/resourcemanager.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
class FontTrueType;
struct FontDesc;
/** @brief The Font Manager is a singleton class that manages all the instance of fonts
instantiated. And releases the font instances automatically. So the user doesn't need to release
any font instance.
*/
class EE_API FontManager : public ResourceManager<Font> {
SINGLETON_DECLARE_HEADERS( FontManager )
public:
virtual ~FontManager();
/** @brief Adds a new font to the manager */
Graphics::Font* add( Graphics::Font* Font );
Font* getColorEmojiFont() const;
void setColorEmojiFont( Graphics::Font* font );
Font* getEmojiFont() const;
void setEmojiFont( Font* newEmojiFont );
const std::vector<Font*>& getFallbackFonts() const;
bool hasFallbackFonts() const;
bool addFallbackFont( Font* fallbackFont );
bool removeFallbackFont( Font* fallbackFont );
FontHinting getHinting() const;
void setHinting( FontHinting hinting );
FontAntialiasing getAntialiasing() const;
void setAntialiasing( FontAntialiasing antialiasing );
Font* getByInternalId( Uint32 internalId ) const;
FontTrueType* getOrLoadSystemFallbackFont( const FontDesc& desc );
protected:
Font* mColorEmojiFont{ nullptr };
Font* mEmojiFont{ nullptr };
std::vector<Font*> mFallbackFonts;
std::vector<Font*> mSystemFallbackFonts;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
FontManager();
};
}} // namespace EE::Graphics
#endif

View File

@@ -0,0 +1,139 @@
#ifndef EE_GRAPHICS_FONTSERVICE_HPP
#define EE_GRAPHICS_FONTSERVICE_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
namespace EE { namespace Graphics {
class FontTrueType;
class ResourceScope;
struct FontDesc;
/**
* @brief Owns font fallback state and rendering policy for a ResourceScope.
*
* Every ResourceScope has one FontService. Fonts published locally by that scope are associated
* with its service, allowing glyph lookup to resolve configured emoji, explicit fallback, and
* system fallback fonts without consulting global state.
*
* The service strongly owns configured emoji and fallback fonts. Raw-pointer setters only accept
* fonts that can be resolved through the associated scope; passing an unrelated pointer clears or
* ignores the corresponding configuration. Removing a locally published font from the scope also
* removes any service references to it.
*
* Rendering policy changes are applied to TrueType fonts associated with this service. Imported
* fonts remain associated with the service of their owning scope and are therefore not mutated.
* A FontTrueType stores one borrowed FontService pointer, so the same FontTrueType instance must
* not be published locally into multiple scopes: the latest publication would replace its service
* association. Share such a font by importing its owning catalog instead. A future design may move
* fallback resolution entirely out of the shared font object and remove this restriction.
*
* System fonts can be loaded with two different lifetime contracts:
* - loadSystemFont() returns an independently owned, uncached font.
* - getOrLoadSystemFallbackFont() retains the font in this service for repeated fallback lookup.
*/
class EE_API FontService {
friend class ResourceScope;
public:
/** Creates a service associated with @p resourceScope. ResourceScope owns its service. */
explicit FontService( ResourceScope& resourceScope );
/** @return The resource scope whose fonts and policy are managed by this service. */
ResourceScope& getResourceScope() const;
/** @return The configured color emoji font, or nullptr when none is configured. */
Font* getColorEmojiFont() const;
/**
* Sets the color emoji font. The font must be resolvable through the associated scope. Passing
* nullptr or an unrelated font clears the current value.
*/
void setColorEmojiFont( Font* font );
/** @return The configured monochrome emoji font, or nullptr when none is configured. */
Font* getEmojiFont() const;
/**
* Sets the monochrome emoji font. The font must be resolvable through the associated scope.
* Passing nullptr or an unrelated font clears the current value.
*/
void setEmojiFont( Font* font );
/** @return The strongly owned explicit fallback fonts in lookup order. */
const std::vector<FontPtr>& getFallbackFonts() const;
/** @return Whether at least one explicit fallback font is configured. */
bool hasFallbackFonts() const;
/** Adds an owning fallback handle unless the same font is already configured. */
bool addFallbackFont( FontPtr fallbackFont );
/**
* Adds a fallback font resolved through the associated scope.
* @return True when the font was found and added; false otherwise.
*/
bool addFallbackFont( Font* fallbackFont );
/** Removes the matching explicit fallback font without removing it from its resource scope. */
bool removeFallbackFont( Font* fallbackFont );
/** @return The policy used when loading and updating associated TrueType fonts. */
FontHinting getHinting() const;
/** Updates the hinting policy and applies it to associated non-emoji TrueType fonts. */
void setHinting( FontHinting hinting );
/** @return The antialiasing policy used by associated TrueType fonts. */
FontAntialiasing getAntialiasing() const;
/** Updates the antialiasing policy and applies it to associated non-emoji TrueType fonts. */
void setAntialiasing( FontAntialiasing antialiasing );
/**
* Finds a TrueType font visible through the associated scope by its runtime internal ID.
* @return A borrowed pointer, or nullptr when no matching font is visible.
*/
Font* getByInternalId( Uint32 internalId ) const;
/**
* Loads a standalone system font described by @p desc.
*
* The font is not published into the associated scope and is not retained by this service. The
* returned handle is its sole owner and can be released independently, immediately freeing its
* glyph pages when no other handle exists. Current hinting and antialiasing policy is applied
* at load time. The standalone font does not use this service for subsequent fallback
* resolution.
*
* @return An owning handle, or an empty handle when the descriptor cannot be loaded.
*/
ResourcePtr<FontTrueType> loadSystemFont( const FontDesc& desc );
/**
* Finds or loads a system fallback font described by @p desc.
*
* Successfully loaded fonts are published into the associated scope and strongly retained by
* the service for future glyph fallback requests. The returned pointer is borrowed and remains
* valid until the font is removed from the scope or the service is destroyed.
*
* @return A borrowed pointer to the cached font, or nullptr when loading fails.
*/
FontTrueType* getOrLoadSystemFallbackFont( const FontDesc& desc );
private:
FontPtr findHandle( Font* font ) const;
void onFontRemoved( Font* font );
ResourceScope& mResourceScope;
FontPtr mColorEmojiFont;
FontPtr mEmojiFont;
std::vector<FontPtr> mFallbackFonts;
std::vector<FontPtr> mSystemFallbackFonts;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
};
}} // namespace EE::Graphics
#endif

View File

@@ -13,12 +13,20 @@ class IOStream;
namespace EE { namespace Graphics {
class FontSprite;
class ResourceScope;
using FontSpritePtr = ResourcePtr<FontSprite>;
using FontSpriteWeakPtr = ResourceWeakPtr<FontSprite>;
/** @brief Implementation of XNA Font Sprites */
class EE_API FontSprite : public Font {
public:
static FontSprite* New( const std::string fontName );
static FontSpritePtr New( const std::string fontName );
static FontSpritePtr New( const std::string fontName, ResourceScope& resourceScope );
static FontSprite* New( const std::string fontName, const std::string& filename );
static FontSpritePtr New( const std::string fontName, const std::string& filename );
static FontSpritePtr New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope );
~FontSprite();
@@ -58,7 +66,7 @@ class EE_API FontSprite : public Font {
Float getUnderlineThickness( unsigned int characterSize ) const;
Texture* getTexture( unsigned int characterSize ) const;
const TexturePtr& getTexture( unsigned int characterSize ) const;
bool loaded() const;
@@ -75,8 +83,8 @@ class EE_API FontSprite : public Font {
GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph
GlyphDrawableTable
drawables; ///> Table mapping code points to their corresponding glyph drawables.
Texture* texture; ///< Texture containing the pixels of the glyphs
drawables; ///> Table mapping code points to their corresponding glyph drawables.
TexturePtr texture; ///< Texture containing the pixels of the glyphs
};
void cleanup();

View File

@@ -15,15 +15,26 @@ namespace EE { namespace Graphics {
enum class FontWeight : Uint16;
struct FontDesc;
class ResourceScope;
class FontTrueType;
class FontService;
using FontTrueTypePtr = ResourcePtr<FontTrueType>;
using FontTrueTypeWeakPtr = ResourceWeakPtr<FontTrueType>;
class EE_API FontTrueType : public Font {
public:
static FontTrueType* New( const std::string& FontName );
static FontTrueTypePtr New( const std::string& FontName );
static FontTrueTypePtr New( const std::string& FontName, ResourceScope& resourceScope );
static FontTrueType* New( const std::string& FontName, const std::string& filename );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
ResourceScope& resourceScope );
static FontTrueType* New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex, ResourceScope& resourceScope );
~FontTrueType();
@@ -48,6 +59,9 @@ class EE_API FontTrueType : public Font {
Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
Glyph getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
@@ -77,9 +91,10 @@ class EE_API FontTrueType : public Font {
Float getUnderlineThickness( unsigned int characterSize ) const;
Texture* getTexture( unsigned int characterSize ) const;
const TexturePtr& getTexture( unsigned int characterSize ) const;
bool loaded() const;
FontService* getFontService() const;
FontTrueType( const FontTrueType& ) = delete;
FontTrueType& operator=( const FontTrueType& ) = delete;
@@ -151,19 +166,19 @@ class EE_API FontTrueType : public Font {
virtual bool hasItalic() const { return mIsItalic || mFontItalic != nullptr; }
virtual bool hasBoldItalic() const { return isBoldItalic() || mFontBoldItalic; }
virtual bool hasBoldItalic() const { return isBoldItalic() || mFontBoldItalic != nullptr; }
FontTrueType* getBoldFont() const { return mFontBold; }
const FontTrueTypePtr& getBoldFont() const { return mFontBold; }
FontTrueType* getItalicFont() const { return mFontItalic; }
const FontTrueTypePtr& getItalicFont() const { return mFontItalic; }
FontTrueType* getBoldItalicFont() const { return mFontBoldItalic; }
const FontTrueTypePtr& getBoldItalicFont() const { return mFontBoldItalic; }
void setBoldFont( FontTrueType* fontBold );
void setBoldFont( const FontTrueTypePtr& fontBold );
void setItalicFont( FontTrueType* fontItalic );
void setItalicFont( const FontTrueTypePtr& fontItalic );
void setBoldItalicFont( FontTrueType* fontBoldItalic );
void setBoldItalicFont( const FontTrueTypePtr& fontBoldItalic );
void* face() const { return mFace; }
@@ -178,8 +193,11 @@ class EE_API FontTrueType : public Font {
protected:
friend class Text;
friend class TextLayout;
friend class FontService;
friend class ResourceScope;
explicit FontTrueType( const std::string& FontName );
explicit FontTrueType( const std::string& FontName, FontService& fontService );
void setFontService( FontService* fontService );
struct Row {
Row( unsigned int rowTop, unsigned int rowHeight ) :
@@ -201,11 +219,11 @@ class EE_API FontTrueType : public Font {
GlyphTable glyphs; ///< Table mapping code points to their corresponding glyph
GlyphDrawableTable
drawables; ///> Table mapping code points to their corresponding glyph drawables.
Texture* texture{ nullptr }; ///< Texture containing the pixels of the glyphs
std::vector<Row> rows; ///< List containing the position of all the existing rows
Uint32 fontInternalId{ 0 }; // The font internal id
unsigned int nextRow; ///< Y position of the next new row in the texture
drawables; ///> Table mapping code points to their corresponding glyph drawables.
TexturePtr texture; ///< Texture containing the pixels of the glyphs
std::vector<Row> rows; ///< List containing the position of all the existing rows
Uint32 fontInternalId{ 0 }; // The font internal id
unsigned int nextRow; ///< Y position of the next new row in the texture
const FontTrueType* font{ nullptr };
};
@@ -267,15 +285,14 @@ class EE_API FontTrueType : public Font {
mutable UnorderedMap<Uint32, std::tuple<Uint32, Uint32, bool>> mKeyCache;
mutable UnorderedMap<Uint64, Float> mKerningCache; // For codepoints (getKerning)
mutable UnorderedMap<Uint64, Float> mKerningGlyphCache; // For glyph indices
mutable UnorderedMap<unsigned int, UnorderedMap<Uint64, Float>> mGlyphAdvanceCache;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
FontService* mFontService{ nullptr };
Uint32 mFaceIndex{ 0 };
FontTrueType* mFontBold{ nullptr };
FontTrueType* mFontItalic{ nullptr };
FontTrueType* mFontBoldItalic{ nullptr };
Uint32 mFontBoldCb{ 0 };
Uint32 mFontItalicCb{ 0 };
Uint32 mFontBoldItalicCb{ 0 };
FontTrueTypePtr mFontBold;
FontTrueTypePtr mFontItalic;
FontTrueTypePtr mFontBoldItalic;
Float getGlyphTopOffset( unsigned int characterSize ) const;
@@ -284,12 +301,6 @@ class EE_API FontTrueType : public Font {
bool setFontFace( void* face );
void updateMonospaceState() const;
void disconnectBoldFont();
void disconnectItalicFont();
void disconnectBoldItalicFont();
};
}} // namespace EE::Graphics

View File

@@ -2,6 +2,7 @@
#define EE_GRAPHICSCFRAMEBUFFER_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/view.hpp>
@@ -13,6 +14,9 @@ using namespace EE::Window;
namespace EE { namespace Graphics {
class FrameBuffer;
using FrameBufferUniquePtr = std::unique_ptr<FrameBuffer, ResourceDeleter<FrameBuffer>>;
/** @brief A frame buffer allows rendering to a off-screen 2D texture */
class EE_API FrameBuffer {
public:
@@ -26,9 +30,10 @@ class EE_API FrameBuffer {
** @param window In case that the application is using more than one window, the user can
*indicate which one to use ( by default uses the current active window )
*/
static FrameBuffer* New( const Uint32& Width, const Uint32& Height, bool StencilBuffer = true,
bool DepthBuffer = false, bool useColorBuffer = false,
const Uint32& channels = 4, EE::Window::Window* window = NULL );
static FrameBufferUniquePtr New( const Uint32& Width, const Uint32& Height,
bool StencilBuffer = true, bool DepthBuffer = false,
bool useColorBuffer = false, const Uint32& channels = 4,
EE::Window::Window* window = NULL );
virtual ~FrameBuffer();
@@ -62,7 +67,7 @@ class EE_API FrameBuffer {
** The frame buffer must be unbinded before any rendering is done outside the frame buffer.
** For example MyFrameBufferPtr->getTexture()->Draw(0,0);
*/
Texture* getTexture() const;
const TexturePtr& getTexture() const;
/** @brief Sets the frame buffer clear color. */
void setClearColor( const ColorAf& color );
@@ -123,7 +128,7 @@ class EE_API FrameBuffer {
bool mHasStencilBuffer{ false };
bool mAdjustCurrentClipping{ true };
bool mNeedsToRestoreScissorsClipping{ false };
Texture* mTexture{ nullptr };
TexturePtr mTexture;
ColorAf mClearColor;
View mView;
float mProjMat[16];

View File

@@ -10,11 +10,12 @@ using namespace EE::System;
namespace EE { namespace Graphics { namespace Private {
class EE_API FrameBufferManager : public Container<FrameBuffer> {
SINGLETON_DECLARE_HEADERS( FrameBufferManager )
/** Non-owning registry of framebuffers visible to the active graphics context. */
class EE_API FrameBufferRegistry : public Container<FrameBuffer> {
SINGLETON_DECLARE_HEADERS( FrameBufferRegistry )
public:
virtual ~FrameBufferManager();
virtual ~FrameBufferRegistry();
FrameBuffer* getCurrentlyBound();
@@ -23,7 +24,7 @@ class EE_API FrameBufferManager : public Container<FrameBuffer> {
FrameBuffer* getFromId( const String::HashType& id );
protected:
FrameBufferManager();
FrameBufferRegistry();
};
}}} // namespace EE::Graphics::Private

View File

@@ -1,27 +0,0 @@
#ifndef EE_GRAPHICSCGLOBALTEXTUREATLAS_HPP
#define EE_GRAPHICSCGLOBALTEXTUREATLAS_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
/** @brief Any TextureRegion that doesn't belong to an specific TextureAtlas ( a real texture atlas
texture ), goes here. This is useful to auto release the TextureRegions.
*/
class EE_API GlobalTextureAtlas : public TextureAtlas {
SINGLETON_DECLARE_HEADERS( GlobalTextureAtlas )
public:
~GlobalTextureAtlas();
protected:
GlobalTextureAtlas();
};
}} // namespace EE::Graphics
#endif

View File

@@ -11,7 +11,7 @@ class VertexBuffer;
class EE_API GlyphDrawable : public DrawableResource {
public:
static GlyphDrawable* New( Texture* texture, const Rect& srcRect, const Sizef& destSize = {},
static GlyphDrawable* New( TexturePtr texture, const Rect& srcRect, const Sizef& destSize = {},
const std::string& resourceName = "" );
enum class DrawMode {
@@ -21,7 +21,7 @@ class EE_API GlyphDrawable : public DrawableResource {
///< italic skew
};
GlyphDrawable( Texture* texture, const Rect& srcRect, const Sizef& destSize = {},
GlyphDrawable( TexturePtr texture, const Rect& srcRect, const Sizef& destSize = {},
const std::string& resourceName = "" );
virtual void draw();
@@ -35,8 +35,10 @@ class EE_API GlyphDrawable : public DrawableResource {
virtual bool isStateful();
DrawablePtr clone() const;
/** @return The texture instance used by the GlyphDrawable. */
Texture* getTexture();
const TexturePtr& getTexture() const;
/** @return The Texture sector that represents the GlyphDrawable */
const Rectf& getSrcRect() const;
@@ -69,7 +71,7 @@ class EE_API GlyphDrawable : public DrawableResource {
void setAdvance( Float advance );
protected:
Texture* mTexture;
TexturePtr mTexture;
Rectf mSrcRect;
Sizef mDestSize;
Float mPixelDensity;

View File

@@ -7,6 +7,10 @@
namespace EE { namespace Graphics {
class NinePatch;
using NinePatchPtr = ResourcePtr<NinePatch>;
using NinePatchWeakPtr = ResourceWeakPtr<NinePatch>;
class EE_API NinePatch : public DrawableResource {
public:
enum NinePatchSides {
@@ -22,16 +26,16 @@ class EE_API NinePatch : public DrawableResource {
SideCount
};
static NinePatch* New( ResourceId textureId, int left, int top, int right, int bottom,
const Float& pixelDensity = 1, const std::string& name = "" );
static NinePatchPtr New( ResourceId textureId, int left, int top, int right, int bottom,
const Float& pixelDensity = 1, const std::string& name = "" );
static NinePatch* New( Texture* tex, int left, int top, int right, int bottom,
const Float& pixelDensity = 1, const std::string& name = "" );
static NinePatchPtr New( TexturePtr tex, int left, int top, int right, int bottom,
const Float& pixelDensity = 1, const std::string& name = "" );
static NinePatch* New( TextureRegion* textureRegion, int left, int top, int right, int bottom,
const std::string& name = "" );
static NinePatchPtr New( TextureRegion* textureRegion, int left, int top, int right, int bottom,
const std::string& name = "" );
NinePatch( Texture* tex, int left, int top, int right, int bottom,
NinePatch( TexturePtr tex, int left, int top, int right, int bottom,
const Float& pixelDensity = 1, const std::string& name = "" );
NinePatch( TextureRegion* textureRegion, int left, int top, int right, int bottom,
@@ -51,17 +55,19 @@ class EE_API NinePatch : public DrawableResource {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
TextureRegion* getTextureRegion( const int& side );
protected:
TextureRegion* mDrawable[SideCount];
TextureRegionPtr mDrawable[SideCount];
Rect mRect;
Rectf mRectf;
Sizef mSize;
Sizef mDestSize;
Float mPixelDensity;
void createFromTexture( Texture* tex, int left, int top, int right, int bottom );
void createFromTexture( const TexturePtr& tex, int left, int top, int right, int bottom );
virtual void onAlphaChange();

View File

@@ -1,21 +0,0 @@
#ifndef EE_GRAPHICS_NINEPATCHMANAGER_HPP
#define EE_GRAPHICS_NINEPATCHMANAGER_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/ninepatch.hpp>
#include <eepp/system/resourcemanager.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
class EE_API NinePatchManager : public ResourceManager<NinePatch> {
SINGLETON_DECLARE_HEADERS( NinePatchManager )
~NinePatchManager();
};
}} // namespace EE::Graphics
#endif

View File

@@ -12,6 +12,7 @@ using namespace EE::System;
namespace EE { namespace Graphics {
class Texture;
using TexturePtr = ResourcePtr<Texture>;
/** @enum EE::Graphics::ParticleEffect Predefined effects for the particle system. Use Callback when
* wan't to create a new effect, o set the parameters using NoFx, but it's much more limited. */
@@ -157,7 +158,7 @@ class EE_API ParticleSystem {
private:
Particle* mParticle;
Uint32 mPCount;
const Texture* mTexture;
TexturePtr mTexture;
Uint32 mPLeft;
Uint32 mLoops;

View File

@@ -3,11 +3,10 @@
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/primitivetype.hpp>
#include <eepp/graphics/vertexbuffer.hpp>
namespace EE { namespace Graphics {
class VertexBuffer;
class EE_API PrimitiveDrawable : public Drawable {
public:
virtual ~PrimitiveDrawable();
@@ -47,7 +46,7 @@ class EE_API PrimitiveDrawable : public Drawable {
bool mNeedsUpdate;
bool mRecreateVertexBuffer;
bool mSmooth{ false };
VertexBuffer* mVertexBuffer;
VertexBufferUniquePtr mVertexBuffer;
virtual void onAlphaChange();

View File

@@ -28,6 +28,8 @@ class EE_API RectangleDrawable : public PrimitiveDrawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
Float getRotation() const;
void setRotation( const Float& rotation );

View File

@@ -68,7 +68,7 @@ class EE_API RendererGL3 : public RendererGLShader {
void reloadCurrentShader();
protected:
ShaderProgram* mShaders[EEGL3_SHADERS_COUNT];
ShaderProgramPtr mShaders[EEGL3_SHADERS_COUNT];
int mAttribsLoc[EEGL_ARRAY_STATES_COUNT];
int mAttribsLocStates[EEGL_ARRAY_STATES_COUNT];
int mPlanes[EE_MAX_PLANES];

View File

@@ -70,7 +70,7 @@ class EE_API RendererGL3CP : public RendererGLShader {
void reloadCurrentShader();
protected:
ShaderProgram* mShaders[EEGL3CP_SHADERS_COUNT];
ShaderProgramPtr mShaders[EEGL3CP_SHADERS_COUNT];
unsigned int mVAO;
unsigned int mVBO[8];
int mAttribsLoc[EEGL_ARRAY_STATES_COUNT];

View File

@@ -74,7 +74,7 @@ class EE_API RendererGLES2 : public RendererGLShader {
void reloadCurrentShader();
protected:
ShaderProgram* mShaders[EEGLES2_SHADERS_COUNT];
ShaderProgramPtr mShaders[EEGLES2_SHADERS_COUNT];
int mAttribsLoc[EEGL_ARRAY_STATES_COUNT];
int mAttribsLocStates[EEGL_ARRAY_STATES_COUNT];
int mPlanes[EE_MAX_PLANES];

View File

@@ -1,7 +1,11 @@
#ifndef EE_GRAPHICS_RESOURCE_HPP
#define EE_GRAPHICS_RESOURCE_HPP
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <eepp/core.hpp>
@@ -25,6 +29,58 @@ class ResourceId {
Uint64 mValue{ 0 };
};
/**
* Strong 64-bit hash of a semantic resource name.
*
* This is a fast, process-local convenience key for trusted resource names. It is deliberately
* distinct from String::HashType so legacy 32-bit hashes cannot enter resource-name APIs through
* an implicit integer conversion. Complete ResourceKey values remain the authoritative identity
* whenever collision safety or persistence is required.
*/
class ResourceNameHash {
public:
constexpr ResourceNameHash() = default;
explicit constexpr ResourceNameHash( Uint64 value ) : mValue( value ) {}
constexpr Uint64 value() const { return mValue; }
explicit constexpr operator bool() const { return mValue != 0; }
constexpr bool operator==( const ResourceNameHash& other ) const {
return mValue == other.mValue;
}
constexpr bool operator!=( const ResourceNameHash& other ) const { return !( *this == other ); }
constexpr bool operator<( const ResourceNameHash& other ) const {
return mValue < other.mValue;
}
private:
Uint64 mValue{ 0 };
};
/**
* Hashes a semantic resource name with the vendored wyhash implementation used by
* UnorderedMap. Do not serialize the result: use the complete ResourceKey in persistent formats.
*/
inline ResourceNameHash resourceNameHash( std::string_view name ) {
return ResourceNameHash( ankerl::unordered_dense::hash<std::string_view>{}( name ) );
}
/** Immutable semantic lookup key. Catalog equality always compares the complete key value. */
class ResourceKey {
public:
ResourceKey() = default;
explicit ResourceKey( std::string value ) : mValue( std::move( value ) ) {}
const std::string& value() const { return mValue; }
bool empty() const { return mValue.empty(); }
bool operator==( const ResourceKey& other ) const { return mValue == other.mValue; }
bool operator!=( const ResourceKey& other ) const { return !( *this == other ); }
private:
std::string mValue;
};
template <typename T> using ResourcePtr = std::shared_ptr<T>;
template <typename T> using ResourceWeakPtr = std::weak_ptr<T>;
@@ -33,6 +89,26 @@ template <typename T> struct ResourceDeleter {
void operator()( T* resource ) const noexcept { eeDelete( resource ); }
};
template <typename T, typename... Args> ResourcePtr<T> makeResource( Args&&... args ) {
return ResourcePtr<T>( eeNew( T, ( std::forward<Args>( args )... ) ), ResourceDeleter<T>() );
}
}} // namespace EE::Graphics
namespace std {
template <> struct hash<EE::Graphics::ResourceId> {
std::size_t operator()( const EE::Graphics::ResourceId& id ) const noexcept {
return std::hash<EE::Uint64>{}( id.value() );
}
};
template <> struct hash<EE::Graphics::ResourceNameHash> {
std::size_t operator()( const EE::Graphics::ResourceNameHash& hash ) const noexcept {
return std::hash<EE::Uint64>{}( hash.value() );
}
};
} // namespace std
#endif

View File

@@ -0,0 +1,174 @@
#ifndef EE_GRAPHICS_RESOURCECATALOG_HPP
#define EE_GRAPHICS_RESOURCECATALOG_HPP
#include <eepp/core/containers.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/shaderprogram.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/system/mutex.hpp>
namespace EE { namespace Graphics {
class ResourceCatalog;
using ResourceCatalogPtr = ResourcePtr<ResourceCatalog>;
/**
* @brief Thread-safe, strongly owning collection of named graphics resources.
*
* A catalog maps semantic string keys to textures, drawable sources, texture atlases, and fonts.
* Publishing a resource gives the catalog shared ownership of it. Publishing another resource of
* the same kind under the same key replaces that binding; the key and resource name are never
* changed automatically. Publishing a null handle is equivalent to erasing the corresponding key,
* while an empty key is ignored.
*
* Lookups return owning handles. A resource obtained from a catalog therefore remains alive even
* if its binding is subsequently replaced, erased, or the catalog is cleared. Final handles are
* released after dropping the catalog mutex so resource destruction and callbacks never execute
* while the catalog is locked.
*
* Drawable and font hash lookups use resourceNameHash() as a direct secondary index. The dedicated
* 64-bit hash provides a cheap expected-O(1) convenience lookup for trusted names without changing
* the repository-wide 32-bit String::HashType. A hash is not mathematically collision-free, so
* complete ResourceKey lookup remains authoritative and must be used for attacker-controlled names
* or persistent identity. ResourceNameHash values are process-local conveniences and must not be
* serialized.
*
* ResourceCatalog performs no parent, scene, live-registry, filesystem, or fallback search. A
* ResourceScope defines lookup precedence by searching its local catalog and then explicitly
* imported catalogs. Importing a catalog shares this object and its live contents; it does not copy
* any resource.
*
* All public operations are safe to call concurrently. Enumeration methods return snapshots and
* allocate vectors containing owning handles.
*/
class EE_API ResourceCatalog {
public:
/** @return A new empty catalog using eepp resource allocation and deletion. */
static ResourceCatalogPtr New();
/** @brief Publishes or replaces a texture binding. A null texture erases @p key. */
void publish( ResourceKey key, TexturePtr texture );
/** @copydoc publish(ResourceKey,TexturePtr) */
void publish( std::string key, TexturePtr texture );
/** @brief Publishes or replaces a drawable-source binding. A null drawable erases @p key. */
void publishDrawable( ResourceKey key, DrawablePtr drawable );
/** @copydoc publishDrawable(ResourceKey,DrawablePtr) */
void publishDrawable( std::string key, DrawablePtr drawable );
/** @brief Publishes or replaces a texture-atlas binding. A null atlas erases @p key. */
void publishAtlas( ResourceKey key, TextureAtlasPtr atlas );
/** @copydoc publishAtlas(ResourceKey,TextureAtlasPtr) */
void publishAtlas( std::string key, TextureAtlasPtr atlas );
/** @brief Publishes or replaces a font binding. A null font erases @p key. */
void publishFont( ResourceKey key, FontPtr font );
/** @copydoc publishFont(ResourceKey,FontPtr) */
void publishFont( std::string key, FontPtr font );
/** @brief Publishes or replaces a shader-program binding. A null program erases @p key. */
void publishShaderProgram( ResourceKey key, ShaderProgramPtr program );
/** @copydoc publishShaderProgram(ResourceKey,ShaderProgramPtr) */
void publishShaderProgram( std::string key, ShaderProgramPtr program );
/** @return The texture bound to @p key, or an empty handle when it is not present. */
TexturePtr findTexture( const ResourceKey& key ) const;
/** @copydoc findTexture(const ResourceKey&)const */
TexturePtr findTexture( const std::string& key ) const;
/** @return The drawable source bound to @p key, or an empty handle when it is not present. */
DrawablePtr findDrawable( const ResourceKey& key ) const;
/** @copydoc findDrawable(const ResourceKey&)const */
DrawablePtr findDrawable( const std::string& key ) const;
/**
* @brief Looks up a drawable through the resourceNameHash(key) convenience index.
*/
DrawablePtr findDrawable( ResourceNameHash hash ) const;
/**
* @brief Legacy lookup for persisted 32-bit drawable hashes.
*
* This compatibility path scans full bindings and should not be used by new code. Persistent
* formats should migrate to complete ResourceKey values rather than serializing another hash.
* If several names share @p legacyHash, which matching drawable is returned is unspecified.
*/
DrawablePtr findDrawable( String::HashType legacyHash ) const;
/** @return The texture atlas bound to @p key, or an empty handle when it is not present. */
TextureAtlasPtr findAtlas( const ResourceKey& key ) const;
/** @copydoc findAtlas(const ResourceKey&)const */
TextureAtlasPtr findAtlas( const std::string& key ) const;
/** @return An owning snapshot of all texture atlases currently published in this catalog. */
std::vector<TextureAtlasPtr> getAtlases() const;
/** @return The font bound to @p key, or an empty handle when it is not present. */
FontPtr findFont( const ResourceKey& key ) const;
/** @copydoc findFont(const ResourceKey&)const */
FontPtr findFont( const std::string& key ) const;
/**
* @brief Looks up a font through the resourceNameHash(key) convenience index.
*/
FontPtr findFont( ResourceNameHash hash ) const;
/** @return An owning snapshot of all fonts currently published in this catalog. */
std::vector<FontPtr> getFonts() const;
/** @return The shader program bound to @p key, or an empty handle when absent. */
ShaderProgramPtr findShaderProgram( const ResourceKey& key ) const;
/** @copydoc findShaderProgram(const ResourceKey&)const */
ShaderProgramPtr findShaderProgram( const std::string& key ) const;
/** @return An owning snapshot of all shader programs published in this catalog. */
std::vector<ShaderProgramPtr> getShaderPrograms() const;
/** @brief Removes the texture binding for @p key. @return Whether a binding was removed. */
bool erase( const ResourceKey& key );
/** @copydoc erase(const ResourceKey&) */
bool erase( const std::string& key );
/** @brief Removes the drawable binding for @p key. @return Whether a binding was removed. */
bool eraseDrawable( const ResourceKey& key );
/** @copydoc eraseDrawable(const ResourceKey&) */
bool eraseDrawable( const std::string& key );
/** @brief Removes the texture-atlas binding for @p key. @return Whether a binding was removed.
*/
bool eraseAtlas( const ResourceKey& key );
/** @copydoc eraseAtlas(const ResourceKey&) */
bool eraseAtlas( const std::string& key );
/** @brief Removes the font binding for @p key. @return Whether a binding was removed. */
bool eraseFont( const ResourceKey& key );
/** @copydoc eraseFont(const ResourceKey&) */
bool eraseFont( const std::string& key );
/**
* @brief Removes @p font only when its current name maps to that exact font in this catalog.
* @return Whether the matching binding was removed.
*/
bool eraseFont( Font* font );
/** @brief Removes the shader-program binding for @p key. */
bool eraseShaderProgram( const ResourceKey& key );
/** @copydoc eraseShaderProgram(const ResourceKey&) */
bool eraseShaderProgram( const std::string& key );
/** @brief Removes every binding while allowing previously returned handles to remain valid. */
void clear();
/** @return The total number of bindings of every supported resource kind. */
std::size_t size() const;
private:
mutable System::Mutex mMutex;
UnorderedMap<std::string, TexturePtr> mTextures;
UnorderedMap<std::string, DrawablePtr> mDrawables;
UnorderedMap<ResourceNameHash, DrawableWeakPtr> mDrawablesByNameHash;
UnorderedMap<std::string, TextureAtlasPtr> mAtlases;
UnorderedMap<std::string, FontPtr> mFonts;
UnorderedMap<ResourceNameHash, FontWeakPtr> mFontsByNameHash;
UnorderedMap<std::string, ShaderProgramPtr> mShaderPrograms;
};
}} // namespace EE::Graphics
#endif

View File

@@ -0,0 +1,127 @@
#ifndef EE_GRAPHICS_RESOURCESCOPE_HPP
#define EE_GRAPHICS_RESOURCESCOPE_HPP
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/resourcecatalog.hpp>
#include <eepp/graphics/textureregion.hpp>
namespace EE { namespace Graphics {
class ResourceScope;
using ResourceScopePtr = ResourcePtr<ResourceScope>;
/**
* @brief Graphics resource lookup boundary with local ownership and explicit catalog visibility.
*
* A scope owns resources published into its local catalog. Lookups search that local catalog first,
* followed by imported catalogs in import order. Importing a catalog retains the catalog and makes
* its resources visible; it does not copy resources and does not transfer them into the local
* catalog. Consequently, removing an import only removes lookup visibility and releases the
* scope's catalog reference.
*
* Use importCatalog() when resources owned by another lifetime boundary must be visible in this
* scope, such as application assets shared with a scene or a theme catalog used by UI widgets.
* Avoid importing unrelated scene or document catalogs: keeping imports explicit prevents name
* collisions and resource leakage between independent documents. UISceneNode imports the default
* resource catalog automatically unless that behavior is disabled at construction time.
*/
class EE_API ResourceScope {
public:
static ResourceScopePtr New();
ResourceScope();
~ResourceScope();
FontService& getFontService();
const FontService& getFontService() const;
TexturePtr findTexture( const ResourceKey& key ) const;
TexturePtr findTexture( const std::string& key ) const;
DrawablePtr findDrawableSource( const ResourceKey& key ) const;
DrawablePtr findDrawableSource( const std::string& key ) const;
DrawablePtr findDrawable( const std::string& name, bool firstSearchSprite = false ) const;
DrawablePtr findDrawable( ResourceNameHash hash ) const;
DrawablePtr findDrawable( String::HashType legacyHash ) const;
TextureAtlasPtr findAtlas( const ResourceKey& key ) const;
TextureAtlasPtr findAtlas( const std::string& key ) const;
std::vector<TextureAtlasPtr> getAtlases() const;
FontPtr findFont( const ResourceKey& key ) const;
FontPtr findFont( const std::string& key ) const;
FontPtr findFont( ResourceNameHash hash ) const;
std::vector<FontPtr> getFonts() const;
ShaderProgramPtr findShaderProgram( const ResourceKey& key ) const;
ShaderProgramPtr findShaderProgram( const std::string& key ) const;
std::vector<ShaderProgramPtr> getShaderPrograms() const;
std::vector<TextureRegionPtr>
findTextureRegionsByPattern( const std::string& name, const std::string& extension = "",
TextureAtlas* searchInTextureAtlas = nullptr ) const;
std::vector<TextureRegionPtr>
findTextureRegionsByPatternId( const String::HashType& id, const std::string& extension = "",
TextureAtlas* searchInTextureAtlas = nullptr ) const;
void publishLocal( ResourceKey key, TexturePtr texture );
void publishLocal( std::string key, TexturePtr texture );
void publishLocalDrawable( ResourceKey key, DrawablePtr drawable );
void publishLocalDrawable( std::string key, DrawablePtr drawable );
void publishLocalAtlas( ResourceKey key, TextureAtlasPtr atlas );
void publishLocalAtlas( std::string key, TextureAtlasPtr atlas );
/**
* @brief Publishes a font under @p key, replacing any existing local binding for that key.
*
* The requested semantic key is preserved. Fonts are never renamed to avoid a collision.
* A FontTrueType instance can belong locally to only one ResourceScope because it has one
* FontService association. To expose the same font to another scope, import this scope's local
* catalog instead of publishing the same handle locally again.
*/
void publishLocalFont( ResourceKey key, FontPtr font );
void publishLocalFont( std::string key, FontPtr font );
void publishLocalShaderProgram( ResourceKey key, ShaderProgramPtr program );
void publishLocalShaderProgram( std::string key, ShaderProgramPtr program );
bool eraseLocal( const ResourceKey& key );
bool eraseLocal( const std::string& key );
bool eraseLocalDrawable( const ResourceKey& key );
bool eraseLocalDrawable( const std::string& key );
bool eraseLocalAtlas( const ResourceKey& key );
bool eraseLocalAtlas( const std::string& key );
bool eraseLocalFont( const ResourceKey& key );
bool eraseLocalFont( const std::string& key );
bool eraseLocalFont( Font* font );
bool eraseLocalShaderProgram( const ResourceKey& key );
bool eraseLocalShaderProgram( const std::string& key );
void clearLocal();
/**
* @brief Makes resources from @p catalog visible after this scope's local resources.
*
* Importing the same catalog more than once has no effect. The catalog is retained strongly for
* as long as it remains imported. Catalog contents stay live: resources published after this
* call become visible without importing the catalog again.
*/
void importCatalog( ResourceCatalogPtr catalog );
/** @brief Removes an imported catalog without modifying the catalog or its resources. */
bool removeCatalog( const ResourceCatalogPtr& catalog );
/** @brief Removes every imported catalog while preserving this scope's local resources. */
void clearImports();
ResourceCatalogPtr getLocalCatalog() const;
private:
void attachFontService( const FontPtr& font );
void detachFontService( const FontPtr& font );
ResourceCatalogPtr mLocalCatalog;
FontService mFontService;
std::vector<ResourceCatalogPtr> mImports;
mutable System::Mutex mMutex;
};
/** Engine-owned process defaults for pure Graphics and application-wide resolution. */
EE_API ResourceCatalog& globalResourceCatalog();
EE_API ResourceScope& defaultResourceScope();
}} // namespace EE::Graphics
#endif

View File

@@ -89,7 +89,7 @@ class EE_API ScrollParallax {
const Vector2f& getSpeed() const;
private:
TextureRegion* mTextureRegion;
TextureRegionPtr mTextureRegion;
BlendMode mBlend;
Color mColor;
Vector2f mInitPos;

View File

@@ -2,12 +2,17 @@
#define EE_GRAPHICSCSHADER_H
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/system/pack.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
class Shader;
using ShaderPtr = ResourcePtr<Shader>;
using ShaderWeakPtr = ResourceWeakPtr<Shader>;
/** @brief The basic shader class. */
class EE_API Shader {
public:

View File

@@ -6,6 +6,10 @@
namespace EE { namespace Graphics {
class ShaderProgram;
using ShaderProgramPtr = ResourcePtr<ShaderProgram>;
using ShaderProgramWeakPtr = ResourceWeakPtr<ShaderProgram>;
/** @brief The Shader Program Class.
@short Program is a GPU-executed program that is ready to be used for manipulating geometry and
colors. * ShaderProgram can encapsulate vertex and fragment shaders or just one of them. If only
@@ -15,40 +19,42 @@ other stage.
class EE_API ShaderProgram {
public:
/** Creates an empty shader program */
static ShaderProgram* New( const std::string& Name = "" );
static ShaderProgramPtr New( const std::string& Name = "" );
/** Creates a program shader with a vector of shaders and link them. */
static ShaderProgram* New( const std::vector<Shader*>& Shaders, const std::string& Name = "" );
static ShaderProgramPtr New( const std::vector<ShaderPtr>& Shaders,
const std::string& Name = "" );
/** Creates a VertexShader from file and a Fragment Shader from file, and link them. */
static ShaderProgram* New( const std::string& VertexShaderFile,
const std::string& FragmentShaderFile,
const std::string& Name = "" );
static ShaderProgramPtr New( const std::string& VertexShaderFile,
const std::string& FragmentShaderFile,
const std::string& Name = "" );
/** Creates a VertexShader from memory and a Fragment Shader from memory, and link them. */
static ShaderProgram* New( const char* VertexShaderData, const Uint32& VertexShaderDataSize,
const char* FragmentShaderData, const Uint32& FragmentShaderDataSize,
const std::string& Name = "" );
static ShaderProgramPtr New( const char* VertexShaderData, const Uint32& VertexShaderDataSize,
const char* FragmentShaderData,
const Uint32& FragmentShaderDataSize,
const std::string& Name = "" );
/** Creates the vertex shader and fragment shader from two files inside a pack */
static ShaderProgram* New( Pack* Pack, const std::string& VertexShaderPath,
const std::string& FragmentShaderPath,
const std::string& Name = "" );
static ShaderProgramPtr New( Pack* Pack, const std::string& VertexShaderPath,
const std::string& FragmentShaderPath,
const std::string& Name = "" );
/** Creates the vertex and fragment shader from an array of strings */
static ShaderProgram* New( const char** VertexShaderData, const Uint32& NumLinesVS,
const char** FragmentShaderData, const Uint32& NumLinesFS,
const std::string& Name = "" );
static ShaderProgramPtr New( const char** VertexShaderData, const Uint32& NumLinesVS,
const char** FragmentShaderData, const Uint32& NumLinesFS,
const std::string& Name = "" );
typedef std::function<void( ShaderProgram* )> ShaderProgramReloadCb;
virtual ~ShaderProgram();
/** Add a new shader */
void addShader( Shader* Shader );
void addShader( ShaderPtr shader );
/** Add a vector of shaders */
void addShaders( const std::vector<Shader*>& Shaders );
void addShaders( const std::vector<ShaderPtr>& shaders );
virtual bool link();
@@ -151,7 +157,7 @@ class EE_API ShaderProgram {
bool mValid;
std::string mLinkLog;
std::vector<Shader*> mShaders;
std::vector<ShaderPtr> mShaders;
std::map<std::string, Int32> mUniformLocations;
std::map<std::string, Int32> mAttributeLocations;
@@ -159,15 +165,15 @@ class EE_API ShaderProgram {
void init();
void addToManager( const std::string& Name );
void addToRegistry( const std::string& Name );
void removeFromManager();
void removeFromRegistry();
/** Creates an empty shader program */
ShaderProgram( const std::string& Name = "" );
/** Construct a program shader with a vector of shaders and link them. */
ShaderProgram( const std::vector<Shader*>& Shaders, const std::string& Name = "" );
ShaderProgram( const std::vector<ShaderPtr>& Shaders, const std::string& Name = "" );
/** Constructor that creates a VertexShader from file and a Fragment Shader from file, and link
* them. */

View File

@@ -3,26 +3,23 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/shaderprogram.hpp>
#include <eepp/system/resourcemanager.hpp>
#include <eepp/system/container.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
/** @brief The Shader Program Manager is a singleton class that manages all the instances of Shader
Programs instantiated. Releases the Shader Program instances automatically. So the user doesn't
need to release any Shader Program instance. */
class EE_API ShaderProgramManager : public ResourceManager<ShaderProgram> {
SINGLETON_DECLARE_HEADERS( ShaderProgramManager )
/** Non-owning registry of shader programs associated with the active graphics context. */
class EE_API ShaderProgramRegistry : public Container<ShaderProgram> {
SINGLETON_DECLARE_HEADERS( ShaderProgramRegistry )
public:
virtual ~ShaderProgramManager();
virtual ~ShaderProgramRegistry();
void reload();
protected:
ShaderProgramManager();
ShaderProgramRegistry();
};
}} // namespace EE::Graphics

View File

@@ -11,6 +11,10 @@ using namespace EE::System;
namespace EE { namespace Graphics {
class Sprite;
class ResourceScope;
using SpritePtr = ResourcePtr<Sprite>;
/** @brief A Sprite controller class, can hold and control sprites animations. */
class EE_API Sprite : public Drawable {
public:
@@ -26,22 +30,28 @@ class EE_API Sprite : public Drawable {
SPRITE_EVENT_USER // User vents
};
static Sprite* New();
static SpritePtr New();
static Sprite* New( const std::string& name, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
static SpritePtr New( const std::string& name, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
static Sprite* New( TextureRegion* TextureRegion );
static SpritePtr New( ResourceScope& resourceScope, const std::string& name,
const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
static Sprite* New( ResourceId textureId, const Sizef& DestSize = Sizef( 0, 0 ),
const Vector2i& offset = Vector2i( 0, 0 ),
const Rect& TexSector = Rect( 0, 0, 0, 0 ) );
static SpritePtr New( TextureRegion* TextureRegion );
static Sprite* fromGif( IOStream& gif );
static SpritePtr New( ResourceId textureId, const Sizef& DestSize = Sizef( 0, 0 ),
const Vector2i& offset = Vector2i( 0, 0 ),
const Rect& TexSector = Rect( 0, 0, 0, 0 ) );
static SpritePtr fromGif( IOStream& gif );
/** Instantiate an empty sprite */
Sprite();
Sprite( const Sprite& other );
/** Creates an animated Sprite from a animation name. It will search for a pattern name.
* For example search for name "car" with extensions "png", i will try to find car00.png
* car01.png car02.png, and so on, it will continue if find something, otherwise it will stop (
@@ -51,11 +61,14 @@ class EE_API Sprite : public Drawable {
* @param SearchInTextureAtlas If you want only to search in a especific atlas ( NULL if you
* want to search in all atlases )
* @note Texture atlases saves the TextureRegions names without extension by default.
* @see TextureAtlasManager::GetTextureRegionsByPattern
* @see ResourceScope::findTextureRegionsByPattern
*/
Sprite( const std::string& name, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
Sprite( ResourceScope& resourceScope, const std::string& name,
const std::string& extension = "", TextureAtlas* SearchInTextureAtlas = NULL );
/** Creates a Sprite from a TextureRegion
** @param TextureRegion The TextureRegion to use */
Sprite( TextureRegion* TextureRegion );
@@ -211,7 +224,7 @@ class EE_API Sprite : public Drawable {
* @param TexSector The texture sector to be rendered ( default all the texture )
* @return True if success
*/
bool createStatic( Texture* tex, const Sizef& DestSize = Sizef( 0, 0 ),
bool createStatic( TexturePtr tex, const Sizef& DestSize = Sizef( 0, 0 ),
const Vector2i& offset = Vector2i( 0, 0 ),
const Rect& TexSector = Rect( 0, 0, 0, 0 ) );
@@ -238,7 +251,7 @@ class EE_API Sprite : public Drawable {
* @param TexSector The texture sector to be rendered ( default all the texture )
* @return The frame position or 0 if fails
*/
unsigned int addFrame( Texture* tex, const Sizef& DestSize = Sizef( 0, 0 ),
unsigned int addFrame( TexturePtr tex, const Sizef& DestSize = Sizef( 0, 0 ),
const Vector2i& offset = Vector2i( 0, 0 ),
const Rect& TexSector = Rect( 0, 0, 0, 0 ) );
@@ -253,13 +266,21 @@ class EE_API Sprite : public Drawable {
*/
bool addFrames( const std::vector<TextureRegion*> TextureRegions );
/** @see TextureAtlasManager::GetTextureRegionsByPattern */
/** @see ResourceScope::findTextureRegionsByPattern */
bool addFramesByPattern( const std::string& name, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
bool addFramesByPattern( ResourceScope& resourceScope, const std::string& name,
const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
bool addFramesByPatternId( const Uint32& TextureRegionId, const std::string& extension,
TextureAtlas* SearchInTextureAtlas );
bool addFramesByPatternId( ResourceScope& resourceScope, const Uint32& TextureRegionId,
const std::string& extension,
TextureAtlas* SearchInTextureAtlas = NULL );
/** Add a frame on an specific subframe to the sprite
* @param tex The texture
* @param NumFrame The Frame Number
@@ -269,7 +290,7 @@ class EE_API Sprite : public Drawable {
* @param TexSector The texture sector to be rendered ( default all the texture )
* @return True if success
*/
bool addSubFrame( Texture* tex, const unsigned int& NumFrame, const unsigned int& NumSubFrame,
bool addSubFrame( TexturePtr tex, const unsigned int& NumFrame, const unsigned int& NumSubFrame,
const Sizef& DestSize = Sizef( 0, 0 ),
const Vector2i& offset = Vector2i( 0, 0 ),
const Rect& TexSector = Rect( 0, 0, 0, 0 ) );
@@ -312,6 +333,8 @@ class EE_API Sprite : public Drawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
/** Set the number of repetitions of the animation. Any number below 0 the animation will loop.
*/
void setRepetitions( const int& Repeations );
@@ -379,8 +402,8 @@ class EE_API Sprite : public Drawable {
/** Pop the event callback id indicated. */
bool popEventsCallback( const Uint32& callbackId );
/** Creates a copy of the current sprite and returns it */
Sprite clone();
/** Creates an independent sprite sharing the same texture resources. */
SpritePtr cloneSprite() const;
/** Update the sprite animation */
void update( const Time& ElapsedTime );
@@ -391,14 +414,6 @@ class EE_API Sprite : public Drawable {
/** Fire a User Event in the sprite */
void fireEvent( const Uint32& Event );
Sprite& setAsTextureRegionOwner( bool set );
bool isTextureRegionOwner() const;
Sprite& setAsTextureOwner( bool set );
bool isTextureOwner() const;
protected:
enum SpriteFlags {
SPRITE_FLAG_AUTO_ANIM = ( 1 << 0 ),
@@ -406,8 +421,6 @@ class EE_API Sprite : public Drawable {
SPRITE_FLAG_ANIM_PAUSED = ( 1 << 2 ),
SPRITE_FLAG_ANIM_TO_FRAME_AND_STOP = ( 1 << 3 ),
SPRITE_FLAG_EVENTS_ENABLED = ( 1 << 4 ),
SPRITE_FLAG_TEXTURE_OWNER = ( 1 << 5 ),
SPRITE_FLAG_TEXTURE_REGION_OWNER = ( 1 << 6 ),
};
Uint32 mFlags{ SPRITE_FLAG_AUTO_ANIM | SPRITE_FLAG_EVENTS_ENABLED };
@@ -438,7 +451,7 @@ class EE_API Sprite : public Drawable {
UnorderedMap<Uint32, SpriteCbData> mCallbacks;
struct Frame {
std::vector<TextureRegion*> Spr;
std::vector<TextureRegionPtr> Spr;
};
std::vector<Frame> mFrames;
@@ -446,11 +459,12 @@ class EE_API Sprite : public Drawable {
void clearFrame();
void cleanUpResources();
unsigned int getFrame( const unsigned int& FrameNum );
unsigned int getSubFrame( const unsigned int& SubFrame );
bool addSubFrame( TextureRegionPtr textureRegion, const unsigned int& numFrame,
const unsigned int& numSubFrame );
};
}} // namespace EE::Graphics

View File

@@ -28,14 +28,15 @@ class EE_API StateListDrawable : public StatefulDrawable {
virtual bool isStateful();
DrawablePtr clone() const;
virtual StatefulDrawable* setState( Uint32 state );
virtual const Uint32& getState() const;
virtual Drawable* getStateDrawable( const Uint32& state );
virtual StateListDrawable* setStateDrawable( const Uint32& state, Drawable* drawable,
bool ownIt = false );
virtual StateListDrawable* setStateDrawable( const Uint32& state, DrawablePtr drawable );
virtual Sizef getStateSize( const Uint32& state );
@@ -56,8 +57,7 @@ class EE_API StateListDrawable : public StatefulDrawable {
protected:
Uint32 mCurrentState;
Drawable* mCurrentDrawable;
std::map<Uint32, Drawable*> mDrawables;
std::map<Drawable*, bool> mDrawablesOwnership;
std::map<Uint32, DrawablePtr> mDrawables;
std::map<Uint32, Color> mDrawableColors;
explicit StateListDrawable( const std::string& name = "" );

View File

@@ -48,7 +48,16 @@ class EE_API TextLayout {
LineWrapMode lineWrapMode = LineWrapMode::NoWrap, Uint32 wrapWidth = 0,
bool keepIndentation = false, Float initialXOffset = 0 );
static void clearLayoutCache();
/**
* Removes entries from the shared text-layout LRU cache.
*
* @param font Optional borrowed font identity. When provided, only layouts requested with this
* font or containing shaped glyphs produced by this font are evicted. Passing nullptr clears
* the entire cache. Font destruction uses selective eviction before its borrowed pointers
* become invalid.
*/
static void clearLayoutCache( Font* font = nullptr );
protected:
static void wrapLayout( const String::View& string, TextLayout&, LineWrapMode lineWrapMode,
Float wrapWidth, Float vspace, bool keepIndentation, Font* font,

View File

@@ -34,7 +34,7 @@ class EE_API Texture : public DrawableResource, public Image, private NonCopyabl
static Uint32 getMaximumSize();
/* @return an array of Textures and the delay of the first frame */
static std::pair<std::vector<Texture*>, int> loadGif( IOStream& stream );
static std::pair<std::vector<TexturePtr>, int> loadGif( IOStream& stream );
/** Set the OpenGL Texture Id (texture handle) */
void setHandle( const int& texture ) { mTexture = texture; }
@@ -294,6 +294,8 @@ class EE_API Texture : public DrawableResource, public Image, private NonCopyabl
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
/** @return The process-wide identity assigned to this texture. */
ResourceId getTextureId() const;

View File

@@ -3,18 +3,21 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/textureregion.hpp>
#include <eepp/system/resourcemanager.hpp>
using namespace EE::System;
#include <eepp/system/mutex.hpp>
namespace EE { namespace Graphics {
class TextureAtlas;
using TextureAtlasPtr = ResourcePtr<TextureAtlas>;
using TextureAtlasWeakPtr = ResourceWeakPtr<TextureAtlas>;
/** @brief The texture atlas class represents a large image containing a collection of sub-images,
* or "atlas" which contains many smaller sub-images. The texture atlas in eepp can represent more
* than one texture or image, but the common use should be a image with sub-images.
* More information about Texture Atlases: http://en.wikipedia.org/wiki/Texture_atlas */
class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
class EE_API TextureAtlas {
public:
static TextureAtlas* New( const std::string& name = "" );
static TextureAtlasPtr New( const std::string& name = "" );
/** Creates a new texture atlas with the given name. */
TextureAtlas( const std::string& name = "" );
@@ -22,21 +25,21 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
~TextureAtlas();
/** Adds a TextureRegion to the Texture Atlas */
TextureRegion* add( TextureRegion* textureRegion );
TextureRegionPtr add( TextureRegionPtr textureRegion );
/** Creates and add to the texture atlas a TextureRegion from a Texture. It will use the full
*Texture as a TextureRegion.
* @param textureId The texture identity
* @param Name The texture name ( if any )
*/
TextureRegion* add( ResourceId textureId, const std::string& Name = "" );
TextureRegionPtr add( ResourceId textureId, const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param textureId The texture identity
* @param SrcRect The texture part that will be used as the TextureRegion.
* @param Name The texture name ( if any )
*/
TextureRegion* add( ResourceId textureId, const Rect& SrcRect, const std::string& Name = "" );
TextureRegionPtr add( ResourceId textureId, const Rect& SrcRect, const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param textureId The texture identity
@@ -44,8 +47,8 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
* @param DestSize The destination size that the TextureRegion will have when rendered.
* @param Name The texture name ( if any )
*/
TextureRegion* add( ResourceId textureId, const Rect& SrcRect, const Sizef& DestSize,
const std::string& Name = "" );
TextureRegionPtr add( ResourceId textureId, const Rect& SrcRect, const Sizef& DestSize,
const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param textureId The texture identity
@@ -55,22 +58,22 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
*used.
* @param Name The texture name ( if any )
*/
TextureRegion* add( ResourceId textureId, const Rect& SrcRect, const Sizef& DestSize,
const Vector2i& Offset, const std::string& Name = "" );
TextureRegionPtr add( ResourceId textureId, const Rect& SrcRect, const Sizef& DestSize,
const Vector2i& Offset, const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion from a Texture. It will use the full
*Texture as a TextureRegion.
* @param tex The texture
* @param Name The texture name ( if any )
*/
TextureRegion* add( Texture* tex, const std::string& Name = "" );
TextureRegionPtr add( TexturePtr tex, const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param tex The texture
* @param SrcRect The texture part that will be used as the TextureRegion.
* @param Name The texture name ( if any )
*/
TextureRegion* add( Texture* tex, const Rect& SrcRect, const std::string& Name = "" );
TextureRegionPtr add( TexturePtr tex, const Rect& SrcRect, const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param tex The texture
@@ -78,8 +81,8 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
* @param DestSize The destination size that the TextureRegion will have when rendered.
* @param Name The texture name ( if any )
*/
TextureRegion* add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize,
const std::string& Name = "" );
TextureRegionPtr add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize,
const std::string& Name = "" );
/** Creates and add to the texture atlas a TextureRegion of the indicated part of the texture.
* @param tex The texture
@@ -89,8 +92,19 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
*used.
* @param Name The texture name ( if any )
*/
TextureRegion* add( Texture* tex, const Rect& SrcRect, const Sizef& DestSize,
const Vector2i& Offset, const std::string& Name = "" );
TextureRegionPtr add( TexturePtr tex, const Rect& SrcRect, const Sizef& DestSize,
const Vector2i& Offset, const std::string& Name = "" );
TextureRegionPtr getByName( const std::string& name ) const;
TextureRegionPtr getById( const String::HashType& id ) const;
bool remove( const TextureRegionPtr& textureRegion );
bool removeByName( const std::string& name );
bool removeById( const String::HashType& id );
bool exists( const std::string& name ) const;
bool existsId( const String::HashType& id ) const;
void clear();
void printNames() const;
const UnorderedMap<String::HashType, TextureRegionPtr>& getResources() const;
/** @return The texture atlas name. */
const std::string& getName() const;
@@ -108,7 +122,7 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
const String::HashType& getId() const;
/** @return The number of TextureRegions inside the texture atlas. */
Uint32 getCount();
Uint32 getCount() const;
/** @return The texture that corresponds to the texture atlas.
* @param texnum The texture index. A texture atlas can use more than one texture, so it can be
@@ -119,10 +133,10 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
* linked to a texture. \n The Global Texture Atlas for example doesn't have any texture linked
* to it.
*/
Texture* getTexture( const Uint32& texnum = 0 ) const;
const TexturePtr& getTexture( const Uint32& texnum = 0 ) const;
/** @return The number of textures linked to the texture atlas. */
Uint32 getTexturesCount();
Uint32 getTexturesCount() const;
protected:
friend class TextureAtlasLoader;
@@ -130,9 +144,11 @@ class EE_API TextureAtlas : public ResourceManager<TextureRegion> {
std::string mName;
String::HashType mId;
std::string mPath;
std::vector<Texture*> mTextures;
std::vector<TexturePtr> mTextures;
mutable System::Mutex mMutex;
UnorderedMap<String::HashType, TextureRegionPtr> mResources;
void setTextures( std::vector<Texture*> textures );
void setTextures( std::vector<TexturePtr> textures );
};
}} // namespace EE::Graphics

View File

@@ -3,6 +3,8 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/packerhelper.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/textureloader.hpp>
#include <eepp/system/iostream.hpp>
@@ -12,8 +14,6 @@ namespace EE { namespace Graphics {
using namespace Private;
class TextureAtlas;
/** @brief The Texture Atlas Loader loads any previously created Texture Atlas. */
class EE_API TextureAtlasLoader {
public:
@@ -146,13 +146,13 @@ class EE_API TextureAtlasLoader {
* 0 to GetTexturesLoadedCount(). Usually a texture atlas corresponds to only one texture, so
* the texture index is 0.
*/
Texture* getTexture( const Uint32& texnum = 0 ) const;
const TexturePtr& getTexture( const Uint32& texnum = 0 ) const;
/** @return The number of textures linked to the texture atlas. */
Uint32 getTexturesLoadedCount();
/** @return The texture atlas instance pointer ( NULL if the atlas isn't loaded yet ). */
TextureAtlas* getTextureAtlas() const;
const TextureAtlasPtr& getTextureAtlas() const;
/** Sets a load notification callback. */
void setLoadCallback( GLLoadCallback LoadCallback );
@@ -161,6 +161,11 @@ class EE_API TextureAtlasLoader {
void setTextureFilter( const Texture::Filter& textureFilter );
/** Sets the semantic texture lookup boundary used by subsequent loads. */
void setResourceScope( ResourceScopePtr resourceScope );
const ResourceScopePtr& getResourceScope() const;
protected:
std::string mTextureAtlasPath;
bool mThreaded;
@@ -168,13 +173,15 @@ class EE_API TextureAtlasLoader {
Pack* mPack;
bool mSkipResourceLoad;
std::atomic<bool> mIsLoading;
TextureAtlas* mTextureAtlas;
TextureAtlasPtr mTextureAtlas;
GLLoadCallback mLoadCallback;
std::vector<Texture*> mTexturesLoaded;
ResourceScopePtr mResourceScope;
std::vector<TexturePtr> mTexturesLoaded;
struct sTempTexAtlas {
sTextureHdr Texture;
std::vector<sTextureRegionHdr> TextureRegions;
TexturePtr LoadedTexture;
};
sTextureAtlasHdr mTexGrHdr;

View File

@@ -1,85 +0,0 @@
#ifndef EE_GRAPHICSCTEXTUREATLASMANAGER_HPP
#define EE_GRAPHICSCTEXTUREATLASMANAGER_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/graphics/textureregion.hpp>
#include <eepp/system/pack.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
/** @brief The Texture Atlas Manager is a singleton class that manages all the instances of Texture
Atlases instantiated. Releases the Texture Atlases instances automatically. So the user doesn't
need to release any Texture Atlas instance. */
class EE_API TextureAtlasManager : public ResourceManagerMulti<TextureAtlas> {
SINGLETON_DECLARE_HEADERS( TextureAtlasManager )
public:
virtual ~TextureAtlasManager();
/** Loads a texture atlas from its path ( the texture atlas binary is expected, not the texture,
* the ".eta" file ). */
TextureAtlas* loadFromFile( const std::string& TextureAtlasPath );
/** Loads a texture atlas from a io stream. */
TextureAtlas* loadFromStream( IOStream& IOS );
/** Loads a texture atlas from memory. */
TextureAtlas* loadFromMemory( const Uint8* Data, const Uint32& DataSize,
const std::string& TextureAtlasName );
/** Loads a texture atlas from a pack file. */
TextureAtlas* loadFromPack( Pack* Pack, const std::string& FilePackPath );
/** It will search for a TextureRegion Name in the texture atlases loaded.
* @return The first TextureRegion found with the given name in any atlas. */
TextureRegion* getTextureRegionByName( const std::string& Name );
/** It will search for a TextureRegion Id in the texture atlases loaded.
* @return The first TextureRegion found with the given id in any atlas. */
TextureRegion* getTextureRegionById( const String::HashType& Id );
/** Search for a pattern name
* For example search for name "car" with extensions "png", i will try to find car00.png
* car01.png car02.png, and so on, it will continue if find something, otherwise it will stop (
* it will always search at least for car00.png and car01.png )
* @param name First part of the sub texture name
* @param extension Extension of the sub texture name ( if have one, otherwise is empty )
* @param SearchInTextureAtlas If you want only to search in a especific atlas ( NULL if you
* want to search in all atlases )
* @note Texture atlases saves the TextureRegions names without extension by default.
*/
std::vector<TextureRegion*>
getTextureRegionsByPattern( const std::string& name, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
/** Search for a pattern id.
* This will look for the TextureRegion with the id passed, and it will try to find any pattern
*by the TextureRegion name.
* @see GetTextureRegionsByPattern
*/
std::vector<TextureRegion*>
getTextureRegionsByPatternId( const Uint32& TextureRegionId, const std::string& extension = "",
TextureAtlas* SearchInTextureAtlas = NULL );
/** Prints all the resources name to the screen. */
void printResources();
/** Sets if the warnings for not finding a resource must be printed in screen. */
void setPrintWarnings( const bool& warn );
/** @return If warnings are being printed. */
const bool& getPrintWarnings() const;
protected:
bool mWarnings;
TextureAtlasManager();
};
}} // namespace EE::Graphics
#endif

View File

@@ -0,0 +1,36 @@
#ifndef EE_GRAPHICS_TEXTUREDRAWABLE_HPP
#define EE_GRAPHICS_TEXTUREDRAWABLE_HPP
#include <eepp/graphics/drawableresource.hpp>
#include <eepp/graphics/texture.hpp>
namespace EE { namespace Graphics {
class TextureDrawable;
using TextureDrawablePtr = ResourcePtr<TextureDrawable>;
/** Per-consumer drawable state backed by a shared texture resource. */
class EE_API TextureDrawable : public DrawableResource {
public:
static TextureDrawablePtr New( TexturePtr texture );
explicit TextureDrawable( TexturePtr texture );
Sizef getSize();
Sizef getPixelsSize();
void draw();
void draw( const Vector2f& position );
void draw( const Vector2f& position, const Sizef& size );
bool isStateful();
DrawablePtr clone() const;
const TexturePtr& getTexture() const;
protected:
TexturePtr mTexture;
DrawableResourceConnection mTextureChangeConnection;
};
}} // namespace EE::Graphics
#endif

View File

@@ -21,7 +21,7 @@ struct TextureRegistryRecord {
using TextureRegistrySnapshot = std::vector<TextureRegistryRecord>;
/** @brief The Texture Manager Class. Here we do all the textures stuff. (Singleton Class) */
/** Creates textures and weakly observes every live texture for diagnostics. */
class EE_API TextureFactory : protected Mutex {
SINGLETON_DECLARE_HEADERS( TextureFactory )
@@ -39,7 +39,7 @@ class EE_API TextureFactory : protected Mutex {
* @param Filename A filename to recognize the texture.
* @return The created texture
*/
Texture* createEmptyTexture(
TexturePtr createEmptyTexture(
const unsigned int& Width, const unsigned int& Height, const unsigned int& Channels = 4,
const Color& DefaultColor = Color( 0, 0, 0, 255 ), const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
@@ -60,12 +60,13 @@ class EE_API TextureFactory : protected Mutex {
* outside the texture factory ).
* @return The texture loaded or null if error
*/
Texture* loadFromPixels( const unsigned char* Pixels, const unsigned int& Width,
const unsigned int& Height, const unsigned int& Channels,
const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
const std::string& FileName = std::string( "" ) );
TexturePtr
loadFromPixels( const unsigned char* Pixels, const unsigned int& Width,
const unsigned int& Height, const unsigned int& Channels,
const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
const std::string& FileName = std::string( "" ) );
/** Load a texture from Pack file
* @param Pack Pointer to the pack instance
@@ -79,7 +80,7 @@ class EE_API TextureFactory : protected Mutex {
* the image.
* @return The texture loaded or null if error
*/
Texture* loadFromPack(
TexturePtr loadFromPack(
Pack* Pack, const std::string& FilePackPath, const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
@@ -97,7 +98,7 @@ class EE_API TextureFactory : protected Mutex {
* the image.
* @return The texture loaded or null if error
*/
Texture* loadFromMemory(
TexturePtr loadFromMemory(
const unsigned char* ImagePtr, const unsigned int& Size, const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
@@ -114,7 +115,7 @@ class EE_API TextureFactory : protected Mutex {
* the image.
* @return The texture loaded or null if error
*/
Texture* loadFromStream(
TexturePtr loadFromStream(
IOStream& Stream, const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
@@ -131,24 +132,12 @@ class EE_API TextureFactory : protected Mutex {
* the image.
* @return The texture loaded or null if error
*/
Texture* loadFromFile(
TexturePtr loadFromFile(
const std::string& Filepath, const bool& Mipmap = false,
const Texture::ClampMode& ClampMode = Texture::ClampMode::ClampToEdge,
const bool& CompressTexture = false, const bool& KeepLocalCopy = false,
const Image::FormatConfiguration& imageformatConfiguration = Image::FormatConfiguration() );
/** Removes and unloads the texture identified by @p textureId.
* @param textureId The process-wide texture identity.
* @return True if was removed
*/
bool remove( ResourceId textureId );
/** Removes and Unload the Texture
* @param texture The texture pointer
* @return True if was removed
*/
bool remove( Texture* texture );
/** Binds the texture identity indicated. This is useful if you are rendering a texture
* outside this class.
* @param textureId The process-wide texture identity.
@@ -183,12 +172,9 @@ class EE_API TextureFactory : protected Mutex {
*/
void setCurrentTexture( const int& textureHandle, const Uint32& TextureUnit );
/** Returns the number of textures loaded */
/** Returns the number of currently live textures. */
Uint32 getTextureCount();
/** @return All the active textures */
std::vector<Texture*> getTextures();
/** @return A non-owning diagnostic snapshot of every currently live texture. */
TextureRegistrySnapshot snapshotTextures();
@@ -215,14 +201,11 @@ class EE_API TextureFactory : protected Mutex {
*/
unsigned int getValidTextureSize( const unsigned int& Size );
/** Determines whether the texture identity exists in the factory. */
/** Determines whether the texture identity is currently live. */
bool existsId( ResourceId textureId );
/** Determines whether the texture is retained by the factory. */
bool exists( const Texture* tex );
/** @return The texture matching @p textureId, or null if it is not factory-retained. */
Texture* getTexture( ResourceId textureId );
/** @return The live texture matching @p textureId, or null if it has expired. */
TexturePtr getTexture( ResourceId textureId );
/** @return The memory used by the textures (in bytes) */
unsigned int getTextureMemorySize();
@@ -243,24 +226,12 @@ class EE_API TextureFactory : protected Mutex {
* @param MemSize The size of the texture in memory ( just if you need to specify the real size
* in memory, just useful to calculate the total texture memory ).
*/
Texture* pushTexture( const std::string& Filepath, const Uint32& textureHandle,
const unsigned int& Width, const unsigned int& Height,
const unsigned int& ImgWidth, const unsigned int& ImgHeight,
const bool& Mipmap, const unsigned int& Channels,
const Texture::ClampMode& ClampMode, const bool& CompressTexture,
const bool& LocalCopy = false, const Uint32& MemSize = 0 );
/** Return a texture by it file path name
* @param Name File path name
* @return The texture, NULL if not exists.
*/
Texture* getByName( const std::string& Name );
/** Return a texture by it hash path name
* @param Hash The file path hash
* @return The texture, NULL if not exists
*/
Texture* getByHash( const String::HashType& hash );
TexturePtr pushTexture( const std::string& Filepath, const Uint32& textureHandle,
const unsigned int& Width, const unsigned int& Height,
const unsigned int& ImgWidth, const unsigned int& ImgHeight,
const bool& Mipmap, const unsigned int& Channels,
const Texture::ClampMode& ClampMode, const bool& CompressTexture,
const bool& LocalCopy = false, const Uint32& MemSize = 0 );
~TextureFactory();
@@ -273,8 +244,6 @@ class EE_API TextureFactory : protected Mutex {
std::vector<int> mCurrentTexture;
using TextureMap = UnorderedMap<Uint64, TexturePtr>;
struct LiveTextureRecord {
ResourceId id;
TextureWeakPtr texture;
@@ -284,17 +253,16 @@ class EE_API TextureFactory : protected Mutex {
void operator()( Texture* texture ) const noexcept;
};
TextureMap mTextures;
UnorderedMap<Uint64, LiveTextureRecord> mLiveTextures;
std::vector<Texture*> mReleasedTextures;
std::atomic<Uint64> mLiveTextureGeneration{ 0 };
Texture::CoordinateType mLastCoordinateType;
void unloadTextures();
void resetTextureBinding( const Texture* texture );
/** Thread-safe final-handle handoff. Actual Texture destruction remains graphics-thread-only.
*/
void queueReleasedTexture( Texture* texture );
void diagnoseLiveTexturesAtShutdown();

View File

@@ -89,9 +89,9 @@ class EE_API TextureLoader {
* is done. */
void setColorKey( RGB Color );
/** @brief Releases the texture loaded ( if was already loaded ), it will destroy the texture
* from memory. */
void unload();
/** Clears the loader state and releases its texture handle. Other texture owners remain valid.
*/
void reset();
/** @return The file path to the texture ( if any ) */
const std::string& getFilepath() const;
@@ -100,7 +100,7 @@ class EE_API TextureLoader {
ResourceId getId() const;
/** @return The texture instance ( if it was loaded ). */
Texture* getTexture() const;
const TexturePtr& getTexture() const;
Image::FormatConfiguration getFormatConfiguration() const;
@@ -112,7 +112,7 @@ class EE_API TextureLoader {
protected:
Uint32 mLoadType{ 0 }; // From memory, from path, from pack
Uint8* mPixels{ nullptr }; // Texture Info
Texture* mTexture{ nullptr };
TexturePtr mTexture;
Int32 mImgWidth{ 0 };
Int32 mImgHeight{ 0 };
@@ -133,18 +133,18 @@ class EE_API TextureLoader {
RGB* mColorKey{ nullptr };
Image::FormatConfiguration mFormatConfiguration;
void reset();
private:
bool mLoaded{ false };
bool mTexLoaded{ false };
bool mDirectUpload{ false };
bool mPixelsUseSystemFree{ false };
Image::Format mImgType{ 0 };
int mIsCompressed{ 0 };
Clock mTE;
void loadFile();
void freePixels();
void loadFromFile();
void loadFromMemory();
void loadFromPack();

View File

@@ -8,31 +8,36 @@
namespace EE { namespace Graphics {
class TextureRegion;
using TextureRegionPtr = ResourcePtr<TextureRegion>;
using TextureRegionWeakPtr = ResourceWeakPtr<TextureRegion>;
/** @brief A TextureRegion is a part of a texture that represent an sprite.*/
class EE_API TextureRegion : public DrawableResource {
public:
static TextureRegion* New();
static TextureRegionPtr New();
static TextureRegion* New( ResourceId textureId, const std::string& name = "" );
static TextureRegionPtr New( ResourceId textureId, const std::string& name = "" );
static TextureRegion* New( ResourceId textureId, const Rect& srcRect,
const std::string& name = "" );
static TextureRegionPtr New( ResourceId textureId, const Rect& srcRect,
const std::string& name = "" );
static TextureRegion* New( ResourceId textureId, const Rect& srcRect, const Sizef& destSize,
const std::string& name = "" );
static TextureRegionPtr New( ResourceId textureId, const Rect& srcRect, const Sizef& destSize,
const std::string& name = "" );
static TextureRegion* New( ResourceId textureId, const Rect& srcRect, const Sizef& destSize,
const Vector2i& offset, const std::string& name = "" );
static TextureRegionPtr New( ResourceId textureId, const Rect& srcRect, const Sizef& destSize,
const Vector2i& offset, const std::string& name = "" );
static TextureRegion* New( Texture* tex, const std::string& name = "" );
static TextureRegionPtr New( TexturePtr tex, const std::string& name = "" );
static TextureRegion* New( Texture* tex, const Rect& srcRect, const std::string& name = "" );
static TextureRegionPtr New( TexturePtr tex, const Rect& srcRect,
const std::string& name = "" );
static TextureRegion* New( Texture* tex, const Rect& srcRect, const Sizef& destSize,
const std::string& name = "" );
static TextureRegionPtr New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize,
const std::string& name = "" );
static TextureRegion* New( Texture* tex, const Rect& srcRect, const Sizef& destSize,
const Vector2i& offset, const std::string& name = "" );
static TextureRegionPtr New( TexturePtr tex, const Rect& srcRect, const Sizef& destSize,
const Vector2i& offset, const std::string& name = "" );
/** Creates an empty TextureRegion */
TextureRegion();
@@ -41,14 +46,14 @@ class EE_API TextureRegion : public DrawableResource {
* @param tex The texture
* @param name The texture name ( if any )
*/
TextureRegion( Texture* tex, const std::string& name = "" );
TextureRegion( TexturePtr tex, const std::string& name = "" );
/** Creates a TextureRegion of the indicated part of the texture.
* @param tex The texture
* @param srcRect The texture part that will be used as the TextureRegion.
* @param name The texture name ( if any )
*/
TextureRegion( Texture* tex, const Rect& srcRect, const std::string& name = "" );
TextureRegion( TexturePtr tex, const Rect& srcRect, const std::string& name = "" );
/** Creates a TextureRegion of the indicated part of the texture.
* @param tex The texture
@@ -56,7 +61,7 @@ class EE_API TextureRegion : public DrawableResource {
* @param destSize The destination size that the TextureRegion will have when rendered.
* @param name The texture name ( if any )
*/
TextureRegion( Texture* tex, const Rect& srcRect, const Sizef& destSize,
TextureRegion( TexturePtr tex, const Rect& srcRect, const Sizef& destSize,
const std::string& name = "" );
/** Creates a TextureRegion of the indicated part of the texture.
@@ -67,8 +72,8 @@ class EE_API TextureRegion : public DrawableResource {
*used.
* @param name The texture name ( if any )
*/
TextureRegion( Texture* tex, const Rect& srcRect, const Sizef& destSize, const Vector2i& offset,
const std::string& name = "" );
TextureRegion( TexturePtr tex, const Rect& srcRect, const Sizef& destSize,
const Vector2i& offset, const std::string& name = "" );
virtual ~TextureRegion();
@@ -76,7 +81,7 @@ class EE_API TextureRegion : public DrawableResource {
void setTextureId( ResourceId textureId );
/** Set the Texture that holds the TextureRegion. */
void setTexture( Texture* texture );
void setTexture( TexturePtr texture );
/** @return The Texture sector that represents the TextureRegion */
const Rect& getSrcRect() const;
@@ -126,8 +131,10 @@ class EE_API TextureRegion : public DrawableResource {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
/** @return The texture instance used by the TextureRegion. */
Graphics::Texture* getTexture();
const TexturePtr& getTexture() const;
/** Replaces a color in the TextureRegion ( needs Lock() ) */
void replaceColor( Color ColorKey, Color NewColor );
@@ -204,7 +211,7 @@ class EE_API TextureRegion : public DrawableResource {
protected:
Uint8* mPixels;
Uint8* mAlphaMask;
Graphics::Texture* mTexture;
TexturePtr mTexture;
Rect mSrcRect;
Sizef mOriDestSize;
Sizef mDestSize;

View File

@@ -28,6 +28,8 @@ class EE_API TriangleDrawable : public PrimitiveDrawable {
virtual bool isStateful() { return false; }
DrawablePtr clone() const;
void setSize( const Sizef& size );
const Triangle2f& getTriangle() const;
@@ -41,7 +43,7 @@ class EE_API TriangleDrawable : public PrimitiveDrawable {
Triangle2f mComputedTriangle;
Sizef mSize;
Color mColors[3];
bool mCustomColors;
bool mCustomColors{ false };
virtual void onColorFilterChange();

View File

@@ -3,6 +3,7 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/primitivetype.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/vertexbufferhelper.hpp>
#include <eepp/system/color.hpp>
@@ -10,6 +11,9 @@ using namespace EE::System;
namespace EE { namespace Graphics {
class VertexBuffer;
using VertexBufferUniquePtr = std::unique_ptr<VertexBuffer, ResourceDeleter<VertexBuffer>>;
/** @brief The vertex buffer class holds vertex data. The vertex position, colors, texture
*coordinates and indexes. This is useful to accelerate and encapsulate data.
*/
@@ -27,14 +31,14 @@ class EE_API VertexBuffer {
*extensions are supported ( almost for sure that it's supported ). More information here:
*http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml
*/
static VertexBuffer* New( const Uint32& vertexFlags = VERTEX_FLAGS_DEFAULT,
PrimitiveType drawType = PRIMITIVE_QUADS,
const Int32& reserveVertexSize = 0, const Int32& reserveIndexSize = 0,
VertexBufferUsageType usageType = VertexBufferUsageType::Static );
static VertexBufferUniquePtr
New( const Uint32& vertexFlags = VERTEX_FLAGS_DEFAULT, PrimitiveType drawType = PRIMITIVE_QUADS,
const Int32& reserveVertexSize = 0, const Int32& reserveIndexSize = 0,
VertexBufferUsageType usageType = VertexBufferUsageType::Static );
/** Creates the simple vertex array implementation ( without VBOs or VAO ), which it's faster
* for many cases. */
static VertexBuffer*
static VertexBufferUniquePtr
NewVertexArray( const Uint32& vertexFlags = VERTEX_FLAGS_DEFAULT,
PrimitiveType drawType = PRIMITIVE_QUADS, const Int32& reserveVertexSize = 0,
const Int32& reserveIndexSize = 0,
@@ -215,7 +219,7 @@ class EE_API VertexBuffer {
// Creates a rounded rectangle.
Polygon2f Poly = Polygon2f::createRoundedRectangle( 0, 0, 256, 50 );
VertexBuffer * VBO = VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN );
auto VBO = VertexBuffer::New( VERTEX_FLAGS_PRIMITIVE, PRIMITIVE_TRIANGLE_FAN );
if ( NULL != VBO ) {
// Upload the rounded rectangle data to the vertex buffer.

View File

@@ -10,16 +10,17 @@ using namespace EE::System;
namespace EE { namespace Graphics { namespace Private {
class EE_API VertexBufferManager : public Container<VertexBuffer> {
SINGLETON_DECLARE_HEADERS( VertexBufferManager )
/** Non-owning registry of vertex buffers visible to the active graphics context. */
class EE_API VertexBufferRegistry : public Container<VertexBuffer> {
SINGLETON_DECLARE_HEADERS( VertexBufferRegistry )
public:
virtual ~VertexBufferManager();
virtual ~VertexBufferRegistry();
void reload();
protected:
VertexBufferManager();
VertexBufferRegistry();
};
}}} // namespace EE::Graphics::Private

View File

@@ -1,14 +1,12 @@
#ifndef EE_SCENENODE_HPP
#define EE_SCENENODE_HPP
#include <eepp/graphics/framebuffer.hpp>
#include <eepp/scene/node.hpp>
#include <eepp/system/translator.hpp>
#include <eepp/window/cursor.hpp>
#include <unordered_set>
namespace EE { namespace Graphics {
class FrameBuffer;
}} // namespace EE::Graphics
using namespace EE::Graphics;
namespace EE { namespace Window {
@@ -421,7 +419,7 @@ class EE_API SceneNode : public Node {
EE::Window::Window* mWindow;
ActionManager* mActionManager;
FrameBuffer* mFrameBuffer;
Graphics::FrameBufferUniquePtr mFrameBuffer;
EventDispatcher* mEventDispatcher;
CloseList mCloseList;
Clock mClock;

View File

@@ -36,7 +36,6 @@
#include <eepp/system/rc4.hpp>
#include <eepp/system/regex.hpp>
#include <eepp/system/resourceloader.hpp>
#include <eepp/system/resourcemanager.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <eepp/system/scopedop.hpp>
#include <eepp/system/singleton.hpp>

View File

@@ -1,411 +0,0 @@
#ifndef EE_SYSTEMTRESOURCEMANAGER_HPP
#define EE_SYSTEMTRESOURCEMANAGER_HPP
#include <eepp/core/containers.hpp>
#include <eepp/core/string.hpp>
#include <eepp/system/lock.hpp>
#include <eepp/system/mutex.hpp>
#include <string>
#include <unordered_map>
namespace EE { namespace System {
/** @brief A simple resource manager. It keeps a list of the resources, and free the instances of
* the resources when the manager is closed. Resources must implement getId() and getName()
* properties getId() is the string hash of getName().
*/
template <class T> class ResourceManager {
public:
ResourceManager();
/** @brief The destructor will call destroy() and destroy all the resources added to the manager
*/
virtual ~ResourceManager();
/** @brief Add the resource to the resource manager
** @param resource The resource to be managed by the manager */
virtual T* add( T* resource );
/** @brief Removes the resource from the manager
** @param resource The resource to remove
** @param remove Indicates if the resource must be destroyed after being removed from the
*manager */
bool remove( T* resource, bool remove = true );
/** @brief Removes the resource by its id
** @see remove */
bool removeById( const String::HashType& id, bool remove = true );
/** @brief Removes the resource by its name
** @see remove */
bool removeByName( const std::string& name, bool remove = true );
/** @returns A resource by its name. If not found returns NULL. */
T* getByName( const std::string& name );
/** @returns A resource by its id. If not found returns NULL. */
T* getById( const String::HashType& id );
/** @returns The number of resources added */
Uint32 getCount();
/** @returns The number of resources that where added with the indicated name. */
Uint32 getCount( const std::string& name );
/** @returns The number of resources that where added with the indicated id. */
Uint32 getCount( const String::HashType& id );
/** @returns If the resource name exists in the resources list. */
bool exists( const std::string& name );
/** @returns If the resource id exists in the resources list. */
bool existsId( const String::HashType& id );
/** @brief Destroy all the resources added ( delete the instances of the resources ) */
void destroy();
/** @brief Prints all the resources names added to the manager. */
void printNames();
/** @returns A reference to the resources list of the manager. */
UnorderedMap<String::HashType, T*>& getResources();
/** @brief Indicates if the resource manager is destroy the resources. */
const bool& isDestroying() const;
template <typename Predicate> void each( Predicate pred ) const {
for ( const auto& res : mResources )
pred( res );
}
template <typename Predicate> void each( Predicate pred ) {
for ( auto& res : mResources )
pred( res );
}
template <typename Predicate> T* findIf( Predicate pred ) const {
for ( const auto& res : mResources )
if ( pred( res ) )
return res.second;
return nullptr;
}
template <typename Predicate> T* findIf( Predicate pred ) {
for ( auto& res : mResources )
if ( pred( res ) )
return res.second;
return nullptr;
}
protected:
Mutex mMutex;
UnorderedMap<String::HashType, T*> mResources;
bool mIsDestroying;
};
template <class T> ResourceManager<T>::ResourceManager() : mIsDestroying( false ) {}
template <class T> const bool& ResourceManager<T>::isDestroying() const {
return mIsDestroying;
}
template <class T> ResourceManager<T>::~ResourceManager() {
destroy();
}
template <class T> void ResourceManager<T>::destroy() {
mIsDestroying = true;
{
Lock l( mMutex );
for ( auto& it : mResources ) {
T* res = it.second;
eeSAFE_DELETE( res );
}
mResources.clear();
}
mIsDestroying = false;
}
// This is not thread safe
template <class T> UnorderedMap<String::HashType, T*>& ResourceManager<T>::getResources() {
return mResources;
}
template <class T> T* ResourceManager<T>::add( T* resource ) {
if ( NULL != resource ) {
if ( !existsId( resource->getId() ) ) {
Lock l( mMutex );
mResources[resource->getId()] = resource;
return resource;
} else {
std::string realName( resource->getName() );
Uint32 c = 1;
while ( existsId( resource->getId() ) ) {
c++;
resource->setName( realName + String::toString( c ) );
}
return add( resource );
}
Lock l( mMutex );
mResources[resource->getId()] = resource;
return resource;
}
return NULL;
}
template <class T> bool ResourceManager<T>::remove( T* resource, bool remove ) {
if ( NULL != resource ) {
{
Lock l( mMutex );
mResources.erase( resource->getId() );
}
if ( remove )
eeSAFE_DELETE( resource );
return true;
}
return false;
}
template <class T> bool ResourceManager<T>::removeById( const String::HashType& id, bool _remove ) {
return remove( getById( id ), _remove );
}
template <class T> bool ResourceManager<T>::removeByName( const std::string& name, bool _remove ) {
return remove( getByName( name ), _remove );
}
template <class T> bool ResourceManager<T>::exists( const std::string& name ) {
return existsId( String::hash( name ) );
}
template <class T> bool ResourceManager<T>::existsId( const String::HashType& id ) {
Lock l( mMutex );
return mResources.find( id ) != mResources.end();
}
template <class T> T* ResourceManager<T>::getByName( const std::string& name ) {
return getById( String::hash( name ) );
}
template <class T> T* ResourceManager<T>::getById( const String::HashType& id ) {
Lock l( mMutex );
auto it = mResources.find( id );
return it != mResources.end() ? it->second : nullptr;
}
template <class T> void ResourceManager<T>::printNames() {
Lock l( mMutex );
for ( auto& it : mResources ) {
eePRINTL( "'%s'", it.second->getName().c_str() );
}
}
template <class T> Uint32 ResourceManager<T>::getCount() {
Lock l( mMutex );
return (Uint32)mResources.size();
}
template <class T> Uint32 ResourceManager<T>::getCount( const String::HashType& id ) {
return existsId( id ) ? 1 : 0;
}
template <class T> Uint32 ResourceManager<T>::getCount( const std::string& name ) {
return getCount( String::hash( name ) );
}
/** @brief A simple resource manager. It keeps a list of the resources, and free the instances of
* the resources when the manager is closed. Resources must implement getId() and getName()
* properties getId() is the string hash of getName(). Allows repeated keys.
*/
template <class T> class ResourceManagerMulti {
public:
/** @param UniqueId Indicates if the resources id must be unique */
ResourceManagerMulti();
/** @brief The destructor will call destroy() and destroy all the resources added to the manager
*/
virtual ~ResourceManagerMulti();
/** @brief Add the resource to the resource manager
** @param resource The resource to be managed by the manager */
virtual T* add( T* resource );
/** @brief Removes the resource from the manager
** @param resource The resource to remove
** @param remove Indicates if the resource must be destroyed after being removed from the
*manager */
bool remove( T* resource, bool remove = true );
/** @brief Removes the resource by its id
** @see remove */
bool removeById( const String::HashType& id, bool remove = true );
/** @brief Removes the resource by its name
** @see remove */
bool removeByName( const std::string& name, bool remove = true );
/** @returns A resource by its name. If not found returns NULL. */
T* getByName( const std::string& name );
/** @returns A resource by its id. If not found returns NULL. */
T* getById( const String::HashType& id );
/** @returns The number of resources added */
Uint32 getCount();
/** @returns The number of resources that where added with the indicated name. */
Uint32 getCount( const std::string& name );
/** @returns The number of resources that where added with the indicated id. */
Uint32 getCount( const String::HashType& id );
/** @returns If the resource name exists in the resources list. */
bool exists( const std::string& name );
/** @returns If the resource id exists in the resources list. */
bool existsId( const String::HashType& id );
/** @brief Destroy all the resources added ( delete the instances of the resources ) */
void destroy();
/** @brief Prints all the resources names added to the manager. */
void printNames();
/** @returns A reference to the resources list of the manager. */
std::unordered_multimap<String::HashType, T*>& getResources();
/** @brief Indicates if the resource manager is destroy the resources. */
const bool& isDestroying() const;
protected:
Mutex mMutex;
std::unordered_multimap<String::HashType, T*> mResources;
bool mIsDestroying;
};
template <class T> ResourceManagerMulti<T>::ResourceManagerMulti() : mIsDestroying( false ) {}
template <class T> const bool& ResourceManagerMulti<T>::isDestroying() const {
return mIsDestroying;
}
template <class T> ResourceManagerMulti<T>::~ResourceManagerMulti() {
destroy();
}
template <class T> void ResourceManagerMulti<T>::destroy() {
mIsDestroying = true;
{
Lock l( mMutex );
for ( auto& it : mResources ) {
T* res = it.second;
eeSAFE_DELETE( res );
}
mResources.clear();
}
mIsDestroying = false;
}
template <class T>
std::unordered_multimap<String::HashType, T*>& ResourceManagerMulti<T>::getResources() {
return mResources;
}
template <class T> T* ResourceManagerMulti<T>::add( T* resource ) {
if ( NULL != resource ) {
Lock l( mMutex );
mResources.insert( std::pair<String::HashType, T*>( resource->getId(), resource ) );
return resource;
}
return NULL;
}
template <class T> bool ResourceManagerMulti<T>::remove( T* resource, bool remove ) {
if ( NULL != resource ) {
{
Lock l( mMutex );
auto range = mResources.equal_range( resource->getId() );
auto it = range.first;
while ( it != range.second ) {
if ( it->second == resource ) {
mResources.erase( it );
break;
}
it++;
}
}
if ( remove )
eeSAFE_DELETE( resource );
return true;
}
return false;
}
template <class T>
bool ResourceManagerMulti<T>::removeById( const String::HashType& id, bool _remove ) {
return remove( getById( id ), _remove );
}
template <class T>
bool ResourceManagerMulti<T>::removeByName( const std::string& name, bool _remove ) {
return remove( getByName( name ), _remove );
}
template <class T> bool ResourceManagerMulti<T>::exists( const std::string& name ) {
return existsId( String::hash( name ) );
}
template <class T> bool ResourceManagerMulti<T>::existsId( const String::HashType& id ) {
Lock l( mMutex );
return mResources.find( id ) != mResources.end();
}
template <class T> T* ResourceManagerMulti<T>::getByName( const std::string& name ) {
return getById( String::hash( name ) );
}
template <class T> T* ResourceManagerMulti<T>::getById( const String::HashType& id ) {
Lock l( mMutex );
auto it = mResources.find( id );
return it != mResources.end() ? it->second : nullptr;
}
template <class T> void ResourceManagerMulti<T>::printNames() {
Lock l( mMutex );
for ( auto& it : mResources ) {
eePRINTL( "'%s'", it.second->getName().c_str() );
}
}
template <class T> Uint32 ResourceManagerMulti<T>::getCount() {
Lock l( mMutex );
return (Uint32)mResources.size();
}
template <class T> Uint32 ResourceManagerMulti<T>::getCount( const String::HashType& id ) {
Lock l( mMutex );
return mResources.count( id );
}
template <class T> Uint32 ResourceManagerMulti<T>::getCount( const std::string& name ) {
return getCount( String::hash( name ) );
}
}} // namespace EE::System
#endif

View File

@@ -47,6 +47,7 @@
#include <eepp/ui/doc/textposition.hpp>
#include <eepp/ui/doc/textrange.hpp>
#include <eepp/ui/doc/textundostack.hpp>
#include <eepp/ui/drawableresolver.hpp>
#include <eepp/ui/iconmanager.hpp>
#include <eepp/ui/inlinelayouter.hpp>
#include <eepp/ui/keyboardshortcut.hpp>
@@ -179,6 +180,7 @@
#include <eepp/ui/uiwidgettablerow.hpp>
#include <eepp/ui/uiwindow.hpp>
#include <eepp/ui/undostack.hpp>
#include <eepp/ui/webresourcecache.hpp>
#include <eepp/ui/widgetcommandexecuter.hpp>
#endif

View File

@@ -2,14 +2,12 @@
#define EE_UI_CSS_DRAWABLEIMAGEPARSER_HPP
#include <eepp/core.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/math/size.hpp>
#include <eepp/system/functionstring.hpp>
#include <functional>
#include <map>
namespace EE { namespace Graphics {
class Drawable;
}} // namespace EE::Graphics
namespace EE { namespace UI {
class UINode;
}} // namespace EE::UI
@@ -20,8 +18,8 @@ using namespace EE::System;
namespace EE { namespace UI { namespace CSS {
typedef std::function<Drawable*( const FunctionString& functionType, const Sizef& size, bool& ownIt,
UINode* node )>
typedef std::function<DrawablePtr( const FunctionString& functionType, const Sizef& size,
UINode* node )>
DrawableImageParserFunc;
class EE_API DrawableImageParser {
@@ -30,8 +28,7 @@ class EE_API DrawableImageParser {
bool exists( const std::string& name ) const;
Drawable* createDrawable( const std::string& value, const Sizef& size, bool& ownIt,
UINode* node );
DrawablePtr createDrawable( const std::string& value, const Sizef& size, UINode* node );
void addParser( const std::string& name, const DrawableImageParserFunc& func );

View File

@@ -0,0 +1,32 @@
#ifndef EE_UI_DRAWABLERESOLVER_HPP
#define EE_UI_DRAWABLERESOLVER_HPP
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/resourcescope.hpp>
namespace EE { namespace UI {
class UISceneNode;
/** Resolves named drawables through an explicit UI scene or Graphics resource scope. */
class EE_API DrawableResolver {
public:
explicit DrawableResolver( UISceneNode& sceneNode );
explicit DrawableResolver( Graphics::ResourceScope& resourceScope );
Graphics::DrawablePtr resolve( const std::string& name, bool firstSearchSprite = false ) const;
Graphics::DrawablePtr resolveById( Graphics::ResourceNameHash hash ) const;
Graphics::DrawablePtr resolveById( String::HashType legacyHash ) const;
void setPrintWarnings( bool printWarnings );
bool getPrintWarnings() const;
protected:
UISceneNode* mSceneNode{ nullptr };
Graphics::ResourceScope* mResourceScope{ nullptr };
bool mPrintWarnings{ false };
};
}} // namespace EE::UI
#endif

View File

@@ -13,8 +13,9 @@ class UIIconTheme;
class EE_API IconManager {
public:
static UIIconTheme* init( const std::string& iconThemeName, FontTrueType* remixIconFont,
FontTrueType* noniconFont, FontTrueType* codIconFont );
static ResourcePtr<UIIconTheme> init( const std::string& iconThemeName,
FontTrueType* remixIconFont, FontTrueType* noniconFont,
FontTrueType* codIconFont );
};
}} // namespace EE::UI

View File

@@ -50,6 +50,8 @@ class EE_API LinearGradientDrawable : public Graphics::Drawable {
virtual bool isStateful() { return false; }
Graphics::DrawablePtr clone() const;
const std::vector<ColorStop>& getColorStops() const;
void setColorStops( std::vector<ColorStop> stops );

View File

@@ -43,10 +43,7 @@ class EE_API Variant {
explicit Variant( const String* string ) : mType( Type::StringPtr ) {
mValue.asStringPtr = string;
}
Variant( Drawable* drawable, bool ownDrawable = false ) : mType( Type::Drawable ) {
mValue.asDrawable = drawable;
mOwnsObject = ownDrawable;
}
Variant( DrawablePtr drawable ) : mDrawable( std::move( drawable ) ), mType( Type::Drawable ) {}
Variant( UIIcon* icon ) : mType( Type::Icon ) { mValue.asIcon = icon; }
Variant( const Vector2f& v ) : mType( Type::Vector2f ) {
mValue.asVector2f = eeNew( Vector2f, ( v ) );
@@ -62,7 +59,7 @@ class EE_API Variant {
explicit Variant( const char* data ) : mType( Type::cstr ) { mValue.asCStr = data; }
~Variant() { reset(); }
Variant( const Variant& other ) : mType( Type::Invalid ), mOwnsObject( other.mOwnsObject ) {
Variant( const Variant& other ) : mType( Type::Invalid ) {
switch ( other.mType ) {
case Type::StdString:
mValue.asStdString = eeNew( std::string, ( *other.mValue.asStdString ) );
@@ -74,7 +71,7 @@ class EE_API Variant {
mValue.asStringPtr = other.mValue.asStringPtr;
break;
case Type::Drawable:
mValue.asDrawable = other.mValue.asDrawable;
mDrawable = other.mDrawable;
break;
case Type::Icon:
mValue.asIcon = other.mValue.asIcon;
@@ -116,9 +113,8 @@ class EE_API Variant {
}
Variant( Variant&& other ) noexcept :
mValue( other.mValue ), mType( other.mType ), mOwnsObject( other.mOwnsObject ) {
mValue( other.mValue ), mDrawable( std::move( other.mDrawable ) ), mType( other.mType ) {
other.mType = Type::Invalid;
other.mOwnsObject = false;
other.mValue = {};
}
@@ -134,10 +130,9 @@ class EE_API Variant {
if ( this != &other ) {
reset();
mType = other.mType;
mOwnsObject = other.mOwnsObject;
mDrawable = std::move( other.mDrawable );
mValue = other.mValue;
other.mType = Type::Invalid;
other.mOwnsObject = false;
other.mValue = {};
}
return *this;
@@ -146,7 +141,7 @@ class EE_API Variant {
const std::string& asStdString() const { return *mValue.asStdString; }
const String& asString() const { return *mValue.asString; }
const String& asStringPtr() const { return *mValue.asStringPtr; }
Drawable* asDrawable() const { return mValue.asDrawable; }
const DrawablePtr& asDrawable() const { return mDrawable; }
const bool& asBool() const { return mValue.asBool; }
const Float& asFloat() const { return mValue.asFloat; }
const int& asInt() const { return mValue.asInt; }
@@ -172,8 +167,7 @@ class EE_API Variant {
eeSAFE_DELETE( mValue.asString );
break;
case Type::Drawable:
if ( mOwnsObject )
eeSAFE_DELETE( mValue.asDrawable );
mDrawable.reset();
break;
case Type::Vector2f:
eeSAFE_DELETE( mValue.asVector2f );
@@ -210,7 +204,7 @@ class EE_API Variant {
return asStringPtr();
case Type::Drawable:
return asDrawable()->isDrawableResource()
? static_cast<DrawableResource*>( asDrawable() )->getName()
? static_cast<DrawableResource*>( asDrawable().get() )->getName()
: "Drawable";
case Type::Icon:
return asIcon()->getName();
@@ -330,7 +324,7 @@ class EE_API Variant {
case Type::StringPtr:
return asStringPtr().size();
case Type::Drawable:
return sizeof( mValue.asDrawable );
return sizeof( mDrawable );
case Type::Icon:
return asIcon()->getName().size();
case Type::DataPtr:
@@ -350,7 +344,6 @@ class EE_API Variant {
private:
union {
void* asDataPtr{ nullptr };
Drawable* asDrawable;
UIIcon* asIcon;
std::string* asStdString;
String* asString;
@@ -365,8 +358,8 @@ class EE_API Variant {
Rectf* asRectf;
const char* asCStr;
} mValue;
DrawablePtr mDrawable;
Type mType;
bool mOwnsObject{ false };
};
}}} // namespace EE::UI::Models

View File

@@ -54,6 +54,8 @@ class EE_API RadialGradientDrawable : public Graphics::Drawable {
virtual bool isStateful() { return false; }
Graphics::DrawablePtr clone() const;
const std::vector<ColorStop>& getColorStops() const;
void setColorStops( std::vector<ColorStop> stops );

View File

@@ -9,6 +9,9 @@ namespace EE { namespace UI { namespace Tools {
class EE_API HTMLFormatter {
public:
static std::string HTMLtoXML( const std::string& layoutString );
/** Converts HTML to XML, serializing only the children of the parsed body element. */
static std::string HTMLBodyToXML( const std::string& layoutString );
};
}}} // namespace EE::UI::Tools

View File

@@ -2,7 +2,6 @@
#define EE_UITOOLSCTEXTUREATLASEDITOR_HPP
#include <eepp/graphics/textureatlasloader.hpp>
#include <eepp/graphics/textureatlasmanager.hpp>
#include <eepp/graphics/texturepacker.hpp>
#include <eepp/scene/scenenode.hpp>
#include <eepp/ui/base.hpp>

View File

@@ -78,9 +78,9 @@ class EE_API UIColorPicker {
void windowClose( const Event* Event );
Texture* createHueTexture( const Sizef& size );
TexturePtr createHueTexture( const Sizef& size );
Texture* createGridTexture();
TexturePtr createGridTexture();
void updateColorPicker();

View File

@@ -118,6 +118,9 @@ class EE_API UIFontPickerDialog : public UIWindow {
std::vector<Uint32> mSizes;
UnorderedSet<std::string> mLoadedFontKeys;
UnorderedMap<std::string, std::string> mFontTags;
Graphics::FontTrueTypePtr mPreviewFont;
Graphics::Font* mPreviewTextDefaultFont{ nullptr };
Graphics::Font* mPreviewInputDefaultFont{ nullptr };
std::shared_ptr<Models::Model> mFamilyModel;
std::shared_ptr<Models::Model> mStyleModel;
std::shared_ptr<Models::Model> mSizeModel;
@@ -171,7 +174,7 @@ class EE_API UIFontPickerDialog : public UIWindow {
void sortFonts();
void mergeFontManagerFonts( std::vector<FontDesc>& fonts );
void mergeLoadedFonts( std::vector<FontDesc>& fonts );
void updateFontTags();
@@ -189,6 +192,8 @@ class EE_API UIFontPickerDialog : public UIWindow {
void updatePreview();
void clearPreviewFont();
void selectInitialRows();
void selectFamily( const std::string& family );

View File

@@ -2,6 +2,7 @@
#define EE_UI_UIBACKGROUNDDRAWABLE_HPP
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/vertexbuffer.hpp>
#include <eepp/ui/border.hpp>
using namespace EE::Graphics;
@@ -63,7 +64,7 @@ class EE_API UIBackgroundDrawable : public Drawable {
protected:
const UINode* mOwner;
BorderRadiuseStr mRadiusesStr;
VertexBuffer* mVertexBuffer;
Graphics::VertexBufferUniquePtr mVertexBuffer;
Sizef mSize;
BorderRadiuses mRadiuses;
bool mNeedsUpdate;

View File

@@ -2,6 +2,7 @@
#define EE_UI_UIBORDERDRAWABLE_HPP
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/vertexbuffer.hpp>
#include <eepp/math/rect.hpp>
#include <eepp/ui/border.hpp>
@@ -87,7 +88,7 @@ class EE_API UIBorderDrawable : public Drawable {
protected:
const UINode* mOwner;
VertexBuffer* mVertexBuffer;
Graphics::VertexBufferUniquePtr mVertexBuffer;
mutable Borders mBorders;
BorderStr mBorderStr;
BorderType mBorderType;

View File

@@ -768,13 +768,13 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void setShowFoldingRegion( bool showFoldingRegion );
Drawable* getFoldDrawable() const;
const DrawablePtr& getFoldDrawable() const;
void setFoldDrawable( Drawable* foldDrawable );
void setFoldDrawable( DrawablePtr foldDrawable );
Drawable* getFoldedDrawable() const;
const DrawablePtr& getFoldedDrawable() const;
void setFoldedDrawable( Drawable* foldedDrawable );
void setFoldedDrawable( DrawablePtr foldedDrawable );
bool getFoldsAlwaysVisible() const;
@@ -999,8 +999,8 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
UIIcon* mFileLockIcon{ nullptr };
std::string mFileLockIconName{ "file-lock-fill" };
LineWrapType mLineWrapType{ LineWrapType::Viewport };
Drawable* mFoldDrawable{ nullptr };
Drawable* mFoldedDrawable{ nullptr };
DrawablePtr mFoldDrawable;
DrawablePtr mFoldedDrawable;
String::HashType mTagFoldRange{ 0 };
Uint32 mTabIndentCharacter{ 187 /*'»'*/ };
CharacterAlignment mTabIndentAlignment{ CharacterAlignment::Center };
@@ -1157,7 +1157,7 @@ class EE_API UICodeEditor : public UIWidget, public TextDocument::Client {
void updateGlyphWidth();
Drawable* findIcon( const std::string& name );
DrawablePtr findIcon( const std::string& name );
void createDefaultContextMenuOptions( UIPopUpMenu* menu );

View File

@@ -343,7 +343,7 @@ class EE_API UIConsole : public UIWidget,
UIMenuItem* menuAdd( UIPopUpMenu* menu, const String& translateString, const std::string& icon,
const std::string& cmd );
Drawable* findIcon( const std::string& name );
DrawablePtr findIcon( const std::string& name );
void copySelection();

View File

@@ -12,32 +12,44 @@ using namespace EE::Graphics;
namespace EE { namespace UI {
class UIIcon;
using UIIconPtr = ResourcePtr<UIIcon>;
using UIIconWeakPtr = ResourceWeakPtr<UIIcon>;
class EE_API UIIcon {
public:
static UIIcon* New( const std::string& name );
static UIIconPtr New( const std::string& name );
virtual ~UIIcon();
const std::string& getName() const;
virtual Drawable* getSize( const int& size ) const;
/** Returns the icon source closest to the requested size.
*
* The returned drawable is shared icon data and must not be mutated by consumers. Use
* createDrawable() when a consumer needs its own mutable drawable instance. */
virtual const DrawablePtr& getSource( const int& size ) const;
virtual void setSize( const int& size, Drawable* drawable );
/** Creates a private drawable instance for a consumer. This must not be called from a rendering
* loop; retain the returned instance instead. */
DrawablePtr createDrawable( const int& size ) const;
virtual void setSource( const int& size, DrawablePtr drawable );
protected:
UIIcon( const std::string& name );
std::string mName;
mutable UnorderedMap<int, Drawable*> mSizes;
mutable UnorderedMap<int, DrawablePtr> mSizes;
};
class EE_API UIGlyphIcon : public UIIcon {
public:
static UIIcon* New( const std::string& name, FontTrueType* font, const Uint32& codePoint );
static UIIconPtr New( const std::string& name, FontTrueType* font, const Uint32& codePoint );
virtual ~UIGlyphIcon();
virtual Drawable* getSize( const int& size ) const;
virtual const DrawablePtr& getSource( const int& size ) const;
protected:
UIGlyphIcon( const std::string& name, FontTrueType* font, const Uint32& codePoint );
@@ -49,17 +61,16 @@ class EE_API UIGlyphIcon : public UIIcon {
class EE_API UISVGIcon : public UIIcon {
public:
static UIIcon* New( const std::string& name, const std::string& svgXML );
static UIIconPtr New( const std::string& name, const std::string& svgXML );
virtual ~UISVGIcon();
virtual Drawable* getSize( const int& size ) const;
virtual const DrawablePtr& getSource( const int& size ) const;
protected:
UISVGIcon( const std::string& name, const std::string& svgXML );
std::string mSVGXml;
mutable UnorderedMap<int, Texture*> mSVGs;
mutable Sizei mOriSize;
mutable int mOriChannels{ 0 };
};

View File

@@ -9,15 +9,19 @@ using namespace EE::Graphics;
namespace EE { namespace UI {
class UIIconTheme;
using UIIconThemePtr = ResourcePtr<UIIconTheme>;
using UIIconThemeWeakPtr = ResourceWeakPtr<UIIconTheme>;
class EE_API UIIconTheme {
public:
static UIIconTheme* New( const std::string& name );
static UIIconThemePtr New( const std::string& name );
~UIIconTheme();
UIIconTheme* add( UIIcon* icon );
UIIconTheme* add( UIIconPtr icon );
UIIconTheme* add( const std::unordered_map<std::string, UIIcon*>& icons );
UIIconTheme* add( const std::unordered_map<std::string, UIIconPtr>& icons );
const std::string& getName() const;
@@ -25,7 +29,7 @@ class EE_API UIIconTheme {
protected:
std::string mName;
std::unordered_map<std::string, UIIcon*> mIcons;
std::unordered_map<std::string, UIIconPtr> mIcons;
UIIconTheme( const std::string& name );
};

View File

@@ -17,15 +17,15 @@ class EE_API UIIconThemeManager {
~UIIconThemeManager();
UIIconThemeManager* add( UIIconTheme* iconTheme );
UIIconThemeManager* add( UIIconThemePtr iconTheme );
UIIconTheme* getCurrentTheme() const;
UIIconThemeManager* setCurrentTheme( UIIconTheme* currentTheme );
UIIconThemeManager* setCurrentTheme( UIIconThemePtr currentTheme );
UIIconTheme* getFallbackTheme() const;
UIIconThemeManager* setFallbackTheme( UIIconTheme* fallbackTheme );
UIIconThemeManager* setFallbackTheme( UIIconThemePtr fallbackTheme );
UIIcon* findIcon( const std::string& name );
@@ -36,7 +36,7 @@ class EE_API UIIconThemeManager {
void remove( UIIconTheme* iconTheme );
protected:
std::vector<UIIconTheme*> mIconThemes;
std::vector<UIIconThemePtr> mIconThemes;
UIIconTheme* mCurrentTheme{ nullptr };
UIIconTheme* mFallbackTheme{ nullptr };
UIThemeManager* mFallbackThemeManager{ nullptr };

View File

@@ -24,9 +24,11 @@ class EE_API UIImage : public UIWidget {
virtual void setAlpha( const Float& alpha );
Drawable* getDrawable() const;
const DrawablePtr& getDrawable() const;
UIImage* setDrawable( Drawable* drawable, bool ownIt = false );
UIImage* setDrawable( DrawablePtr drawable );
UIImage* setDrawable( TexturePtr texture );
const Color& getColor() const;
@@ -53,12 +55,12 @@ class EE_API UIImage : public UIWidget {
protected:
UIScaleType mScaleType;
Drawable* mDrawable;
DrawablePtr mDrawable;
Color mColor;
Vector2f mAlignOffset;
Vector2f mDestSize;
Uint32 mResourceChangeCb;
bool mDrawableOwner;
DrawableResourceConnection mResourceChangeConnection;
Uint32 mSpriteChangeCb{ 0 };
bool mDeferLoad{ false };
std::shared_ptr<std::atomic<bool>> mAsyncImageAlive;
Uint64 mRemoteImageLoadId{ 0 };
@@ -79,9 +81,9 @@ class EE_API UIImage : public UIWidget {
void autoAlign();
void safeDeleteDrawable();
void clearDrawable();
void onDrawableResourceEvent( DrawableResource::Event event, DrawableResource* );
void onDrawableResourceChange();
bool loadFileDrawable( const Network::URI& uri );

View File

@@ -24,7 +24,7 @@ class EE_API UIMenu : public UIWidget {
virtual bool isType( const Uint32& type ) const;
UIMenuItem* add( const String& text, Drawable* icon = NULL, const String& shortcutText = "" );
UIMenuItem* add( const String& text, DrawablePtr icon = {}, const String& shortcutText = "" );
UIWidget* add( UIWidget* widget );
@@ -35,7 +35,8 @@ class EE_API UIMenu : public UIWidget {
UIMenuRadioButton* addRadioButton( const String& text, const bool& active = false );
UIMenuSubMenu* addSubMenu( const String& text, Drawable* icon = NULL, UIMenu* subMenu = NULL );
UIMenuSubMenu* addSubMenu( const String& text, DrawablePtr icon = {},
UIMenu* subMenu = NULL );
UIWidget* getItem( const Uint32& index );
@@ -55,7 +56,7 @@ class EE_API UIMenu : public UIWidget {
void removeAll();
void insert( const String& text, Drawable* icon, const Uint32& index );
void insert( const String& text, DrawablePtr icon, const Uint32& index );
void insert( UIWidget* widget, const Uint32& index );
@@ -121,7 +122,7 @@ class EE_API UIMenu : public UIWidget {
void resizeMe();
UIMenuItem* createMenuItem( const String& text, Drawable* icon,
UIMenuItem* createMenuItem( const String& text, DrawablePtr icon,
const String& shortcutText = "" );
UIMenuCheckBox* createMenuCheckBox( const String& text, const bool& active,
@@ -129,7 +130,7 @@ class EE_API UIMenu : public UIWidget {
UIMenuRadioButton* createMenuRadioButton( const String& text, const bool& active );
UIMenuSubMenu* createSubMenu( const String& text, Drawable* icon, UIMenu* subMenu );
UIMenuSubMenu* createSubMenu( const String& text, DrawablePtr icon, UIMenu* subMenu );
void onThemeLoaded();

View File

@@ -336,12 +336,11 @@ class EE_API UINode : public Node {
*
* Enables background fill and sets the specified drawable at the given index.
*
* @param drawable Pointer to the Drawable to use.
* @param ownIt If true, the node takes ownership of the drawable.
* @param drawable Drawable instance to use.
* @param index The layer index (0-based).
* @return Pointer to this node for method chaining.
*/
UINode* setBackgroundDrawable( Drawable* drawable, bool ownIt = false, int index = 0 );
UINode* setBackgroundDrawable( DrawablePtr drawable, int index = 0 );
/**
* @brief Sets a background drawable from a skin name.
@@ -521,12 +520,11 @@ class EE_API UINode : public Node {
*
* Enables foreground fill and sets the specified drawable at the given index.
*
* @param drawable Pointer to the Drawable to use.
* @param ownIt If true, the node takes ownership of the drawable.
* @param drawable Drawable instance to use.
* @param index The layer index (0-based).
* @return Pointer to this node for method chaining.
*/
UINode* setForegroundDrawable( Drawable* drawable, bool ownIt = false, int index = 0 );
UINode* setForegroundDrawable( DrawablePtr drawable, int index = 0 );
/**
* @brief Sets a foreground drawable from a skin name.
@@ -852,12 +850,12 @@ class EE_API UINode : public Node {
void setThemeByName( const std::string& Theme );
/**
* @brief Sets the theme for this node.
* @brief Sets the borrowed theme used by this node.
*
* Applies the specified UITheme to this node, affecting its visual appearance
* through skins and styles.
* The node does not retain @p Theme. Its owner, normally the containing scene's UIThemeManager,
* must keep the theme alive until this node switches themes or is destroyed.
*
* @param Theme Pointer to the UITheme to apply.
* @param Theme Borrowed theme to apply, or null to use no explicit theme.
*/
virtual void setTheme( UITheme* Theme );

View File

@@ -3,6 +3,7 @@
#include <atomic>
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/math/ease.hpp>
#include <eepp/scene/action.hpp>
#include <eepp/ui/uibackgrounddrawable.hpp>
@@ -38,6 +39,8 @@ class EE_API UINodeDrawable : public Drawable {
static LayerDrawable* New( UINodeDrawable* container );
LayerDrawable( UINodeDrawable* container );
LayerDrawable( const LayerDrawable& ) = delete;
LayerDrawable& operator=( const LayerDrawable& ) = delete;
virtual ~LayerDrawable();
@@ -55,11 +58,13 @@ class EE_API UINodeDrawable : public Drawable {
virtual void setSize( const Sizef& size );
Drawable* getDrawable() const;
const DrawablePtr& getDrawable() const;
const std::string& getDrawableRef() const;
void setDrawable( Drawable* drawable, const bool& ownIt );
void setDrawable( DrawablePtr drawable );
void setDrawable( TexturePtr texture );
void setDrawable( const std::string& drawableRef );
@@ -128,11 +133,10 @@ class EE_API UINodeDrawable : public Drawable {
std::string mPositionY;
std::string mSizeEq;
bool mNeedsUpdate{ false };
bool mOwnsDrawable{ false };
bool mColorWasSet{ false };
Drawable* mDrawable;
DrawablePtr mDrawable;
std::string mDrawableRef;
Uint32 mResourceChangeCbId;
DrawableResourceConnection mResourceChangeConnection;
RepeatX mRepeatX{ RepeatX::NoRepeat };
RepeatY mRepeatY{ RepeatY::NoRepeat };
std::string mOriginEq{ "padding-box" };
@@ -141,16 +145,13 @@ class EE_API UINodeDrawable : public Drawable {
Origin mOrigin{ Origin::PaddingBox };
Clip mClip{ Clip::BorderBox };
Attachment mAttachment{ Attachment::Scroll };
std::shared_ptr<std::atomic<bool>> mAsyncDrawableAlive;
Uint64 mRemoteDrawableLoadId{ 0 };
virtual void onPositionChange();
virtual void onColorFilterChange();
void update();
Drawable* createDrawable( const std::string& value, const Sizef& size, bool& ownIt );
DrawablePtr createDrawable( const std::string& value, const Sizef& size );
bool loadRemoteDrawable( const std::string& value );
};
@@ -158,6 +159,8 @@ class EE_API UINodeDrawable : public Drawable {
static UINodeDrawable* New( UINode* owner );
UINodeDrawable( UINode* owner );
UINodeDrawable( const UINodeDrawable& ) = delete;
UINodeDrawable& operator=( const UINodeDrawable& ) = delete;
virtual ~UINodeDrawable();
@@ -187,7 +190,7 @@ class EE_API UINodeDrawable : public Drawable {
LayerDrawable* getLayer( int index );
void setDrawable( int index, Drawable* drawable, bool ownIt );
void setDrawable( int index, DrawablePtr drawable );
void setDrawable( int index, const std::string& drawable );
@@ -234,7 +237,8 @@ class EE_API UINodeDrawable : public Drawable {
protected:
UINode* mOwner;
UIBackgroundDrawable mBackgroundColor;
std::map<int, LayerDrawable*> mGroup;
using LayerDrawablePtr = std::unique_ptr<LayerDrawable, ResourceDeleter<LayerDrawable>>;
std::map<int, LayerDrawablePtr> mGroup;
Sizef mSize;
bool mNeedsUpdate{ true };
bool mClipEnabled{ false };

View File

@@ -40,7 +40,7 @@ class EE_API UIPushButton : public UIWidget {
virtual void setTheme( UITheme* Theme );
virtual UIPushButton* setIcon( Drawable* icon, bool ownIt = false );
virtual UIPushButton* setIcon( DrawablePtr icon );
virtual UIImage* getIcon();

View File

@@ -1,6 +1,7 @@
#ifndef EE_UISCENENODE_HPP
#define EE_UISCENENODE_HPP
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/network/cookiemanager.hpp>
#include <eepp/network/uri.hpp>
@@ -9,8 +10,10 @@
#include <eepp/system/translator.hpp>
#include <eepp/ui/colorschemepreferences.hpp>
#include <eepp/ui/css/stylesheet.hpp>
#include <eepp/ui/drawableresolver.hpp>
#include <eepp/ui/keyboardshortcut.hpp>
#include <eepp/ui/layoutinvalidation.hpp>
#include <eepp/ui/webresourcecache.hpp>
#include <atomic>
#include <functional>
@@ -20,6 +23,7 @@ using namespace EE::Network;
namespace EE { namespace Graphics {
class Font;
using FontPtr = ResourcePtr<Font>;
}} // namespace EE::Graphics
namespace EE { namespace Window {
@@ -54,9 +58,14 @@ class EE_API UISceneNode : public SceneNode {
*
* @param window Pointer to the window to associate with this UI scene node.
* If NULL, uses the current window from Engine.
* @param importDefaultResources Whether the scene scope automatically imports the catalog from
* Graphics::defaultResourceScope(). Keep this enabled for normal
* application scenes. Disable it for intentionally isolated
* scenes that must only resolve local or explicitly imported resources.
* @return Pointer to the newly created UISceneNode instance.
*/
static UISceneNode* New( EE::Window::Window* window = NULL );
static UISceneNode* New( EE::Window::Window* window = NULL,
bool importDefaultResources = true );
/**
* @brief Destroys the UISceneNode and cleans up resources.
@@ -153,8 +162,8 @@ class EE_API UISceneNode : public SceneNode {
*
* Copies only shared platform/configuration services: dispatcher, DPI/window pointer,
* thread pool, color/contrast preferences, and default font/theme pointers. Stylesheets,
* URI, referer, cookies, navigation callbacks, actions, roots, and dirty queues remain owned
* by this scene.
* URI, referer, cookies, navigation callbacks, actions, roots, resource scope, and dirty queues
* remain owned by this scene.
*/
void initializeEmbeddedFromHost( UISceneNode* hostScene );
@@ -563,7 +572,13 @@ class EE_API UISceneNode : public SceneNode {
* @param drawableSize The desired size of the drawable in pixels.
* @return Pointer to the Drawable, or nullptr if not found.
*/
Drawable* findIconDrawable( const std::string& iconName, const size_t& drawableSize );
DrawablePtr findIconDrawable( const std::string& iconName, const size_t& drawableSize );
/** @return This scene's drawable resolver. */
DrawableResolver& getDrawableResolver();
/** @return This scene's drawable resolver. */
const DrawableResolver& getDrawableResolver() const;
/**
* @brief Gets the keybindings manager.
@@ -770,12 +785,27 @@ class EE_API UISceneNode : public SceneNode {
*/
void setThreadPool( const std::shared_ptr<ThreadPool>& threadPool );
/** @return The Graphics resource lookup and ownership boundary of this scene. */
const Graphics::ResourceScopePtr& getResourceScope() const;
/**
* @brief Sets the theme for the entire UI scene.
* @brief Replaces this scene's resource boundary, allowing intentional sharing between scenes.
*
* Applies the theme to the root widget and all children.
* Scenes created with default-resource importing enabled also import the default catalog into
* the replacement scope. Scenes created with it disabled leave the replacement scope unchanged.
*/
UISceneNode* setResourceScope( Graphics::ResourceScopePtr resourceScope );
/**
* @brief Applies a borrowed theme to the widgets in this UI scene.
*
* @param theme Pointer to the UITheme to set.
* Each affected widget stores a non-owning `UITheme*`; this function does not retain @p theme.
* The theme must therefore outlive every widget using it. Normally callers establish that
* lifetime first by adding the corresponding `UIThemePtr` to this scene's UIThemeManager or by
* setting it as the manager's default theme.
*
* @param theme Borrowed theme to apply recursively. May be null to clear explicit widget
* themes.
*/
void setTheme( UITheme* theme );
@@ -836,6 +866,21 @@ class EE_API UISceneNode : public SceneNode {
Network::CookieManager& getCookieManager() { return mCookieManager; }
const WebResourceCachePtr& getWebResourceCache() const { return mWebResourceCache; }
UISceneNode* setWebResourceCache( WebResourceCachePtr cache, CachePartitionId partition = 0 );
DocumentSessionId getDocumentSessionId() const { return mDocumentSessionId; }
Uint64 beginDocumentNavigation( const URI& uri );
Uint64 getDocumentGeneration() const;
void requestWebResource( WebResourceRequest request, WebResourceCache::Callback callback );
Graphics::TexturePtr requestWebTexture( WebResourceRequest request,
WebResourceCache::Callback callback = {} );
void invalidateAsyncResourceLoads();
virtual void invalidate( Node* invalidator );
@@ -898,15 +943,21 @@ class EE_API UISceneNode : public SceneNode {
bool mStyleDuringLoad{ false };
UIThemeManager* mUIThemeManager{ nullptr };
UIIconThemeManager* mUIIconThemeManager{ nullptr };
std::vector<Font*> mFontFaces;
std::vector<Graphics::FontPtr> mFontFaces;
UnorderedMap<std::string, Font*> mFontFaceAliases;
UnorderedMap<Font*, std::string> mFontFaceFamilies;
std::shared_ptr<AsyncResourceLoadState> mAsyncResourceLoadState;
bool mImportDefaultResources{ true };
Graphics::ResourceScopePtr mResourceScope;
DrawableResolver mDrawableResolver;
WebResourceCachePtr mWebResourceCache;
DocumentSessionId mDocumentSessionId{ 0 };
KeyBindings mKeyBindings;
std::map<std::string, KeyBindingCommand> mKeyBindingCommands;
UnorderedSet<UIWidget*> mDirtyStyle;
UnorderedSet<UIWidget*> mDirtyStyleState;
UnorderedMap<UIWidget*, bool> mDirtyStyleStateCSSAnimations;
SmallVector<std::pair<UIWidget*, bool>, 64> mDirtyStyleStateSnapshot;
UnorderedSet<UILayout*> mDirtyLayouts;
SmallVector<UILayout*, 64> mDirtyLayoutsSnapshot;
std::vector<std::pair<Float, std::string>> mTimes;
@@ -936,8 +987,9 @@ class EE_API UISceneNode : public SceneNode {
* Creates a UISceneNode with optional window association.
*
* @param window Pointer to the window, or NULL for default.
* @param importDefaultResources Whether the scene scope imports the default resource catalog.
*/
explicit UISceneNode( EE::Window::Window* window = NULL );
explicit UISceneNode( EE::Window::Window* window = NULL, bool importDefaultResources = true );
/**
* @brief Handles node resize.
@@ -1151,11 +1203,13 @@ class EE_API UISceneNode : public SceneNode {
void resetTooltips( Node* node );
/**
* @brief Applies a theme to a node and its subtree.
* @brief Applies a borrowed theme to the widgets below a node.
*
* Recursively applies the specified UITheme to all widgets in the subtree.
* Each affected widget stores a non-owning pointer. This function does not retain @p theme; an
* owner such as this scene's UIThemeManager must keep it alive for the complete period in which
* the subtree uses it.
*
* @param theme Pointer to the UITheme to apply.
* @param theme Borrowed theme to apply. May be null to clear explicit widget themes.
* @param to The root node of the subtree to theme.
*/
void setTheme( UITheme* theme, Node* to );

View File

@@ -8,7 +8,7 @@ namespace EE { namespace UI {
class EE_API UISkin : public StateListDrawable {
public:
static UISkin* New( const std::string& name = "" );
static ResourcePtr<UISkin> New( const std::string& name = "" );
virtual ~UISkin();
@@ -20,9 +20,11 @@ class EE_API UISkin : public StateListDrawable {
virtual Sizef getPixelsSize();
virtual UISkin* clone();
DrawablePtr clone() const;
virtual UISkin* clone( const std::string& NewName );
ResourcePtr<UISkin> cloneSkin() const;
ResourcePtr<UISkin> clone( const std::string& newName ) const;
virtual Rectf getBorderSize( const Uint32& state );

View File

@@ -2,6 +2,7 @@
#define EE_UI_UISKINSTATE_HPP
#include <eepp/ui/uistate.hpp>
#include <eepp/graphics/resource.hpp>
#include <map>
namespace EE { namespace UI {
@@ -10,7 +11,7 @@ class UISkin;
class EE_API UISkinState : public UIState {
public:
static UISkinState* New( UISkin* skin );
static UISkinState* New( ResourcePtr<UISkin> skin );
virtual ~UISkinState();
@@ -28,11 +29,11 @@ class EE_API UISkinState : public UIState {
bool hasStateColor( const Uint32& state ) const;
protected:
UISkin* mSkin;
ResourcePtr<UISkin> mSkin;
std::map<Uint32, Color> mColors;
Color mCurrentColor;
explicit UISkinState( UISkin* Skin );
explicit UISkinState( ResourcePtr<UISkin> skin );
void updateState();

View File

@@ -1,13 +1,9 @@
#ifndef EE_UICUISPRITE_HPP
#define EE_UICUISPRITE_HPP
#include <eepp/graphics/sprite.hpp>
#include <eepp/ui/uiwidget.hpp>
namespace EE { namespace Graphics {
class Sprite;
class TextureRegion;
}} // namespace EE::Graphics
namespace EE { namespace UI {
class EE_API UISprite : public UIWidget {
@@ -26,11 +22,9 @@ class EE_API UISprite : public UIWidget {
virtual void setAlpha( const Float& alpha );
Graphics::Sprite* getSprite() const;
const Graphics::SpritePtr& getSprite() const;
Drawable* getDrawable() const;
UISprite* setSprite( Graphics::Sprite* sprite );
UISprite* setSprite( Graphics::SpritePtr sprite );
Color getColor() const;
@@ -42,10 +36,6 @@ class EE_API UISprite : public UIWidget {
const Vector2f& getAlignOffset() const;
UISprite* setIsSpriteOwner( const bool& dealloc );
bool getDeallocSprite();
virtual bool applyProperty( const StyleSheetProperty& attribute );
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
@@ -54,11 +44,10 @@ class EE_API UISprite : public UIWidget {
virtual std::vector<PropertyId> getPropertiesImplemented() const;
protected:
Graphics::Sprite* mSprite;
Graphics::SpritePtr mSprite;
RenderMode mRender;
Vector2f mAlignOffset;
TextureRegion* mTextureRegionLast;
bool mDealloc;
UISprite();
@@ -70,7 +59,6 @@ class EE_API UISprite : public UIWidget {
virtual void onSizeChange();
Uint32 deallocSprite();
};
}} // namespace EE::UI

View File

@@ -68,7 +68,7 @@ class EE_API UITabWidget : public UIWidget {
virtual bool isType( const Uint32& type ) const;
UITab* add( const String& text, UINode* nodeOwned, Drawable* icon = NULL );
UITab* add( const String& text, UINode* nodeOwned, DrawablePtr icon = {} );
UITabWidget* add( UITab* tab );
@@ -92,7 +92,7 @@ class EE_API UITabWidget : public UIWidget {
void removeAllTabs( bool destroyOwnedNode = true, bool immediateClose = false );
void insertTab( const String& text, UINode* nodeOwned, Drawable* icon, const Uint32& index );
void insertTab( const String& text, UINode* nodeOwned, DrawablePtr icon, const Uint32& index );
void insertTab( UITab* tab, const Uint32& index );
@@ -265,7 +265,7 @@ class EE_API UITabWidget : public UIWidget {
void onThemeLoaded();
UITab* createTab( const String& text, UINode* nodeOwned, Drawable* icon );
UITab* createTab( const String& text, UINode* nodeOwned, DrawablePtr icon );
void removeTab( const Uint32& index, bool destroyOwnedNode, bool destroyTab,
bool immediateClose,

View File

@@ -268,7 +268,7 @@ class EE_API UITextInput : public UITextView, public TextDocument::Client {
UIMenuItem* menuAdd( UIPopUpMenu* menu, const String& translateString, const std::string& icon,
const std::string& cmd );
Drawable* findIcon( const std::string& name );
DrawablePtr findIcon( const std::string& name );
};
}} // namespace EE::UI

View File

@@ -51,7 +51,7 @@ class EE_API UITextureRegion : public UIWidget {
virtual std::vector<PropertyId> getPropertiesImplemented() const;
protected:
UIScaleType mScaleType;
UIScaleType mScaleType{ UIScaleType::None };
Graphics::TextureRegion* mTextureRegion;
Color mColor;
RenderMode mRender;
@@ -65,7 +65,9 @@ class EE_API UITextureRegion : public UIWidget {
void autoAlign();
void drawTextureRegion();
void drawTextureRegion( const Sizef& destSize, const Vector2i& offset );
void autoAlign( const Sizef& drawableSize );
};
}} // namespace EE::UI

View File

@@ -1,11 +1,12 @@
#ifndef EE_UICUITHEME_HPP
#define EE_UICUITHEME_HPP
#include <eepp/system/resourcemanager.hpp>
#include <eepp/graphics/resourcecatalog.hpp>
#include <eepp/ui/base.hpp>
#include <eepp/ui/css/stylesheet.hpp>
#include <eepp/ui/uifontstyleconfig.hpp>
#include <eepp/ui/uihelper.hpp>
#include <eepp/ui/uiicontheme.hpp>
#include <eepp/ui/uiskin.hpp>
namespace EE { namespace Graphics {
@@ -20,36 +21,37 @@ namespace EE { namespace UI {
class UIIcon;
class UIIconTheme;
class EE_API UITheme : protected ResourceManagerMulti<UISkin> {
class UITheme;
using UIThemePtr = ResourcePtr<UITheme>;
using UIThemeWeakPtr = ResourceWeakPtr<UITheme>;
using UISkinPtr = ResourcePtr<UISkin>;
class EE_API UITheme {
public:
using ResourceManagerMulti<UISkin>::getById;
using ResourceManagerMulti<UISkin>::getByName;
using ResourceManagerMulti<UISkin>::exists;
using ResourceManagerMulti<UISkin>::existsId;
static UIThemePtr New( const std::string& name, const std::string& abbr,
Graphics::Font* defaultFont = NULL );
static UITheme* New( const std::string& name, const std::string& abbr,
Graphics::Font* defaultFont = NULL );
static UIThemePtr load( const std::string& name, const std::string& abbr,
const std::string& textureAtlasPath, Graphics::Font* defaultFont,
const std::string& styleSheetPath );
static UITheme* load( const std::string& name, const std::string& abbr,
const std::string& textureAtlasPath, Graphics::Font* defaultFont,
const std::string& styleSheetPath );
static UIThemePtr loadFromString( const std::string& name, const std::string& abbr,
const std::string& textureAtlasPath,
Graphics::Font* defaultFont,
const std::string& styleSheetString );
static UITheme* loadFromString( const std::string& name, const std::string& abbr,
const std::string& textureAtlasPath,
Graphics::Font* defaultFont,
const std::string& styleSheetString );
static UIThemePtr loadFromTextureAtlas( UIThemePtr theme,
Graphics::TextureAtlasPtr textureAtlas );
static UITheme* loadFromTextureAtlas( UITheme* tTheme,
Graphics::TextureAtlas* getTextureAtlas );
static UIThemePtr loadFromTextureAtlas( Graphics::TextureAtlasPtr textureAtlas,
const std::string& Name, const std::string& NameAbbr );
static UITheme* loadFromTextureAtlas( Graphics::TextureAtlas* getTextureAtlas,
const std::string& Name, const std::string& NameAbbr );
static UIThemePtr loadFromDirectory( UIThemePtr theme, const std::string& Path,
const Float& pixelDensity = 1 );
static UITheme* loadFromDirectory( UITheme* tTheme, const std::string& Path,
const Float& pixelDensity = 1 );
static UITheme* loadFromDirectory( const std::string& Path, const std::string& Name,
const std::string& NameAbbr, const Float& pixelDensity = 1 );
static UIThemePtr loadFromDirectory( const std::string& Path, const std::string& Name,
const std::string& NameAbbr,
const Float& pixelDensity = 1 );
virtual ~UITheme();
@@ -61,7 +63,15 @@ class EE_API UITheme : protected ResourceManagerMulti<UISkin> {
const std::string& getAbbr() const;
virtual UISkin* add( UISkin* Resource );
UISkin* add( UISkinPtr skin );
UISkin* getById( const String::HashType& id ) const;
UISkin* getByName( const std::string& name ) const;
bool exists( const std::string& name ) const;
bool existsId( const String::HashType& id ) const;
Graphics::TextureAtlas* getTextureAtlas() const;
@@ -87,6 +97,8 @@ class EE_API UITheme : protected ResourceManagerMulti<UISkin> {
UIIconTheme* getIconTheme() const;
const Graphics::ResourceCatalogPtr& getResourceCatalog() const;
const std::string& getStyleSheetPath() const;
void setStyleSheetPath( const std::string& styleSheetPath );
@@ -97,14 +109,16 @@ class EE_API UITheme : protected ResourceManagerMulti<UISkin> {
std::string mName;
String::HashType mNameHash;
std::string mAbbr;
Graphics::TextureAtlas* mTextureAtlas;
Graphics::TextureAtlasPtr mTextureAtlas;
Font* mDefaultFont;
Float mDefaultFontSize;
CSS::StyleSheet mStyleSheet;
std::string mStyleSheetPath;
UIIconTheme* mIconTheme;
UIIconThemePtr mIconTheme;
UnorderedMap<String::HashType, std::vector<UISkinPtr>> mSkins;
Graphics::ResourceCatalogPtr mResourceCatalog;
void setTextureAtlas( Graphics::TextureAtlas* SG );
void setTextureAtlas( Graphics::TextureAtlasPtr textureAtlas );
UITheme( const std::string& name, const std::string& abbr, Graphics::Font* defaultFont = NULL );
};

View File

@@ -1,6 +1,7 @@
#ifndef EE_UICTHEMEMANAGER
#define EE_UICTHEMEMANAGER
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/ui/base.hpp>
#include <eepp/ui/uitheme.hpp>
@@ -8,12 +9,22 @@ namespace EE { namespace UI {
class UINode;
class EE_API UIThemeManager : public ResourceManager<UITheme> {
class EE_API UIThemeManager {
public:
static UIThemeManager* New();
virtual ~UIThemeManager();
UITheme* add( UIThemePtr theme );
bool remove( UITheme* theme );
bool removeById( const String::HashType& id );
bool removeByName( const std::string& name );
UIThemeManager* setResourceScope( Graphics::ResourceScopePtr resourceScope );
UIThemeManager* setDefaultFont( Font* Font );
Font* getDefaultFont() const;
@@ -24,10 +35,19 @@ class EE_API UIThemeManager : public ResourceManager<UITheme> {
UIThemeManager* setDefaultTheme( UITheme* Theme );
UIThemeManager* setDefaultTheme( UIThemePtr theme );
UIThemeManager* setDefaultTheme( const std::string& Theme );
UITheme* getDefaultTheme() const;
/** @return An owning handle to the default theme, or an empty handle when unset. */
UIThemePtr getDefaultThemeHandle() const;
UITheme* getById( const String::HashType& id ) const;
UITheme* getByName( const std::string& name ) const;
UIThemeManager* applyDefaultTheme( UINode* node );
UIThemeManager* setAutoApplyDefaultTheme( const bool& apply );
@@ -61,7 +81,8 @@ class EE_API UIThemeManager : public ResourceManager<UITheme> {
protected:
Font* mFont;
Float mFontSize;
UITheme* mThemeDefault;
UIThemePtr mThemeDefault;
UnorderedMap<String::HashType, UIThemePtr> mThemes;
bool mAutoApplyDefaultTheme;
bool mEnableDefaultEffects;
@@ -72,6 +93,7 @@ class EE_API UIThemeManager : public ResourceManager<UITheme> {
bool mTooltipFollowMouse;
Sizei mCursorSize;
Graphics::ResourceScopePtr mResourceScope;
UIThemeManager();
};

View File

@@ -7,6 +7,7 @@
#include <eepp/system/time.hpp>
#include <eepp/ui/layoutinvalidation.hpp>
#include <eepp/ui/uiscrollview.hpp>
#include <eepp/ui/webresourcecache.hpp>
#include <functional>
#include <memory>
@@ -72,6 +73,10 @@ class EE_API UIWebView : public UIScrollView {
UISceneNode* getDocumentSceneNode() const;
const WebResourceCachePtr& getWebResourceCache() const;
UIWebView* setWebResourceCache( WebResourceCachePtr cache, CachePartitionId partition = 0 );
void setStyleSheetDefaultMarker( Uint32 marker );
void setUserAgent( const std::string& userAgent );
@@ -117,6 +122,7 @@ class EE_API UIWebView : public UIScrollView {
Uint64 mNavigationGeneration{ 0 };
std::string mUserAgent;
Time mDefaultTimeout{ Seconds( 30 ) };
Time mWebResourceCachePruneElapsed;
Uint32 mStyleSheetDefaultMarker{ 0 };
void loadURI( URI uri, bool isHistoryNav );

View File

@@ -130,12 +130,14 @@ class EE_API UIWidget : public UINode {
virtual UIWidget* setAnchors( const Uint32& flags );
/**
* @brief Sets the theme for this widget.
* @brief Sets the borrowed theme used by this widget.
*
* Applies the specified theme to the widget, affecting its visual appearance.
* The theme controls colors, fonts, borders, and other visual properties.
* The widget stores @p Theme as a non-owning pointer and does not increment its reference
* count. The theme must outlive this use; normally it is retained by the containing scene's
* UIThemeManager. This keeps per-widget theme access inexpensive while centralizing ownership
* at the scene boundary.
*
* @param Theme Pointer to the UITheme to apply.
* @param Theme Borrowed theme to apply, or null to use no explicit theme.
*/
virtual void setTheme( UITheme* Theme );

View File

@@ -220,7 +220,7 @@ class EE_API UIWindow : public UIWidget {
RESIZE_TOPRIGHT
};
FrameBuffer* mFrameBuffer;
Graphics::FrameBufferUniquePtr mFrameBuffer;
StyleConfig mStyleConfig;
UIWidget* mWindowDecoration;
UIWidget* mBorderLeft;

View File

@@ -0,0 +1,306 @@
#ifndef EE_UI_WEBRESOURCECACHE_HPP
#define EE_UI_WEBRESOURCECACHE_HPP
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/network/http.hpp>
#include <eepp/network/uri.hpp>
#include <eepp/system/time.hpp>
#include <functional>
#include <memory>
#include <string>
namespace EE { namespace UI {
/** Shared ownership handle for a WebResourceCache.
*
* A cache can be installed into more than one UIWebView. Sharing the cache does not by itself make
* all resources visible between those views: sessions must also use the same CachePartitionId. */
using WebResourceCachePtr = std::shared_ptr<class WebResourceCache>;
/** Identifies one document consumer of a WebResourceCache.
*
* UISceneNode creates a session for its current document. A session tracks the current navigation
* generation and the cache entries leased by that document. IDs are process-wide and opaque. */
using DocumentSessionId = Uint64;
/** Identifies a cache sharing and privacy boundary.
*
* Sessions in the same partition may reuse and coalesce resources. Sessions in different
* partitions never share entries, even when requesting the same URI. A partition should therefore
* represent one intentionally shared HTTP state, normally one cookie jar/authentication context.
*
* For example, browser tabs that share cookies should use the same WebResourceCache and
* CachePartitionId. A private tab or a view logged into a different account must use another
* partition. Passing zero to createSession() creates a new private partition automatically.
* Partition IDs are process-wide and opaque.
*
* @code
* auto cache = WebResourceCache::New();
* auto normalProfile = cache->createPartition();
* firstTab->setWebResourceCache( cache, normalProfile );
* secondTab->setWebResourceCache( cache, normalProfile ); // May reuse firstTab resources.
* privateTab->setWebResourceCache( cache, cache->createPartition() ); // Fully isolated entries.
* @endcode */
using CachePartitionId = Uint64;
/** Canonical network origin used to describe a document navigation.
*
* Origins compare scheme, host, and port. Consequently HTTP and HTTPS origins are distinct, as are
* equal hosts using different ports. Paths, queries, and fragments are not part of an origin. */
struct EE_API WebOriginKey {
/** Lowercase URI scheme, such as "http" or "https". */
std::string scheme;
/** Lowercase host name. */
std::string host;
/** URI port, or the URI implementation's default/empty port value. */
Uint16 port{ 0 };
/** @return True when no origin components have been assigned. */
bool empty() const { return scheme.empty() && host.empty() && port == 0; }
/** @return True when both values describe the same scheme, host, and port. */
bool operator==( const WebOriginKey& other ) const;
/** @return True when at least one origin component differs. */
bool operator!=( const WebOriginKey& other ) const { return !( *this == other ); }
/** Creates an origin key from a URI, normalizing the scheme and host to lowercase. */
static WebOriginKey fromURI( const Network::URI& uri );
};
/** Semantic type of a cached web resource.
*
* The kind is part of cache identity, so one URI requested as a document and as a stylesheet uses
* distinct entries. Images additionally carry texture decode options in WebResourceRequest. */
enum class WebResourceKind : Uint8 {
/** Top-level HTML or another document response. */
Document,
/** CSS stylesheet response. */
StyleSheet,
/** Downloadable font response. */
Font,
/** Image response decoded into a Graphics::Texture. */
Image
};
/** Current lifecycle state of a cache entry. */
enum class WebResourceLoadState : Uint8 {
/** Entry exists but has not started loading. */
Empty,
/** One fetch is active; additional subscribers join it. */
Loading,
/** Resource completed successfully and is available for reuse. */
Ready,
/** Last fetch failed and remains subject to the retry delay. */
Failed,
/** Entry was cleared and any late fetch completion will be ignored. */
Cancelled
};
/** Complete input required to identify and fetch one web resource variant.
*
* Cache identity includes the partition, canonical URI, resource kind, method, non-navigation
* headers, body, and image decode options. Cookie and Referer are deliberately excluded from entry
* identity: the partition isolates cookie contexts, while these two values naturally change during
* navigation. They are still sent with the HTTP request.
*
* Transport policy such as timeout, proxy, and completionDispatcher controls a fetch but does not
* describe the resulting resource and is therefore not part of cache identity. */
struct EE_API WebResourceRequest {
/** Dispatches a completion function to the thread on which it is safe to finalize a resource.
*/
using CompletionDispatcher = std::function<void( std::function<void()> )>;
/** Absolute URI to fetch. Fragments are removed and the URI is normalized for cache lookup. */
Network::URI uri;
/** Semantic resource type. */
WebResourceKind kind{ WebResourceKind::Document };
/** HTTP method. The method is part of cache identity. */
Network::Http::Request::Method method{ Network::Http::Request::Method::Get };
/** HTTP request headers. See the type documentation for cache-key rules. */
Network::Http::Request::FieldTable headers;
/** HTTP request body. The complete body is part of cache identity. */
std::string body;
/** Maximum duration allowed for the HTTP request. */
System::Time timeout{ System::Seconds( 5 ) };
/** Whether HTTPS certificates must be validated. */
bool validateCertificate{ true };
/** Optional HTTP proxy URI. An empty URI uses a direct connection. */
Network::URI proxy;
/** Whether HTTP redirects should be followed. */
bool followRedirect{ true };
/** Image-only texture wrapping policy. True selects ClampToEdge. */
bool clampToEdge{ true };
/** Image-only option controlling mipmap generation. */
bool mipmaps{ false };
/** Image-only option requesting texture compression. */
bool compressTexture{ false };
/** Image-only SVG rasterization scale. */
Float svgScale{ 1.f };
/** Image-only completion dispatcher.
*
* Image decode/upload completion must execute where a graphics context is current. This policy
* is not part of cache identity and only the request that starts a coalesced load supplies it.
*/
CompletionDispatcher completionDispatcher;
};
/** Result delivered to a WebResourceCache subscriber.
*
* Data resources set data, while image resources set texture. A texture request may already have
* returned the same TexturePtr as a transparent placeholder before this result is delivered. */
struct EE_API WebResourceResult {
/** True when the request completed and produced a usable resource. */
bool success{ false };
/** Final cache-entry state observed by this completion. */
WebResourceLoadState state{ WebResourceLoadState::Empty };
/** Numeric HTTP response status. */
int status{ 0 };
/** Failure description. Empty for successful results. */
std::string error;
/** Set-Cookie value from the final response, or from its redirect chain when applicable. */
std::string setCookie;
/** Shared immutable response body for documents, stylesheets, and fonts. */
std::shared_ptr<const std::string> data;
/** Shared texture for image resources. */
Graphics::TexturePtr texture;
};
/** Shared HTTP-backed document resource cache.
*
* The cache separates three concepts:
* - A partition defines which HTTP/cookie context may share entries.
* - A session represents one active document using entries from that partition.
* - A navigation generation prevents an obsolete document from receiving asynchronous results.
*
* Entries are strongly retained by the cache after their final document lease is released. Their
* TTL starts at that release point, allowing Back/Forward navigation to reuse them. Expired entries
* are removed by prune(); UIWebView invokes it periodically. A byte budget additionally evicts the
* least-recently-used unleased entries. Active leases and in-flight loads are not evicted.
*
* Requests for the same key are coalesced into one HTTP operation. Each current subscriber receives
* the result, while callbacks belonging to obsolete navigation generations are discarded. Public
* operations are internally synchronized. Subscriber callbacks run without the cache mutex held. */
class EE_API WebResourceCache : public std::enable_shared_from_this<WebResourceCache> {
public:
/** Receives the completed result of a data or texture request. */
using Callback = std::function<void( const WebResourceResult& )>;
/** @return A newly allocated shared web-resource cache. */
static WebResourceCachePtr New();
/** Creates an empty cache with a 30-second TTL, 1-second retry delay, and 64 MiB budget. */
WebResourceCache();
/** Cancels cache delivery and releases all retained entries and sessions. */
~WebResourceCache();
/** Allocates a new process-wide partition identifier.
* @return An opaque, non-zero partition ID. */
CachePartitionId createPartition();
/** Creates a document session.
* @param partition Partition to join. Zero creates a new private partition.
* @return An opaque, non-zero document session ID. */
DocumentSessionId createSession( CachePartitionId partition = 0 );
/** Destroys a session and releases all entries leased by it.
*
* Releasing the final lease starts each entry's TTL; it does not normally erase entries
* immediately. Pending callbacks for the destroyed session will not be delivered. */
void destroySession( DocumentSessionId session );
/** Begins a new document navigation in an existing session.
*
* Previous document leases are released and the generation is incremented. Pending subscribers
* from older generations become stale, but shared in-flight requests continue for other current
* subscribers.
* @param session Session performing the navigation.
* @param uri Destination document URI, used to record its origin.
* @return The new generation, or zero when the session does not exist. */
Uint64 beginNavigation( DocumentSessionId session, const Network::URI& uri );
/** @return The current generation for a session, or zero when it does not exist. */
Uint64 getSessionGeneration( DocumentSessionId session ) const;
/** @return The partition used by a session, or zero when it does not exist. */
CachePartitionId getSessionPartition( DocumentSessionId session ) const;
/** Requests a document, stylesheet, font, or other non-texture response body.
*
* A ready cache hit may invoke callback synchronously. A miss starts or joins an asynchronous
* fetch. The callback is omitted when the session/generation is stale.
* @param session Requesting document session.
* @param generation Generation returned by beginNavigation().
* @param request Resource and transport description.
* @param callback Optional completion callback. */
void requestData( DocumentSessionId session, Uint64 generation, WebResourceRequest request,
Callback callback );
/** Requests an image as a shared texture.
*
* On a miss, this creates and returns a transparent placeholder immediately. The same
* TexturePtr is populated after download and decode. A ready hit returns the existing texture
* without a new HTTP request. This function must be called where texture creation is valid, and
* the request must provide an appropriate completionDispatcher for asynchronous GPU upload.
* @return The cached/new texture, or null for an invalid or stale session. */
Graphics::TexturePtr requestTexture( DocumentSessionId session, Uint64 generation,
WebResourceRequest request, Callback callback = {} );
/** Sets the retention duration used when an entry's final document lease is released. */
void setTTL( System::Time ttl );
/** @return The current post-lease retention duration. */
System::Time getTTL() const;
/** Sets how long a failed entry suppresses another fetch attempt. */
void setRetryDelay( System::Time delay );
/** @return The current failed-request retry delay. */
System::Time getRetryDelay() const;
/** Sets the maximum retained response/texture byte estimate.
*
* Applying a smaller budget immediately evicts least-recently-used unleased entries where
* possible. Active entries may temporarily make retained bytes exceed the budget. */
void setByteBudget( std::size_t bytes );
/** @return The configured retained-byte budget. */
std::size_t getByteBudget() const;
/** @return Estimated bytes retained by ready data bodies and decoded image textures. */
std::size_t getRetainedBytes() const;
/** @return Number of cache entries in all states and partitions. */
std::size_t getEntryCount() const;
/** @return Number of HTTP requests belonging to the cache's current epoch.
*
* `clear()` resets this count even though invalidated underlying operations may still finish;
* those stale completions are ignored and do not alter the count. */
std::size_t getInFlightCount() const;
/** Removes expired entries and enforces the byte budget.
*
* Active document leases and loading entries are preserved. UIWebView calls this periodically;
* other cache owners should provide their own maintenance point. */
void prune();
/** Removes every entry immediately and suppresses delivery from outstanding fetches.
*
* Sessions remain valid but no longer lease entries. This does not cancel the underlying HTTP
* operation. A late completion is ignored using its operation identity, including when a new
* request has already recreated an entry with the same cache key. */
void clear();
/** Completion supplied to a custom Fetcher. */
using FetchCompletion = std::function<void( Network::Http::Response )>;
/** Custom fetch implementation, primarily intended for deterministic tests.
*
* The fetcher must eventually invoke FetchCompletion exactly once. Production uses
* Http::requestAsync when no custom fetcher is installed. */
using Fetcher = std::function<void( const WebResourceRequest&, FetchCompletion )>;
/** Installs or clears a custom HTTP fetch implementation. */
void setFetcher( Fetcher fetcher );
private:
/** Private implementation containing synchronized sessions and cache entries. */
struct Impl;
/** Exclusive implementation state. */
std::unique_ptr<Impl> mImpl;
};
}} // namespace EE::UI
#endif

View File

@@ -78,6 +78,7 @@ class EE_API Cursor {
Vector2i mHotSpot;
EE::Window::Window* mWindow;
// The texture pixels are copied synchronously; Cursor does not retain this borrow.
Cursor( Texture* tex, const Vector2i& hotspot, const std::string& getName,
EE::Window::Window* window );

View File

@@ -6,6 +6,13 @@
#include <eepp/window/platformhelper.hpp>
#include <eepp/window/window.hpp>
#include <memory>
namespace EE { namespace Graphics {
class ResourceCatalog;
class ResourceScope;
}} // namespace EE::Graphics
namespace EE { namespace System {
class IniFile;
class Pack;
@@ -140,6 +147,12 @@ class EE_API Engine {
/** @return The display manager. Holds the physical displays information. */
DisplayManager* getDisplayManager();
/** @return The catalog used for resources intentionally exported application-wide. */
std::shared_ptr<Graphics::ResourceCatalog> getGlobalResourceCatalog() const;
/** @return The default Graphics scope. It explicitly imports the global resource catalog. */
std::shared_ptr<Graphics::ResourceScope> getDefaultResourceScope() const;
/** Open a URL in a separate, system-provided application.
* @return true if success
*/
@@ -156,6 +169,8 @@ class EE_API Engine {
PlatformHelper* mPlatformHelper;
Pack* mZip;
DisplayManager* mDisplayManager;
std::shared_ptr<Graphics::ResourceCatalog> mGlobalResourceCatalog;
std::shared_ptr<Graphics::ResourceScope> mDefaultResourceScope;
Engine();

View File

@@ -654,7 +654,7 @@ function build_link_configuration( package_name, use_ee_icon )
add_cross_config_links()
configuration "emscripten"
linkoptions { "-s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2" }
linkoptions { "-s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web" }
buildoptions { "-s USE_SDL=2" }
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }

View File

@@ -372,7 +372,7 @@ function build_base_configuration( package_name )
buildoptions { "/utf-8" }
filter "system:emscripten"
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
buildoptions { "-O3 -s USE_SDL=2" }
buildoptions { "-s USE_PTHREADS=1" }
filter {}
@@ -412,7 +412,7 @@ function build_base_cpp_configuration( package_name )
symbols "On"
filter "system:emscripten"
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
buildoptions { "-O3 -s USE_SDL=2" }
buildoptions { "-s USE_PTHREADS=1" }
filter {}
@@ -445,6 +445,23 @@ function build_link_configuration( package_name, use_ee_icon )
incdirs { "include" }
local extension = "";
if os.istarget("emscripten") and package_name ~= "eepp" and package_name ~= "eepp-static" then
local without_assets = {
["eepp-empty-window"] = true,
["eepp-sound"] = true,
["eepp-vbo-fbo-batch"] = true,
["eepp-physics-demo"] = true,
["eepp-http-request"] = true,
}
if not without_assets[package_name] then
if package_name == "ecode" then
linkoptions { "--preload-file " .. package_name .. "/assets/" }
else
linkoptions { "--preload-file assets/" }
end
end
end
if package_name == "eepp" then
defines { "EE_EXPORTS" }
elseif package_name == "eepp-static" then
@@ -583,8 +600,11 @@ function build_link_configuration( package_name, use_ee_icon )
filter "system:emscripten"
targetname ( package_name .. extension )
linkoptions { "-O3 -s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2" }
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
if package_name ~= "eepp" and package_name ~= "eepp-static" then
targetextension ".html"
end
linkoptions { "-O3 -s TOTAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s USE_SDL=2 -s ENVIRONMENT=worker,web" }
buildoptions { "-O3 -s USE_SDL=2" }
buildoptions { "-s USE_PTHREADS=1" }
linkoptions { "-s USE_PTHREADS=1 -sPTHREAD_POOL_SIZE=8" }
@@ -739,7 +759,9 @@ end
function add_sdl2()
print("Using SDL2 backend");
if not can_add_static_backend("SDL2") then
table.insert( link_list, get_backend_link_name( "SDL2" ) )
if not os.istarget("emscripten") then
table.insert( link_list, get_backend_link_name( "SDL2" ) )
end
else
print("Using static backend")
insert_static_backend( "SDL2" )
@@ -1042,6 +1064,8 @@ function build_eepp( build_name )
end
function target_dir_lib(path)
filter "architecture:wasm32"
targetdir("libs/" .. os.target() .. "/wasm32/" .. path .. "/")
filter "architecture:x86"
targetdir("libs/" .. os.target() .. "/x86/" .. path .. "/")
filter "architecture:x86_64"
@@ -1084,6 +1108,9 @@ workspace "eepp"
if _ACTION == "ninja" then
configurations { "debug", "release" }
platforms { get_architecture() }
elseif os.istarget("emscripten") then
configurations { "debug", "release" }
platforms { "wasm32" }
else
configurations { "debug", "release" }
platforms { "x86_64", "x86", "arm64" }
@@ -1111,6 +1138,9 @@ workspace "eepp"
filter "platforms:x86_64"
architecture "x86_64"
filter "platforms:wasm32"
architecture "wasm32"
filter { "platforms:x86_64", "system:macosx" }
architecture "x86_64"
buildoptions { "-arch x86_64" }
@@ -1518,19 +1548,21 @@ workspace "eepp"
filter "action:not vs*"
buildoptions { "-Wall" }
project "eepp-maps"
kind "SharedLib"
language "C++"
cppdialect "C++20"
incdirs { "include", "src/modules/maps/include/","src/modules/maps/src/" }
files { "src/modules/maps/src/**.cpp" }
links { "eepp-shared" }
defines { "EE_MAPS_EXPORTS" }
build_base_cpp_configuration( "eepp-maps" )
postsymlinklib_arch( "eepp-maps" )
target_dir_lib("")
filter "action:not vs*"
buildoptions { "-Wall" }
if not os.istarget("emscripten") then
project "eepp-maps"
kind "SharedLib"
language "C++"
cppdialect "C++20"
incdirs { "include", "src/modules/maps/include/","src/modules/maps/src/" }
files { "src/modules/maps/src/**.cpp" }
links { "eepp-shared" }
defines { "EE_MAPS_EXPORTS" }
build_base_cpp_configuration( "eepp-maps" )
postsymlinklib_arch( "eepp-maps" )
target_dir_lib("")
filter "action:not vs*"
buildoptions { "-Wall" }
end
project "eepp-physics-static"
kind "StaticLib"
@@ -1547,19 +1579,21 @@ workspace "eepp"
filter "action:not vs*"
buildoptions { "-Wall" }
project "eepp-physics"
kind "SharedLib"
language "C++"
cppdialect "C++20"
incdirs { "include", "src/modules/physics/include/","src/modules/physics/src/" }
files { "src/modules/physics/src/**.cpp", "src/eepp/physics/constraints/*.cpp" }
links { "chipmunk-static", "eepp-shared" }
defines { "EE_PHYSICS_EXPORTS" }
build_base_cpp_configuration( "eepp-physics" )
postsymlinklib_arch( "eepp-physics" )
target_dir_lib("")
filter "action:not vs*"
buildoptions { "-Wall" }
if not os.istarget("emscripten") then
project "eepp-physics"
kind "SharedLib"
language "C++"
cppdialect "C++20"
incdirs { "include", "src/modules/physics/include/","src/modules/physics/src/" }
files { "src/modules/physics/src/**.cpp", "src/eepp/physics/constraints/*.cpp" }
links { "chipmunk-static", "eepp-shared" }
defines { "EE_PHYSICS_EXPORTS" }
build_base_cpp_configuration( "eepp-physics" )
postsymlinklib_arch( "eepp-physics" )
target_dir_lib("")
filter "action:not vs*"
buildoptions { "-Wall" }
end
project "eterm-static"
kind "StaticLib"
@@ -1605,12 +1639,14 @@ workspace "eepp"
target_dir_lib("")
end
project "eepp-shared"
kind "SharedLib"
language "C++"
build_eepp( "eepp" )
postsymlinklib_arch( "eepp" )
target_dir_lib("")
if not os.istarget("emscripten") then
project "eepp-shared"
kind "SharedLib"
language "C++"
build_eepp( "eepp" )
postsymlinklib_arch( "eepp" )
target_dir_lib("")
end
-- Examples
project "eepp-external-shader"

View File

@@ -1,17 +1,25 @@
#!/bin/sh
# Currently latest emsdk tested and working version: latest-fastcomp
# remember to first set the environment
set -e
# Currently tested emsdk version: 4.0.1
# Remember to first set the environment:
# source /path/to/emsdk/emsdk_env.sh
cd $(dirname "$0") || exit
cd "$(dirname "$0")"
unset CPLUS_INCLUDE_PATH
premake4 --file=../../premake4.lua --with-gles2 --with-static-eepp --platform=emscripten --with-backend=SDL2 gmake
cd ../../make/emscripten/ || exit
PREMAKE5=${PREMAKE5:-premake5}
if [ -x ../../premake5 ]; then
PREMAKE5=../../premake5
fi
"$PREMAKE5" --file=../../premake5.lua --os=emscripten --with-gles2 --with-static-eepp --with-backend=SDL2 gmake
cd ../../make/emscripten/
rm -rf ./assets
cp -r ../../bin/assets/ .
rm assets/fonts/NotoColorEmoji.ttf assets/fonts/DejaVuSansMonoNerdFontComplete.ttf assets/fonts/DroidSansFallbackFull.ttf
rm -f assets/fonts/NotoColorEmoji.ttf assets/fonts/DejaVuSansMonoNerdFontComplete.ttf assets/fonts/DroidSansFallbackFull.ttf
rm -rf ./ecode
mkdir ecode
cp -r ../../bin/assets/ ecode/assets/
rm ecode/assets/fonts/DejaVuSansMonoNerdFontComplete.ttf ecode/assets/fonts/DroidSansFallbackFull.ttf ecode/assets/fonts/NotoColorEmoji.ttf ecode/assets/test.zip ecode/assets/ca-bundle.pem ecode/assets/icon/ee.icns ecode/assets/icon/ee.rc ecode/assets/icon/ee.res ecode/assets/icon/ee.ico ecode/assets/fonts/*.png ecode/assets/fonts/*.fnt ecode/assets/fonts/OpenSans-Regular.ttf ecode/assets/icon/ecode.icns ecode/assets/icon/eterm* ecode/assets/icon/*.svg
rm -r ecode/assets/atlases ecode/assets/screenshots ecode/assets/cursors ecode/assets/layouts ecode/assets/maps ecode/assets/sounds ecode/assets/sprites ecode/assets/tiles ecode/assets/shaders ecode/assets/ui/uitheme*
rm -f ecode/assets/fonts/DejaVuSansMonoNerdFontComplete.ttf ecode/assets/fonts/DroidSansFallbackFull.ttf ecode/assets/fonts/NotoColorEmoji.ttf ecode/assets/test.zip ecode/assets/ca-bundle.pem ecode/assets/icon/ee.icns ecode/assets/icon/ee.rc ecode/assets/icon/ee.res ecode/assets/icon/ee.ico ecode/assets/fonts/*.png ecode/assets/fonts/*.fnt ecode/assets/fonts/OpenSans-Regular.ttf ecode/assets/icon/ecode.icns ecode/assets/icon/eterm* ecode/assets/icon/*.svg
rm -rf ecode/assets/atlases ecode/assets/screenshots ecode/assets/cursors ecode/assets/layouts ecode/assets/maps ecode/assets/sounds ecode/assets/sprites ecode/assets/tiles ecode/assets/shaders ecode/assets/ui/uitheme*
emmake make -j"$(nproc)" "$@"

Some files were not shown because too many files have changed in this diff Show More