Files
leocad/common/lc_view.h
T
Leonardo Zide 3db4b8e70b Preserve ancestor steps while editing nested submodels
Drilling into a child deactivated its parent and evaluated the parent at
its final step. After navigating to an earlier step, this moved surrounding
geometry and separated the child's editing transform from its placement.

Keep the complete editing path active at its chosen steps, and use that
path when filtering ancestor geometry for rendering. Rebuild the transform
from the selected instances when restoring a tab so changes in an ancestor's
own tab also keep the editing target aligned. Returning through a breadcrumb
deactivates only departed descendants; ending editing restores completed
assembly poses while retaining stored step choices.

Also route Submodel Properties to the model currently being edited rather
than the tab model.

Validated the macOS Qt 6 application build, all 8 Qt Test cases, and 106
focused compiled-application checks covering ancestor poses and visibility,
properties edits, tab switching, breadcrumbs, focus status, and exports.
2026-10-24 13:16:12 -07:00

412 lines
9.0 KiB
C++

#pragma once
#include "lc_assettypes.h"
#include "lc_context.h"
#include "lc_math.h"
#include "lc_commands.h"
#include "lc_result.h"
struct lcInsertPieceInfo;
enum class lcCameraProjection;
enum class lcDragState
{
None,
Piece,
Color
};
enum class lcCursor
{
First,
Hidden = First,
Default,
Brick,
PointLight,
SpotLight,
DirectionalLight,
AreaLight,
Camera,
Select,
SelectAdd,
SelectRemove,
Move,
Rotate,
RotateX,
RotateY,
Delete,
Paint,
ColorPicker,
Zoom,
ZoomRegion,
Pan,
Roll,
RotateView,
Count
};
enum class lcTrackButton
{
None,
Left,
Middle,
Right
};
enum class lcTrackTool
{
None,
Insert,
PointLight,
SpotLight,
DirectionalLight,
AreaLight,
Camera,
Select,
MoveX,
MoveY,
MoveZ,
MoveXY,
MoveXZ,
MoveYZ,
MoveXYZ,
RotateX,
RotateY,
RotateZ,
RotateTrackBall,
RotateCamera,
RotateTrainTrackRight,
RotateTrainTrackLeft,
InsertTrainTrack,
SelectTrainTrack,
ScalePlus,
ScaleMinus,
Eraser,
Paint,
ColorPicker,
Zoom,
Pan,
OrbitX,
OrbitY,
OrbitXY,
Roll,
ZoomRegion,
Count
};
enum class lcViewType
{
View,
Preview,
Minifig,
PartsList,
Count
};
struct lcFindReplaceParams
{
lcPieceData* FindPieceData = nullptr;
QString FindString;
int FindColorIndex = 0;
lcPieceData* ReplacePieceData = nullptr;
int ReplaceColorIndex = 0;
};
class lcView : public QObject
{
Q_OBJECT
public:
lcView(lcViewType ViewType, lcModel* Model);
~lcView();
lcView(const lcView&) = delete;
lcView(lcView&&) = delete;
lcView& operator=(const lcView&) = delete;
lcView& operator=(lcView&&) = delete;
static lcFindReplaceParams& GetFindReplaceParams()
{
return mFindReplaceParams;
}
lcModel* GetModel() const
{
return mModel;
}
lcViewType GetViewType() const
{
return mViewType;
}
lcCamera* GetCamera() const
{
return mCamera;
}
bool IsLastFocused() const
{
return mLastFocusedView == this;
}
bool IsTracking() const
{
return mTrackButton != lcTrackButton::None;
}
int GetWidth() const
{
return mWidth;
}
int GetHeight() const
{
return mHeight;
}
void SetSize(int Width, int Height)
{
mWidth = Width;
mHeight = Height;
}
lcViewWidget* GetWidget() const
{
return mWidget;
}
void SetWidget(lcViewWidget* Widget)
{
mWidget = Widget;
}
int GetMouseX() const
{
return mMouseX;
}
int GetMouseY() const
{
return mMouseY;
}
int GetMouseDownX() const
{
return mMouseDownX;
}
int GetMouseDownY() const
{
return mMouseDownY;
}
float GetCameraRotationStartAngle() const
{
return mCameraRotationMouseAngle;
}
void SetBackgroundColorOverride(quint32 BackgroundColor)
{
mOverrideBackgroundColor = true;
mBackgroundColor = BackgroundColor;
}
lcMatrix44 GetActiveSubmodelTransform() const
{
return mActiveSubmodelTransform;
}
static std::vector<lcView*> GetModelViews(const lcModel* Model);
static void UpdateProjectViews(const Project* Project);
static void UpdateAllViews();
static void CreateResources(lcContext* Context);
static void DestroyResources(lcContext* Context);
void MakeCurrent();
bool PrepareOutlineFramebuffers();
void Redraw();
void SetOffscreenContext();
void SetFocus(bool Focus);
void SetMousePosition(int MouseX, int MouseY);
void SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers);
lcModel* GetActiveModel() const;
std::vector<lcModel*> GetModelEditingPath() const;
void RestoreModelEditingContext();
void SetSubmodelActive(size_t Depth);
void SetTopSubmodelActive();
void SetSelectedSubmodelActive();
void OnDraw();
bool HasMissingAssets() const;
void OnLeftButtonDown();
void OnLeftButtonUp();
void OnLeftButtonDoubleClick();
void OnMiddleButtonDown();
void OnMiddleButtonUp();
void OnRightButtonDown();
void OnRightButtonUp();
void OnBackButtonDown();
void OnBackButtonUp();
void OnForwardButtonDown();
void OnForwardButtonUp();
void OnMouseMove();
void OnMouseLeave();
void OnMouseWheel(float Direction);
void BeginDrag(lcDragState DragState);
void EndDrag(bool Accept);
void UpdateCursor();
void StartPanGesture();
void UpdatePanGesture(int dx, int dy);
void EndPanGesture(bool Accept);
void StartOrbitTracking();
void StopTracking(bool Accept);
void CancelTrackingOrClearSelectionAction();
void SetViewpoint(lcViewpoint Viewpoint);
void SetViewpoint(const lcVector3& Position);
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
void SetCameraAngles(float Latitude, float Longitude);
void SetDefaultCamera();
void SetCamera(lcCamera* Camera, bool ForceCopy);
void SetCamera(const QString& CameraName);
void SetCameraIndex(size_t CameraIndex);
void SetCameraProjection(lcCameraProjection CameraProjection);
void LookAt();
void MoveCamera(const lcVector3& Direction);
void Zoom(float Amount);
void ZoomExtents(lcGeometryBoundsMode Mode, bool AdjustFarPlane);
void ZoomExtentsAtStep(lcStep Step, lcGeometryBoundsMode Mode, bool AdjustFarPlane);
void RemoveCamera();
void ShowContextMenu() const;
bool CloseFindReplaceDialog();
void ShowFindReplaceWidget(bool Replace);
float GetUIScale() const;
float GetOverlayScale() const;
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
void UpdatePiecePreview();
std::pair<std::vector<lcInsertPieceInfo>, bool> GetMouseInsertPieceInfo(bool IgnoreSelected, bool AllowNewPieces, const lcPieceDataRef& PieceData, lcPiece* MovingPiece) const;
lcVector3 GetCameraLightInsertPosition() const;
void GetRayUnderPointer(lcVector3& Start, lcVector3& End) const;
lcObjectRayTest RayTest(bool PiecesOnly, bool IgnoreSelected) const;
lcObjectSection FindObjectUnderPointer(bool PiecesOnly, bool IgnoreSelected) const;
std::vector<lcObject*> FindObjectsInBox(float x1, float y1, float x2, float y2) const;
lcVector3 ProjectPoint(const lcVector3& Point) const;
lcVector3 UnprojectPoint(const lcVector3& Point) const;
void UnprojectPoints(lcVector3* Points, int NumPoints) const;
lcMatrix44 GetProjectionMatrix() const;
bool BeginRenderToImage(int Width, int Height);
void EndRenderToImage();
QImage GetRenderImage() const;
void BindRenderFramebuffer();
void UnbindRenderFramebuffer();
QImage GetRenderFramebufferImage() const;
std::vector<QImage> GetStepImages(lcStep Start, lcStep End);
lcResult<void> SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep Start, lcStep End, std::function<void(const QString&)> ProgressCallback);
lcContext* mContext = nullptr;
signals:
void FocusReceived();
protected:
void DestroyOutlineFramebuffers();
bool GenerateOutlineMasks();
void DrawBackground(int CurrentTileRow, int TotalTileRows, int CurrentTileHeight) const;
void DrawViewport() const;
void DrawAxes() const;
void DrawSelectZoomRegionOverlay();
void DrawRotateViewOverlay();
void DrawGrid();
lcMatrix44 GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const;
lcCursor GetCursor() const;
void SetCursor(lcCursor Cursor);
lcTool GetCurrentTool() const;
void UpdateTrackTool();
lcTrackTool GetOverrideTrackTool(Qt::MouseButton Button) const;
void StartTracking(lcTrackButton TrackButton);
void OnButtonDown(lcTrackButton TrackButton);
void StartPan(int x, int y);
void UpdatePan(int x, int y);
lcVector3 GetTrackballPoint(int x, int y) const;
void ShowTrainTrackPopup();
lcViewWidget* mWidget = nullptr;
int mWidth = 1;
int mHeight = 1;
lcViewType mViewType;
int mMouseX = 0;
int mMouseY = 0;
int mMouseDownX = 0;
int mMouseDownY = 0;
float mCameraRotationMouseAngle = 0.0f;
float mCameraRotationLastMouseAngle = 0.0f;
float mCameraRotationAngle = 0.0f;
lcVector3 mTrackballCenter;
lcVector3 mTrackballVector;
float mTrackballRadius = 1.0f;
lcMatrix33 mTrackballPendingRotation = lcMatrix33Identity();
bool mTrackballSnapping = false;
bool mTrackballHasPendingRotation = false;
Qt::KeyboardModifiers mMouseModifiers = Qt::NoModifier;
bool mTrackUpdated = false;
bool mToolClicked = false;
lcTrackTool mTrackTool = lcTrackTool::None;
lcTrackButton mTrackButton = lcTrackButton::None;
lcCursor mCursor = lcCursor::Default;
lcDragState mDragState;
bool mTrackToolFromOverlay;
quint32 mTrackToolSection = ~0U;
lcMatrix44 mMouseDownTransform;
lcPiece* mMouseDownPiece = nullptr;
int mPanX = 0;
int mPanY = 0;
QImage mRenderImage;
std::unique_ptr<QOpenGLFramebufferObject> mRenderFramebuffer;
std::unique_ptr<QOpenGLFramebufferObject> mOutlineFullFramebuffer;
std::unique_ptr<QOpenGLFramebufferObject> mOutlineVisibleFramebuffer;
QSize mOutlineAttemptSize;
QPointer<QOpenGLContext> mOutlineGLContext;
bool mOverrideBackgroundColor = false;
quint32 mBackgroundColor = 0;
std::unique_ptr<lcScene> mScene;
std::unique_ptr<lcViewManipulator> mViewManipulator;
std::unique_ptr<lcViewSphere> mViewSphere;
lcModel* mModel = nullptr;
lcPiece* mActiveSubmodelInstance = nullptr;
lcMatrix44 mActiveSubmodelTransform;
std::vector<lcPiece*> mSubmodelEditingPath;
lcCamera* mCamera = nullptr;
lcVertexBuffer mGridBuffer;
int mGridSettings[7];
static QPointer<lcFindReplaceWidget> mFindWidget;
static lcFindReplaceParams mFindReplaceParams;
static lcView* mLastFocusedView;
static std::vector<lcView*> mViews;
};