Skip to content

feat(#461): UV editor transforms with undo and live viewport sync - #772

Merged
fernandotonon merged 2 commits into
masterfrom
feature/uv-transforms-461
Jun 28, 2026
Merged

feat(#461): UV editor transforms with undo and live viewport sync#772
fernandotonon merged 2 commits into
masterfrom
feature/uv-transforms-461

Conversation

@fernandotonon

@fernandotonon fernandotonon commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add UV move/rotate/scale/mirror transforms in the UV Editor with Q/W/E/R shortcuts (aligned with the main viewport)
  • Undo/redo via UVEditCommand; live 3D viewport updates during drag without entity re-init (mesh + skeletal anim buffers)
  • Fix GL setDrawBuffer spam from material-preview RTTs and cache inspector preview URIs

Test plan

  • UnitTests --gtest_filter="UVTransformTest.*:UVEditorControllerTest.*" (26 passed)
  • Drag UV verts in UV Editor — 3D viewport updates live; release mouse does not crash
  • Undo/redo UV transform (Ctrl+Z / Ctrl+Shift+Z)
  • Mirror X/Y toolbar buttons
  • Skinned/animated mesh (e.g. Mixamo FBX)
  • Material preview in Inspector — no GL spam flood

Closes #461

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added richer UV editing tools, including transform mode switching, numeric input, snapping, mirroring, and pivot controls.
    • Improved material previews with faster thumbnail loading and more responsive refreshes.
    • Added support for updating UV changes directly in the editor with undo/redo.
  • Bug Fixes

    • Fixed preview and render target handling so editor views restore correctly after offscreen rendering.
    • Ensured UV changes are applied consistently across meshes and reflected properly in the viewport.
  • Tests

    • Expanded automated coverage for UV transforms, undo/redo, shared-vertex meshes, and preview rendering.

Add move/rotate/scale/mirror UV transforms with Q/W/E/R shortcuts, undo via
UVEditCommand, and GPU commits that update skeletal anim buffers without
entity re-init. Also fix GL render-target spam from material preview RTTs.

Closes #461

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@fernandotonon, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 41 minutes and 20 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 54460b5b-bb31-4330-93dc-9aeca1f1a591

📥 Commits

Reviewing files that changed from the base of the PR and between cf32bbd and c561020.

📒 Files selected for processing (9)
  • qml/MaterialListModal.qml
  • qml/PropertiesPanel.qml
  • qml/UVEditorPanel.qml
  • src/EditableMesh.cpp
  • src/MaterialPreviewRenderer.cpp
  • src/UVEditorController.cpp
  • src/UVTransform.cpp
  • src/UVTransform.h
  • src/commands/UVEditCommand.cpp
📝 Walkthrough

Walkthrough

This PR implements UV editor transform operations (move/rotate/scale/mirror) with undo/redo via a new UVEditCommand, adds GPU UV commit back to Ogre entity vertex buffers through new EditableMesh methods, introduces OgreRenderTargetUtil for consistent offscreen render target management across all renderers, and adds material preview URI caching in both C++ (MaterialPreviewRenderer) and QML.

Changes

UV Editor Transform System

Layer / File(s) Summary
UVTransform data types and math
src/UVTransform.h, src/UVTransform.cpp, src/UVTransform_test.cpp
Defines UVTransform namespace with PivotMode/SnapMode/TransformOp enums, VertRef/Settings structs, and implements medianPivot, snapUv, transformPoint, applyTransform plus unit tests for all operations.
UVEditCommand undo/redo
src/commands/UVEditCommand.h, src/commands/UVEditCommand.cpp
UVEditCommand : QUndoCommand stores per-vertex VertChange (old/new UV, submesh/vertex indices); apply() resolves editable mesh from edit-mode, UV controller working mesh, or direct entity, applies UV changes, commits, and notifies; undo()/redo() delegate with Sentry breadcrumbs.
EditableMesh GPU UV commit
src/EditableMesh.h, src/EditableMesh.cpp
Adds commitUvsToEntity (shared/non-shared buffer handling, skeletal anim UV sync via syncSkelAnimUvBuffers), writeUvChannel (locates VES_TEXTURE_COORDINATES, upgrades static→dynamic buffers), and refreshEntityGpuCachesAfterUvWrite (normal-map tangent rebuild).
EditModeController notification
src/EditModeController.h, src/EditModeController.cpp
Adds Q_INVOKABLE notifyMeshDataChanged() that emits meshDataChanged(), enabling UV edit commands to trigger editor refresh.
UVEditorController transform API
src/UVEditorController.h, src/UVEditorController.cpp
Expands UVEditorController with transformMode/pivotMode/snapMode/cursorU/cursorV/transformActive Q_PROPERTYs, cursor setters, drag lifecycle (beginTransformDrag/updateTransformDrag/commitTransformDrag/cancelTransformDrag), numeric transform, mirror operations, working-mesh UV sync, vertex mapping helpers, and applyUvRefChanges that pushes UVEditCommand onto UndoManager; buildFromEntity now rebuilds submesh index maps and working mesh.
UV Editor QML panel and tests
qml/UVEditorPanel.qml, src/UVEditorController_test.cpp
Adds draggingTransform/numericBuffer state, Q/W/E/R/G/Escape/Enter/digit key handling, clickable mode buttons and numeric buffer HUD, right-click UV cursor placement, mouse-press transform drag initiation, drag update/commit on release; tests cover GPU UV undo/redo round-trip, mirror undoability, and shared-submesh commit.
Build system
src/CMakeLists.txt, tests/CMakeLists.txt
Adds UVEditCommand.cpp and UVTransform.cpp to both production and test source file lists.

Render Target Management and Material Preview Caching

Layer / File(s) Summary
OgreRenderTargetUtil inline helpers
src/OgreRenderTargetUtil.h
New header-only utility with configureOffscreenRenderTarget (disables auto-update on RTT) and restoreEditorRenderTarget (locates editor RenderWindow by name and calls _setRenderTarget).
Renderer adoption of OgreRenderTargetUtil
src/MaterialPreviewRenderer.cpp, src/MeshDepthRenderer.cpp, src/ModelIsometricRenderer.cpp, src/ModelTurntableRenderer.cpp, src/mainwindow.cpp
Each renderer calls configureOffscreenRenderTarget after RTT creation and restoreEditorRenderTarget after rendering; mainwindow calls restoreEditorRenderTarget before each renderOneFrame.
Material preview caching
src/MaterialPreviewRenderer.h, src/MaterialPreviewRenderer.cpp, src/MaterialPreviewRenderer_test.cpp, src/MaterialEditorQML.cpp, qml/PropertiesPanel.qml, qml/MaterialListModal.qml
MaterialPreviewRenderer adds m_interactiveCache keyed by (material, size, shape, wrapped-yaw); clearCache clears both caches; applyMaterial calls clearCache after reload. QML PropertiesPanel and MaterialListModal cache materialPreviewUris maps rebuilt on list refresh or material applied; interactive preview uses a scheduled-timer refreshPreviewSource flow.

Sequence Diagram(s)

sequenceDiagram
    participant QML as UVEditorPanel (QML)
    participant UVCtrl as UVEditorController
    participant UVTransform
    participant UndoManager
    participant UVEditCommand
    participant EditableMesh
    participant OgreEntity

    QML->>UVCtrl: beginTransformDrag(u, v, modifiers)
    UVCtrl->>UVCtrl: collectSelectedUvRefs() → beforeRefs
    QML->>UVCtrl: updateTransformDrag(u, v, modifiers)
    UVCtrl->>UVTransform: applyTransform(op, refs, settings, delta)
    UVTransform-->>UVCtrl: updated VertRefs
    UVCtrl->>UVCtrl: applyWorkingMeshUv() per vertex
    QML->>UVCtrl: commitTransformDrag()
    UVCtrl->>UVCtrl: applyUvRefChanges(refs, before, op, desc)
    UVCtrl->>EditableMesh: commitUvsToEntity(entity, uvChannel)
    EditableMesh->>OgreEntity: writeUvChannel() → GPU buffer update
    UVCtrl->>UndoManager: push(UVEditCommand)
    UVCtrl->>UVCtrl: syncUvLayoutFromWorkingMesh() → emit meshDataChanged
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • #461 (UV: Slice C — UV transforms with undo): This PR directly implements the issue's scope — move/rotate/scale/mirror with numeric input, all three pivot modes, snap modes, UVEditCommand with undo/redo, Sentry breadcrumbs, and unit tests.
  • #458 (UV Map editing epic): The PR implements a major slice of the UV editor epic, adding the transform pipeline, GPU UV commit, and working-mesh synchronization described in the parent epic.
  • #465: Changes to UVEditorController_test.cpp and UVEditCommand overlap with the test coverage and undo infrastructure referenced in this issue.

Possibly related PRs

  • fernandotonon/QtMeshEditor#281: Introduced EditableMesh for in-editor vertex editing; this PR extends the same class with UV-specific commit/write helpers (commitUvsToEntity, writeUvChannel, GPU cache refresh).
  • fernandotonon/QtMeshEditor#760: Modifies the same qml/UVEditorPanel.qml and src/UVEditorController.* selection and cache-rebuild pipeline that this PR extends with transform-mode drag and numeric input.
  • fernandotonon/QtMeshEditor#492: Overlaps with this PR's qml/PropertiesPanel.qml changes for cached material preview URIs and the interactive yaw-based preview pane rework.

Poem

🐇 Hop, hop, transform!
In UV space the rabbit glides,
G to move, R to spin around,
Ctrl+Z brings back what was found.
Caches warm, render targets tame—
Every pixel snaps right into frame!

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description only has Summary and Test plan; it omits the required Technical Details, PS1 runtime rip, Features, and Bugfixes sections. Add the template's Technical Details section and fill the Features/Bugfixes headings; include PS1 runtime rip items if applicable.
Out of Scope Changes check ⚠️ Warning The PR also changes material-preview RTT caching and render-target plumbing, which is unrelated to the UV transform issue scope. Split the material-preview and render-target fixes into a separate PR unless they are required for the UV editor change.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: UV editor transforms with undo and viewport sync.
Linked Issues check ✅ Passed The changes implement UV move/rotate/scale, mirror actions, pivot/snap modes, numeric input, undo command support, shortcuts, and tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/uv-transforms-461

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf32bbd83d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (!m_activeEntity)
return false;

return m_workingMesh.commitUvsToEntity(m_activeEntity, m_uvChannel, nullptr);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve hidden UV channels when committing filtered edits

When the UV editor is opened for a sub-entity selection on UV channel 1, m_workingMesh still contains every submesh, but applyUvChannel(..., m_submeshFilter) only reloads the requested channel for the visible submeshes; the hidden submeshes keep the channel-0 UVs from loadFromEntity(). This unfiltered commit then writes every submesh back to channel 1, so transforming one selected submesh can overwrite channel-1 UVs on all unselected submeshes with their channel-0 coordinates. The commit path should either load the requested channel for all submeshes or restrict commitUvsToEntity to the edited submesh set.

Useful? React with 👍 / 👎.

Comment thread qml/UVEditorPanel.qml Outdated
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
applyNumericBuffer()
event.accepted = numericBuffer.length > 0
} else if (event.key >= Qt.Key_0 && event.key <= Qt.Key_9) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Route numeric digits before selection shortcuts

Because this new numeric digit handler is placed after the existing Qt.Key_1/2/3 selection-mode shortcuts above, those digits never reach appendNumericChar() while a transform is active. As a result, common numeric transforms such as rotate 180, scale 2, or move 1.25 switch selection mode instead of entering the value; handle numeric input before the selection shortcuts when transform numeric entry is active.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
qml/MaterialListModal.qml (1)

161-168: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Disable QML pixmap caching for these preview thumbnails.

The preview URI is deterministic per material name, so reassigning the same source string after an edit can keep the old bitmap alive. PropertiesPanel.qml already sets cache: false for the same preview path; without that, this modal can still show stale thumbnails even if materialPreviewUris is rebuilt.

Suggested fix
                             Image {
                                 anchors.horizontalCenter: parent.horizontalCenter
                                 width: 52; height: 52
                                 source: materialListModal.materialPreviewUris[modelData] || ""
                                 fillMode: Image.PreserveAspectFit
                                 asynchronous: true
+                                cache: false
                                 sourceSize.width: 52
                                 sourceSize.height: 52
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@qml/MaterialListModal.qml` around lines 161 - 168, The preview thumbnail
Image in MaterialListModal.qml is still using the default QML pixmap cache,
which can keep stale bitmaps around when materialPreviewUris is rebuilt. Update
the Image block in the MaterialListModal preview delegate to disable caching the
same way PropertiesPanel.qml does by setting cache to false, so reusing the same
source string after edits reloads the thumbnail instead of showing an old
bitmap.
🧹 Nitpick comments (2)
src/commands/UVEditCommand.cpp (1)

70-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the standard breadcrumb category here.

These are user-facing undo/redo actions, but mesh.uv.transform does not follow the repo's documented Sentry taxonomy. Please log them under ui.action and keep the specific operation in the message so UV editor telemetry stays queryable with the rest of the UI events. As per coding guidelines, **/*.{cpp,h} should track user-facing actions with SentryReporter::addBreadcrumb(category, message) using documented categories such as ui.action.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/UVEditCommand.cpp` around lines 70 - 85, The undo/redo
breadcrumbs in UVEditCommand::undo and UVEditCommand::redo are using a
nonstandard Sentry category. Update the SentryReporter::addBreadcrumb calls to
use the documented ui.action category, while keeping the operation-specific
message text like “Undo UV edit” and “Redo UV edit” so these user-facing actions
stay consistent with the repo taxonomy.

Source: Coding guidelines

src/UVEditorController_test.cpp (1)

401-467: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add controller undo tests for rotate and scale.

This adds move and mirror undo coverage, but the new controller paths for RotateTransform and ScaleTransform also need undo/redo round-trip tests. As per coding guidelines, src/**/*_test.cpp: “Add Google Test unit tests for new functionality”; the PR objective also calls for tests for each transform plus undo.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/UVEditorController_test.cpp` around lines 401 - 467, Add Google Test
coverage in UVEditorControllerTest for the missing RotateTransform and
ScaleTransform undo/redo paths, similar to
MoveSelectionUpdatesGpuAndUndoRoundTrip and MirrorXCommandIsUndoable. Create
tests that set up an in-memory mesh, select a face through UVEditorController,
call setTransformMode with RotateTransform and ScaleTransform, apply the numeric
transform, then verify the UVs change and that UndoManager::undo() and redo()
restore/reapply the same values. Keep the assertions aligned with the existing
readEntityUv0 helper and controller flow used in the other UVEditorController
tests.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@qml/MaterialListModal.qml`:
- Around line 43-56: The thumbnail cache in MaterialListModal.qml is not being
invalidated after edits, so previews stay stale while the modal remains open.
Update the MaterialListModal flow so `editMaterial()` triggers a refresh of
`materialPreviewUris` after the editor applies changes, reusing the same
invalidation pattern already used in `PropertiesPanel.qml`. Ensure the cache is
rebuilt through `rebuildMaterialPreviews()` and then `refreshMaterialList()` (or
equivalent) so `MaterialEditorQML.materialPreview(...)` is re-queried for the
edited material.

In `@qml/PropertiesPanel.qml`:
- Around line 4491-4520: The interactive preview can stay stale when the
selected material is edited and reapplied because
`previewHost.refreshPreviewSource()` only updates on selection/shape/yaw/width
changes and leaves `previewSource` unchanged when
`MaterialEditorQML.interactiveMaterialPreview()` returns an empty string. Update
the `refreshPreviewSource()` flow so it explicitly invalidates or clears
`previewSource` when the current material’s preview can’t be generated, and make
sure the existing `schedulePreviewRefresh()` path is also triggered from the
material-apply/update flow that changes the underlying material content, not
just `onSelectedMaterialNameChanged`, `onPreviewShapeChanged`,
`onPreviewYawChanged`, and `onWidthChanged`.

In `@qml/UVEditorPanel.qml`:
- Around line 183-206: The key handling in UVEditorPanel.qml is letting the
selection hotkeys consume digit keys before the numeric transform path, so when
transform mode is active the key handler should route 1/2/3 to appendNumericChar
instead of the earlier selection branches. Update the main key handler to check
the numeric-transform state before the selection shortcuts, using the existing
appendNumericChar, applyNumericBuffer, and root.draggingTransform logic to keep
transform input active. Also fix the Enter/Return branch so event.accepted is
determined from the buffer before numericBuffer is cleared, ensuring successful
submissions are marked handled.

In `@src/EditableMesh.cpp`:
- Around line 827-830: The first-pass lookup in the EditableMesh UV refresh path
is not fully guarded, since getTechnique(0) can return a technique with zero
passes. Update the logic around mat->getTechnique(0)->getPass(0) to check
getNumPasses() first and skip the material when there are no passes, keeping the
existing getNumTechniques() guard intact. Use the existing
material/technique/pass handling in EditableMesh to ensure the pass pointer is
only accessed when it is valid.

In `@src/MaterialPreviewRenderer.cpp`:
- Around line 349-354: The interactive cache in
MaterialPreviewRenderer::renderMaterialPreview uses a rounded yaw for the cache
key but still renders with the unrounded wrappedYaw, so nearby angles can reuse
the wrong image. Make the cache key and the rendered yaw use the same quantized
value by computing the yaw once at the chosen precision and reusing that value
for both the key and the preview generation.

In `@src/UVEditorController.cpp`:
- Around line 875-889: Rollback the local working/edit UV state if
commitWorkingMeshUvs() fails, because applyWorkingMeshUv() has already mutated
editor state before the GPU commit attempt. In the method that builds
UVEditCommand::VertChange entries, capture enough pre-change UV data to restore
each touched vertex and, on a false return from commitWorkingMeshUvs(), revert
those vertices back to their previous values instead of returning or refreshing
from the uncommitted state. Apply the same rollback behavior in the other
affected path near the second commit call so the working mesh, GPU, and undo
stack stay consistent.

In `@src/UVTransform.cpp`:
- Around line 31-57: The vertex snapping path in snapUv() still does a linear
std::find over selectedIds for every vertex in allVerts, which makes
UVEditorController::updateTransformDrag() too slow on large drags. Change
applyTransform() to build a hash-based membership structure once, update the
selectedIds parameter type in UVTransform.h, and use constant-time lookups
inside snapUv() instead of scanning the vector.

---

Outside diff comments:
In `@qml/MaterialListModal.qml`:
- Around line 161-168: The preview thumbnail Image in MaterialListModal.qml is
still using the default QML pixmap cache, which can keep stale bitmaps around
when materialPreviewUris is rebuilt. Update the Image block in the
MaterialListModal preview delegate to disable caching the same way
PropertiesPanel.qml does by setting cache to false, so reusing the same source
string after edits reloads the thumbnail instead of showing an old bitmap.

---

Nitpick comments:
In `@src/commands/UVEditCommand.cpp`:
- Around line 70-85: The undo/redo breadcrumbs in UVEditCommand::undo and
UVEditCommand::redo are using a nonstandard Sentry category. Update the
SentryReporter::addBreadcrumb calls to use the documented ui.action category,
while keeping the operation-specific message text like “Undo UV edit” and “Redo
UV edit” so these user-facing actions stay consistent with the repo taxonomy.

In `@src/UVEditorController_test.cpp`:
- Around line 401-467: Add Google Test coverage in UVEditorControllerTest for
the missing RotateTransform and ScaleTransform undo/redo paths, similar to
MoveSelectionUpdatesGpuAndUndoRoundTrip and MirrorXCommandIsUndoable. Create
tests that set up an in-memory mesh, select a face through UVEditorController,
call setTransformMode with RotateTransform and ScaleTransform, apply the numeric
transform, then verify the UVs change and that UndoManager::undo() and redo()
restore/reapply the same values. Keep the assertions aligned with the existing
readEntityUv0 helper and controller flow used in the other UVEditorController
tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f7d18be-9d32-49ab-8bf5-c98553cbcf82

📥 Commits

Reviewing files that changed from the base of the PR and between df53b58 and cf32bbd.

📒 Files selected for processing (26)
  • qml/MaterialListModal.qml
  • qml/PropertiesPanel.qml
  • qml/UVEditorPanel.qml
  • src/CMakeLists.txt
  • src/EditModeController.cpp
  • src/EditModeController.h
  • src/EditableMesh.cpp
  • src/EditableMesh.h
  • src/MaterialEditorQML.cpp
  • src/MaterialPreviewRenderer.cpp
  • src/MaterialPreviewRenderer.h
  • src/MaterialPreviewRenderer_test.cpp
  • src/MeshDepthRenderer.cpp
  • src/ModelIsometricRenderer.cpp
  • src/ModelTurntableRenderer.cpp
  • src/OgreRenderTargetUtil.h
  • src/UVEditorController.cpp
  • src/UVEditorController.h
  • src/UVEditorController_test.cpp
  • src/UVTransform.cpp
  • src/UVTransform.h
  • src/UVTransform_test.cpp
  • src/commands/UVEditCommand.cpp
  • src/commands/UVEditCommand.h
  • src/mainwindow.cpp
  • tests/CMakeLists.txt

Comment thread qml/MaterialListModal.qml
Comment thread qml/PropertiesPanel.qml
Comment thread qml/UVEditorPanel.qml Outdated
Comment thread src/EditableMesh.cpp
Comment thread src/MaterialPreviewRenderer.cpp Outdated
Comment thread src/UVEditorController.cpp
Comment thread src/UVTransform.cpp
Refresh material preview thumbnails after apply, guard pass lookup, roll back
UV edits when GPU commit fails, use hash-set vertex snap, fix numeric input
hotkeys, and align interactive preview yaw cache with rendered angle.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

Copy link
Copy Markdown

@fernandotonon
fernandotonon merged commit c41e170 into master Jun 28, 2026
21 checks passed
@fernandotonon
fernandotonon deleted the feature/uv-transforms-461 branch June 28, 2026 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UV: Slice C — UV transforms with undo (move/rotate/scale)

1 participant