Explain array counts, offsets, rotations, image dimensions, file naming,
and step ranges with translated tooltips and contextual help. Give both
dialogs a standard Help button and dialog-scoped F1 support that falls back
from the focused control through its parent groups to the overview.
Link image field labels to their buddies and share tooltip and field help
text. Add accessible names for unlabeled controls. Document the writing and
maintenance conventions, with concise guidance in the existing AGENTS.md.
Refresh all eight language catalogs while preserving existing translations
and review status. The 62 new help and accessibility strings remain
unfinished pending translation.
Validation: Qt 6.10 debug build; runtime checks for seven F1 routes, Help,
Escape, dialog state, spin-box focus, and five label buddies with matching
help; visual layout inspection; catalog coverage for all 2,118 active source
messages and existing translation preservation; git diff --check.
Callback-based include readers hid open failures and required parser callbacks
to report success through captured variables. Replace them with OpenPieceDataFile
and OpenPrimitiveFile returning lcResult of an owned file positioned at zero.
The mesh loader consumes the file directly and retains its existing strict or
permissive policy for missing includes.
Route include reads, piece builds and primitive builds through the existing
OpenFile service for archive and disk access. Preserve registered-source and
fallback search order, directory retries after parse failure, and primitive
high/low-detail selection. Primitive opening uses its own source metadata,
including stud-style archives with directory libraries, and records opening
errors through the existing synchronized failure path.
Document the owning file contract and retry boundary. Validation: warning-free
macOS Qt 6.10 Debug build, all 51 offscreen lifecycle checks and whitespace checks
pass. Coverage includes independent cursors across unload, missing/invalid sources,
include failure policy, parse retries, official precedence and low-detail/styled
primitive builds. Successful GPU rendering was not tested.
Loading the unofficial archive replaced same-name official part registrations,
while directory loading and include/primitive lookup already preferred official
sources. Keep registered official part sources when scanning unofficial archives;
unofficial-only parts remain available and other source policies stay unchanged.
Bump the library cache version so descriptions and mesh geometry built under the
previous override policy cannot survive the precedence change. Document the
consistent official-first behavior and cache invalidation.
Validation: warning-free macOS Qt 6.10 Debug build, all 47 offscreen lifecycle
checks and diff whitespace checks pass. Added checks cover cold/warm archive and
directory parts, primitives, subparts and includes, plus rejection and rebuilding
of legacy description and geometry caches. GPU rendering was not tested.
Move sparse piece load errors and registry locking into lcPieceManager so
registry access, reference bookkeeping and copied worker metadata share one
owner. Release registry and error locks before resource teardown, recursive
project deletion or loader cancellation; remove library lock scopes around
UI source resolution and worker-drained settings changes.
Add HasOtherReferences to the shared asset reference for piece and texture
consumer checks, removing the library/manager consumer-query wrappers. Keep
the post-release cancellation count check and existing lifetime policies.
Rename the sparse error map to mPieceDataLoadErrors and document the completed
manager boundary and thread/teardown contracts.
Validation: warning-free macOS Qt 6.10 Debug build and all 43 offscreen
lifecycle checks pass, including concurrent metadata/error reads, settings
changes with pending requests and shared reference queries. Qt 5, ASan and
successful GPU rendering were not tested.
Piece registrations were centralized but creation, reference bookkeeping and
cleanup still lived in the library. Move creation/model reuse, normalization,
metadata renaming, reference operations, temporary cleanup, project transfer and
ordered identity teardown into the manager. Keep registration/deletion helpers
private and remove the temporary local-registry enumeration APIs.
The library remains the acquisition facade and coordinates source resolution,
loading, invalidation and cancellation after unlocking. Handles still bind to
the library. Clear sparse errors from lcPieceData::Unload before resource teardown
so manager deletion does not require a library pointer or callback. Sparse error
storage and the existing synchronization remain library-side.
Use one project-aware manager lookup, passing nullptr for shared-only searches.
Remove the maximum-size name reservation so short names can use inline storage.
Replace remaining bounded C-string copy/terminator pairs with lcstrcpy and record
the helper convention in common/AGENTS.md. Update the asset lifetime documentation.
Validation: macOS Qt 6.10 Debug build, whitespace checks and 40 offscreen lifecycle
checks, including already-zero release, last-owner cancellation, model reuse,
project detach/transfer cleanup, sparse errors, archive/directory caches and forced
nested external-project teardown. Successful GPU rendering is not covered by the
offscreen checks.
Library and project name registries were accessed directly by source discovery,
cache processing and UI consumers. Centralize their storage and index operations
in a library-owned lcPieceManager, with ordered borrowed snapshots and copied
file metadata for worker include lookup.
Keep source resolution, reference counts, unload/deletion policy, cache I/O and
existing synchronization in lcPiecesLibrary. Preserve project-index collisions,
name normalization and reentrant teardown ordering while routing registration
changes through the manager.
Return the GetParts snapshot by value, name model rename/reservation operations
RenameModelPieceData, and centralize manager forward declarations in the PCH.
Document the registry boundary and register the new files in qmake.
Validation: macOS Qt 6.10 Debug build, whitespace checks and 35 offscreen lifecycle
checks, including archive/directory cold and warm caches, source precedence,
worker includes, borrowed snapshot lifetimes, rename collisions, project transfer
and nested external-project destruction. Successful GPU rendering is not covered
by the offscreen checks.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
SetImage previously uploaded automatically on the UI thread while the asset
loader needed a separate AdoptDecodedImage path to control context switching
and retries. Make SetImage and the renamed SetImages prepare and store pixels
only, remove AdoptDecodedImage and LoadImages, and upload generated atlases
explicitly. CacheStrings now accepts the caller's current rendering context.
Retain cube-map faces and supplied mipmaps through SetImages. Advance the
image index after each face so a supplied mip chain does not leave the next
face reading the previous face's last mip level.
Validation: full application build and diff checks passed. OpenGL readback
checks covered explicit setters, all six cube faces with generated and supplied
mipmaps, narrow and custom-stride image uploads, alignment restoration, failure
cleanup, and all nine grid levels against the previous generator.
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.
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.
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.
PieceInfo::Unload previously called back into the library to delete itself, making model and external-project teardown difficult to follow. Unregister and delete local identities in the library, and limit PieceInfo cleanup to its mesh, borrowed model pointer, and owned project.
Always clean owned projects in the PieceInfo destructor, including meshless containers. Bulk unload destroys outer external projects before remaining local identities and the shared catalog so nested teardown can safely release references.
Validation: debug build and lifetime checks covering final-reference release, retained deleted models, direct container deletion, 30 nested bulk-unload cycles, and 20 owner deletions with pending loads. AddressSanitizer stalled before main; sanitizer coverage remains unverified.
Large models can extend beyond the default far plane after fitting,
leaving the view blank or clipped. Pass an explicit adjustment flag
through view, model, and camera fitting, and reuse the fitted bounds
to expand clipping with a margin, rounded up to multiples of 10,000.
Adjust restored ordinary cameras after applying their saved state.
Preserve named cameras and explicit command-line clipping planes,
and avoid recalculating clipping during redraws or navigation.
Route output fitting through the view and move the bounds policy
definition out of the precompiled header.
Watching referenced and inactive projects can produce reload prompts outside the current document. Register watches only when a project becomes active, and retain content baselines so unchanged writes and application saves stay quiet.
Debounce file and directory events, retry transient read failures, and restore monitoring after replacement or deletion and recreation. Validate reload ownership around the dialog and scope candidate projects so failed reloads release their resources. Check read errors before clearing existing model data.