Commit Graph
31 Commits
Author SHA1 Message Date
Leonardo Zide 3d1091492e Reduce asset header dependencies
Keep library source storage details in the implementation and move the primitive constructor out of line so the library header no longer needs string helpers. Use shared forward declarations and asset types in loader and manager headers, keeping the full texture definition in its implementation.
2026-10-20 21:31:31 -07:00
Leonardo Zide 98c67f3705 Align texture acquisition and scoped ownership
Texture lookup previously acquired references implicitly, and mesh sections and
loader requests paired raw texture pointers with manual release paths. Separate
borrowed lookup from scoped acquisition and explicit load requests/waits to match
the piece data ownership API.

Store lcTextureRef in mesh sections and loader requests, retain references on
section copies, and reset worker-shared request handles on the UI thread before
completion, cancellation, or shutdown. Keep reference primitives internal and use
scoped acquisitions for merge validation. Remove redundant section initialization
and synth-notification resets, and document the resulting ownership contracts.

Validation: macOS Debug build, diff whitespace checks, and 30 offscreen lifecycle
checks covering reference copies/moves, texture dependencies, cancellation,
shutdown, merge conflicts, and existing piece ownership paths. Successful GPU
upload/rendering is not covered by the offscreen checks.
2026-10-19 10:38:51 -07:00
Leonardo Zide 61be531444 Manage piece data ownership with scoped asset references
Replace manual piece-data retain/release bookkeeping with shared copyable
asset-reference handles. Pieces, models, selection, minifigs, thumbnails,
and stored insertion previews retain their dependencies explicitly, while
transient queries continue to borrow pointers.

Separate registered lookup and acquisition from asynchronous load requests
and explicit readiness waits. Keep loader-held references through work and
notification delivery, resetting shared request handles on the UI thread
and guarding callback-triggered library teardown.

Validated with the Qt 6.10 debug build and 26 offscreen lifecycle checks,
including cancellation, stale requests, copy/move operations, model/preview
teardown, undo, project merge/export, and loader shutdown.
2026-10-19 10:02:26 -07:00
Leonardo Zide 7bc6c018b1 Rename PieceInfo to lcPieceData
Use PieceData consistently for the shared part/model record, its related
APIs and variables, and its source files. Keep the existing reference
counting and loading behavior so ownership and readiness changes can be
reviewed separately.
2026-10-18 23:22:28 -07:00
Leonardo Zide 58f60b9423 Separate asset readiness from loader request progress
Keep piece readiness, mesh publication, and settled synth errors in the
library while the loader manages scheduling, request outcomes, cancellation,
and deferred notifications. Capture synth inputs and base identities at the
library boundary so the loader treats pieces as opaque identities.

Use a shared asset readiness enum for pieces and textures. Keep texture
queueing, decoding, and retry progress in requests, pass resolved sources to
the loader, and centralize texture failure messages in lcTexture. Preserve
scoped wait failure and cancellation results alongside final readiness checks.

Consolidate shared priorities, sources, snapshots, build results, and texture
error codes in lc_assettypes.h, replacing lc_filesource.h. Forward declarations
remove the loader header's piece, library, and texture-manager dependencies.

Validated with the Qt Debug build, header isolation compilation, asset loader
lifecycle and scheduling regression checks, and 14 first/repeat export checks.
2026-10-16 17:42:16 -07:00
Leonardo Zide c7de6bfecc Keep asset refresh orchestration in the library
Keep the persistent registry of live synth instances in the library, where
settings changes can refresh completed and failed generations through the
normal request lifecycle. The loader retains only pending work and errors.

After draining assigned jobs to change shared settings safely, resume
replacement work asynchronously instead of waiting for unrelated queued
assets. Rebuild model geometry through the normal loader entry point,
invalidating stale requests without adding a consumer reference.

Reduce the loader's public API, group its declarations by responsibility,
and document the ownership and asynchronous refresh behavior.

Validated with the Qt Debug build, loader lifecycle and scheduling regression
checks, model and synth refresh checks, and 14 first/repeat export checks.
2026-10-16 15:17:40 -07:00
Leonardo Zide 6795887758 Schedule asset builds on the UI thread
Move request selection and lifecycle updates to the UI thread so worker jobs
only build their assigned asset and hand back a completion. This removes
request-map locking and keeps priority promotion, cancellation, and publication
under one thread's ownership.

Limit outstanding jobs to half the reported hardware threads, with a minimum
of one and no fixed cap. Release job slots before texture dependency settlement
and retain completion wakeups for synchronous waits, pause, and shutdown.

Share piece-request cleanup while preserving in-flight load holds. Use cancelled
request states to suppress invalidated notifications instead of an obsolete flag.
Clarify function names, document the lifecycle, and group header declarations.

Validation: Qt Debug build, scheduler and lifecycle harness, one-slot texture
success/retry checks, notification suppression and reference checks, 14 asset
exports, and git diff --check passed.
2026-10-16 13:13:02 -07:00
Leonardo Zide 793815efe8 Simplify asset loader scheduling with request states
The loader kept separate queues alongside its request maps and represented
request progress with overlapping booleans. Keep pending work in the maps
and select queued requests by priority and age using a shared lifecycle
state and scheduling fields.

Preserve cancellation ownership through outstanding worker completions,
restart staged meshes after settings changes, and protect wait-state reads
with the request mutex. Skip request scans when workers cannot start.
Pass the existing piece source snapshot to texture resolution instead of
separate lookup containers, and document the updated request lifecycle.

Validation: Qt Debug build, loader scheduling/cancellation/cache/lifecycle
checks, 14 first/repeat exports, and git diff --check passed.
2026-10-16 12:30:34 -07:00
Leonardo Zide 4129788f95 Build piece and synth meshes in one worker job
Color finalization no longer requires a UI-thread handoff between parsing and mesh conversion. Have the library and synth build services return converted private meshes, removing intermediate request/result mesh data and conversion requeue paths.

Fall back to source parsing immediately when a cached mesh cannot be decoded, eliminating SkipCache and the UI retry branch. Simplify paused staging cleanup and document the combined worker lifecycle; section finalization and publication remain on the UI thread.
2026-10-15 14:37:07 -07:00
Leonardo Zide 9f7e4d3a41 Unify mesh color resolution and section finalization
Cached meshes retained color-dependent flags and section ordering from the palette used when they were saved. Finalize fresh piece, synth, and cached mesh sections on the UI thread so color indices, flags, and ordering all reflect the current palette before publication.

Keep color codes in private mesh sections until finalization and remove separate color-code vectors, worker palette snapshots, and the early color-resolution path. Geometry conversion now runs without global color access or texture lookup callbacks.
2026-10-15 14:11:05 -07:00
Leonardo Zide f4fe4f8e87 Clarify asset loader request and completion APIs
Use consistent names for piece loading, synth generation, worker completions, and outstanding work. Remove the unused library drain wrapper and call the loader directly during settings updates.

Check for the final consumer release in the library before cancelling queued piece work, and document how running builds retain their load hold until completion. Update callers and asset-loading documentation.
2026-10-15 13:35:34 -07:00
Leonardo Zide d493eee066 Simplify asset loader state and shutdown
Asset requests carried duplicate phase, generation, and notification state.
Remove unused texture dependencies and project-path storage, derive conversion
from owned mesh data, and use request identity, cancellation, and the stopping
flag to reject obsolete results.

Decode cached meshes in the library's worker build service so serialized bytes
stay local and completions retain only decoded data and a cache-origin flag.
Make draining private to the loader destructor and remove duplicate shutdown
calls from library unload and destruction. Document the resulting lifecycle.

Validation: macOS Qt 6.10 Debug build; 14 first/repeat CLI exports; temporary
lifecycle checks covering cold/warm/corrupt caches, notification delivery and
suppression, pause/resume, cancellation, destructor-only draining, and reload.
2026-10-14 21:33:17 -07:00
Leonardo Zide 6a8c05acc5 Initialize stud settings and simplify loader bookkeeping
Pass effective startup stud settings into the library and apply color preferences before loading. Replace the reload toggle with UpdateStudStyleAndColors, preserve configured settings in the fallback library, and save the selected color config before combined preferences updates.

Remove temporary consumer references from synchronous piece waits, the redundant drain mutex, and worker-start queues. Derive loading states from current requests and use explicit piece names for request, queue, and notification storage. Document the updated ownership and settings contracts.

Validated with a Debug build, startup style and color exports, 14 asset export checks, and temporary lifecycle checks covering owned waits, failed and duplicate requirements, regeneration, cancellation, pause/resume, reference cleanup, and shutdown.
2026-10-14 10:57:30 -07:00
Leonardo Zide 3ec8b274b1 Unify asset loading priorities and clarify wait APIs
Replace load flags and the loader's separate priority enum with Low, Normal, and Blocking priorities. Blocking loads wait for completion; asynchronous loads and internal scheduling retain promotion-only behavior.

Acquire consumer references in the library, reuse loader loading for stud-style rebuilds, and remove QueuePiece, single-piece readiness wrappers, and the library texture readiness wrapper. Rename scoped readiness APIs to WaitFor functions and document their scheduling and lifetime contracts.

Validated with a Debug build and a temporary lifecycle harness covering priority promotion, blocking loads, reference cleanup, selective style reloads, cancellation, pause/resume, and shutdown.
2026-10-13 23:27:29 -07:00
Leonardo Zide 2051eeed42 Simplify asset loader lifecycle and paused scheduling
Make the loading lifecycle easier to follow by ordering functions by phase, splitting completion handling by asset type, and sharing color and texture preparation. Use Piece terminology, rename model rebuilding, and document reference and waiting behavior.

Keep pending work in the normal queues while paused, refresh piece snapshots before resuming, and remove duplicate enqueue and cancellation paths. QueuePiece now explicitly schedules background work.

Validated with a Debug build, 14 CLI export checks, and a temporary lifecycle harness covering staging resets, style refresh, cancellation, eight in-flight pause/resume cycles, last-consumer release, and shutdown.
2026-10-13 19:32:12 -07:00
Leonardo Zide 232fc54dee Remove unused asset request IDs
Part request IDs were assigned and copied to build results but never read. Remove the fields, counter, and assignments; stale completion checks continue to use request identity and generation.
2026-10-13 19:07:09 -07:00
Leonardo Zide b69db29428 Replace custom Image buffers with QImage
Texture decoding and generated atlases previously used a custom packed-pixel
container alongside QImage, duplicating storage and image-processing code.
Use QImage throughout texture preparation and upload, remove Image and its
pixel-format enum, and store font and string masks in Alpha8 atlases.

Preserve power-of-two dimensions with smooth scaling and keep the existing
OpenGL formats, shaders, and CPU mipmap filtering. Handle padded scanlines,
restore the caller's unpack alignment on every upload return, and centralize
binding cleanup so failed uploads do not leave stale texture caches.

Validation: full application build and diff checks passed. OpenGL readback
checks covered RGB/RGBA/alpha data, padded and custom strides, generated and
supplied mipmaps, unpack-state restoration, and failure cleanup. All nine
grid mip levels matched the previous generator. Visual rendering was checked
by the user.
2026-10-12 19:24:44 -07:00
Leonardo Zide 05ba97dd88 Simplify texture sources and remove unused loading paths
The direct texture-loading overloads and synchronous library/manager chain
have no callers. Remove them and the filename image-loading overload so
texture requests use the existing loader path.

Replace the texture's separate source fields with a shared lcFileSource
value in its own header. Keep source identity comparisons unchanged,
including content-based embedded texture checks during project merging.
The loader copies the source directly into its request, eliminating the
library and manager snapshot forwarding methods. Preserve the library
header's regrouping and update the asset-loading documentation.

Validated the debug build, file ownership/cursor/error checks, loader
failure and retry behavior, 800 concurrent archive reads, and matching
embedded/disk texture renders.
2026-10-12 12:15:48 -07:00
Leonardo Zide 1098c2de75 Separate texture management from library source access
Texture lookup, references, decoding, and scheduling were mixed into the pieces library. Introduce lcTextureManager to own texture identities, references, and CPU decoding, while keeping source lookup and file indexes in the library and asynchronous scheduling, uploads, retries, and publication in lcAssetLoader.

Add lcFileSourceSnapshot and OpenFile to return owned disk or memory streams. The library opens files on the existing loading thread and passes lcFile references to the manager. Image decoding uses QFile or existing memory buffers directly, preserving file cursors without an extra adapter.

Hide loader-only texture services, centralize failure state and diagnostics in lcTexture::SetFailed, and use each zip archive internal extraction lock instead of a library-wide mutex. Workers are drained before archive replacement or texture-manager teardown.

Validation: debug build, file ownership and cursor checks, texture lookup and decoding checks, bounded upload-retry and reference-release checks, 800 concurrent archive reads, and matching native GPU renders for embedded and disk textures.
2026-10-12 11:45:25 -07:00
Leonardo Zide f39e1ae70a Support embedded LDraw texture data
Parse !DATA blocks as project-scoped assets and resolve TEXMAP textures
from immutable asset snapshots without sharing same-named embedded images
between external projects. Preserve original document blocks when saving,
including blank lines, payload formatting, and unchanged model text.

Carry required submodels and embedded assets through copy, paste, and
exports, validating conflicts before import. Return clipboard errors to
the main window and preserve selected objects when Cut cannot copy them.

Fixes #937
2026-10-08 21:49:14 -07:00
Leonardo Zide 202035d4ea Follow TEXMAP texture search order
Search all texture locations with the textures/ prefix before trying bare filenames, so model-folder images cannot override prefixed library textures. Resolve nested textures across LDraw library roots and retain the selected disk path or archive entry for decoding and reuse.

Index disk-library PNG paths when loading the library to avoid repeated directory scans on the UI thread. Parse quoted filenames and escaped quotes and backslashes in all TEXMAP projection methods, and reject names that exceed texture storage.

Validated with the macOS debug build and focused checks for disk and archive precedence, nested and mixed-case paths, exact archive decoding, source reuse, reloads, symlinks, and filename parsing.
2026-10-08 10:54:38 -07:00
Leonardo Zide 145b3238db Document asset loading contracts and clarify queue helper naming 2026-10-04 19:29:33 -07:00
Leonardo Zide 622774f254 Simplify streaming asset priorities to promotion only
Keep each pending mesh and texture request at its highest requested priority
until it completes or is cancelled. Use one promotion helper for visible
requests and synchronous waits, propagating promotions to pending textures
without lowering priorities required by shared work.

Remove outgoing-project demotion and restoration during file opening and
LDD import. Existing reference counts continue to cancel unused queued work
and preserve assets shared with the incoming project or other views.

Validation: macOS Debug build, git diff --check, 16 priority/cancellation
checks, and 199 bounds, external-project undo, and output regression checks.
2026-10-04 17:19:28 -07:00
Leonardo Zide dcd2ef5a3b Defer synth notifications and reject missing mesh includes 2026-10-04 12:37:17 -07:00
Leonardo Zide b242cf9ad5 Generate synth meshes asynchronously
Queue per-piece synth builds alongside mesh and texture work, with cooperative cancellation for obsolete requests. Keep the previous mesh visible during edits and account for generated meshes in blocking output and loading progress. Defer preview and thumbnail rendering until their required synth meshes settle.
2026-09-28 22:49:16 -07:00
Leonardo Zide 1d02dde890 Scope project pieces and preserve assets across model changes
Keep project-local piece mappings separate from library pieces and preserve references across rename, merge, delete, and Save As.

Remap local external pieces after Save As, retain texture source order, invalidate stale loads, and refresh previews and thumbnails after asset changes. Save projects atomically and preserve active model selection in the model list.
2026-09-28 09:22:09 -07:00
Leonardo Zide 8e2490c4ba Open LDraw and LDD projects without waiting for meshes
Queue model geometry builds and mesh conversion on workers so project opening can return after parsing. Keep complete-asset waits for previews and output, and show project loading progress in the status bar.

Preserve live pieces when project names overlap, restore mappings after failed loads, and include detached pieces in buffer and stud-style updates.
2026-09-27 10:59:34 -07:00
Leonardo Zide d6359a063a Show loading placeholders and require complete assets for output
- Draw a shared cube for parts whose meshes or textures are still loading.
- Update model bounds, picking, views, and loading status as assets complete.
- Wait for required assets before thumbnails, screenshots, instructions,
  and geometry exports; report failures instead of rendering placeholders.
- Render and pick direct geometry in external projects.
- Defer shared buffer repacking until pending loads finish.
2026-09-26 16:06:20 -07:00
Leonardo Zide 9fd8d50179 Harden asset cache and mesh loading paths
Validate cache I/O and zlib results, reject incomplete mesh allocations, and keep shared buffer offsets safe when rebuilding. Document loader priorities and repository editing conventions.
2026-09-26 11:10:02 -07:00
Leonardo Zide a79d4953e3 Implement staged mesh and texture loading
Build meshes and decode textures in workers, then publish meshes and upload textures on the UI thread. Mark a part loaded only after its textures are ready.

Add request cancellation, priorities, and waits scoped to required assets. Keep previews and thumbnails from rendering incomplete parts, preserve failure diagnostics, and handle corrupt caches and project changes.
2026-09-25 16:58:29 -07:00
Leonardo Zide 29c9c98402 Introduce asset loader boundary for streaming groundwork
Move part scheduling and futures into a library-owned lcAssetLoader while preserving current loading behavior. Hold queued parts alive through completion, deliver completion notifications on the UI thread, and drain work before library teardown.

Pause queued work during stud-style changes, rebuild affected meshes, and use an unambiguous mesh-cache settings key. Guard mesh-buffer rebuilding against allocation failure.

Add the loader to the qmake build and document common build conventions.
2026-09-24 18:56:48 -07:00