The worker and synchronous texture paths duplicated embedded data decoding and disk/archive source handling. Centralize CPU decoding in DecodeTextureData while keeping resizing and upload behavior in each caller.
Report synchronous decode failures consistently with the worker path. Validation: debug build and ten CPU decoding checks covering valid, corrupt, missing, and invalid embedded, disk, and archive sources.
Changing parts display options in a popup previously overwrote the settings
used by the main Pieces panel. Store icon size, list mode, part names,
decorated pieces, and aliases separately for the main panel and for all
popups, while retaining shared search preferences.
Initialize popup context before loading preferences. Keep color locking
exclusive to the main panel so popups use the color supplied by their
caller, and hide color locking and palette editing in popup menus.
Popup preferences begin with their own defaults.
Validation: the Qt 6.10 debug build passes.
The fixed-function renderer was removed, but shader capability guards,
bitmap text paths, and legacy attribute state still implied a working
shaderless fallback. Remove that obsolete state and check shader support
once when initializing rendering resources.
Return detailed context and shader errors through lcResult and show fatal
startup errors in GUI mode. Keep lighting, conditional lines, SDF text,
view sphere, and outlines optional, with program validity checks selecting
Flat shading, skipping unavailable overlays, or retaining selection tint.
Non-rendering exports initialize only the context needed for asset loading.
Apply icon availability to every parts list without overwriting requested
sizes. Disable unavailable lighting and view-sphere preference controls,
make attribute aliases explicit, and prevent signed-byte glyph indexing.
Validation: macOS debug build, GUI and image export under forced optional
shader compile/link failures, Flat fallback image comparisons, export
initialization checks, preference preservation, and glyph byte-range checks.
Persist enum preferences through named typed accessors using stable PascalCase tokens. Keep explicit legacy integer mappings so existing settings continue to load when enum members are reordered, and fall back to declared defaults for invalid values.
Validate scalar conversions and reject non-finite floats while preserving unsigned color bits returned by signed native settings backends. Read fixed part colors as unsigned values and remove their override when unlocking so the unlocked state survives restart.
Save both view-sphere enabled flags directly, preserving disabled spheres even when their remembered sizes are nonzero.
Validation: macOS application build and temporary enum and persistence regression checks passed. Windows and Linux execution was not performed.
Render selected pieces with an outline above scene geometry and a faint selection-colored fill only over obscured portions. Preserve line-only selection colors and insertion preview tint, and suppress bounding box corners in outline mode.
Keep the existing tint and edges mode as a preference and fallback when outline rendering is unavailable. Own outline framebuffers in each view, keep OpenGL operations in lcContext, and capture selection visibility before the grid through a callback scoped to each scene draw.
Validation: debug build and desktop OpenGL checks passed for occlusion, transparency, MSAA, HiDPI, line-only selection, framebuffer fallback, grid exclusion, and widget resource cleanup.
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.
Highlight the full selected item and preserve thumbnail colors when part names are hidden. Keep cell dimensions stable while thumbnails load and update every entry sharing a completed thumbnail.
Use four columns for the default parts grid and fixed popup layouts for each icon size. Resize open popups when icons, names, or list mode change, account for capped widths and menu margins, and keep complete rows visible with room for at least two when needed. Enable part names by default for fresh preferences.
Validated with a Qt build, 240 sizing cases, and actual popup checks for constrained widths, name toggling, and menu frames across three Qt styles.
Closes#670
Freeze the Part column with a width cap and full-name tooltips. Synchronize row selection across views, forward wheel scrolling, and avoid the initial cell highlight.
Closes#565
Duplicate MPD definitions and circular model references were skipped silently, leaving files such as the examples in issue #533 empty without an explanation.
Record load warnings and display them alongside asset failures in the existing status icon tooltip. Collect warnings from nested external projects, deduplicate repeated references, and preserve source filenames across successful merges. Reset diagnostics when loading another document.
Validated both issue examples, nested and repeated references, merge warning preservation and deduplication, failed merges, and clean reloads. The macOS debug build and diff checks pass.
Fixes#533
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
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.
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.
Filesystem watcher events can be triggered by metadata updates or identical rewrites, so forwarding every event directly to the reload dialog produces false notifications.
Track a content hash after loading, saving, and observing external edits. Only prompt for different readable contents, ignore stale and duplicate events, and restore the file watch after atomic replacement even when the contents are unchanged.
Validation: macOS debug build and native Qt watcher checks covering timestamp updates, identical replacements, same-size edits, repeated changes, own-save baselines, stale events, and empty files.
Direct geometry in root and nested models was collected with a null mesh override, despite the documented export contract. Exporters recovered the mesh through PieceInfo, which also selected the shared-part path in POV-Ray.
Supply the direct model mesh explicitly and document the borrowed mesh override semantics. This aligns collection with the contract while preserving catalog fallback and generated instance meshes.
Validation: Debug build, 33 targeted collection/export checks covering OBJ, COLLADA, 3DS and POV-Ray/LGEO, and git diff --check passed.
A null framebuffer readback was treated as empty geometry, so a parts
list could retain a blank entry or silently omit it after rendering failed.
The QImage return type also conflated an empty inventory with an error.
Return lcResult<QImage> and abort on failed thumbnail readback after
framebuffer and renderer cleanup. Report framebuffer creation and image
allocation failures explicitly while preserving successful empty inventory
and unavailable-geometry behavior. HTML export propagates the error text;
the instructions UI clears its stale image and displays a warning parented
to the scene's view.
Validation: full debug build and whitespace checks passed. A temporary
OpenGL fault-injection harness covered first and later readback failures
with both missing-parts policies, framebuffer creation failure, successful
empty results, and restoration of caller context, surface, and framebuffer
bindings. The warning dialog was not exercised interactively.
Step-image and parts-list helpers switched to the shared offscreen context
and left it current after rendering. Framebuffer release and destruction
also replaced a caller's existing binding with the default framebuffer.
This violated the output helpers' state-restoration contract on both
success and failure.
Capture the caller's context, surface, and framebuffer bindings in a scope
guard before asset waits and rendering. Restore them after the temporary
view is destroyed, preserving separate draw/read bindings where supported
and leaving no context current when the caller started without one.
Validation: full debug build and whitespace checks passed. A temporary
OpenGL regression harness verified step-image and parts-list success and
framebuffer creation failure with an alternate caller context, an alternate
surface on the shared context, nondefault framebuffer bindings, and no
initially current context.
External projects were loaded before their identities were registered,
allowing mutually referencing files to recurse until stack exhaustion.
Track canonical paths during nested loads and reject repeated paths
with a failed-piece error.
Primitive dependencies could wait indefinitely on themselves or form
cycles across workers. Track active dependency edges, reject cycles,
and replace polling with cancellation-aware condition waits. Signal
cancellation during queue drains and restore its previous state afterward.
Validation: full debug build and whitespace checks passed. A temporary
regression harness covered external and primitive cycles, 100 concurrent
cyclic-load attempts, cancellation, completion, cache hits, and queue
shutdown.
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.
Reported by appstream validate-tree:
leocad.appdata.xml
I: org.leocad.LeoCAD:15: developer-name-tag-deprecated
The toplevel `developer_name` element is deprecated. Please use the `name` element in a
`developer` block instead.
I: org.leocad.LeoCAD:~: developer-info-missing
This component contains no `developer` element with information about its author.
W: org.leocad.LeoCAD:~: metainfo-filename-cid-mismatch
The metainfo filename does not match the component ID.
✘ Validation failed: warnings: 1, infos: 2, pedantic: 2
Skip container bounds publication for temporary models without a PieceInfo. Avoid accessing the GL context when releasing an empty shared buffer set while preserving dirty-state tracking.
Keep COLLADA and POV-Ray identifiers close to source names while resolving collisions and maintaining consistent references.
Encode HTML filenames safely, escape display text, and use stable model ordinals. Preserve LGEO slope mappings and apply slope materials and bump normals correctly.
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.
Report missing generated meshes and failed image writes, keep thumbnails and interactive geometry using their fallback behavior, and frame command-line images at the requested step or full range. Use explicit mesh loader flags and reject incomplete synthesized meshes. Keep selection and ray tests aligned with the rendered mesh.
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.
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.
- 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.