Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 133 additions & 30 deletions qml/PropertiesPanel.qml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,34 @@ Rectangle {
id: root
color: PropertiesPanelController.panelColor

readonly property int inspectorTab: EditorModeController.InspectorTab
readonly property int sceneTab: EditorModeController.SceneTab
readonly property int modeToolsTab: EditorModeController.ModeToolsTab
readonly property int historyTab: EditorModeController.HistoryTab
property int currentTab: 0
property bool showAllModeTools: false

function showModeToolsForMode(mode) {
return mode === EditorModeController.EditMode
|| mode === EditorModeController.AnimationMode
|| mode === EditorModeController.MaterialMode
|| mode === EditorModeController.ValidationMode
return EditorModeController.modeHasModeTools(mode)
}

function defaultTabForMode(mode) {
return EditorModeController.defaultInspectorTabForMode(mode)
}

function shouldKeepExplicitTab(tab) {
return EditorModeController.shouldKeepExplicitInspectorTab(tab)
}

function modeToolMatches(mode) {
return EditorModeController.modeToolMatchesCurrentMode(
mode, root.showAllModeTools, EditorModeController.currentMode)
}

function modeToolSectionVisible(mode, available) {
return root.currentTab === root.modeToolsTab
&& available
&& root.modeToolMatches(mode)
}

function targetAccent(kind) {
Expand All @@ -36,9 +57,14 @@ Rectangle {
// Don't yank the user away from Scene (1) or History (3) when
// they're explicitly browsing those tabs. Only retarget the
// Inspector/Mode-Tools pair, which are the mode-aware ones.
if (root.currentTab === 1 || root.currentTab === 3)
if (root.shouldKeepExplicitTab(root.currentTab))
return
root.currentTab = root.showModeToolsForMode(EditorModeController.currentMode) ? 2 : 0
root.currentTab = root.defaultTabForMode(EditorModeController.currentMode)
// Switching modes resets the Mode-Tools filter back to "Current"
// so each mode lands on its own tools by default. A sticky "All"
// would silently survive a mode change and contradict the
// "current-mode tools" default the filter advertises.
root.showAllModeTools = false
}
}

Expand All @@ -62,13 +88,24 @@ Rectangle {
spacing: 3

Repeater {
model: [ "Inspector", "Scene", "Mode Tools", "History" ]
// Bind label order to the canonical InspectorTabId enum
// values exposed by EditorModeController. Don't rely on
// the Repeater's implicit `index` to map tabs — that
// would silently couple this array's order to the C++
// enum order and break every `sectionVisible` binding
// if anyone reordered either.
model: [
{ label: "Inspector", id: root.inspectorTab },
{ label: "Scene", id: root.sceneTab },
{ label: "Mode Tools", id: root.modeToolsTab },
{ label: "History", id: root.historyTab }
]

Rectangle {
width: Math.max(66, (parent.width - 9) / 4)
height: 28
radius: 4
color: root.currentTab === index
color: root.currentTab === modelData.id
? PropertiesPanelController.highlightColor
: tabMouse.containsMouse
? Qt.lighter(PropertiesPanelController.panelColor, 1.2)
Expand All @@ -78,10 +115,10 @@ Rectangle {

Text {
anchors.centerIn: parent
text: modelData
text: modelData.label
color: PropertiesPanelController.textColor
font.pixelSize: 10
font.bold: root.currentTab === index
font.bold: root.currentTab === modelData.id
elide: Text.ElideRight
}

Expand All @@ -90,7 +127,67 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.currentTab = index
onClicked: root.currentTab = modelData.id
}
}
}
}
}

Rectangle {
width: parent.width
height: visible ? 34 : 0
visible: root.currentTab === root.modeToolsTab
color: Qt.darker(PropertiesPanelController.headerColor, 1.08)

RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
spacing: 6

Text {
Layout.fillWidth: true
text: EditorModeController.modeName + " Tools"
color: PropertiesPanelController.textColor
font.pixelSize: 11
font.bold: true
elide: Text.ElideRight
}

Repeater {
model: [
{ label: "Current", all: false },
{ label: "All", all: true }
]

Rectangle {
width: Math.max(54, filterLabel.implicitWidth + 16)
height: 22
radius: 4
color: root.showAllModeTools === modelData.all
? PropertiesPanelController.highlightColor
: filterMouse.containsMouse
? Qt.lighter(PropertiesPanelController.panelColor, 1.2)
: PropertiesPanelController.panelColor
border.color: PropertiesPanelController.borderColor
border.width: 1

Text {
id: filterLabel
anchors.centerIn: parent
text: modelData.label
color: PropertiesPanelController.textColor
font.pixelSize: 10
font.bold: root.showAllModeTools === modelData.all
}

MouseArea {
id: filterMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.showAllModeTools = modelData.all
}
}
}
Expand Down Expand Up @@ -170,7 +267,9 @@ Rectangle {
// ---- Edit Mode Tools ----
CollapsibleSection {
title: "Edit Mode Tools"
sectionVisible: root.currentTab === 2 && EditModeController.editModeActive
sectionVisible: root.modeToolSectionVisible(
EditorModeController.EditMode,
EditModeController.editModeActive)
expanded: true

Component.onCompleted: content = editModeToolsComponent
Expand All @@ -179,7 +278,7 @@ Rectangle {
// ---- Scene Outliner ----
CollapsibleSection {
title: "Scene"
sectionVisible: root.currentTab === 1
sectionVisible: root.currentTab === root.sceneTab
expanded: true

Component.onCompleted: content = sceneOutlinerComponent
Expand All @@ -188,15 +287,16 @@ Rectangle {
// ---- Transform ----
CollapsibleSection {
title: PropertiesPanelController.transformTargetLabel
sectionVisible: root.currentTab === 0 && PropertiesPanelController.hasSelection
sectionVisible: root.currentTab === root.inspectorTab
&& PropertiesPanelController.hasSelection

Component.onCompleted: content = transformComponent
}

// ---- Snap Settings ----
CollapsibleSection {
title: "Snap Settings"
sectionVisible: root.currentTab === 0
sectionVisible: root.currentTab === root.inspectorTab
expanded: false

Component.onCompleted: content = snapSettingsComponent
Expand All @@ -205,27 +305,28 @@ Rectangle {
// ---- Primitive Parameters ----
CollapsibleSection {
title: "Primitive: " + PropertiesPanelController.primitiveType
sectionVisible: root.currentTab === 0 && PropertiesPanelController.hasPrimitive
sectionVisible: root.currentTab === root.inspectorTab
&& PropertiesPanelController.hasPrimitive

Component.onCompleted: content = primitiveComponent
}

// ---- Animations ----
CollapsibleSection {
title: "Animations"
sectionVisible: root.currentTab === 2
&& EditorModeController.currentMode === EditorModeController.AnimationMode
&& PropertiesPanelController.hasAnimations
sectionVisible: root.modeToolSectionVisible(
EditorModeController.AnimationMode,
PropertiesPanelController.hasAnimations)

Component.onCompleted: content = animationComponent
}

// ---- Animation Control (keyframe editor) ----
CollapsibleSection {
title: "Animation Control"
sectionVisible: root.currentTab === 2
&& EditorModeController.currentMode === EditorModeController.AnimationMode
&& AnimationControlController.hasAnimation
sectionVisible: root.modeToolSectionVisible(
EditorModeController.AnimationMode,
AnimationControlController.hasAnimation)
expanded: false

Component.onCompleted: content = animControlComponent
Expand All @@ -234,7 +335,9 @@ Rectangle {
// ---- LOD Generation ----
CollapsibleSection {
title: "LOD Generation"
sectionVisible: root.currentTab === 2 && MeshLodController.hasSelection
sectionVisible: root.modeToolSectionVisible(
EditorModeController.ValidationMode,
MeshLodController.hasSelection)
expanded: false

Component.onCompleted: content = lodComponent
Expand All @@ -243,9 +346,9 @@ Rectangle {
// ---- Material Presets ----
CollapsibleSection {
title: "Material Presets"
sectionVisible: root.currentTab === 2
&& EditorModeController.currentMode === EditorModeController.MaterialMode
&& PropertiesPanelController.hasSelection
sectionVisible: root.modeToolSectionVisible(
EditorModeController.MaterialMode,
PropertiesPanelController.hasSelection)
expanded: false

Component.onCompleted: content = materialPresetsComponent
Expand All @@ -254,9 +357,9 @@ Rectangle {
// ---- Mesh Validation ----
CollapsibleSection {
title: "Mesh Validation"
sectionVisible: root.currentTab === 2
&& EditorModeController.currentMode === EditorModeController.ValidationMode
&& MeshValidator.hasSelection
sectionVisible: root.modeToolSectionVisible(
EditorModeController.ValidationMode,
MeshValidator.hasSelection)
expanded: false

Component.onCompleted: content = validationComponent
Expand All @@ -265,7 +368,7 @@ Rectangle {
// ---- Undo History ----
CollapsibleSection {
title: "Undo History"
sectionVisible: root.currentTab === 3
sectionVisible: root.currentTab === root.historyTab
expanded: false

Component.onCompleted: content = undoHistoryComponent
Expand Down
49 changes: 48 additions & 1 deletion src/EditorModeController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

EditorModeController* EditorModeController::m_pSingleton = nullptr;

namespace {
bool isValidMode(int mode)
{
return mode >= EditorModeController::ObjectMode
&& mode <= EditorModeController::ValidationMode;
}
}

EditorModeController::EditorModeController(QObject* parent)
: QObject(parent)
{
Expand Down Expand Up @@ -58,7 +66,7 @@ void EditorModeController::setCurrentMode(int mode)

void EditorModeController::requestMode(int mode)
{
if (mode < ObjectMode || mode > ValidationMode)
if (!isValidMode(mode))
return;

setModeInternal(static_cast<Mode>(mode), true);
Expand Down Expand Up @@ -124,6 +132,45 @@ QVariantList EditorModeController::availableModes() const
return modes;
}

bool EditorModeController::modeHasModeTools(int mode) const
{
if (!isValidMode(mode))
return false;

return mode == EditMode
|| mode == AnimationMode
|| mode == MaterialMode
|| mode == ValidationMode;
}

int EditorModeController::defaultInspectorTabForMode(int mode) const
{
return modeHasModeTools(mode) ? ModeToolsTab : InspectorTab;
}

bool EditorModeController::shouldKeepExplicitInspectorTab(int tab) const
{
return tab == SceneTab || tab == HistoryTab;
}

bool EditorModeController::modeToolMatches(int sectionMode, bool showAllModeTools) const
{
return modeToolMatchesCurrentMode(
sectionMode, showAllModeTools, static_cast<int>(m_currentMode));
}

bool EditorModeController::modeToolMatchesCurrentMode(
int sectionMode, bool showAllModeTools, int currentMode) const
{
if (!isValidMode(sectionMode))
return false;

if (!isValidMode(currentMode))
return false;

return showAllModeTools || currentMode == sectionMode;
}

bool EditorModeController::editModeAvailable() const
{
auto* edit = editController();
Expand Down
14 changes: 14 additions & 0 deletions src/EditorModeController.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@
};
Q_ENUM(Mode)

enum InspectorTabId {

Check warning on line 39 in src/EditorModeController.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this "enum" with "enum class".

See more on https://sonarcloud.io/project/issues?id=fernandotonon_QtMeshEditor&issues=AZ4HxK2Ljh2h2E9QdSC0&open=AZ4HxK2Ljh2h2E9QdSC0&pullRequest=435
InspectorTab = 0,
SceneTab = 1,
ModeToolsTab = 2,
HistoryTab = 3
};
Q_ENUM(InspectorTabId)

static EditorModeController* instance();
static EditorModeController* qmlInstance(QQmlEngine* engine, QJSEngine* scriptEngine);
static void kill();
Expand All @@ -52,6 +60,12 @@
Q_INVOKABLE void toggleObjectEditMode();
Q_INVOKABLE QString modeNameFor(int mode) const;
Q_INVOKABLE QString modeTooltipFor(int mode) const;
Q_INVOKABLE bool modeHasModeTools(int mode) const;
Q_INVOKABLE int defaultInspectorTabForMode(int mode) const;
Q_INVOKABLE bool shouldKeepExplicitInspectorTab(int tab) const;
Q_INVOKABLE bool modeToolMatches(int sectionMode, bool showAllModeTools) const;
Q_INVOKABLE bool modeToolMatchesCurrentMode(
int sectionMode, bool showAllModeTools, int currentMode) const;

signals:
void modeChanged();
Expand Down
Loading
Loading