diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt
index 43423d52..3ebae7ea 100644
--- a/editor/CMakeLists.txt
+++ b/editor/CMakeLists.txt
@@ -84,8 +84,7 @@ add_subdirectory(
if (APPLE)
set(ATLAS_APP_ICON
- "${CMAKE_SOURCE_DIR}/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png"
- CACHE FILEPATH "Atlas Engine macOS bundle icon"
+ CACHE FILEPATH "Atlas Engine macOS bundle icon"
)
get_filename_component(ATLAS_APP_ICON_NAME "${ATLAS_APP_ICON}" NAME)
set_source_files_properties("${ATLAS_APP_ICON}" PROPERTIES
@@ -135,9 +134,14 @@ qt_add_resources(AtlasEditor "atlas_editor_assets"
PREFIX "/editor"
BASE "${CMAKE_SOURCE_DIR}/editor"
FILES
- "${CMAKE_SOURCE_DIR}/editor/assets/Icon-iOS-Default-1024x1024@1x.png"
- "${CMAKE_SOURCE_DIR}/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png"
- "${CMAKE_SOURCE_DIR}/editor/assets/atlas_ball_bright.png"
+ "${CMAKE_SOURCE_DIR}/editor/assets/atlas-app-dev.png"
+ "${CMAKE_SOURCE_DIR}/editor/assets/atlas-star.png"
+ "${CMAKE_SOURCE_DIR}/editor/assets/check.svg"
+ "${CMAKE_SOURCE_DIR}/editor/assets/close.svg"
+ "${CMAKE_SOURCE_DIR}/editor/assets/link.svg"
+ "${CMAKE_SOURCE_DIR}/editor/assets/chevron-down.svg"
+ "${CMAKE_SOURCE_DIR}/editor/assets/chevron-up.svg"
+ "${CMAKE_SOURCE_DIR}/editor/assets/atlas-app.png"
"${CMAKE_SOURCE_DIR}/editor/assets/Manrope-VariableFont_wght.ttf"
"${CMAKE_SOURCE_DIR}/editor/assets/Phosphor.ttf"
"${CMAKE_SOURCE_DIR}/editor/assets/PHOSPHOR_LICENSE.txt"
diff --git a/editor/assets/AtlasEngine.icon.json b/editor/assets/AtlasEngine.icon.json
deleted file mode 100644
index b5ed7814..00000000
--- a/editor/assets/AtlasEngine.icon.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "fill": {
- "automatic-gradient": "extended-srgb:0.00000,0.00000,0.00000,1.00000"
- },
- "groups": [
- {
- "layers": [
- {
- "glass": true,
- "image-name": "atlas_ball_bright.png",
- "name": "atlas_ball_bright"
- }
- ],
- "shadow": {
- "kind": "neutral",
- "opacity": 0.5
- },
- "translucency": {
- "enabled": true,
- "value": 0.5
- }
- }
- ],
- "supported-platforms": {
- "circles": [
- "watchOS"
- ],
- "squares": "shared"
- }
-}
diff --git a/editor/assets/AtlasEngine.icon/Assets/atlasStarGradient.svg b/editor/assets/AtlasEngine.icon/Assets/atlasStarGradient.svg
new file mode 100644
index 00000000..4b19137f
--- /dev/null
+++ b/editor/assets/AtlasEngine.icon/Assets/atlasStarGradient.svg
@@ -0,0 +1,46 @@
+
+
diff --git a/editor/assets/AtlasEngine.icon/icon.json b/editor/assets/AtlasEngine.icon/icon.json
new file mode 100644
index 00000000..93733db0
--- /dev/null
+++ b/editor/assets/AtlasEngine.icon/icon.json
@@ -0,0 +1,50 @@
+{
+ "fill" : {
+ "linear-gradient" : [
+ "srgb:1.00000,0.95276,0.98370,1.00000",
+ "srgb:0.69138,0.67074,0.76447,1.00000"
+ ],
+ "orientation" : {
+ "start" : {
+ "x" : 0.5,
+ "y" : 0
+ },
+ "stop" : {
+ "x" : 0.5,
+ "y" : 0.7
+ }
+ }
+ },
+ "groups" : [
+ {
+ "layers" : [
+ {
+ "fill" : "none",
+ "image-name" : "atlasStarGradient.svg",
+ "name" : "atlasStarGradient",
+ "position" : {
+ "scale" : 1.34,
+ "translation-in-points" : [
+ 0,
+ 0
+ ]
+ }
+ }
+ ],
+ "shadow" : {
+ "kind" : "neutral",
+ "opacity" : 0.5
+ },
+ "translucency" : {
+ "enabled" : true,
+ "value" : 0.3
+ }
+ }
+ ],
+ "supported-platforms" : {
+ "circles" : [
+ "watchOS"
+ ],
+ "squares" : "shared"
+ }
+}
\ No newline at end of file
diff --git a/editor/assets/AtlasEngineDev.icon/Assets/atlasStar.svg b/editor/assets/AtlasEngineDev.icon/Assets/atlasStar.svg
new file mode 100644
index 00000000..65a93fdf
--- /dev/null
+++ b/editor/assets/AtlasEngineDev.icon/Assets/atlasStar.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/editor/assets/AtlasEngineDev.icon.json b/editor/assets/AtlasEngineDev.icon/icon.json
similarity index 62%
rename from editor/assets/AtlasEngineDev.icon.json
rename to editor/assets/AtlasEngineDev.icon/icon.json
index a2c2a8c8..1aab94ac 100644
--- a/editor/assets/AtlasEngineDev.icon.json
+++ b/editor/assets/AtlasEngineDev.icon/icon.json
@@ -6,8 +6,16 @@
{
"layers": [
{
- "image-name": "atlas_ball_bright.png",
- "name": "atlas_ball_bright"
+ "fill": "system-light",
+ "image-name": "atlasStar.svg",
+ "name": "atlasStar",
+ "position": {
+ "scale": 1.34,
+ "translation-in-points": [
+ 0,
+ 0
+ ]
+ }
}
],
"shadow": {
diff --git a/editor/assets/Icon-iOS-Default-1024x1024@1x.png b/editor/assets/Icon-iOS-Default-1024x1024@1x.png
deleted file mode 100644
index 8259c7c8..00000000
Binary files a/editor/assets/Icon-iOS-Default-1024x1024@1x.png and /dev/null differ
diff --git a/editor/assets/atlas-app-dev.png b/editor/assets/atlas-app-dev.png
new file mode 100644
index 00000000..bc4e561c
Binary files /dev/null and b/editor/assets/atlas-app-dev.png differ
diff --git a/editor/assets/atlas-app.icns b/editor/assets/atlas-app.icns
new file mode 100644
index 00000000..d0a7ebab
Binary files /dev/null and b/editor/assets/atlas-app.icns differ
diff --git a/editor/assets/atlas-app.png b/editor/assets/atlas-app.png
new file mode 100644
index 00000000..bda26463
Binary files /dev/null and b/editor/assets/atlas-app.png differ
diff --git a/editor/assets/atlas-star.png b/editor/assets/atlas-star.png
new file mode 100644
index 00000000..ff0d461a
Binary files /dev/null and b/editor/assets/atlas-star.png differ
diff --git a/editor/assets/atlasStar.svg b/editor/assets/atlasStar.svg
new file mode 100644
index 00000000..65a93fdf
--- /dev/null
+++ b/editor/assets/atlasStar.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/editor/assets/atlasStarColored.svg b/editor/assets/atlasStarColored.svg
new file mode 100644
index 00000000..65a93fdf
--- /dev/null
+++ b/editor/assets/atlasStarColored.svg
@@ -0,0 +1,10 @@
+
+
+
diff --git a/editor/assets/atlasStarGradient.svg b/editor/assets/atlasStarGradient.svg
new file mode 100644
index 00000000..4b19137f
--- /dev/null
+++ b/editor/assets/atlasStarGradient.svg
@@ -0,0 +1,46 @@
+
+
diff --git a/editor/assets/atlas_ball_bright.png b/editor/assets/atlas_ball_bright.png
deleted file mode 100644
index 18276831..00000000
Binary files a/editor/assets/atlas_ball_bright.png and /dev/null differ
diff --git a/editor/assets/check.svg b/editor/assets/check.svg
new file mode 100644
index 00000000..fc46d37e
--- /dev/null
+++ b/editor/assets/check.svg
@@ -0,0 +1 @@
+
diff --git a/editor/assets/chevron-down.svg b/editor/assets/chevron-down.svg
new file mode 100644
index 00000000..131e5678
--- /dev/null
+++ b/editor/assets/chevron-down.svg
@@ -0,0 +1 @@
+
diff --git a/editor/assets/chevron-up.svg b/editor/assets/chevron-up.svg
new file mode 100644
index 00000000..1e2ffe9d
--- /dev/null
+++ b/editor/assets/chevron-up.svg
@@ -0,0 +1 @@
+
diff --git a/editor/assets/close.svg b/editor/assets/close.svg
new file mode 100644
index 00000000..cadc964d
--- /dev/null
+++ b/editor/assets/close.svg
@@ -0,0 +1 @@
+
diff --git a/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png b/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png
index fe0fe439..bda26463 100644
Binary files a/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png and b/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png differ
diff --git a/editor/assets/iconFile-iOS-Default-1024x1024@1x.png b/editor/assets/iconFile-iOS-Default-1024x1024@1x.png
deleted file mode 100644
index 90730d9b..00000000
Binary files a/editor/assets/iconFile-iOS-Default-1024x1024@1x.png and /dev/null differ
diff --git a/editor/assets/landing.png b/editor/assets/landing.png
deleted file mode 100644
index 48f4cf39..00000000
Binary files a/editor/assets/landing.png and /dev/null differ
diff --git a/editor/assets/link.svg b/editor/assets/link.svg
new file mode 100644
index 00000000..a1c931cf
--- /dev/null
+++ b/editor/assets/link.svg
@@ -0,0 +1 @@
+
diff --git a/editor/debug.cpp b/editor/debug.cpp
index 40de2a8d..5d63dcca 100644
--- a/editor/debug.cpp
+++ b/editor/debug.cpp
@@ -8,6 +8,8 @@
*/
#include
+#include
+#include
#include
#include
#include
@@ -98,18 +100,18 @@ QWidget* DebugComponentsView::createBasicControlsSection() {
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(8);
- auto* normalButton = new QPushButton("Normal", container);
- auto* defaultButton = new QPushButton("Default", container);
+ auto* normalButton = new styling::Button("Normal", container);
+ auto* defaultButton = new styling::Button("Default", container);
defaultButton->setDefault(true);
- auto* disabledButton = new QPushButton("Disabled", container);
+ auto* disabledButton = new styling::Button("Disabled", container);
disabledButton->setEnabled(false);
- auto* checkableButton = new QPushButton("Checkable", container);
+ auto* checkableButton = new styling::Button("Checkable", container);
checkableButton->setCheckable(true);
checkableButton->setChecked(true);
- auto* toolButton = new QToolButton(container);
+ auto* toolButton = new styling::ToolButton(container);
toolButton->setText("Tool");
layout->addWidget(normalButton);
@@ -354,13 +356,13 @@ QWidget* DebugComponentsView::createCollapsibleSection() {
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(4);
- auto* header = new QToolButton(section);
+ auto* header = new styling::ToolButton(section);
header->setObjectName("collapsibleHeader");
header->setText("Transform");
header->setCheckable(true);
header->setChecked(true);
header->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- header->setArrowType(Qt::DownArrow);
+ header->setIcon(styling::icon(styling::Icon::CaretDown));
auto* body = new QWidget(section);
body->setObjectName("collapsibleBody");
@@ -390,7 +392,7 @@ QWidget* DebugComponentsView::createCollapsibleSection() {
form->addRow("Visibility", visible);
QObject::connect(header, &QToolButton::toggled, section, [header, body, section](bool checked) {
- header->setArrowType(checked ? Qt::DownArrow : Qt::RightArrow);
+ header->setIcon(styling::icon(checked ? styling::Icon::CaretDown : styling::Icon::CaretRight));
body->setVisible(checked);
body->updateGeometry();
section->updateGeometry();
diff --git a/editor/main.cpp b/editor/main.cpp
index abd90e0d..cb64c6d2 100644
--- a/editor/main.cpp
+++ b/editor/main.cpp
@@ -25,6 +25,7 @@
#include "editor/debug.h"
#include "editor/application/toolchainInstaller.h"
#include "editor/styling/icons.h"
+#include "editor/styling/workbench.h"
#include "editor/views/editorWindow.h"
#include "editor/views/projectBrowser.h"
#include "editor/views/splashScreen.h"
@@ -51,10 +52,10 @@ int main(int argc, char **argv) {
#ifndef Q_OS_MACOS
#ifdef ATLAS_DEBUG_BUILD
app.setWindowIcon(
- QIcon(":/editor/assets/Icon-iOS-Default-1024x1024@1x.png"));
+ QIcon(":/editor/assets/atlas-app-dev.png"));
#else
app.setWindowIcon(
- QIcon(":/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png"));
+ QIcon(":/editor/assets/atlas-app.png"));
#endif
#endif
@@ -64,6 +65,7 @@ int main(int argc, char **argv) {
app.setStyle("Fusion");
styling::applyTheme(app);
+ styling::installWorkbench(app);
ToolchainInstaller::ensureInstalled();
auto *startupSplash = new SplashScreen();
diff --git a/editor/styling/dark.qss b/editor/styling/dark.qss
index a7f9f02e..e2983148 100644
--- a/editor/styling/dark.qss
+++ b/editor/styling/dark.qss
@@ -1,153 +1,59 @@
* {
font-family: "SF Pro Text", "Inter", "Segoe UI", "Arial";
- font-size: 11px;
- color: #D6D6D6;
- selection-background-color: #4772B3;
- selection-color: #FFFFFF;
+ font-size: 13px;
+ color: #C5C5BE;
+ selection-background-color: #353532;
+ selection-color: #F1F1EC;
}
QWidget {
- background-color: #1C1C1C;
- color: #D6D6D6;
+ background: #191918;
}
QMainWindow,
QDialog,
-QFrame {
- background-color: #1C1C1C;
+#editorFrame,
+#projectBrowserRoot {
+ background: #121211;
}
-QLabel {
+QLabel,
+QCheckBox,
+QRadioButton,
+QToolButton,
+QPushButton {
background: transparent;
}
QLabel:disabled {
- color: #566174;
-}
-
-QToolTip {
- background-color: #303030;
- color: #F7F9FC;
- border: 1px solid #505050;
- border-radius: 4px;
- padding: 4px 6px;
-}
-
-QGroupBox {
- background-color: #242424;
- border: 1px solid #3B3B3B;
- border-radius: 4px;
- margin-top: 13px;
- padding: 7px;
- color: #F1F4F8;
- font-weight: 650;
-}
-
-QGroupBox::title {
- subcontrol-origin: margin;
- subcontrol-position: top left;
- left: 9px;
- padding: 0 6px;
- color: #AEB8C8;
- background-color: #242424;
-}
-
-QScrollArea,
-QAbstractScrollArea {
- background-color: #202020;
- border: none;
-}
-
-QAbstractScrollArea::corner {
- background-color: #202020;
-}
-
-QScrollBar:vertical {
- background-color: transparent;
- width: 9px;
- margin: 2px;
- border: none;
-}
-
-QScrollBar:horizontal {
- background-color: transparent;
- height: 9px;
- margin: 2px;
- border: none;
-}
-
-QScrollBar::handle:vertical,
-QScrollBar::handle:horizontal {
- background-color: #4A4A4A;
- border-radius: 4px;
- min-height: 30px;
- min-width: 30px;
-}
-
-QScrollBar::handle:vertical:hover,
-QScrollBar::handle:horizontal:hover {
- background-color: #666666;
+ color: #62625D;
}
-QScrollBar::add-line,
-QScrollBar::sub-line,
-QScrollBar::add-page,
-QScrollBar::sub-page {
- background: none;
- border: none;
- width: 0;
- height: 0;
+QLabel[muted="true"] {
+ color: #92928B;
}
QPushButton,
QToolButton {
- background-color: #303030;
- border: 1px solid #464646;
- border-radius: 3px;
- padding: 3px 8px;
- color: #D8D8D8;
- min-height: 22px;
- font-weight: 500;
+ border: none;
+ border-radius: 7px;
+ padding: 5px 10px;
+ min-height: 24px;
}
QPushButton:hover,
QToolButton:hover {
- background-color: #3A3A3A;
- border-color: #606060;
-}
-
-QPushButton:pressed,
-QToolButton:pressed {
- background-color: #242424;
- border-color: #4772B3;
+ background: #292928;
}
QPushButton:checked,
QToolButton:checked {
- background-color: #3B5F8A;
- border-color: #5D8BC0;
- color: #FFFFFF;
-}
-
-QPushButton:default,
-#primaryAction {
- background-color: #4772B3;
- border-color: #6791C9;
- color: #FFFFFF;
- font-weight: 650;
-}
-
-QPushButton:default:hover,
-#primaryAction:hover {
- background-color: #5682C2;
- border-color: #7AA1D4;
+ background: #30302E;
}
QPushButton:disabled,
QToolButton:disabled {
- background-color: #242424;
- border-color: #333333;
- color: #686868;
+ color: #646460;
}
QToolButton::menu-indicator {
@@ -156,1015 +62,670 @@ QToolButton::menu-indicator {
QLineEdit,
QTextEdit,
-QPlainTextEdit,
+QPlainTextEdit {
+ background: #20201F;
+ border: 1px solid transparent;
+ border-radius: 6px;
+ padding: 7px 9px;
+ selection-background-color: #42423E;
+}
+
+QLineEdit:hover,
+QTextEdit:hover,
+QPlainTextEdit:hover {
+ background: #242423;
+}
+
+QLineEdit:focus,
+QTextEdit:focus,
+QPlainTextEdit:focus {
+ border-color: #53534D;
+}
+
+QLineEdit:disabled,
+QTextEdit:disabled,
+QPlainTextEdit:disabled {
+ color: #666660;
+}
+
QComboBox,
QSpinBox,
QDoubleSpinBox,
QDateEdit,
QTimeEdit,
QDateTimeEdit {
- background-color: #181818;
- border: 1px solid #3D3D3D;
- border-radius: 3px;
- padding: 3px 7px;
- color: #E2E2E2;
- min-height: 22px;
+ background: #252524;
+ border: 1px solid transparent;
+ border-radius: 5px;
+ min-height: 24px;
+ padding: 3px 8px;
+ color: #D3D3CC;
}
-QLineEdit:hover,
-QTextEdit:hover,
-QPlainTextEdit:hover,
QComboBox:hover,
QSpinBox:hover,
QDoubleSpinBox:hover {
- border-color: #5A5A5A;
+ background: #2B2B29;
}
-QLineEdit:focus,
-QTextEdit:focus,
-QPlainTextEdit:focus,
QComboBox:focus,
QSpinBox:focus,
QDoubleSpinBox:focus {
- background-color: #222222;
- border-color: #5D8BC0;
+ border-color: #666660;
}
-QLineEdit:disabled,
-QTextEdit:disabled,
QComboBox:disabled,
QSpinBox:disabled,
QDoubleSpinBox:disabled {
- background-color: #202020;
- border-color: #303030;
- color: #666666;
+ color: #666660;
}
QComboBox {
- padding-right: 24px;
+ padding-right: 28px;
}
QComboBox::drop-down {
- subcontrol-origin: padding;
- subcontrol-position: top right;
- width: 22px;
- border-left: 1px solid #3B3B3B;
+ width: 26px;
+ border: none;
}
-QComboBox QAbstractItemView {
- background-color: #292929;
- border: 1px solid #4B4B4B;
- border-radius: 4px;
- padding: 3px;
- selection-background-color: #3B5F8A;
+QComboBox::down-arrow,
+QAbstractSpinBox::down-arrow {
+ image: url(:/editor/assets/chevron-down.svg);
+ width: 12px;
+ height: 12px;
+}
+
+QAbstractSpinBox::up-arrow {
+ image: url(:/editor/assets/chevron-up.svg);
+ width: 12px;
+ height: 12px;
}
QAbstractSpinBox::up-button,
QAbstractSpinBox::down-button {
- background-color: #292929;
+ background: transparent;
border: none;
- width: 16px;
+ width: 18px;
}
-QAbstractSpinBox::up-button:hover,
-QAbstractSpinBox::down-button:hover {
- background-color: #3E3E3E;
+QComboBox QAbstractItemView {
+ background: #222221;
+ border: 1px solid #393936;
+ border-radius: 8px;
+ padding: 5px;
}
QCheckBox,
QRadioButton {
- spacing: 7px;
- color: #C9D1DE;
+ spacing: 9px;
}
-QCheckBox::indicator,
-QRadioButton::indicator {
- width: 15px;
- height: 15px;
- background-color: #171717;
- border: 1px solid #555555;
- border-radius: 3px;
+QCheckBox::indicator {
+ width: 16px;
+ height: 16px;
+ border: 1px solid #55554F;
+ border-radius: 4px;
+ background: #232322;
}
-QCheckBox::indicator:hover,
-QRadioButton::indicator:hover {
- border-color: #777777;
+QCheckBox::indicator:hover {
+ border-color: #999991;
+}
+
+QCheckBox::indicator:checked {
+ image: url(:/editor/assets/check.svg);
+ background: #74746C;
+ border-color: #999991;
+}
+
+QCheckBox::indicator:indeterminate {
+ background: #999991;
+ border: 4px solid #44443F;
+}
+
+QRadioButton::indicator {
+ width: 16px;
+ height: 16px;
+ background: #232322;
+ border: 1px solid #55554F;
+ border-radius: 9px;
}
-QCheckBox::indicator:checked,
QRadioButton::indicator:checked {
- background-color: #4772B3;
- border-color: #6D98CE;
+ width: 8px;
+ height: 8px;
+ background: #DDDDD5;
+ border: 5px solid #55554F;
+ border-radius: 9px;
}
QSlider::groove:horizontal {
- background-color: #353535;
- height: 4px;
- border-radius: 2px;
+ height: 3px;
+ background: #343431;
+ border-radius: 1px;
+}
+
+QSlider::sub-page:horizontal {
+ background: #93938A;
+ border-radius: 1px;
}
QSlider::handle:horizontal {
- background-color: #5D8BC0;
- border: 2px solid #A0B9D7;
- width: 12px;
- margin: -5px 0;
- border-radius: 7px;
+ background: #D5D5CD;
+ border: none;
+ width: 10px;
+ margin: -4px 0;
+ border-radius: 5px;
}
QProgressBar {
- background-color: #262626;
- border: 1px solid #424242;
+ background: #292927;
+ border: none;
border-radius: 3px;
- height: 8px;
+ min-height: 6px;
text-align: center;
+ color: #F1F1EC;
}
QProgressBar::chunk {
- background-color: #4772B3;
+ background: #76766D;
+ border-radius: 3px;
+}
+
+QScrollArea,
+QAbstractScrollArea {
+ background: #191918;
+ border: none;
+}
+
+QAbstractScrollArea::corner {
+ background: transparent;
+}
+
+QScrollBar:vertical {
+ background: transparent;
+ border: none;
+ width: 8px;
+ margin: 3px 1px;
+}
+
+QScrollBar:horizontal {
+ background: transparent;
+ border: none;
+ height: 8px;
+ margin: 1px 3px;
+}
+
+QScrollBar::handle:vertical,
+QScrollBar::handle:horizontal {
+ background: #3B3B36;
border-radius: 3px;
+ min-height: 32px;
+ min-width: 32px;
+}
+
+QScrollBar::handle:vertical:hover,
+QScrollBar::handle:horizontal:hover {
+ background: #606059;
+}
+
+QScrollBar::add-line,
+QScrollBar::sub-line,
+QScrollBar::add-page,
+QScrollBar::sub-page {
+ border: none;
+ background: transparent;
+ width: 0;
+ height: 0;
}
QTreeView,
QListView,
-QListWidget,
-QTableView,
-QTableWidget {
- background-color: #202020;
- alternate-background-color: #242424;
+QTableView {
+ background: #191918;
border: none;
- color: #DCE3EC;
+ outline: none;
+ alternate-background-color: #1D1D1C;
show-decoration-selected: 1;
}
QTreeView::item,
QListView::item,
-QListWidget::item,
-QTableView::item,
-QTableWidget::item {
- border: 1px solid transparent;
- border-radius: 2px;
- padding: 3px 5px;
-}
-
-QTreeView::item:hover,
-QListView::item:hover,
-QListWidget::item:hover,
-QTableView::item:hover,
-QTableWidget::item:hover {
- background-color: #303030;
- border-color: #464646;
+QTableView::item {
+ border: none;
+ padding: 5px 8px;
}
QTreeView::item:selected,
QListView::item:selected,
-QListWidget::item:selected,
-QTableView::item:selected,
-QTableWidget::item:selected {
- background-color: #3B5F8A;
- border-color: #5D8BC0;
- color: #FFFFFF;
+QTableView::item:selected {
+ background: #30302E;
+ color: #F1F1EC;
}
-QHeaderView {
- background-color: #202020;
+QHeaderView::section {
+ background: #191918;
+ border: none;
+ border-bottom: 1px solid #2B2B28;
+ color: #92928B;
+ padding: 9px;
+ font-weight: 400;
}
-QHeaderView::section {
- background-color: #292929;
+QGroupBox {
+ background: transparent;
border: none;
- border-right: 1px solid #404040;
- border-bottom: 1px solid #404040;
- padding: 5px 7px;
- color: #98A4B7;
- font-weight: 600;
+ border-top: 1px solid #2B2B28;
+ margin-top: 26px;
+ padding: 14px 2px 6px 2px;
+ font-weight: 500;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ padding: 0;
+ color: #DDDDD6;
}
QTabWidget::pane {
- background-color: #202020;
- border: 1px solid #3B3B3B;
- border-radius: 0;
+ background: #191918;
+ border: none;
+}
+
+QTabBar {
+ background: transparent;
}
QTabBar::tab {
- background-color: #252525;
+ background: transparent;
border: none;
- border-right: 1px solid #393939;
- border-bottom: 1px solid #3B3B3B;
- color: #7F8B9D;
- min-width: 88px;
- padding: 5px 10px;
- margin: 1px 0;
- border-radius: 0;
+ color: #92928B;
+ padding: 9px 16px;
+ margin: 4px 3px;
+ border-radius: 6px;
}
-QTabBar::tab:hover {
- background-color: #303030;
- color: #C8D1DF;
+QTabBar::tab:selected {
+ background: #2B2B29;
+ color: #EAEAE3;
}
-QTabBar::tab:selected {
- background-color: #333333;
- color: #F2F5F9;
- border-bottom: 2px solid #5D8BC0;
+QTabBar::tab:hover {
+ color: #EAEAE3;
}
-QMenuBar#atlasMenuBar {
- background-color: #181818;
- border-bottom: 1px solid #303030;
- padding: 1px 6px;
+QMenuBar {
+ background: #121211;
+ border: none;
+ padding: 3px 10px;
}
-QMenuBar#atlasMenuBar::item {
+QMenuBar::item {
background: transparent;
- color: #B8C2D0;
padding: 5px 9px;
- border-radius: 3px;
}
-QMenuBar#atlasMenuBar::item:selected,
-QMenuBar#atlasMenuBar::item:pressed {
- background-color: #343434;
- color: #FFFFFF;
+QMenuBar::item:selected {
+ background: #2B2B29;
+ border-radius: 5px;
}
QMenu {
- background-color: #292929;
- border: 1px solid #515151;
- border-radius: 4px;
- padding: 4px;
+ background: #20201F;
+ border: 1px solid #393936;
+ border-radius: 8px;
+ padding: 6px;
}
QMenu::item {
background: transparent;
- border-radius: 2px;
- padding: 6px 32px 6px 9px;
- color: #DCE3EC;
+ padding: 9px 34px 9px 12px;
+ border-radius: 5px;
}
QMenu::item:selected {
- background-color: #3B5F8A;
- color: #FFFFFF;
+ background: #33332F;
}
QMenu::item:disabled {
- color: #596477;
+ color: #64645E;
}
QMenu::separator {
- background-color: #424242;
+ background: #343431;
height: 1px;
- margin: 5px 8px;
+ margin: 6px 10px;
}
-QSplitter::handle {
- background-color: #111111;
-}
-
-QSplitter::handle:horizontal {
- width: 4px;
+QToolTip {
+ background: #292927;
+ color: #E1E1DA;
+ border: 1px solid #44443E;
+ border-radius: 5px;
+ padding: 6px 9px;
}
-QSplitter::handle:vertical {
- height: 4px;
+QSplitter::handle {
+ background: #121211;
}
QSplitter::handle:hover {
- background-color: #5D8BC0;
+ background: #41413C;
}
QStatusBar {
- background-color: #181818;
- border-top: 1px solid #303030;
- color: #8490A4;
+ background: #121211;
+ color: #888882;
+ border: none;
+ padding: 3px 14px;
+ min-height: 24px;
+ font-size: 11px;
+}
+
+QStatusBar::item {
+ border: none;
}
-#atlasStatusBar {
- min-height: 23px;
- padding: 0 6px;
+#workspaceBar,
+#workspaceChrome,
+#workspaceIdentity,
+#workspaceIdentityText,
+#workspaceActivity,
+#workspaceUtilities {
+ background: #121211;
+ border: none;
}
-#statusRuntimeIcon {
+#workspaceBar {
padding: 0;
+ spacing: 0;
}
-#statusRuntime {
- background: transparent;
- border-right: 1px solid #343434;
+#workspaceProject {
+ color: #D7D7D0;
+ font-size: 13px;
}
-#statusRuntimeText {
- color: #9BA79F;
- font-size: 10px;
+#workspaceSwitcher,
+#workspaceSurface,
+#workspaceHeading,
+#editorWorkspaceStack {
+ background: #191918;
+ border: none;
}
-#statusRenderer {
- background-color: #292929;
- border: 1px solid #454545;
- border-radius: 3px;
- color: #B6BCB8;
- font-size: 9px;
- font-weight: 700;
- padding: 2px 6px;
+#workspaceHeading {
+ border-bottom: 1px solid #282825;
}
-#statusVersion {
- color: #68758A;
- font-size: 9px;
- padding: 0 6px;
+#workspaceSwitcher {
+ padding: 0;
}
-#workspaceBar {
- background-color: #202020;
+#workspaceMark {
+ background: transparent;
border: none;
- border-bottom: 1px solid #3B3B3B;
- spacing: 4px;
- padding: 3px 6px 3px 0;
- min-height: 38px;
}
-#workspaceIdentity {
+#workspaceContextPath,
+#statusVersion,
+#statusRenderer,
+#statusRuntimeText,
+#viewportFpsLabel,
+#viewportShortcutHint {
background: transparent;
- border-right: 1px solid #424242;
+ color: #898982;
+ font-size: 11px;
+ border: none;
}
-#workspaceMark {
- background-color: #292929;
- border: 1px solid #3F3F3F;
- border-radius: 4px;
- padding: 3px;
+#statusRuntime {
+ background: transparent;
}
-#workspaceIdentityText {
- background: transparent;
+#sceneTabs {
+ background: #191918;
+ border: none;
}
-#workspaceBrand {
- color: #8C8C8C;
- font-size: 8px;
- font-weight: 750;
+#sceneTabs::tab {
+ padding: 9px 14px;
+ min-width: 92px;
}
-#workspaceProject {
- color: #EFEFEF;
- font-size: 12px;
- font-weight: 650;
+#viewportTools {
+ background: #191918;
}
-#workspaceSwitcher {
- background-color: #181818;
- border: 1px solid #383838;
- border-radius: 4px;
- margin-left: 7px;
+#viewportToolbar,
+#panelToolbar,
+#materialEditorHeader,
+#postProcessingToolbar,
+#workspaceToolbar {
+ background: #191918;
+ border: none;
}
-#workspaceModeButton {
- background-color: #222222;
- border: 1px solid transparent;
- border-radius: 3px;
- color: #A0A0A0;
- padding: 3px 9px;
- min-height: 22px;
+#hierarchySearch,
+#contentSearchField {
+ background: #222221;
+ padding: 6px 9px;
}
-#workspaceModeButton:hover {
- background-color: #333333;
- color: #E2E2E2;
+#contentPathField {
+ background: transparent;
+ border: none;
+ color: #A7A7A0;
}
-#workspaceModeButton:checked {
- background-color: #3B5F8A;
- border-color: #5D8BC0;
- color: #FFFFFF;
+#inspectorScroll,
+#inspectorContent,
+#materialEditorBody,
+#postProcessingBody,
+#environmentPages,
+#environmentWorkspace,
+#environmentPage {
+ background: #191918;
+ border: none;
}
-#workspaceCommandButton,
-#workspaceUtilityButton,
-#workspaceBuildButton,
-#workspaceLaunchButton {
- min-width: 42px;
- padding: 3px 9px;
- margin-left: 2px;
- min-height: 24px;
-}
-
-#workspaceCommandButton,
-#workspaceUtilityButton,
-#workspaceBuildButton {
- background-color: #292929;
- border-color: #444444;
-}
-
-#workspaceLaunchButton {
- background-color: #3F684F;
- border-color: #5A8B6B;
- color: #FFFFFF;
- font-weight: 650;
-}
-
-#workspaceCommandButton:hover,
-#workspaceUtilityButton:hover,
-#workspaceBuildButton:hover,
-#workspaceLaunchButton:hover {
- background-color: #3A3A3A;
- border-color: #606060;
-}
-
-#workspaceLaunchButton:hover {
- background-color: #4E7B5E;
- border-color: #6B9B79;
-}
-
-#workspaceContextBar {
- background-color: #292929;
- border: none;
- border-bottom: 1px solid #3C3C3C;
- spacing: 2px;
- padding: 1px 5px 1px 0;
- min-height: 27px;
-}
-
-#workspaceBreadcrumb {
- background: transparent;
- border-right: 1px solid #414141;
-}
-
-#workspaceContextIcon {
+#inspectorHeader {
background: transparent;
-}
-
-#workspaceContextTitle {
- color: #E0E0E0;
- font-weight: 650;
-}
-
-#workspaceContextPath {
- color: #7F7F7F;
-}
-
-#workspacePanelButton {
- background-color: transparent;
- border-color: transparent;
- color: #8F8F8F;
- padding: 2px 7px;
- min-height: 20px;
-}
-
-#workspacePanelButton:hover {
- background-color: #363636;
- color: #DADADA;
-}
-
-#workspacePanelButton:checked {
- background-color: #333333;
- border-color: #4A4A4A;
- color: #EAEAEA;
-}
-
-#sceneTabs {
- background-color: #181818;
- border-bottom: 1px solid #3B3B3B;
-}
-
-#sceneTabs::tab {
- background-color: #242424;
- border-right: 1px solid #3A3A3A;
- color: #7F8B9D;
- min-width: 112px;
- padding: 5px 10px;
- margin: 0;
- border-radius: 0;
-}
-
-#sceneTabs::tab:selected {
- background-color: #333333;
- color: #F3F6FA;
- border-bottom: 2px solid #5D8BC0;
-}
-
-#viewportTools {
- background-color: #151515;
-}
-
-#viewportToolbar {
- background-color: #292929;
- border-bottom: 1px solid #3B3B3B;
-}
-
-#viewportPlaybackButton,
-#viewportModeButton,
-#viewportOptionButton,
-#viewportShadingButton {
- background-color: #292C2F;
- border-color: #414549;
- min-width: 25px;
- min-height: 22px;
- padding: 3px 5px;
-}
-
-#viewportPlaybackButton:hover,
-#viewportModeButton:hover,
-#viewportOptionButton:hover,
-#viewportShadingButton:hover {
- background-color: #363A3E;
- border-color: #5A5F65;
-}
-
-#viewportModeButton:checked,
-#viewportShadingButton:checked {
- background-color: #3A4248;
- border-color: #6F7B84;
-}
-
-#viewportFpsLabel {
- color: #9CA5A0;
- font-size: 10px;
- font-weight: 650;
-}
-
-#viewportShortcutHint {
- background-color: #141517;
- border-top: 1px solid #303236;
- color: #68758A;
- font-size: 10px;
- padding: 3px 7px;
-}
-
-#panelToolbar,
-#materialEditorHeader,
-#postProcessingToolbar,
-#workspaceToolbar {
- background-color: #292929;
- border-bottom: 1px solid #404040;
- padding: 2px;
-}
-
-#panelAddButton,
-#materialSaveButton,
-#workspaceApplyButton {
- background-color: #333333;
- border-color: #4C4C4C;
- color: #D8DBDE;
-}
-
-#panelMoreButton,
-#browserNavigationButton,
-#browserRevealButton {
- background-color: transparent;
- border-color: transparent;
- min-width: 24px;
-}
-
-#panelMoreButton:hover,
-#browserNavigationButton:hover,
-#browserRevealButton:hover {
- background-color: #34373A;
- border-color: #484C50;
-}
-
-#contentPathField {
- background-color: #1B1D1F;
- color: #8490A4;
- font-size: 11px;
-}
-
-#contentSearchField {
- min-width: 130px;
-}
-
-QTreeView#hierarchyTree {
- background-color: #202020;
- border-top: 1px solid #303030;
- padding: 3px 2px;
-}
-
-QTreeView#hierarchyTree::item {
- min-height: 22px;
- padding: 1px 6px;
-}
-
-QTreeView#hierarchyTree::item:hover {
- background-color: #303030;
- border-color: #444444;
-}
-
-QTreeView#hierarchyTree::item:selected {
- background-color: #3B5F8A;
- border-color: #5D8BC0;
- color: #FFFFFF;
-}
-
-QListView#contentGrid {
- background-color: #1C1C1C;
- border-top: 1px solid #303030;
- padding: 5px;
-}
-
-QListView#contentGrid::item {
- background-color: #252525;
- border: 1px solid #363636;
- border-radius: 4px;
- padding: 6px;
- color: #BCC6D4;
-}
-
-QListView#contentGrid::item:hover {
- background-color: #303030;
- border-color: #505050;
-}
-
-QListView#contentGrid::item:selected {
- background-color: #3B5F8A;
- border-color: #5D8BC0;
- color: #FFFFFF;
-}
-
-QScrollArea#inspectorScroll,
-#inspectorContent,
-#materialEditorBody,
-#postProcessingBody {
- background-color: #202020;
border: none;
-}
-
-#inspectorHeader {
- background-color: #292929;
- border: 1px solid #414141;
- border-radius: 4px;
- padding: 5px;
+ padding: 0;
}
#inspectorObjectIcon {
- background-color: #343434;
- border: 1px solid #4E4E4E;
- border-radius: 4px;
- padding: 4px;
+ background: transparent;
+ border: none;
}
#inspectorNameField {
background: transparent;
border: 1px solid transparent;
- color: #F3F6FA;
- font-size: 14px;
- font-weight: 700;
+ color: #EAEAE3;
+ font-size: 18px;
+ font-weight: 500;
+ padding: 2px 0;
}
-#inspectorNameField:hover,
#inspectorNameField:focus {
- background-color: #202020;
- border-color: #5A5A5A;
+ border-color: #55554F;
}
-#inspectorTypeLabel {
- color: #7E8A9E;
- font-size: 10px;
- font-weight: 600;
+#inspectorTypeLabel,
+#inspectorPropertyLabel,
+#materialTexturePath,
+#materialEditorStatus,
+#postProcessingStatus,
+#workspaceStatus,
+#workspaceAutoApply {
+ color: #93938C;
+ font-size: 12px;
}
#inspectorComponent {
- background-color: #242424;
- border: 1px solid #3D3D3D;
- border-radius: 3px;
- margin-top: 2px;
-}
-
-#inspectorComponentHeaderRow {
- background-color: #2D2D2D;
- border-bottom: 1px solid #3B3B3B;
- border-radius: 3px 3px 0 0;
-}
-
-#inspectorComponentHeader {
background: transparent;
border: none;
- color: #E8ECF2;
- font-weight: 650;
- text-align: left;
- padding: 4px 7px;
-}
-
-#inspectorComponentHeader:hover {
- background-color: #383838;
+ border-top: 1px solid #2C2C29;
+ border-radius: 0;
}
-#inspectorComponentRemoveButton {
+#inspectorComponentHeaderRow,
+#inspectorComponentBody,
+#inspectorPropertyRow,
+#inspectorNestedGroup,
+#inspectorAudioControls {
background: transparent;
border: none;
- min-width: 22px;
-}
-
-#inspectorComponentRemoveButton:hover {
- background-color: #3A3031;
- border: 1px solid #695556;
-}
-
-#inspectorComponentBody {
- background-color: #242424;
- padding: 4px;
-}
-
-#inspectorPropertyRow {
- background: transparent;
- min-height: 27px;
-}
-
-#inspectorPropertyLabel {
- color: #929EB0;
- font-size: 11px;
}
#inspectorVectorField,
-#inspectorColorField,
-#inspectorNumericField {
- background-color: #181818;
- border: 1px solid #3D3D3D;
- border-radius: 3px;
+#inspectorNumericField,
+#inspectorColorField {
+ background: #252524;
+ border: none;
+ border-radius: 5px;
}
#inspectorVectorField QDoubleSpinBox,
#inspectorNumericField QDoubleSpinBox {
background: transparent;
border: none;
+ padding: 4px 2px;
}
#inspectorAxisX,
#inspectorAxisY,
#inspectorAxisZ {
- border-radius: 2px;
- color: #F1F1F1;
- font-size: 9px;
- font-weight: 750;
- padding: 2px 5px;
-}
-
-#inspectorAxisX {
- background-color: #874747;
-}
-
-#inspectorAxisY {
- background-color: #477451;
-}
-
-#inspectorAxisZ {
- background-color: #435E86;
-}
-
-#inspectorSyncButton,
-#inspectorArrayButton {
background: transparent;
- border-color: transparent;
- min-width: 22px;
+ font-size: 10px;
+ padding: 0 3px;
}
-#inspectorSyncButton[matched="true"] {
- background-color: #343936;
- border-color: #555F59;
- color: #B6BEB9;
-}
+#inspectorAxisX { color: #CA9290; }
+#inspectorAxisY { color: #9AB696; }
+#inspectorAxisZ { color: #91A9C7; }
#inspectorColorSwatch {
- background-color: #292929;
- border: 1px solid #4D4D4D;
- border-radius: 3px;
+ border: 1px solid #45453F;
+ border-radius: 4px;
padding: 2px;
}
#inspectorColorText {
- color: #9CA8BA;
- font-family: "Menlo";
- font-size: 10px;
-}
-
-#inspectorNestedGroup {
- background-color: #202020;
- border: 1px solid #383838;
- border-radius: 3px;
- margin: 3px 0;
- padding: 5px;
+ color: #B0B0A8;
+ font-family: "SF Mono", "Menlo", "Consolas";
+ font-size: 11px;
}
#inspectorNestedTitle,
-#inspectorArrayTitle {
- color: #AEB8C8;
- font-weight: 650;
+#inspectorArrayTitle,
+#materialTextureLabel {
+ color: #C9C9C1;
+ font-weight: 500;
}
#inspectorEmptyTitle,
#materialEditorEmpty,
#postProcessingEmpty {
- color: #C4CDDA;
- font-size: 14px;
- font-weight: 650;
-}
-
-#inspectorEmptyHint {
- color: #728096;
-}
-
-#inspectorOpenAssetButton,
-#inspectorAddComponentButton {
- background-color: #292929;
- border: 1px dashed #5A5A5A;
- color: #C7D0DD;
- padding: 6px;
-}
-
-#inspectorAddComponentButton:hover {
- background-color: #363636;
- border-color: #666666;
- color: #FFFFFF;
+ color: #C7C7BF;
+ font-size: 15px;
+ font-weight: 400;
}
-#inspectorAudioControls {
- background-color: #202020;
- border-radius: 3px;
+#inspectorEmptyHint,
+#environmentPageSubtitle,
+#dialogHeroSubtitle {
+ color: #92928B;
}
#materialEditorTitle,
#postProcessingTitle,
#postProcessingSectionTitle,
-#inspectorCameraTitle,
-#workspaceTitle {
- color: #F3F6FA;
+#workspaceTitle,
+#inspectorCameraTitle {
+ color: #D9D9D2;
font-size: 13px;
- font-weight: 700;
-}
-
-#materialEditorStatus,
-#postProcessingStatus,
-#workspaceStatus,
-#workspaceAutoApply {
- color: #7E8A9E;
- font-size: 10px;
+ font-weight: 500;
}
#materialPreview {
- background-color: #151515;
- border: 1px solid #444444;
- border-radius: 4px;
-}
-
-#materialColorButton {
- background-color: #292929;
- border-color: #454545;
- border-radius: 3px;
- color: #C9CDD0;
- text-align: left;
- padding: 4px 8px;
-}
-
-#materialColorButton:hover {
- background-color: #34383B;
- border-color: #5A5F65;
+ background: #151514;
+ border: none;
+ border-radius: 8px;
}
#materialTextureSlot {
- background-color: #252525;
- border: 1px solid #404040;
- border-radius: 4px;
- padding: 4px;
+ background: transparent;
+ border: none;
+ padding: 6px 0;
}
#materialTexturePreview {
- background-color: #1A1A1A;
- border: 1px solid #494949;
- border-radius: 3px;
- color: #9E897D;
- font-weight: 750;
-}
-
-#materialTextureLabel {
- color: #D6DDE7;
- font-weight: 650;
-}
-
-#materialTexturePath {
- color: #7D899C;
-}
-
-#environmentPages,
-#environmentWorkspace,
-#environmentPage {
- background-color: #202020;
+ background: #242423;
border: none;
+ border-radius: 6px;
}
-QListWidget#environmentCategories {
- background-color: #1B1B1B;
- border-right: 1px solid #3B3B3B;
- padding: 5px;
-}
-
-QListWidget#environmentCategories::item {
- padding: 6px 8px;
- margin: 2px 0;
-}
-
-QListWidget#environmentCategories::item:selected {
- background-color: #3B5F8A;
- border-left: 2px solid #5D8BC0;
+#environmentCategories {
+ background: #191918;
+ border: none;
+ padding: 8px;
}
#environmentPageTitle {
- color: #F3F6FA;
- font-size: 17px;
- font-weight: 750;
-}
-
-#environmentPageSubtitle {
- color: #778499;
-}
-
-QGroupBox#environmentSection {
- background-color: #242424;
- border-color: #3B3B3B;
-}
-
-ads--CDockContainerWidget {
- background-color: #111111;
-}
-
-ads--CDockContainerWidget > QSplitter {
- background-color: #111111;
+ color: #E7E7E0;
+ font-size: 22px;
+ font-weight: 500;
}
+ads--CDockContainerWidget,
+ads--CDockContainerWidget > QSplitter,
ads--CDockContainerWidget ads--CDockSplitter::handle {
- background-color: #111111;
-}
-
-ads--CDockContainerWidget ads--CDockSplitter::handle:hover {
- background-color: #5D8BC0;
-}
-
-ads--CDockAreaWidget {
- background-color: #202020;
- border: 1px solid #343434;
+ background: #121211;
}
+ads--CDockAreaWidget,
ads--CDockAreaWidget[focused="true"] {
- border-color: #4A6382;
-}
-
-ads--CDockAreaTitleBar {
- background-color: #292929;
- border-bottom: 1px solid #3B3B3B;
- min-height: 25px;
+ background: #191918;
+ border: none;
+ border-radius: 9px;
}
+ads--CDockAreaTitleBar,
ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
- background-color: #2D2D2D;
+ background: #191918;
+ border: none;
+ min-height: 40px;
}
#tabsContainerWidget {
- background-color: transparent;
-}
-
-ads--CTitleBarButton {
background: transparent;
- border: none;
- border-radius: 2px;
- min-width: 22px;
- min-height: 22px;
- padding: 2px;
-}
-
-ads--CTitleBarButton:hover {
- background-color: #404040;
-}
-
-ads--CDockWidgetTab {
- background-color: #292929;
- border: none;
- border-right: 1px solid #3A3A3A;
- border-bottom: 1px solid #3B3B3B;
- padding: 1px 5px;
- margin: 1px 0;
- border-radius: 0;
-}
-
-ads--CDockWidgetTab:hover {
- background-color: #333333;
-}
-
-ads--CDockWidgetTab[activeTab="true"] {
- background-color: #333333;
- border-bottom: 2px solid #5D8BC0;
}
+ads--CDockWidgetTab,
+ads--CDockWidgetTab[activeTab="true"],
ads--CDockWidgetTab[focused="true"] {
- background-color: #303030;
+ background: transparent;
+ border: none;
+ padding: 3px 10px;
+ margin: 3px;
}
ads--CDockWidgetTab #dockWidgetTabLabel {
- color: #7F8B9D;
- font-size: 11px;
- padding: 4px 2px;
+ color: #A1A19A;
+ font-size: 13px;
+ padding: 4px 0;
}
-ads--CDockWidgetTab[activeTab="true"] #dockWidgetTabLabel,
-ads--CDockWidgetTab[focused="true"] #dockWidgetTabLabel {
- color: #F1F4F8;
+ads--CDockWidgetTab[activeTab="true"] #dockWidgetTabLabel {
+ color: #DADAD3;
}
+ads--CTitleBarButton,
#tabCloseButton,
#dockAreaCloseButton,
#detachGroupButton,
@@ -1173,304 +734,337 @@ ads--CDockWidgetTab[focused="true"] #dockWidgetTabLabel {
#tabsMenuButton {
background: transparent;
border: none;
- min-width: 20px;
- min-height: 20px;
+ padding: 4px;
+ min-width: 18px;
+ min-height: 18px;
}
-#tabCloseButton:hover,
-#dockAreaCloseButton:hover,
-#detachGroupButton:hover,
-#dockAreaAutoHideButton:hover,
-#dockAreaMinimizeButton:hover,
-#tabsMenuButton:hover {
- background-color: #424549;
+ads--CTitleBarButton:hover,
+#tabCloseButton:hover {
+ background: #2B2B29;
+ border-radius: 5px;
}
ads--CDockWidget {
- background-color: #202020;
+ background: #191918;
}
ads--CAutoHideSideBar,
#sideTabsContainerWidget {
- background-color: #141517;
+ background: #121211;
}
ads--CAutoHideTab {
- background-color: #202224;
- border: 1px solid #404448;
- color: #7F8B9D;
- padding: 4px;
- border-radius: 8px;
+ background: transparent;
+ border: none;
+ padding: 7px;
}
-ads--CAutoHideTab:hover,
-ads--CAutoHideTab[activeTab="true"] {
- background-color: #393F44;
- border-color: #66737C;
- color: #FFFFFF;
+#projectSidebar {
+ background: #121211;
+ border: none;
}
-#projectBrowserRoot,
#projectBrowserContent {
- background-color: #18191B;
-}
-
-#projectSidebar {
- background-color: #151618;
- border-right: 1px solid #303236;
+ background: #191918;
+ border: none;
+ border-radius: 10px;
}
#projectBrand {
- color: #F5F7FA;
+ color: #E7E7E0;
font-size: 16px;
- font-weight: 750;
-}
-
-#projectSidebarVersion {
- color: #68758A;
- font-size: 10px;
- font-weight: 600;
-}
-
-#projectNavSelected {
- background-color: #34383C;
- border: 1px solid #51575C;
- border-left: 3px solid #79868F;
- border-radius: 10px;
- color: #DCE9FA;
- padding: 6px 9px;
- text-align: left;
-}
-
-#projectNavSelected:disabled {
- color: #DCE9FA;
-}
-
-#projectBrowserTitle,
-#dialogTitle {
- color: #F4F6FA;
- font-size: 24px;
- font-weight: 750;
+ font-weight: 500;
}
+#projectSidebarVersion,
+#projectSidebarCaption,
+#projectPath,
+#projectDate,
#projectBrowserSubtitle,
#dialogSubtitle,
#emptyStateSubtitle,
#templateDescription {
- color: #7F8B9D;
+ color: #92928B;
+ font-size: 12px;
}
-#projectSearch {
- background-color: #202224;
- border: 1px solid #43474B;
- border-radius: 11px;
- padding: 7px 9px;
- font-size: 13px;
+#projectBrowserTitle,
+#dialogTitle {
+ color: #EAEAE4;
+ font-size: 28px;
+ font-weight: 500;
}
-#projectSearch:focus {
- border-color: #71808A;
+#projectSearch {
+ background: #222221;
+ padding: 10px 12px;
}
#projectList {
- background-color: transparent;
+ background: transparent;
border: none;
}
-#projectList::item {
+#projectRow {
background: transparent;
border: none;
- padding: 0;
+ border-radius: 7px;
}
-#projectRow {
- background-color: #242628;
- border: 1px solid #3B3E41;
- border-radius: 13px;
+#projectRow:hover {
+ background: #242423;
}
-#projectRow:hover {
- background-color: #2C2F32;
- border-color: #565B61;
+#projectRow[selected="true"] {
+ background: #30302E;
}
-#projectRow[available="false"] {
- background-color: #202224;
- border-color: #303235;
+#projectName {
+ color: #DEDED7;
+ font-size: 14px;
+ font-weight: 400;
}
#projectIcon,
#templateIcon {
- background-color: #303337;
- border: 1px solid #484C50;
- border-radius: 10px;
+ background: transparent;
+ border: none;
}
-#projectName {
- color: #EEF2F7;
- font-size: 14px;
- font-weight: 700;
+#rendererBadge {
+ background: #262624;
+ border: none;
+ border-radius: 4px;
+ color: #ABABA2;
+ font-size: 10px;
+ padding: 4px 7px;
}
-#projectPath,
-#projectDate {
- color: #768398;
- font-size: 10px;
+#projectEmptyState {
+ background: transparent;
+ border: none;
}
-#rendererBadge {
- background-color: #2C302E;
- border: 1px solid #494F4B;
+#emptyStateTitle {
+ color: #CFCFC7;
+ font-size: 20px;
+ font-weight: 400;
+}
+
+QFrame[templateCard="true"] {
+ background: #20201F;
+ border: 1px solid transparent;
border-radius: 8px;
- color: #B4BBB6;
- padding: 3px 7px;
- font-size: 9px;
- font-weight: 700;
}
-#projectMoreButton {
- background: transparent;
- border-color: transparent;
+QFrame[templateCard="true"][selected="true"] {
+ background: #2A2A28;
+ border-color: #66665F;
}
-#projectMoreButton:hover {
- background-color: #3E4246;
- border-color: #51565B;
+#templateOption,
+#fieldLabel {
+ color: #BDBDB5;
+ font-weight: 400;
}
-#projectEmptyState {
- background-color: #1E2022;
- border: 1px dashed #484C51;
- border-radius: 14px;
+#dialogError {
+ color: #D69C95;
+ font-size: 12px;
}
-#emptyStateTitle {
- color: #CDD5E1;
- font-size: 16px;
- font-weight: 700;
+#dialogHero {
+ background: transparent;
+ border: none;
+ padding: 2px;
+}
+
+#dialogHeroIcon {
+ background: transparent;
+ border: none;
+ padding: 4px;
}
-#createProjectDialog {
- background-color: #1E2022;
+#dialogHeroTitle {
+ color: #E3E3DB;
+ font-size: 22px;
+ font-weight: 500;
}
-QFrame[templateCard="true"] {
- background-color: #242628;
- border: 1px solid #42464A;
- border-radius: 13px;
+#exportSummary {
+ background: #1D1D1C;
+ border: none;
+ border-radius: 6px;
+ color: #9C9C94;
+ padding: 12px;
}
-QFrame[templateCard="true"]:hover {
- background-color: #2B2E31;
- border-color: #5A5F65;
+#exportLog,
+#runtimeErrors {
+ background: #161615;
+ border: none;
+ padding: 12px;
+ font-family: "SF Mono", "Menlo", "Consolas";
+ font-size: 12px;
+ color: #C3BAB1;
}
-QFrame[templateCard="true"][selected="true"] {
- background-color: #393F44;
- border-color: #66737C;
+#commandPaletteDialog,
+#globalSearchDialog {
+ background: #191918;
+ border: 1px solid #373733;
+ border-radius: 10px;
}
-#templateOption {
- color: #E7ECF3;
- font-weight: 650;
+#commandPaletteSearch,
+#globalSearchField {
+ background: transparent;
+ border: none;
+ border-bottom: 1px solid #30302C;
+ border-radius: 0;
+ padding: 15px 12px;
+ font-size: 16px;
}
-#fieldLabel {
- color: #AAB5C5;
- font-size: 11px;
- font-weight: 650;
+#commandPaletteList,
+#globalSearchResults {
+ background: transparent;
+ padding: 4px;
}
-#dialogError {
- color: #FF7D8A;
+#paletteHint,
+#projectListHint {
+ background: transparent;
+ color: #7E7E77;
font-size: 11px;
+ padding: 7px 12px;
}
-QPushButton[secondary="true"] {
- background-color: #292C2F;
- border-color: #494D52;
+#splashCard {
+ background: #191918;
+ border: 1px solid #343430;
+ border-radius: 12px;
}
-QPushButton[secondary="true"]:hover {
- background-color: #363A3E;
- border-color: #5D6268;
+#atlasSplash,
+#splashIcon {
+ background: transparent;
}
-#projectSettingsDialog,
-#exportDialog {
- background-color: #18191B;
+#splashTitle {
+ color: #ECECE6;
+ font-size: 36px;
+ font-weight: 500;
}
-#dialogHero {
- background-color: #242628;
- border: 1px solid #42464A;
- border-radius: 13px;
- padding: 6px;
+#splashVersion,
+#splashCompany,
+#splashWarning {
+ color: #91918A;
+ font-size: 12px;
}
-#dialogHeroIcon {
- background-color: #2B3034;
- border: 1px solid #50575C;
- border-radius: 10px;
- padding: 6px;
+#splashStatus {
+ color: #BFBFB7;
+ font-size: 12px;
}
-#dialogHeroTitle {
- color: #F3F6FA;
- font-size: 17px;
- font-weight: 750;
+#splashProgress {
+ background: #2C2C28;
+ border: none;
+ min-height: 0;
+ border-radius: 2px;
}
-#dialogHeroSubtitle,
-#exportSummary {
- color: #7F8B9D;
+#splashProgress::chunk {
+ background: #BCBCB2;
+ border-radius: 2px;
}
-#exportSummary {
- background-color: #232527;
- border: 1px solid #3B3E42;
- border-radius: 10px;
- padding: 6px;
+QPushButton:default {
+ background: #E5E5E1;
+ color: #191918;
}
-#exportLog {
- background-color: #141517;
- border-color: #404448;
- color: #B7BDBC;
- font-family: "Menlo";
- font-size: 10px;
+#projectSectionLabel {
+ color: #82827B;
+ font-size: 12px;
+ padding: 3px 10px;
}
-#commandPaletteDialog,
-#globalSearchDialog {
- background-color: #202224;
- border: 1px solid #5A5F65;
- border-radius: 14px;
+#searchPreviewPane {
+ background: #171716;
+ border: none;
+ border-left: 1px solid #30302C;
}
-#commandPaletteSearch,
-#globalSearchField {
- background-color: #1A1C1E;
- border: 1px solid #505459;
- border-radius: 11px;
- padding: 7px 9px;
- font-size: 14px;
+#searchPreviewText {
+ background: transparent;
+ border: none;
+ padding: 0;
+ font-family: "SF Mono", "Menlo", "Consolas";
+ font-size: 12px;
+ color: #B6B6AF;
}
-#commandPaletteSearch:focus,
-#globalSearchField:focus {
- border-color: #71808A;
+#projectRow[available="false"] #projectName {
+ color: #82827B;
}
-#commandPaletteList,
-#globalSearchResults {
- background-color: #202224;
+QAbstractSpinBox QLineEdit {
+ background: transparent;
+ border: none;
+ padding: 0;
+ min-height: 0;
+}
+
+#inspectorVectorField {
+ background: transparent;
border: none;
+}
+
+#inspectorAxisField {
+ background: #252524;
+ border: 1px solid transparent;
+ border-radius: 6px;
+}
+
+#inspectorAxisField:hover {
+ background: #2C2C29;
+ border-color: #44443F;
+}
+
+#inspectorAxisField QDoubleSpinBox {
+ background: transparent;
+ border: none;
+ padding: 5px 2px;
+ min-height: 24px;
+}
+
+#inspectorNumberField,
+#inspectorNameField,
+#inspectorColorText {
+ min-height: 26px;
+}
+
+#inspectorAxisX,
+#inspectorAxisY,
+#inspectorAxisZ {
+ padding: 0;
+ font-size: 11px;
+}
+
+QTabBar::close-button {
+ image: url(:/editor/assets/close.svg);
+ width: 14px;
+ height: 14px;
padding: 5px;
+ border-radius: 5px;
}
-#commandPaletteList::item,
-#globalSearchResults::item {
- min-height: 30px;
- padding: 6px 8px;
+QTabBar::close-button:hover,
+#tabCloseButton:hover,
+#dockAreaCloseButton:hover {
+ background: #343431;
}
diff --git a/editor/styling/icons.cpp b/editor/styling/icons.cpp
index 7eaadb58..0070f1a5 100644
--- a/editor/styling/icons.cpp
+++ b/editor/styling/icons.cpp
@@ -166,7 +166,8 @@ ushort codepoint(styling::Icon icon) {
}
QPixmap renderIcon(styling::Icon icon, const QColor &color, int size) {
- QPixmap pixmap(size, size);
+ QPixmap pixmap(size * 2, size * 2);
+ pixmap.setDevicePixelRatio(2.0);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
@@ -176,7 +177,7 @@ QPixmap renderIcon(styling::Icon icon, const QColor &color, int size) {
font.setPixelSize(qRound(size * 0.82));
font.setStyleStrategy(QFont::PreferAntialias);
painter.setFont(font);
- painter.drawText(pixmap.rect(), Qt::AlignCenter,
+ painter.drawText(QRect(0, 0, size, size), Qt::AlignCenter,
QString(QChar(codepoint(icon))));
return pixmap;
}
@@ -196,11 +197,13 @@ bool styling::loadIconFont() {
}
QIcon styling::icon(Icon icon, const QColor &color) {
+ if (icon == Icon::Close)
+ return QIcon(":/editor/assets/close.svg");
loadIconFont();
if (iconFamily.isEmpty())
return {};
QIcon result;
- const QColor disabled("#566174");
+ const QColor disabled("#74746D");
const QColor active = color.lighter(118);
for (const int size : {16, 20, 24, 32, 48}) {
result.addPixmap(renderIcon(icon, color, size), QIcon::Normal,
@@ -240,3 +243,10 @@ QIcon styling::colorSwatch(const QColor &color, const QSize &size) {
painter.drawRoundedRect(bounds, 4.0, 4.0);
return QIcon(pixmap);
}
+
+QPixmap styling::brandMark(const QSize &size) {
+ QPixmap mark(":/editor/assets/atlas-star.png");
+ mark = mark.scaled(size * 2, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ mark.setDevicePixelRatio(2.0);
+ return mark;
+}
diff --git a/editor/styling/theme.cpp b/editor/styling/theme.cpp
index 13440703..5b37241c 100644
--- a/editor/styling/theme.cpp
+++ b/editor/styling/theme.cpp
@@ -16,12 +16,12 @@
void styling::applyColorPalette(QApplication& app) {
QPalette p;
- const QColor bg = QColor("#18191B");
- const QColor panel = QColor("#25272A");
- const QColor panel2 = QColor("#1E2022");
- const QColor text = QColor("#E7ECF3");
- const QColor mutedText = QColor("#8D9094");
- const QColor accent = QColor("#71808A");
+ const QColor bg = QColor("#121211");
+ const QColor panel = QColor("#20201F");
+ const QColor panel2 = QColor("#191918");
+ const QColor text = QColor("#D5D5CE");
+ const QColor mutedText = QColor("#92928B");
+ const QColor accent = QColor("#30302E");
p.setColor(QPalette::Window, bg);
p.setColor(QPalette::WindowText, text);
@@ -30,24 +30,24 @@ void styling::applyColorPalette(QApplication& app) {
p.setColor(QPalette::ToolTipBase, panel2);
p.setColor(QPalette::ToolTipText, text);
p.setColor(QPalette::Text, text);
- p.setColor(QPalette::Button, QColor("#2B2E31"));
+ p.setColor(QPalette::Button, QColor("#252524"));
p.setColor(QPalette::ButtonText, text);
p.setColor(QPalette::BrightText, QColor("#FFFFFF"));
- p.setColor(QPalette::Light, QColor("#505357"));
- p.setColor(QPalette::Midlight, QColor("#424549"));
- p.setColor(QPalette::Mid, QColor("#34373A"));
- p.setColor(QPalette::Dark, QColor("#141517"));
+ p.setColor(QPalette::Light, QColor("#50504A"));
+ p.setColor(QPalette::Midlight, QColor("#42423C"));
+ p.setColor(QPalette::Mid, QColor("#33332F"));
+ p.setColor(QPalette::Dark, QColor("#121211"));
p.setColor(QPalette::Shadow, QColor("#0D0E0F"));
p.setColor(QPalette::Highlight, accent);
p.setColor(QPalette::HighlightedText, QColor("#FFFFFF"));
p.setColor(QPalette::PlaceholderText, mutedText);
- p.setColor(QPalette::Disabled, QPalette::WindowText, QColor("#566174"));
- p.setColor(QPalette::Disabled, QPalette::Text, QColor("#566174"));
- p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#566174"));
- p.setColor(QPalette::Disabled, QPalette::Button, QColor("#232527"));
- p.setColor(QPalette::Disabled, QPalette::Base, QColor("#202224"));
- p.setColor(QPalette::Disabled, QPalette::Highlight, QColor("#3A4146"));
+ p.setColor(QPalette::Disabled, QPalette::WindowText, QColor("#64645E"));
+ p.setColor(QPalette::Disabled, QPalette::Text, QColor("#64645E"));
+ p.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#64645E"));
+ p.setColor(QPalette::Disabled, QPalette::Button, QColor("#20201F"));
+ p.setColor(QPalette::Disabled, QPalette::Base, QColor("#191918"));
+ p.setColor(QPalette::Disabled, QPalette::Highlight, QColor("#30302E"));
app.setPalette(p);
}
diff --git a/editor/styling/workbench.cpp b/editor/styling/workbench.cpp
new file mode 100644
index 00000000..2fa2e4e4
--- /dev/null
+++ b/editor/styling/workbench.cpp
@@ -0,0 +1,325 @@
+#include "editor/styling/workbench.h"
+#include "editor/styling/icons.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace {
+
+bool prominent(const QAbstractButton *button) {
+ return button->objectName() == "primaryAction" ||
+ button->objectName() == "workspaceLaunchButton" ||
+ (qobject_cast(button) != nullptr &&
+ qobject_cast(button)->isDefault());
+}
+
+void paintButton(QAbstractButton *button, bool showText, bool vertical,
+ bool hasMenu, bool isTool) {
+ QPainter painter(button);
+ painter.setRenderHint(QPainter::Antialiasing);
+ const bool enabled = button->isEnabled();
+ const bool hover = enabled && button->underMouse();
+ const bool header = button->objectName() == "inspectorComponentHeader";
+ const bool selected = (button->isChecked() && !header) ||
+ button->property("matched").toBool();
+ const bool primary = prominent(button);
+ const QRectF bounds = QRectF(button->rect()).adjusted(0.5, 0.5, -0.5, -0.5);
+ QColor background(Qt::transparent);
+ if (primary)
+ background = !enabled ? QColor("#282827")
+ : button->isDown() ? QColor("#C6C6BF")
+ : hover ? QColor("#F4F4EE") : QColor("#E5E5E1");
+ else if (button->isDown())
+ background = QColor("#333331");
+ else if (selected)
+ background = QColor("#30302E");
+ else if (hover)
+ background = QColor("#292928");
+ else if (!isTool && !header)
+ background = QColor("#242423");
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(background);
+ painter.drawRoundedRect(bounds, 7, 7);
+ if (button->hasFocus() && enabled) {
+ painter.setBrush(Qt::NoBrush);
+ painter.setPen(QPen(QColor("#777771"), 1));
+ painter.drawRoundedRect(bounds.adjusted(1, 1, -1, -1), 6, 6);
+ }
+ const QColor foreground = !enabled ? QColor("#646460")
+ : primary ? QColor("#191918")
+ : selected || hover || header ? QColor("#ECECE7")
+ : QColor("#B6B6AF");
+ QRect content = button->rect().adjusted(10, 0, -10, 0);
+ const bool preserveIconColor = button->property("preserveIconColor").toBool() ||
+ button->objectName() == "materialColorButton" ||
+ button->objectName() == "inspectorColorSwatch";
+ const int iconSize = preserveIconColor ? button->iconSize().width() : 18;
+ const int iconHeight = preserveIconColor ? button->iconSize().height() : 18;
+ const bool hasIcon = !button->icon().isNull();
+ if (hasMenu)
+ content.adjust(0, 0, -13, 0);
+ if (hasIcon) {
+ QRect iconRect;
+ if (!showText)
+ iconRect = QRect((button->width() - iconSize) / 2,
+ (button->height() - iconHeight) / 2, iconSize, iconHeight);
+ else if (vertical)
+ iconRect = QRect((button->width() - iconSize) / 2, 8, iconSize, iconHeight);
+ else
+ iconRect = QRect(content.left(), (button->height() - iconHeight) / 2,
+ iconSize, iconHeight);
+ QPixmap glyph = button->icon().pixmap(QSize(iconSize, iconHeight),
+ button->devicePixelRatioF());
+ if (!preserveIconColor) {
+ QPainter tint(&glyph);
+ tint.setCompositionMode(QPainter::CompositionMode_SourceIn);
+ tint.fillRect(glyph.rect(), foreground);
+ }
+ painter.drawPixmap(iconRect, glyph);
+ if (showText && !vertical)
+ content.adjust(iconSize + 7, 0, 0, 0);
+ }
+ if (showText) {
+ QFont font = button->font();
+ font.setPixelSize(13);
+ font.setWeight(primary || selected || header ? QFont::Medium : QFont::Normal);
+ painter.setFont(font);
+ painter.setPen(foreground);
+ if (vertical)
+ content.setTop(28);
+ const Qt::Alignment alignment = hasIcon && !vertical
+ ? Qt::AlignLeft | Qt::AlignVCenter
+ : Qt::AlignCenter;
+ painter.drawText(content, alignment,
+ painter.fontMetrics().elidedText(button->text().remove('&'),
+ Qt::ElideRight, content.width()));
+ }
+ if (hasMenu) {
+ painter.setPen(QPen(foreground, 1.3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ const QPointF center(button->width() - 12, button->height() / 2.0);
+ QPainterPath path;
+ path.moveTo(center + QPointF(-3, -1.5));
+ path.lineTo(center + QPointF(0, 1.5));
+ path.lineTo(center + QPointF(3, -1.5));
+ painter.drawPath(path);
+ }
+}
+
+class WorkbenchInstaller : public QObject {
+public:
+ using QObject::QObject;
+protected:
+ bool eventFilter(QObject *object, QEvent *event) override {
+ if (event->type() == QEvent::Polish) {
+ if (auto *button = qobject_cast(object)) {
+ if (button->accessibleName().isEmpty() && button->text().isEmpty())
+ button->setAccessibleName(button->toolTip());
+ }
+ if (auto *spin = qobject_cast(object))
+ spin->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ auto *view = qobject_cast(object);
+ if (view != nullptr && !view->property("workbenchStyled").toBool() &&
+ !view->inherits("QTableView")) {
+ view->setProperty("workbenchStyled", true);
+ view->setItemDelegate(new styling::ItemDelegate(view));
+ view->setMouseTracking(true);
+ view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ view->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
+ }
+ }
+ return QObject::eventFilter(object, event);
+ }
+};
+
+}
+
+QSize styling::Button::sizeHint() const {
+ QFont textFont = font();
+ textFont.setPixelSize(13);
+ return QSize(QFontMetrics(textFont).horizontalAdvance(text().remove('&')) +
+ (icon().isNull() ? 28 : 53) + (menu() ? 14 : 0), 34);
+}
+
+void styling::Button::paintEvent(QPaintEvent *) {
+ paintButton(this, true, false, menu() != nullptr, false);
+}
+
+styling::ToolButton::ToolButton(QWidget *parent) : QToolButton(parent) {
+ setCursor(Qt::PointingHandCursor);
+ setFocusPolicy(Qt::StrongFocus);
+ setAutoRaise(true);
+ setIconSize(QSize(18, 18));
+}
+
+QSize styling::ToolButton::sizeHint() const {
+ if (toolButtonStyle() == Qt::ToolButtonIconOnly)
+ return QSize(34, 34);
+ QFont textFont = font();
+ textFont.setPixelSize(13);
+ const int textWidth = QFontMetrics(textFont).horizontalAdvance(text().remove('&'));
+ if (toolButtonStyle() == Qt::ToolButtonTextUnderIcon)
+ return QSize(std::max(44, textWidth + 20), 52);
+ return QSize(textWidth + (icon().isNull() ? 24 : 49) + (menu() ? 14 : 0), 34);
+}
+
+void styling::ToolButton::paintEvent(QPaintEvent *) {
+ paintButton(this, toolButtonStyle() != Qt::ToolButtonIconOnly,
+ toolButtonStyle() == Qt::ToolButtonTextUnderIcon, menu() != nullptr, true);
+}
+
+styling::ItemDelegate::ItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
+
+void styling::ItemDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const {
+ QStyleOptionViewItem item(option);
+ initStyleOption(&item, index);
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ const bool selected = item.state & QStyle::State_Selected;
+ const bool hovered = item.state & QStyle::State_MouseOver;
+ const bool enabled = item.state & QStyle::State_Enabled;
+ const auto *list = qobject_cast(item.widget);
+ const bool grid = list != nullptr && list->viewMode() == QListView::IconMode;
+ const QRect bounds = item.rect.adjusted(3, 2, -3, -2);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(selected ? QColor("#30302E")
+ : hovered ? QColor("#242423") : QColor(Qt::transparent));
+ painter->drawRoundedRect(bounds, 6, 6);
+ QRect textRect = bounds.adjusted(10, 0, -10, 0);
+ if (!item.icon.isNull()) {
+ const int size = grid ? 38 : 18;
+ QRect iconRect = grid ? QRect(bounds.center().x() - size / 2, bounds.top() + 14, size, size)
+ : QRect(textRect.left(), bounds.center().y() - size / 2, size, size);
+ item.icon.paint(painter, iconRect, Qt::AlignCenter,
+ enabled ? QIcon::Normal : QIcon::Disabled);
+ if (grid)
+ textRect.setTop(iconRect.bottom() + 9);
+ else
+ textRect.adjust(size + 9, 0, 0, 0);
+ }
+ if (item.features & QStyleOptionViewItem::HasCheckIndicator) {
+ const QRect check(textRect.left(), bounds.center().y() - 7, 14, 14);
+ painter->setPen(QPen(QColor("#666660"), 1));
+ painter->setBrush(item.checkState == Qt::Checked ? QColor("#D5D5CF") : QColor("#242423"));
+ painter->drawRoundedRect(check, 3, 3);
+ if (item.checkState == Qt::Checked)
+ styling::icon(styling::Icon::Check, "#181817").paint(painter, check);
+ textRect.adjust(22, 0, 0, 0);
+ }
+ QFont font = item.font;
+ font.setPixelSize(13);
+ painter->setFont(font);
+ painter->setPen(!enabled ? QColor("#666660")
+ : selected ? QColor("#F0F0EA") : QColor("#BDBDB6"));
+ const QString secondary = index.data(styling::SecondaryTextRole).toString();
+ if (!secondary.isEmpty() && !grid) {
+ QRect secondaryRect = textRect;
+ secondaryRect.setTop(bounds.top() + 27);
+ secondaryRect.setBottom(bounds.bottom() - 3);
+ QFont secondaryFont = font;
+ secondaryFont.setPixelSize(11);
+ painter->setFont(secondaryFont);
+ painter->setPen(QColor("#92928B"));
+ painter->drawText(secondaryRect, Qt::AlignLeft | Qt::AlignVCenter,
+ painter->fontMetrics().elidedText(secondary, Qt::ElideMiddle,
+ secondaryRect.width()));
+ textRect.setTop(bounds.top() + 3);
+ textRect.setBottom(bounds.top() + 25);
+ painter->setFont(font);
+ painter->setPen(selected ? QColor("#F0F0EA") : QColor("#BDBDB6"));
+ }
+ QString text = item.text;
+ const int shortcutAt = text.indexOf('\t');
+ if (shortcutAt >= 0) {
+ const QString shortcut = text.mid(shortcutAt + 1);
+ text = text.left(shortcutAt);
+ const int shortcutWidth = painter->fontMetrics().horizontalAdvance(shortcut);
+ painter->setPen(QColor("#898983"));
+ painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, shortcut);
+ textRect.adjust(0, 0, -shortcutWidth - 24, 0);
+ painter->setPen(selected ? QColor("#F0F0EA") : QColor("#BDBDB6"));
+ }
+ painter->drawText(textRect, grid ? Qt::AlignHCenter | Qt::AlignTop : Qt::AlignLeft | Qt::AlignVCenter,
+ painter->fontMetrics().elidedText(text, Qt::ElideMiddle, textRect.width()));
+ painter->restore();
+}
+
+QSize styling::ItemDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const {
+ const QVariant explicitSize = index.data(Qt::SizeHintRole);
+ if (explicitSize.isValid())
+ return explicitSize.toSize();
+ const auto *list = qobject_cast(option.widget);
+ if (list != nullptr && list->viewMode() == QListView::IconMode)
+ return QSize(120, 102);
+ QSize size = QStyledItemDelegate::sizeHint(option, index);
+ size.setHeight(index.data(styling::SecondaryTextRole).toString().isEmpty() ? 34 : 52);
+ return size;
+}
+
+void styling::TreeView::drawBranches(QPainter *painter, const QRect &rect,
+ const QModelIndex &index) const {
+ if (!model()->hasChildren(index))
+ return;
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->setPen(QPen(QColor("#94948D"), 1.3, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ const QPointF center(rect.right() - indentation() / 2.0, rect.center().y());
+ QPainterPath path;
+ path.moveTo(center + (isExpanded(index) ? QPointF(-3, -1.5) : QPointF(-1.5, -3)));
+ path.lineTo(center + (isExpanded(index) ? QPointF(0, 1.5) : QPointF(1.5, 0)));
+ path.lineTo(center + (isExpanded(index) ? QPointF(3, -1.5) : QPointF(-1.5, 3)));
+ painter->drawPath(path);
+ painter->restore();
+}
+
+void styling::installWorkbench(QApplication &app) {
+ app.installEventFilter(new WorkbenchInstaller(&app));
+}
+
+styling::WorkspaceStack::WorkspaceStack(QWidget *parent) : QStackedWidget(parent) {
+ layout()->setSizeConstraint(QLayout::SetNoConstraint);
+ connect(this, &QStackedWidget::currentChanged, this, [this] { updateGeometry(); });
+}
+
+QSize styling::WorkspaceStack::minimumSizeHint() const {
+ return currentWidget() != nullptr
+ ? currentWidget()->minimumSizeHint().expandedTo(currentWidget()->minimumSize())
+ : QSize(0, 0);
+}
+
+QSize styling::WorkspaceStack::sizeHint() const {
+ return currentWidget() != nullptr ? currentWidget()->sizeHint() : QSize(640, 480);
+}
+
+styling::ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
+ : QLabel(text, parent) {
+ setToolTip(text);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+}
+
+QSize styling::ElidedLabel::minimumSizeHint() const {
+ return QSize(0, fontMetrics().height());
+}
+
+QSize styling::ElidedLabel::sizeHint() const {
+ return QSize(std::min(320, fontMetrics().horizontalAdvance(text())), fontMetrics().height());
+}
+
+void styling::ElidedLabel::paintEvent(QPaintEvent *) {
+ QPainter painter(this);
+ painter.setFont(font());
+ painter.setPen(palette().color(isEnabled() ? QPalette::Active : QPalette::Disabled,
+ QPalette::WindowText));
+ painter.drawText(contentsRect(), Qt::AlignLeft | Qt::AlignVCenter,
+ fontMetrics().elidedText(text(), Qt::ElideMiddle, contentsRect().width()));
+}
diff --git a/editor/views/editor/editor.cpp b/editor/views/editor/editor.cpp
index 9cfabbe5..d7cee368 100644
--- a/editor/views/editor/editor.cpp
+++ b/editor/views/editor/editor.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
/*
* editor.cpp
* As part of the Atlas project
@@ -67,7 +69,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -76,6 +80,8 @@
#include
#include "DockManager.h"
+#include "DockAreaWidget.h"
+#include "IconProvider.h"
#include "editor/debug.h"
#include "editor/styling/icons.h"
#include "editor/views/fileExplorer.h"
@@ -90,8 +96,8 @@
#include "editor/views/splashScreen.h"
namespace {
-constexpr int DockStateVersion = 10;
-constexpr auto DockStateKey = "docking/state/v10";
+constexpr int DockStateVersion = 11;
+constexpr auto DockStateKey = "docking/state/v11";
QIcon commandIcon(const QString &name) {
const QString command = name.toLower();
@@ -281,7 +287,7 @@ void EditorWindow::setupWindow() {
project.has_value() ? project->name : QStringLiteral("Project");
updateWindowTitle(false);
setMinimumSize(1100, 700);
- resize(1440, 900);
+ resize(1512, 940);
menuBar()->setNativeMenuBar(true);
menuBar()->setObjectName("atlasMenuBar");
@@ -298,8 +304,22 @@ void EditorWindow::setupWindow() {
ads::CDockManager::setConfigFlag(ads::CDockManager::DockAreaHasCloseButton,
false);
+ auto &dockIcons = ads::CDockManager::iconProvider();
+ const QIcon closeIcon(":/editor/assets/close.svg");
+ dockIcons.registerCustomIcon(ads::TabCloseIcon, closeIcon);
+ dockIcons.registerCustomIcon(ads::DockAreaCloseIcon, closeIcon);
+ dockIcons.registerCustomIcon(ads::DockAreaUndockIcon,
+ styling::icon(styling::Icon::ArrowsOutCardinal));
+ dockIcons.registerCustomIcon(ads::DockAreaMenuIcon,
+ styling::icon(styling::Icon::CaretDown));
coreManager = new ads::CDockManager(this);
- setCentralWidget(coreManager);
+ auto *workspaceFrame = new QWidget(this);
+ workspaceFrame->setObjectName("editorFrame");
+ auto *workspaceLayout = new QVBoxLayout(workspaceFrame);
+ workspaceLayout->setContentsMargins(10, 0, 10, 0);
+ workspaceLayout->setSpacing(0);
+ workspaceLayout->addWidget(coreManager);
+ setCentralWidget(workspaceFrame);
dockManager = new EditorDockManager(coreManager);
layoutSaveTimer = new QTimer(this);
scriptWatcher = new QFileSystemWatcher(this);
@@ -669,27 +689,68 @@ void EditorWindow::setupDocks() {
[this] { workspaceChangesPending = true; });
connect(graphiteEditorPanel, &GraphiteEditorPanel::documentSaved, this,
[this] { workspaceChangesPending = true; });
- workspaceStack = new QStackedWidget(this);
+ workspaceStack = new styling::WorkspaceStack(this);
workspaceStack->setObjectName("editorWorkspaceStack");
workspaceStack->addWidget(viewportTools);
workspaceStack->addWidget(materialEditorPanel);
workspaceStack->addWidget(postProcessingPanel);
workspaceStack->addWidget(graphiteEditorPanel);
workspaceStack->setCurrentIndex(0);
+ auto *workspaceSurface = new QWidget(this);
+ workspaceSurface->setObjectName("workspaceSurface");
+ auto *surfaceLayout = new QVBoxLayout(workspaceSurface);
+ surfaceLayout->setContentsMargins(0, 0, 0, 0);
+ surfaceLayout->setSpacing(0);
+ auto *workspaceHeading = new QWidget(workspaceSurface);
+ workspaceHeading->setObjectName("workspaceHeading");
+ auto *headingLayout = new QHBoxLayout(workspaceHeading);
+ headingLayout->setContentsMargins(8, 5, 8, 5);
+ headingLayout->setSpacing(4);
+ auto *switcher = new QWidget(workspaceHeading);
+ switcher->setObjectName("workspaceSwitcher");
+ auto *switcherLayout = new QHBoxLayout(switcher);
+ switcherLayout->setContentsMargins(0, 0, 0, 0);
+ switcherLayout->setSpacing(3);
+ workspaceModeGroup = new QButtonGroup(switcher);
+ workspaceModeGroup->setExclusive(true);
+ const QStringList modes{"Scene", "Shading", "Effects", "Interface"};
+ for (int index = 0; index < modes.size(); ++index) {
+ auto *button = new styling::ToolButton(switcher);
+ button->setObjectName("workspaceModeButton");
+ button->setToolButtonStyle(Qt::ToolButtonTextOnly);
+ button->setText(modes.at(index));
+ button->setCheckable(true);
+ button->setChecked(index == 0);
+ workspaceModeGroup->addButton(button, index);
+ switcherLayout->addWidget(button);
+ connect(button, &QToolButton::clicked, this,
+ [this, index] { activateWorkspace(index); });
+ }
+ headingLayout->addWidget(switcher);
+ headingLayout->addStretch();
+ auto *workspaceSearch = new styling::ToolButton(workspaceHeading);
+ workspaceSearch->setIcon(styling::icon(styling::Icon::MagnifyingGlass));
+ workspaceSearch->setToolTip("Search scenes, objects and assets");
+ connect(workspaceSearch, &QToolButton::clicked, this, &EditorWindow::showGlobalSearch);
+ headingLayout->addWidget(workspaceSearch);
+ surfaceLayout->addWidget(workspaceHeading);
+ surfaceLayout->addWidget(workspaceStack, 1);
auto *workspaceDock = dockManager->addPanel(
{.id = "workspace",
.title = "Workspace",
- .widget = workspaceStack,
+ .widget = workspaceSurface,
.area = EditorDockArea::Center,
.icon = styling::icon(styling::Icon::CubeFocus, "#7E929C")});
workspaceDock->setFeature(ads::CDockWidget::NoTab, true);
+ if (auto *area = workspaceDock->dockAreaWidget())
+ area->setDockAreaFlag(ads::CDockAreaWidget::HideSingleWidgetTitleBar, true);
hierarchyPanel = new HierarchyPanel(viewportPanel);
auto *hierarchyDock = dockManager->addPanel(
{.id = "hierarchy",
- .title = "Scene",
+ .title = "Scene Collection",
.widget = hierarchyPanel,
- .area = EditorDockArea::Right,
+ .area = EditorDockArea::Left,
.icon = styling::icon(styling::Icon::TreeStructure, "#8498A8")});
inspectorPanel = new InspectorPanel(viewportPanel, projectFile);
@@ -699,10 +760,6 @@ void EditorWindow::setupDocks() {
.widget = inspectorPanel,
.area = EditorDockArea::Right,
.icon = styling::icon(styling::Icon::SlidersHorizontal, "#A1957D")});
- if (hierarchyDock->dockAreaWidget() != nullptr) {
- coreManager->addDockWidget(ads::BottomDockWidgetArea, inspectorDock,
- hierarchyDock->dockAreaWidget());
- }
contentBrowser = new ContentBrowserPanel(projectFile);
auto *contentDock = dockManager->addPanel(
@@ -745,6 +802,8 @@ void EditorWindow::setupDocks() {
});
workspaceDock->setAsCurrentTab();
+ coreManager->setSplitterSizes(workspaceDock->dockAreaWidget(), {250, 870, 360});
+ coreManager->setSplitterSizes(contentDock->dockAreaWidget(), {650, 240});
defaultDockState = coreManager->saveState(DockStateVersion);
const QList managedDocks{workspaceDock, hierarchyDock,
@@ -875,129 +934,84 @@ void EditorWindow::setupWorkspaceBar() {
bar->setObjectName("workspaceBar");
bar->setMovable(false);
bar->setFloatable(false);
- bar->setIconSize(QSize(18, 18));
- bar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
addToolBar(Qt::TopToolBarArea, bar);
-
- auto *identity = new QWidget(bar);
- identity->setObjectName("workspaceIdentity");
- auto *identityLayout = new QHBoxLayout(identity);
- identityLayout->setContentsMargins(10, 2, 16, 2);
- identityLayout->setSpacing(9);
- auto *mark = new QLabel(identity);
+ auto *chrome = new QWidget(bar);
+ chrome->setObjectName("workspaceChrome");
+ chrome->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ auto *layout = new QGridLayout(chrome);
+ layout->setContentsMargins(12, 7, 12, 7);
+ layout->setHorizontalSpacing(16);
+ layout->setColumnStretch(0, 1);
+ layout->setColumnStretch(2, 1);
+ auto *activity = new QWidget(chrome);
+ activity->setObjectName("workspaceActivity");
+ auto *activityLayout = new QHBoxLayout(activity);
+ activityLayout->setContentsMargins(0, 0, 0, 0);
+ activityLayout->setSpacing(4);
+ auto *mark = new QLabel(activity);
mark->setObjectName("workspaceMark");
-#ifdef ATLAS_DEBUG_BUILD
- mark->setPixmap(QPixmap(":/editor/assets/Icon-iOS-Default-1024x1024@1x.png")
- .scaled(24, 24, Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#else
- mark->setPixmap(QPixmap(":/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png")
- .scaled(24, 24, Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#endif
- auto *identityText = new QWidget(identity);
- identityText->setObjectName("workspaceIdentityText");
- auto *identityTextLayout = new QVBoxLayout(identityText);
- identityTextLayout->setContentsMargins(0, 0, 0, 0);
- identityTextLayout->setSpacing(0);
- auto *brand = new QLabel("ATLAS ENGINE", identityText);
- brand->setObjectName("workspaceBrand");
- auto *project = new QLabel(projectName, identityText);
- project->setObjectName("workspaceProject");
- identityTextLayout->addWidget(brand);
- identityTextLayout->addWidget(project);
- identityLayout->addWidget(mark);
- identityLayout->addWidget(identityText);
- bar->addWidget(identity);
-
- auto *switcher = new QFrame(bar);
- switcher->setObjectName("workspaceSwitcher");
- auto *switcherLayout = new QHBoxLayout(switcher);
- switcherLayout->setContentsMargins(3, 3, 3, 3);
- switcherLayout->setSpacing(1);
- workspaceModeGroup = new QButtonGroup(switcher);
- workspaceModeGroup->setExclusive(true);
- bar->addWidget(switcher);
-
- addToolBarBreak(Qt::TopToolBarArea);
- auto *contextBar = new QToolBar("Context", this);
- contextBar->setObjectName("workspaceContextBar");
- contextBar->setMovable(false);
- contextBar->setFloatable(false);
- contextBar->setIconSize(QSize(15, 15));
- contextBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- addToolBar(Qt::TopToolBarArea, contextBar);
-
- auto *breadcrumb = new QWidget(contextBar);
- breadcrumb->setObjectName("workspaceBreadcrumb");
- auto *breadcrumbLayout = new QHBoxLayout(breadcrumb);
- breadcrumbLayout->setContentsMargins(8, 0, 12, 0);
- breadcrumbLayout->setSpacing(7);
- auto *workspaceContextIcon = new QLabel(breadcrumb);
- workspaceContextIcon->setObjectName("workspaceContextIcon");
- workspaceContextIcon->setPixmap(
- styling::icon(styling::Icon::CubeFocus, "#7E929C").pixmap(15, 15));
- auto *workspaceContextTitle = new QLabel("Scene", breadcrumb);
- workspaceContextTitle->setObjectName("workspaceContextTitle");
- auto *workspaceContextPath = new QLabel("· Layout", breadcrumb);
- workspaceContextPath->setObjectName("workspaceContextPath");
- breadcrumbLayout->addWidget(workspaceContextIcon);
- breadcrumbLayout->addWidget(workspaceContextTitle);
- breadcrumbLayout->addWidget(workspaceContextPath);
- contextBar->addWidget(breadcrumb);
-
- const QStringList workspacePaths{"· Layout", "· Materials", "· Effects",
- "· Interface"};
- auto addMode = [this, switcher, switcherLayout, workspaceContextIcon,
- workspaceContextTitle, workspaceContextPath,
- workspacePaths](const QString &text, styling::Icon icon,
- const QColor &color, int index,
- bool selected = false) {
- auto *button = new QToolButton(switcher);
- button->setObjectName("workspaceModeButton");
+ mark->setPixmap(styling::brandMark(QSize(26, 26)));
+ activityLayout->addWidget(mark);
+ activityLayout->addSpacing(10);
+ auto addPanelToggle = [this, activity, activityLayout](const QString &id,
+ const QString &text,
+ styling::Icon icon) {
+ auto *dock = dockManager->panel(id);
+ if (dock == nullptr)
+ return;
+ auto *button = new styling::ToolButton(activity);
+ button->setObjectName("workspacePanelButton");
+ button->setIcon(styling::icon(icon));
button->setText(text);
- button->setIcon(styling::icon(icon, color));
- button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ button->setToolTip(text);
button->setCheckable(true);
- button->setChecked(selected);
- button->setProperty("workspacePath", workspacePaths.at(index));
- workspaceModeGroup->addButton(button, index);
- switcherLayout->addWidget(button);
- connect(button, &QToolButton::clicked, this,
- [this, workspaceContextIcon, workspaceContextTitle,
- workspaceContextPath, workspacePaths, text, icon, color,
- index] {
- activateWorkspace(index);
- workspaceContextIcon->setPixmap(
- styling::icon(icon, color).pixmap(15, 15));
- workspaceContextTitle->setText(text);
- workspaceContextPath->setText(workspacePaths.at(index));
+ button->setChecked(!dock->isClosed());
+ activityLayout->addWidget(button);
+ connect(button, &QToolButton::toggled, dock,
+ [dock](bool visible) { dock->toggleView(visible); });
+ connect(dock, &ads::CDockWidget::viewToggled, button,
+ [button](bool visible) {
+ const QSignalBlocker blocker(button);
+ button->setChecked(visible);
});
};
- addMode("Scene", styling::Icon::CubeFocus, "#7E929C", 0, true);
- addMode("Shading", styling::Icon::Material, "#A1957D", 1);
- addMode("Post-Processing", styling::Icon::FilmStrip, "#849589", 2);
- addMode("Graphite", styling::Icon::Palette, "#849589", 3);
-
- auto *spacer = new QWidget(bar);
- spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- bar->addWidget(spacer);
-
- auto *commands = new QToolButton(bar);
- commands->setObjectName("workspaceCommandButton");
- commands->setIcon(styling::icon(styling::Icon::MagnifyingGlass, "#7E929C"));
- commands->setText("Commands");
- commands->setToolTip("Command Palette · Command Shift P");
- bar->addWidget(commands);
- connect(commands, &QToolButton::clicked, this,
- &EditorWindow::showCommandPalette);
-
- auto *save = new QToolButton(bar);
- save->setObjectName("workspaceUtilityButton");
- save->setIcon(styling::icon(styling::Icon::FloppyDisk, "#A1957D"));
- save->setText("Save");
- save->setToolTip("Save Scene");
- bar->addWidget(save);
+ addPanelToggle("hierarchy", "Scene collection", styling::Icon::Sidebar);
+ addPanelToggle("fileExplorer", "Assets", styling::Icon::Folder);
+ addPanelToggle("inspector", "Inspector", styling::Icon::SlidersHorizontal);
+ auto *commands = new styling::ToolButton(activity);
+ commands->setIcon(styling::icon(styling::Icon::MagnifyingGlass));
+ commands->setToolTip("Search commands · " +
+ QKeySequence("Ctrl+Shift+P").toString(QKeySequence::NativeText));
+ connect(commands, &QToolButton::clicked, this, &EditorWindow::showCommandPalette);
+ activityLayout->addWidget(commands);
+ activityLayout->addStretch();
+ layout->addWidget(activity, 0, 0);
+
+ auto *project = new styling::ToolButton(chrome);
+ project->setObjectName("workspaceProject");
+ project->setIcon(styling::icon(styling::Icon::FolderOpen));
+ project->setText(projectName);
+ project->setMaximumWidth(280);
+ project->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ project->setPopupMode(QToolButton::InstantPopup);
+ project->setToolTip(projectName);
+ auto *projectMenu = new QMenu(project);
+ projectMenu->addAction("Project Settings…", this, &EditorWindow::showProjectSettings);
+ projectMenu->addAction("Input Actions…", this, &EditorWindow::showInputActions);
+ projectMenu->addSeparator();
+ projectMenu->addAction("Export Project…", this, &EditorWindow::showExportDialog);
+ project->setMenu(projectMenu);
+ layout->addWidget(project, 0, 1, Qt::AlignCenter);
+
+ auto *utilities = new QWidget(chrome);
+ utilities->setObjectName("workspaceUtilities");
+ auto *utilityLayout = new QHBoxLayout(utilities);
+ utilityLayout->setContentsMargins(0, 0, 0, 0);
+ utilityLayout->setSpacing(5);
+ utilityLayout->addStretch();
+ auto *save = new styling::ToolButton(utilities);
+ save->setIcon(styling::icon(styling::Icon::FloppyDisk));
+ save->setToolTip("Save current work");
connect(save, &QToolButton::clicked, this, [this] {
if (materialEditorPanel != nullptr && materialEditorPanel->isVisible())
materialEditorPanel->saveMaterial();
@@ -1006,57 +1020,25 @@ void EditorWindow::setupWorkspaceBar() {
if (viewportPanel != nullptr)
viewportPanel->saveRuntimeScene();
});
-
- auto *build = new QToolButton(bar);
- build->setObjectName("workspaceBuildButton");
- build->setIcon(styling::icon(styling::Icon::Package, "#A1957D"));
- build->setText("Build");
- build->setToolTip("Build Project");
- bar->addWidget(build);
- connect(build, &QToolButton::clicked, this,
- [this] { runProjectCommand(true); });
-
- auto *launch = new QToolButton(bar);
+ utilityLayout->addWidget(save);
+ auto *build = new styling::ToolButton(utilities);
+ build->setIcon(styling::icon(styling::Icon::Package));
+ build->setToolTip("Build project");
+ connect(build, &QToolButton::clicked, this, [this] { runProjectCommand(true); });
+ utilityLayout->addWidget(build);
+ auto *launch = new styling::ToolButton(utilities);
launch->setObjectName("workspaceLaunchButton");
- launch->setIcon(styling::icon(styling::Icon::RocketLaunch, "#849589"));
+ launch->setIcon(styling::icon(styling::Icon::Play));
launch->setText("Run");
- launch->setToolTip("Run Project");
- bar->addWidget(launch);
- connect(launch, &QToolButton::clicked, this,
- [this] { runProjectCommand(false); });
-
- auto *contextSpacer = new QWidget(contextBar);
- contextSpacer->setSizePolicy(QSizePolicy::Expanding,
- QSizePolicy::Preferred);
- contextBar->addWidget(contextSpacer);
- auto addPanelToggle = [this, contextBar](const QString &id,
- const QString &text,
- styling::Icon icon) {
- ads::CDockWidget *dock = dockManager->panel(id);
- if (dock == nullptr)
- return;
- auto *button = new QToolButton(contextBar);
- button->setObjectName("workspacePanelButton");
- button->setText(text);
- button->setIcon(styling::icon(icon, "#8490A4"));
- button->setCheckable(true);
- button->setChecked(dock->isVisible());
- contextBar->addWidget(button);
- connect(button, &QToolButton::toggled, dock,
- [dock](bool visible) { dock->toggleView(visible); });
- connect(dock, &ads::CDockWidget::viewToggled, button,
- [button](bool visible) {
- const QSignalBlocker blocker(button);
- button->setChecked(visible);
- });
- };
- addPanelToggle("hierarchy", "Scene", styling::Icon::TreeStructure);
- addPanelToggle("fileExplorer", "Assets", styling::Icon::FolderOpen);
- addPanelToggle("inspector", "Inspector",
- styling::Icon::SlidersHorizontal);
+ launch->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ launch->setToolTip("Run project");
+ connect(launch, &QToolButton::clicked, this, [this] { runProjectCommand(false); });
+ utilityLayout->addWidget(launch);
+ layout->addWidget(utilities, 0, 2);
+ bar->addWidget(chrome);
statusBar()->setObjectName("atlasStatusBar");
- statusBar()->showMessage("Ready");
+ statusBar()->showMessage("Scene workspace");
auto *runtimeStatus = new QWidget(statusBar());
runtimeStatus->setObjectName("statusRuntime");
auto *runtimeLayout = new QHBoxLayout(runtimeStatus);
@@ -1100,6 +1082,28 @@ void EditorWindow::activateWorkspace(int index) {
index >= workspaceStack->count())
return;
const int previousIndex = workspaceStack->currentIndex();
+ if (previousIndex != index && coreManager != nullptr) {
+ QSettings settings("Neutral Software", "Atlas Engine");
+ const auto layoutKey = [](int mode) {
+ return QStringLiteral("workspace/layout/v11/%1").arg(mode);
+ };
+ if (!restoringLayout)
+ settings.setValue(layoutKey(previousIndex),
+ coreManager->saveState(DockStateVersion));
+ const QByteArray state = settings.value(layoutKey(index)).toByteArray();
+ if (state.isEmpty() || !coreManager->restoreState(state, DockStateVersion)) {
+ if (index == 0) {
+ coreManager->restoreState(defaultDockState, DockStateVersion);
+ } else {
+ for (const QString &id : {QStringLiteral("hierarchy"),
+ QStringLiteral("inspector")}) {
+ if (auto *dock = dockManager->panel(id))
+ dock->toggleView(false);
+ }
+ }
+ }
+ configureDockSplitters();
+ }
if (index == 0 && previousIndex == 1 && materialEditorPanel != nullptr)
materialEditorPanel->flushPendingSave();
if (index == 0 && previousIndex == 3 && graphiteEditorPanel != nullptr)
@@ -1678,7 +1682,7 @@ void EditorWindow::showExportDialog() {
QDir(QFileInfo(projectFile).absolutePath()).filePath("Exports"))
.toString(),
&dialog);
- auto *browse = new QPushButton("Choose…", &dialog);
+ auto *browse = new styling::Button("Choose…", &dialog);
browse->setIcon(styling::icon(styling::Icon::FolderOpen, "#7E929C"));
auto *outputRow = new QWidget(&dialog);
auto *outputLayout = new QHBoxLayout(outputRow);
@@ -1837,15 +1841,22 @@ void EditorWindow::showCommandPalette() {
dialog.setObjectName("commandPaletteDialog");
dialog.setWindowTitle("Command Palette");
dialog.setWindowFlags(dialog.windowFlags() | Qt::FramelessWindowHint);
- dialog.resize(620, 430);
+ dialog.resize(720, 470);
auto *layout = new QVBoxLayout(&dialog);
+ layout->setContentsMargins(8, 8, 8, 8);
+ layout->setSpacing(4);
auto *search = new QLineEdit(&dialog);
search->setObjectName("commandPaletteSearch");
+ search->setClearButtonEnabled(true);
+ search->addAction(styling::icon(styling::Icon::MagnifyingGlass), QLineEdit::LeadingPosition);
search->setPlaceholderText("Type a command…");
auto *commands = new QListWidget(&dialog);
commands->setObjectName("commandPaletteList");
layout->addWidget(search);
layout->addWidget(commands, 1);
+ auto *hint = new QLabel("↑ ↓ Navigate Return Open Esc Dismiss", &dialog);
+ hint->setObjectName("paletteHint");
+ layout->addWidget(hint);
const QList actions = findChildren();
for (QAction *action : actions) {
if (action->text().isEmpty() || action->isSeparator() ||
@@ -1936,17 +1947,96 @@ void EditorWindow::showGlobalSearch() {
dialog.setObjectName("globalSearchDialog");
dialog.setWindowTitle("Search Atlas Project");
dialog.setWindowFlags(dialog.windowFlags() | Qt::FramelessWindowHint);
- dialog.resize(680, 460);
+ dialog.resize(960, 560);
auto *layout = new QVBoxLayout(&dialog);
+ layout->setContentsMargins(8, 8, 8, 8);
+ layout->setSpacing(4);
auto *search = new QLineEdit(&dialog);
search->setObjectName("globalSearchField");
+ search->setClearButtonEnabled(true);
+ search->addAction(styling::icon(styling::Icon::MagnifyingGlass), QLineEdit::LeadingPosition);
search->setPlaceholderText("Search scenes, assets, and commands…");
auto *results = new QListWidget(&dialog);
results->setObjectName("globalSearchResults");
layout->addWidget(search);
- layout->addWidget(results, 1);
+ auto *splitter = new QSplitter(Qt::Horizontal, &dialog);
+ splitter->setChildrenCollapsible(false);
+ splitter->setHandleWidth(1);
+ splitter->addWidget(results);
+ auto *previewPane = new QWidget(splitter);
+ previewPane->setObjectName("searchPreviewPane");
+ auto *previewLayout = new QVBoxLayout(previewPane);
+ previewLayout->setContentsMargins(16, 14, 12, 10);
+ previewLayout->setSpacing(10);
+ auto *previewTitle = new styling::ElidedLabel("Preview", previewPane);
+ previewTitle->setObjectName("workspaceTitle");
+ previewLayout->addWidget(previewTitle);
+ auto *previewStack = new QStackedWidget(previewPane);
+ auto *previewText = new QPlainTextEdit(previewStack);
+ previewText->setObjectName("searchPreviewText");
+ previewText->setReadOnly(true);
+ previewText->setLineWrapMode(QPlainTextEdit::NoWrap);
+ previewText->setPlaceholderText("Select a result to preview it.");
+ auto *previewImage = new QLabel(previewStack);
+ previewImage->setAlignment(Qt::AlignCenter);
+ previewStack->addWidget(previewText);
+ previewStack->addWidget(previewImage);
+ previewLayout->addWidget(previewStack, 1);
+ splitter->addWidget(previewPane);
+ splitter->setSizes({480, 440});
+ layout->addWidget(splitter, 1);
+ auto *hint = new QLabel("↑ ↓ Navigate Return Open Esc Dismiss", &dialog);
+ hint->setObjectName("paletteHint");
+ layout->addWidget(hint);
constexpr int SearchKindRole = Qt::UserRole + 1;
constexpr int SearchValueRole = Qt::UserRole + 2;
+ connect(results, &QListWidget::currentItemChanged, &dialog,
+ [previewTitle, previewText, previewStack, previewImage](QListWidgetItem *item) {
+ previewStack->setCurrentIndex(0);
+ previewText->clear();
+ previewImage->clear();
+ if (item == nullptr || item->data(SearchKindRole).toInt() == 3) {
+ previewTitle->setText("Preview");
+ return;
+ }
+ previewTitle->setText(item->text());
+ previewTitle->setToolTip(item->toolTip());
+ if (item->data(SearchKindRole).toInt() != 0) {
+ previewText->setPlainText(item->data(styling::SecondaryTextRole).toString());
+ return;
+ }
+ const QString path = item->data(SearchValueRole).toString();
+ const QFileInfo info(path);
+ const QStringList textTypes{"ts", "js", "json", "atlas", "ascene", "aui",
+ "amat", "toml", "txt", "md", "glsl", "vert", "frag"};
+ if (textTypes.contains(info.suffix().toLower())) {
+ QFile file(path);
+ if (file.open(QIODevice::ReadOnly)) {
+ QByteArray data = file.read(65536);
+ QString text = QString::fromUtf8(data);
+ if (!file.atEnd())
+ text += "\n\n… Preview limited to 64 KB";
+ previewText->setPlainText(text);
+ return;
+ }
+ }
+ QImageReader reader(path);
+ const QSize dimensions = reader.size();
+ if (dimensions.isValid() && dimensions.width() <= 16384 &&
+ dimensions.height() <= 16384) {
+ reader.setAutoTransform(true);
+ reader.setScaledSize(dimensions.scaled(QSize(360, 300), Qt::KeepAspectRatio));
+ const QImage image = reader.read();
+ if (!image.isNull()) {
+ previewImage->setPixmap(QPixmap::fromImage(image));
+ previewStack->setCurrentIndex(1);
+ return;
+ }
+ }
+ previewText->setPlainText(QStringLiteral("%1\n\n%2\n%3 KB")
+ .arg(info.fileName(), item->data(styling::SecondaryTextRole).toString())
+ .arg(info.size() / 1024.0, 0, 'f', 1));
+ });
QDirIterator iterator(QFileInfo(projectFile).absolutePath(), QDir::Files,
QDirIterator::Subdirectories);
while (iterator.hasNext()) {
@@ -1954,12 +2044,14 @@ void EditorWindow::showGlobalSearch() {
const QString relative =
QDir(QFileInfo(projectFile).absolutePath()).relativeFilePath(path);
if (relative.startsWith(".git/") || relative.startsWith("build/") ||
- relative.startsWith("dist/"))
+ relative.startsWith("dist/") || relative.startsWith(".jj/") ||
+ relative.startsWith("node_modules/") || relative.startsWith("target/"))
continue;
auto *item = new QListWidgetItem(
- QStringLiteral("Asset %1").arg(relative), results);
+ QFileInfo(path).fileName(), results);
item->setIcon(styling::icon(styling::Icon::File, "#7E929C"));
item->setToolTip(path);
+ item->setData(styling::SecondaryTextRole, "Asset · " + QFileInfo(relative).path());
item->setData(SearchKindRole, 0);
item->setData(SearchValueRole, path);
}
@@ -1976,9 +2068,10 @@ void EditorWindow::showGlobalSearch() {
const int id = object.value("id").toInt(-1);
if (!name.isEmpty() && id >= 0) {
auto *item = new QListWidgetItem(
- QStringLiteral("Object %1").arg(name), results);
+ name, results);
item->setIcon(styling::icon(styling::Icon::Cube, "#8498A8"));
item->setToolTip(object.value("type").toString());
+ item->setData(styling::SecondaryTextRole, "Scene object · " + item->toolTip());
item->setData(SearchKindRole, 1);
item->setData(SearchValueRole, id);
}
@@ -1992,10 +2085,11 @@ void EditorWindow::showGlobalSearch() {
!action->isEnabled())
continue;
auto *item = new QListWidgetItem(
- QStringLiteral("Command %1").arg(action->text().remove('&')),
+ action->text().remove('&'),
results);
item->setIcon(action->icon());
item->setData(SearchKindRole, 2);
+ item->setData(styling::SecondaryTextRole, "Command · " + action->shortcut().toString(QKeySequence::NativeText));
item->setData(SearchValueRole, QVariant::fromValue(
reinterpret_cast(action)));
}
@@ -2267,6 +2361,10 @@ void EditorWindow::saveLayout() {
settings.setValue("window/geometry", saveGeometry());
settings.setValue(DockStateKey, coreManager->saveState(DockStateVersion));
+ if (workspaceStack != nullptr)
+ settings.setValue(
+ QStringLiteral("workspace/layout/v11/%1").arg(workspaceStack->currentIndex()),
+ coreManager->saveState(DockStateVersion));
if (workspaceStack != nullptr)
settings.setValue("workspace/mode", workspaceStack->currentIndex());
settings.sync();
@@ -2297,8 +2395,14 @@ void EditorWindow::restoreLayout() {
void EditorWindow::configureDockSplitters() {
if (coreManager == nullptr)
return;
+ if (dockManager != nullptr) {
+ if (auto *workspace = dockManager->panel("workspace")) {
+ if (auto *area = workspace->dockAreaWidget())
+ area->setDockAreaFlag(ads::CDockAreaWidget::HideSingleWidgetTitleBar, true);
+ }
+ }
for (QSplitter *splitter : coreManager->findChildren()) {
- splitter->setHandleWidth(4);
+ splitter->setHandleWidth(10);
splitter->setOpaqueResize(true);
splitter->setChildrenCollapsible(false);
if (!splitter->property("atlasLayoutTracking").toBool()) {
diff --git a/editor/views/editor/graphiteEditor.cpp b/editor/views/editor/graphiteEditor.cpp
index dc5c50e0..0c30e4d4 100644
--- a/editor/views/editor/graphiteEditor.cpp
+++ b/editor/views/editor/graphiteEditor.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include "editor/views/graphiteEditor.h"
#include "editor/styling/icons.h"
@@ -236,7 +238,7 @@ class GraphiteCanvas : public QWidget {
void paintEvent(QPaintEvent *) override {
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
- painter.fillRect(rect(), QColor("#17191D"));
+ painter.fillRect(rect(), QColor("#171716"));
const QJsonObject canvas = document.value("canvas").toObject();
const double width = std::max(1.0, canvas.value("width").toDouble(1280));
const double height =
@@ -410,7 +412,7 @@ class GraphiteCanvas : public QWidget {
}
if (path == selected) {
painter.setBrush(Qt::NoBrush);
- painter.setPen(QPen(QColor("#E39758"), 2.0 / canvasScale));
+ painter.setPen(QPen(QColor("#B7A4ED"), 2.0 / canvasScale));
painter.drawRect(frame.adjusted(-2, -2, 2, 2));
}
if (!element.value("components").toArray().isEmpty()) {
@@ -452,11 +454,11 @@ GraphiteEditorPanel::GraphiteEditorPanel(ViewportPanel *viewport,
titleLabel->setObjectName("materialEditorTitle");
statusLabel = new QLabel(header);
statusLabel->setObjectName("materialEditorStatus");
- auto *attach = new QPushButton("Attach to Scene", header);
+ auto *attach = new styling::Button("Attach to Scene", header);
attach->setIcon(styling::icon(styling::Icon::Assign, "#9E897D"));
- auto *preview = new QPushButton("Preview Camera", header);
+ auto *preview = new styling::Button("Preview Camera", header);
preview->setIcon(styling::icon(styling::Icon::MonitorPlay, "#849589"));
- auto *save = new QPushButton("Save", header);
+ auto *save = new styling::Button("Save", header);
save->setIcon(styling::icon(styling::Icon::FloppyDisk, "#A1957D"));
headerLayout->addWidget(titleLabel, 1);
headerLayout->addWidget(statusLabel);
@@ -473,7 +475,7 @@ GraphiteEditorPanel::GraphiteEditorPanel(ViewportPanel *viewport,
auto *outlineLayout = new QVBoxLayout(outline);
outlineLayout->setContentsMargins(8, 8, 4, 8);
auto *outlineToolbar = new QHBoxLayout();
- auto *add = new QToolButton(outline);
+ auto *add = new styling::ToolButton(outline);
add->setText("Add");
add->setIcon(styling::icon(styling::Icon::Plus, "#8498A8"));
add->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -490,10 +492,10 @@ GraphiteEditorPanel::GraphiteEditorPanel(ViewportPanel *viewport,
for (const auto &[label, type] : types)
addMenu->addAction(label, this, [this, type] { addElement(type); });
add->setMenu(addMenu);
- auto *duplicate = new QToolButton(outline);
+ auto *duplicate = new styling::ToolButton(outline);
duplicate->setIcon(styling::icon(styling::Icon::SquaresFour, "#7E929C"));
duplicate->setToolTip("Duplicate selected element");
- auto *remove = new QToolButton(outline);
+ auto *remove = new styling::ToolButton(outline);
remove->setIcon(styling::icon(styling::Icon::Trash, "#A17F7F"));
remove->setToolTip("Delete selected element");
outlineToolbar->addWidget(add);
@@ -925,7 +927,7 @@ void GraphiteEditorPanel::rebuildInspector() {
QJsonObject fontData = document.value("defaultFont").toObject();
auto *fontPath =
new QLineEdit(fontData.value("source").toString(), fontGroup);
- auto *chooseFont = new QPushButton("Choose…", fontGroup);
+ auto *chooseFont = new styling::Button("Choose…", fontGroup);
auto *fontRow = new QWidget(fontGroup);
auto *fontRowLayout = new QHBoxLayout(fontRow);
fontRowLayout->setContentsMargins(0, 0, 0, 0);
@@ -1074,7 +1076,7 @@ void GraphiteEditorPanel::rebuildInspector() {
} else {
auto *source = new QLineEdit(element.value("source").toString(),
contentGroup);
- auto *choose = new QPushButton("Choose…", contentGroup);
+ auto *choose = new styling::Button("Choose…", contentGroup);
auto *row = new QWidget(contentGroup);
auto *rowLayout = new QHBoxLayout(row);
rowLayout->setContentsMargins(0, 0, 0, 0);
@@ -1135,10 +1137,12 @@ void GraphiteEditorPanel::rebuildInspector() {
jsonColor(normal.value("foreground"),
jsonColor(fallbackNormal.value("foreground"),
QColor("#F5F6F8")));
- auto *backgroundButton = new QPushButton(appearance);
+ auto *backgroundButton = new styling::Button(appearance);
+ backgroundButton->setProperty("preserveIconColor", true);
backgroundButton->setIcon(styling::colorSwatch(background));
backgroundButton->setText(background.name(QColor::HexArgb));
- auto *foregroundButton = new QPushButton(appearance);
+ auto *foregroundButton = new styling::Button(appearance);
+ foregroundButton->setProperty("preserveIconColor", true);
foregroundButton->setIcon(styling::colorSwatch(foreground));
foregroundButton->setText(foreground.name(QColor::HexArgb));
auto *radius =
@@ -1197,8 +1201,8 @@ void GraphiteEditorPanel::rebuildInspector() {
item->setToolTip(component.value("source").toString());
}
auto *componentButtons = new QHBoxLayout();
- auto *addScript = new QPushButton("Add Script…", components);
- auto *removeScript = new QPushButton("Remove", components);
+ auto *addScript = new styling::Button("Add Script…", components);
+ auto *removeScript = new styling::Button("Remove", components);
componentButtons->addWidget(addScript);
componentButtons->addWidget(removeScript);
componentsLayout->addWidget(componentList);
@@ -1209,7 +1213,7 @@ void GraphiteEditorPanel::rebuildInspector() {
auto *componentVariables = new QPlainTextEdit(components);
componentVariables->setPlaceholderText("{}");
componentVariables->setMaximumHeight(92);
- auto *applyComponent = new QPushButton("Apply Component", components);
+ auto *applyComponent = new styling::Button("Apply Component", components);
componentForm->addRow("Class", componentClass);
componentForm->addRow("Source", componentSource);
componentForm->addRow("Variables", componentVariables);
diff --git a/editor/views/editor/hierarchy.cpp b/editor/views/editor/hierarchy.cpp
index 2b84b611..5cfb06a1 100644
--- a/editor/views/editor/hierarchy.cpp
+++ b/editor/views/editor/hierarchy.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
/*
* hierarchy.cpp
* As part of the Atlas project
@@ -130,7 +132,7 @@ HierarchyPanel::HierarchyPanel(ViewportPanel *viewport, QWidget *parent)
: QWidget(parent), viewport(viewport) {
setObjectName("hierarchyPanel");
auto *layout = new QVBoxLayout(this);
- layout->setContentsMargins(4, 4, 4, 4);
+ layout->setContentsMargins(10, 0, 10, 10);
layout->setSpacing(4);
auto *toolbar = new QWidget(this);
@@ -139,30 +141,32 @@ HierarchyPanel::HierarchyPanel(ViewportPanel *viewport, QWidget *parent)
toolbarLayout->setContentsMargins(0, 0, 0, 0);
toolbarLayout->setSpacing(4);
- addButton = new QToolButton(toolbar);
+ addButton = new styling::ToolButton(toolbar);
addButton->setObjectName("panelAddButton");
addButton->setIcon(styling::icon(styling::Icon::Plus, "#8498A8"));
addButton->setText("Add");
- addButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ addButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
addButton->setPopupMode(QToolButton::InstantPopup);
addButton->setToolTip("Add Object");
- moreButton = new QToolButton(toolbar);
+ moreButton = new styling::ToolButton(toolbar);
moreButton->setObjectName("panelMoreButton");
moreButton->setIcon(styling::icon(styling::Icon::DotsVertical, "#8490A4"));
moreButton->setPopupMode(QToolButton::InstantPopup);
moreButton->setToolTip("Hierarchy actions");
- toolbarLayout->addWidget(addButton);
+
searchField = new QLineEdit(toolbar);
searchField->setPlaceholderText("Search hierarchy");
searchField->setClearButtonEnabled(true);
- searchField->setMaximumWidth(180);
+ searchField->setMinimumWidth(80);
+ searchField->setObjectName("hierarchySearch");
toolbarLayout->addWidget(searchField, 1);
+ toolbarLayout->addWidget(addButton);
toolbarLayout->addWidget(moreButton);
layout->addWidget(toolbar);
- treeView = new QTreeView(this);
+ treeView = new styling::TreeView(this);
treeView->setObjectName("hierarchyTree");
model = new QStandardItemModel(this);
treeView->setModel(model);
@@ -171,7 +175,7 @@ HierarchyPanel::HierarchyPanel(ViewportPanel *viewport, QWidget *parent)
treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
- treeView->setIndentation(16);
+ treeView->setIndentation(20);
treeView->setIconSize(QSize(18, 18));
treeView->setContextMenuPolicy(Qt::CustomContextMenu);
treeView->setUniformRowHeights(true);
diff --git a/editor/views/editor/inspector.cpp b/editor/views/editor/inspector.cpp
index 5d4988db..965900ef 100644
--- a/editor/views/editor/inspector.cpp
+++ b/editor/views/editor/inspector.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
/*
* inspector.cpp
* As part of the Atlas project
@@ -679,6 +681,7 @@ QDoubleSpinBox *numberField(double value, QWidget *parent) {
field->setObjectName("inspectorNumberField");
field->setRange(-1000000000.0, 1000000000.0);
field->setDecimals(4);
+ field->setMinimumHeight(34);
field->setSingleStep(0.1);
field->setButtonSymbols(QAbstractSpinBox::NoButtons);
field->setValue(value);
@@ -742,10 +745,9 @@ void addSyncPicker(QHBoxLayout *layout, const QString &path,
const QJsonValue ¤t, const PropertyChanged &changed,
const SyncProvider &provider, QWidget *valueEditor,
QWidget *parent) {
- auto *button = new QToolButton(parent);
+ auto *button = new styling::ToolButton(parent);
button->setObjectName("inspectorSyncButton");
- button->setIcon(
- styling::icon(styling::Icon::ArrowCounterClockwise, "#849589"));
+ button->setIcon(QIcon(":/editor/assets/link.svg"));
button->setToolTip("Match this value with another property");
button->setPopupMode(QToolButton::InstantPopup);
auto showMatch = [button, valueEditor](const QString &name) {
@@ -860,12 +862,12 @@ QWidget *vectorField(const QJsonArray &value, const PropertyChanged &changed,
auto *field = new QFrame(parent);
field->setObjectName("inspectorVectorField");
auto *layout = new QHBoxLayout(field);
- layout->setContentsMargins(3, 0, 3, 0);
+ layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(2);
auto *valueEditor = new QWidget(field);
auto *valueLayout = new QHBoxLayout(valueEditor);
valueLayout->setContentsMargins(0, 0, 0, 0);
- valueLayout->setSpacing(2);
+ valueLayout->setSpacing(6);
layout->addWidget(valueEditor, 1);
auto values = value;
const int dimensions = std::clamp(static_cast(value.size()), 2, 3);
@@ -874,15 +876,22 @@ QWidget *vectorField(const QJsonArray &value, const PropertyChanged &changed,
const QStringList axes{"X", "Y", "Z"};
QList boxes;
for (int index = 0; index < dimensions; ++index) {
- auto *axis = new QLabel(axes.at(index), valueEditor);
+ auto *axisField = new QFrame(valueEditor);
+ axisField->setObjectName("inspectorAxisField");
+ auto *axisLayout = new QHBoxLayout(axisField);
+ axisLayout->setContentsMargins(7, 0, 4, 0);
+ axisLayout->setSpacing(4);
+ auto *axis = new QLabel(axes.at(index), axisField);
axis->setObjectName("inspectorAxis" + axes.at(index));
- auto *box = numberField(values.at(index).toDouble(), valueEditor);
+ axis->setFixedWidth(12);
+ auto *box = numberField(values.at(index).toDouble(), axisField);
box->setButtonSymbols(QAbstractSpinBox::NoButtons);
- box->setMinimumWidth(52);
+ box->setMinimumWidth(58);
tagEditor(box, path, "vector", index);
boxes.append(box);
- valueLayout->addWidget(axis);
- valueLayout->addWidget(box, 1);
+ axisLayout->addWidget(axis);
+ axisLayout->addWidget(box, 1);
+ valueLayout->addWidget(axisField, 1);
}
auto commit = [boxes, changed, path] {
QJsonArray result;
@@ -920,7 +929,7 @@ QWidget *colorField(const QJsonArray &value, const PropertyChanged &changed,
? std::clamp(static_cast(value.at(3).toDouble() * factor), 0,
255)
: 255);
- auto *swatch = new QPushButton(field);
+ auto *swatch = new styling::Button(field);
swatch->setObjectName("inspectorColorSwatch");
swatch->setFixedSize(30, 22);
auto *text = new QLineEdit(field);
@@ -1054,15 +1063,20 @@ QWidget *primitiveField(const QString &name, const QString &path,
QFrame *propertyRow(const QString &label, QWidget *editor, QWidget *parent) {
auto *row = new QFrame(parent);
row->setObjectName("inspectorPropertyRow");
- auto *layout = new QHBoxLayout(row);
- layout->setContentsMargins(8, 3, 8, 3);
- layout->setSpacing(8);
- auto *name = new QLabel(label, row);
+ const bool wide = editor->objectName() == "inspectorVectorField" ||
+ editor->objectName() == "inspectorColorField";
+ QBoxLayout *layout = wide ? static_cast(new QVBoxLayout(row))
+ : static_cast(new QHBoxLayout(row));
+ layout->setContentsMargins(0, 5, 0, 5);
+ layout->setSpacing(wide ? 7 : 12);
+ auto *name = new styling::ElidedLabel(label, row);
name->setObjectName("inspectorPropertyLabel");
- name->setMinimumWidth(82);
- name->setMaximumWidth(108);
+ if (!wide) {
+ name->setMinimumWidth(90);
+ name->setMaximumWidth(112);
+ }
layout->addWidget(name);
- layout->addWidget(editor, 1);
+ layout->addWidget(editor, wide ? 0 : 1);
return row;
}
@@ -1105,7 +1119,7 @@ void addPropertyRows(QVBoxLayout *layout, const QJsonObject &properties,
headingLayout->setSpacing(4);
auto *title = new QLabel(humanize(key), heading);
title->setObjectName("inspectorNestedTitle");
- auto *add = new QToolButton(heading);
+ auto *add = new styling::ToolButton(heading);
add->setObjectName("inspectorArrayButton");
add->setIcon(styling::icon(styling::Icon::Plus, "#8498A8"));
add->setToolTip("Add item");
@@ -1136,7 +1150,7 @@ void addPropertyRows(QVBoxLayout *layout, const QJsonObject &properties,
.arg(index + 1),
itemHeading);
itemTitle->setObjectName("inspectorArrayTitle");
- auto *remove = new QToolButton(itemHeading);
+ auto *remove = new styling::ToolButton(itemHeading);
remove->setObjectName("inspectorArrayButton");
remove->setIcon(
styling::icon(styling::Icon::Trash, "#A17F7F"));
@@ -1283,14 +1297,14 @@ QFrame *componentCard(const QString &title, const QJsonObject &properties,
card->setObjectName("inspectorComponent");
card->setProperty("inspectorScope", scope);
auto *layout = new QVBoxLayout(card);
- layout->setContentsMargins(0, 0, 0, 7);
+ layout->setContentsMargins(0, 10, 0, 4);
layout->setSpacing(2);
auto *headerRow = new QWidget(card);
headerRow->setObjectName("inspectorComponentHeaderRow");
auto *headerLayout = new QHBoxLayout(headerRow);
headerLayout->setContentsMargins(0, 0, 3, 0);
headerLayout->setSpacing(2);
- auto *header = new QToolButton(headerRow);
+ auto *header = new styling::ToolButton(headerRow);
header->setObjectName("inspectorComponentHeader");
header->setText(title);
header->setCheckable(true);
@@ -1299,9 +1313,9 @@ QFrame *componentCard(const QString &title, const QJsonObject &properties,
header->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
headerLayout->addWidget(header, 1);
if (remove) {
- auto *removeButton = new QToolButton(headerRow);
+ auto *removeButton = new styling::ToolButton(headerRow);
removeButton->setObjectName("inspectorComponentRemoveButton");
- removeButton->setIcon(styling::icon(styling::Icon::Trash, "#A17F7F"));
+ removeButton->setIcon(QIcon(":/editor/assets/close.svg"));
removeButton->setToolTip(QStringLiteral("Remove %1").arg(title));
headerLayout->addWidget(removeButton);
QObject::connect(removeButton, &QToolButton::clicked, card, remove);
@@ -1311,7 +1325,7 @@ QFrame *componentCard(const QString &title, const QJsonObject &properties,
body->setObjectName("inspectorComponentBody");
auto *bodyLayout = new QVBoxLayout(body);
bodyLayout->setContentsMargins(0, 2, 0, 0);
- bodyLayout->setSpacing(1);
+ bodyLayout->setSpacing(5);
addPropertyRows(bodyLayout, properties, path, changed, syncProvider, body);
layout->addWidget(body);
QObject::connect(
@@ -1332,9 +1346,9 @@ QFrame *controllerActionsCard(const QJsonArray &actions, bool automaticMoving,
card->setObjectName("inspectorComponent");
card->setProperty("inspectorScope", "camera:actions");
auto *layout = new QVBoxLayout(card);
- layout->setContentsMargins(0, 0, 0, 7);
+ layout->setContentsMargins(0, 10, 0, 4);
layout->setSpacing(2);
- auto *header = new QToolButton(card);
+ auto *header = new styling::ToolButton(card);
header->setObjectName("inspectorComponentHeader");
header->setText("Controller Actions");
header->setCheckable(true);
@@ -1346,7 +1360,7 @@ QFrame *controllerActionsCard(const QJsonArray &actions, bool automaticMoving,
body->setObjectName("inspectorComponentBody");
auto *bodyLayout = new QVBoxLayout(body);
bodyLayout->setContentsMargins(0, 2, 0, 0);
- bodyLayout->setSpacing(1);
+ bodyLayout->setSpacing(5);
auto *automatic = new QCheckBox("Enable Automatic Movement", body);
automatic->setChecked(automaticMoving);
automatic->setCursor(Qt::PointingHandCursor);
@@ -1359,7 +1373,7 @@ QFrame *controllerActionsCard(const QJsonArray &actions, bool automaticMoving,
const QStringList labels{"Movement", "Look", "Vertical"};
QList pickers;
for (int index = 0; index < labels.size(); ++index) {
- auto *picker = new QToolButton(body);
+ auto *picker = new styling::ToolButton(body);
picker->setObjectName("inspectorActionPicker");
picker->setPopupMode(QToolButton::InstantPopup);
picker->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -1479,7 +1493,7 @@ InspectorPanel::InspectorPanel(ViewportPanel *viewport,
const QString &projectFile, QWidget *parent)
: QWidget(parent), viewport(viewport), projectFile(projectFile) {
setObjectName("inspectorPanel");
- setMinimumWidth(400);
+ setMinimumWidth(360);
setAcceptDrops(true);
const QFileInfo projectInfo(projectFile);
projectRoot = projectInfo.absoluteDir().absolutePath();
@@ -1492,8 +1506,8 @@ InspectorPanel::InspectorPanel(ViewportPanel *viewport,
content = new QWidget(scrollArea);
content->setObjectName("inspectorContent");
contentLayout = new QVBoxLayout(content);
- contentLayout->setContentsMargins(8, 8, 8, 10);
- contentLayout->setSpacing(8);
+ contentLayout->setContentsMargins(14, 4, 14, 16);
+ contentLayout->setSpacing(16);
scrollArea->setWidget(content);
layout->addWidget(scrollArea);
if (viewport != nullptr) {
@@ -1751,12 +1765,12 @@ void InspectorPanel::showObject(const QJsonObject &object) {
auto *header = new QFrame(content);
header->setObjectName("inspectorHeader");
auto *headerLayout = new QHBoxLayout(header);
- headerLayout->setContentsMargins(10, 10, 10, 10);
+ headerLayout->setContentsMargins(0, 12, 0, 14);
headerLayout->setSpacing(10);
iconLabel = new QLabel(header);
iconLabel->setObjectName("inspectorObjectIcon");
- iconLabel->setPixmap(inspectorIcon(this, type).pixmap(42, 42));
- iconLabel->setFixedSize(46, 46);
+ iconLabel->setPixmap(inspectorIcon(this, type).pixmap(28, 28));
+ iconLabel->setFixedSize(32, 32);
auto *identity = new QWidget(header);
auto *identityLayout = new QVBoxLayout(identity);
identityLayout->setContentsMargins(0, 0, 0, 0);
@@ -1917,7 +1931,7 @@ void InspectorPanel::showObject(const QJsonObject &object) {
for (int actionIndex = 0; actionIndex < audioActions.size();
++actionIndex) {
const QString &action = audioActions.at(actionIndex);
- auto *button = new QToolButton(controls);
+ auto *button = new styling::ToolButton(controls);
button->setIcon(styling::icon(audioIcons.at(actionIndex),
audioColors.at(actionIndex)));
button->setToolTip(action);
@@ -1934,7 +1948,7 @@ void InspectorPanel::showObject(const QJsonObject &object) {
contentLayout->addWidget(controls);
}
}
- auto *addComponent = new QToolButton(content);
+ auto *addComponent = new styling::ToolButton(content);
addComponent->setObjectName("inspectorAddComponentButton");
addComponent->setIcon(styling::icon(styling::Icon::Plus, "#8498A8"));
addComponent->setText("Add Component");
@@ -2054,11 +2068,11 @@ void InspectorPanel::showCamera() {
auto *header = new QFrame(content);
header->setObjectName("inspectorHeader");
auto *headerLayout = new QHBoxLayout(header);
- headerLayout->setContentsMargins(10, 10, 10, 10);
+ headerLayout->setContentsMargins(0, 12, 0, 14);
headerLayout->setSpacing(10);
auto *cameraIcon = new QLabel(header);
cameraIcon->setObjectName("inspectorObjectIcon");
- cameraIcon->setPixmap(inspectorIcon(this, "camera").pixmap(42, 42));
+ cameraIcon->setPixmap(inspectorIcon(this, "camera").pixmap(28, 28));
cameraIcon->setFixedSize(46, 46);
auto *identity = new QWidget(header);
auto *identityLayout = new QVBoxLayout(identity);
@@ -2074,7 +2088,7 @@ void InspectorPanel::showCamera() {
headerLayout->addWidget(identity, 1);
contentLayout->addWidget(header);
- auto *cameraView = new QToolButton(content);
+ auto *cameraView = new styling::ToolButton(content);
cameraView->setObjectName("inspectorAddComponentButton");
cameraView->setCheckable(true);
cameraView->setChecked(viewport != nullptr && viewport->isCameraFocused());
@@ -2156,12 +2170,12 @@ void InspectorPanel::showEnvironment() {
auto *header = new QFrame(content);
header->setObjectName("inspectorHeader");
auto *headerLayout = new QHBoxLayout(header);
- headerLayout->setContentsMargins(10, 10, 10, 10);
+ headerLayout->setContentsMargins(0, 12, 0, 14);
headerLayout->setSpacing(10);
auto *environmentIcon = new QLabel(header);
environmentIcon->setObjectName("inspectorObjectIcon");
environmentIcon->setPixmap(
- inspectorIcon(this, "environment").pixmap(42, 42));
+ inspectorIcon(this, "environment").pixmap(28, 28));
environmentIcon->setFixedSize(46, 46);
auto *identity = new QWidget(header);
auto *identityLayout = new QVBoxLayout(identity);
@@ -2288,13 +2302,13 @@ void InspectorPanel::showFile() {
auto *header = new QFrame(content);
header->setObjectName("inspectorHeader");
auto *headerLayout = new QHBoxLayout(header);
- headerLayout->setContentsMargins(10, 10, 10, 10);
+ headerLayout->setContentsMargins(0, 12, 0, 14);
headerLayout->setSpacing(10);
iconLabel = new QLabel(header);
iconLabel->setObjectName("inspectorObjectIcon");
const QString iconType = info.isDir() ? "folder" : info.suffix();
- iconLabel->setPixmap(inspectorIcon(this, iconType).pixmap(42, 42));
- iconLabel->setFixedSize(46, 46);
+ iconLabel->setPixmap(inspectorIcon(this, iconType).pixmap(28, 28));
+ iconLabel->setFixedSize(32, 32);
auto *identity = new QWidget(header);
auto *identityLayout = new QVBoxLayout(identity);
identityLayout->setContentsMargins(0, 0, 0, 0);
@@ -2381,7 +2395,7 @@ void InspectorPanel::showFile() {
}
}
}
- auto *open = new QPushButton("Open in Default App", content);
+ auto *open = new styling::Button("Open in Default App", content);
open->setObjectName("inspectorOpenAssetButton");
connect(open, &QPushButton::clicked, this, [this] {
QDesktopServices::openUrl(QUrl::fromLocalFile(inspectedFile));
diff --git a/editor/views/editor/materialEditor.cpp b/editor/views/editor/materialEditor.cpp
index 5ad0d9f0..fd7ea709 100644
--- a/editor/views/editor/materialEditor.cpp
+++ b/editor/views/editor/materialEditor.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include
#include
#include
@@ -345,15 +347,15 @@ MaterialEditorPanel::MaterialEditorPanel(ViewportPanel *viewport,
auto *header = new QWidget(this);
header->setObjectName("materialEditorHeader");
auto *headerLayout = new QHBoxLayout(header);
- headerLayout->setContentsMargins(8, 4, 8, 4);
+ headerLayout->setContentsMargins(12, 6, 12, 6);
titleLabel = new QLabel("Material Editor", header);
titleLabel->setObjectName("materialEditorTitle");
statusLabel = new QLabel(header);
statusLabel->setObjectName("materialEditorStatus");
- auto *saveButton = new QPushButton("Save", header);
+ auto *saveButton = new styling::Button("Save", header);
saveButton->setObjectName("materialSaveButton");
saveButton->setIcon(styling::icon(styling::Icon::FloppyDisk, "#A1957D"));
- auto *assignButton = new QPushButton("Assign to Selected", header);
+ auto *assignButton = new styling::Button("Assign to Selected", header);
assignButton->setObjectName("materialAssignButton");
assignButton->setIcon(styling::icon(styling::Icon::Assign, "#9E897D"));
headerLayout->addWidget(titleLabel, 1);
@@ -370,7 +372,7 @@ MaterialEditorPanel::MaterialEditorPanel(ViewportPanel *viewport,
body->setObjectName("materialEditorBody");
bodyLayout = new QVBoxLayout(body);
bodyLayout->setContentsMargins(10, 10, 10, 12);
- bodyLayout->setSpacing(9);
+ bodyLayout->setSpacing(12);
scroll->setWidget(body);
layout->addWidget(scroll, 1);
@@ -556,7 +558,7 @@ void MaterialEditorPanel::showMaterial() {
auto *surface = new QGroupBox("Surface", properties);
auto *surfaceForm = new QFormLayout(surface);
- albedoButton = new QPushButton(surface);
+ albedoButton = new styling::Button(surface);
displayColor(albedoButton,
jsonColor(material.value("albedo"), QColor(204, 204, 204)));
metallicField = scalarField(0.0, 1.0, 0.01, surface);
@@ -576,7 +578,7 @@ void MaterialEditorPanel::showMaterial() {
auto *emission = new QGroupBox("Emission", properties);
auto *emissionForm = new QFormLayout(emission);
- emissiveButton = new QPushButton(emission);
+ emissiveButton = new styling::Button(emission);
displayColor(emissiveButton,
jsonColor(material.value("emissiveColor"), Qt::black));
emissiveIntensityField = scalarField(0.0, 100.0, 0.1, emission);
@@ -651,11 +653,11 @@ void MaterialEditorPanel::showMaterial() {
field->setObjectName("materialTexturePath");
field->setReadOnly(true);
field->setPlaceholderText("No image");
- auto *choose = new QToolButton(row);
+ auto *choose = new styling::ToolButton(row);
choose->setText("Choose…");
choose->setIcon(styling::icon(styling::Icon::FolderOpen, "#7E929C"));
choose->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- auto *clear = new QToolButton(row);
+ auto *clear = new styling::ToolButton(row);
clear->setIcon(styling::icon(styling::Icon::Close, "#A17F7F"));
clear->setToolTip("Remove texture");
auto *identity = new QWidget(row);
diff --git a/editor/views/editor/postProcessing.cpp b/editor/views/editor/postProcessing.cpp
index 24e9199b..1043e56f 100644
--- a/editor/views/editor/postProcessing.cpp
+++ b/editor/views/editor/postProcessing.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include
#include
#include
@@ -97,18 +99,18 @@ PostProcessingPanel::PostProcessingPanel(ViewportPanel *viewport,
auto *toolbar = new QWidget(this);
toolbar->setObjectName("postProcessingToolbar");
auto *toolbarLayout = new QHBoxLayout(toolbar);
- toolbarLayout->setContentsMargins(8, 4, 8, 4);
+ toolbarLayout->setContentsMargins(12, 6, 12, 6);
toolbarLayout->setSpacing(4);
- auto *title = new QLabel("Post Processing", toolbar);
+ auto *title = new QLabel("Effects", toolbar);
title->setObjectName("postProcessingTitle");
targetSelector = new QComboBox(toolbar);
targetSelector->setMinimumWidth(180);
- auto *addTargetButton = new QToolButton(toolbar);
+ auto *addTargetButton = new styling::ToolButton(toolbar);
addTargetButton->setIcon(
styling::icon(styling::Icon::Plus, "#8498A8"));
addTargetButton->setText("Target");
addTargetButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- removeTargetButton = new QToolButton(toolbar);
+ removeTargetButton = new styling::ToolButton(toolbar);
removeTargetButton->setText("Remove");
removeTargetButton->setIcon(
styling::icon(styling::Icon::Trash, "#A17F7F"));
@@ -130,7 +132,7 @@ PostProcessingPanel::PostProcessingPanel(ViewportPanel *viewport,
body->setObjectName("postProcessingBody");
bodyLayout = new QVBoxLayout(body);
bodyLayout->setContentsMargins(12, 12, 12, 14);
- bodyLayout->setSpacing(9);
+ bodyLayout->setSpacing(12);
scroll->setWidget(body);
layout->addWidget(scroll, 1);
@@ -249,7 +251,7 @@ void PostProcessingPanel::rebuildEditor() {
effectsHeadingLayout->setContentsMargins(0, 4, 0, 0);
auto *effectsTitle = new QLabel("Effect Stack", effectsHeading);
effectsTitle->setObjectName("postProcessingSectionTitle");
- auto *addEffectButton = new QToolButton(effectsHeading);
+ auto *addEffectButton = new styling::ToolButton(effectsHeading);
addEffectButton->setIcon(
styling::icon(styling::Icon::Plus, "#8498A8"));
addEffectButton->setText("Add Effect");
@@ -333,19 +335,19 @@ void PostProcessingPanel::rebuildEditor() {
auto *actionsLayout = new QHBoxLayout(actions);
actionsLayout->setContentsMargins(0, 0, 0, 0);
actionsLayout->setSpacing(4);
- auto *moveUp = new QToolButton(actions);
+ auto *moveUp = new styling::ToolButton(actions);
moveUp->setText("Move Up");
moveUp->setIcon(
styling::icon(styling::Icon::CaretUp, "#7E929C"));
moveUp->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
moveUp->setEnabled(effectIndex > 0);
- auto *moveDown = new QToolButton(actions);
+ auto *moveDown = new styling::ToolButton(actions);
moveDown->setText("Move Down");
moveDown->setIcon(
styling::icon(styling::Icon::CaretDown, "#7E929C"));
moveDown->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
moveDown->setEnabled(effectIndex + 1 < effectStack.size());
- auto *remove = new QToolButton(actions);
+ auto *remove = new styling::ToolButton(actions);
remove->setText("Remove Effect");
remove->setIcon(
styling::icon(styling::Icon::Trash, "#A17F7F"));
diff --git a/editor/views/editor/viewport.cpp b/editor/views/editor/viewport.cpp
index a302a471..65b1c435 100644
--- a/editor/views/editor/viewport.cpp
+++ b/editor/views/editor/viewport.cpp
@@ -813,6 +813,8 @@ void ViewportPanel::showEvent(QShowEvent *event) {
if (playbackState == 1)
captureRuntimeInput();
if (runtimeContext != nullptr) {
+ runtimeContext->setEditorPathTracingPreview(pbrPreview);
+ runtimeContext->setEditorShadingMode(shadingMode);
frameTimer->start(RuntimeFrameIntervalMs);
return;
}
diff --git a/editor/views/editor/viewportTools.cpp b/editor/views/editor/viewportTools.cpp
index d22a09dd..76764e28 100644
--- a/editor/views/editor/viewportTools.cpp
+++ b/editor/views/editor/viewportTools.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include
#include
@@ -89,26 +91,26 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
auto *toolbar = new QWidget(this);
toolbar->setObjectName("viewportToolbar");
auto *tools = new QHBoxLayout(toolbar);
- tools->setContentsMargins(5, 3, 5, 3);
- tools->setSpacing(2);
+ tools->setContentsMargins(8, 4, 8, 4);
+ tools->setSpacing(3);
- playButton = new QToolButton(toolbar);
+ playButton = new styling::ToolButton(toolbar);
playButton->setObjectName("viewportPlaybackButton");
playButton->setIcon(styling::icon(styling::Icon::Play, "#849589"));
playButton->setToolTip("Play");
- pauseButton = new QToolButton(toolbar);
+ pauseButton = new styling::ToolButton(toolbar);
pauseButton->setObjectName("viewportPlaybackButton");
pauseButton->setIcon(styling::icon(styling::Icon::Pause, "#A1957D"));
pauseButton->setToolTip("Pause");
- stepButton = new QToolButton(toolbar);
+ stepButton = new styling::ToolButton(toolbar);
stepButton->setObjectName("viewportPlaybackButton");
stepButton->setIcon(styling::icon(styling::Icon::SkipForward, "#7E929C"));
stepButton->setToolTip("Step one frame");
- stopButton = new QToolButton(toolbar);
+ stopButton = new styling::ToolButton(toolbar);
stopButton->setObjectName("viewportPlaybackButton");
stopButton->setIcon(styling::icon(styling::Icon::Stop, "#A17F7F"));
stopButton->setToolTip("Stop and restore the scene");
- reloadButton = new QToolButton(toolbar);
+ reloadButton = new styling::ToolButton(toolbar);
reloadButton->setObjectName("viewportPlaybackButton");
reloadButton->setIcon(
styling::icon(styling::Icon::ArrowCounterClockwise, "#71889A"));
@@ -123,10 +125,10 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
const QList transformIcons{
styling::Icon::CursorClick, styling::Icon::ArrowsOutCardinal,
styling::Icon::ArrowClockwise, styling::Icon::BoundingBox};
- const QList transformColors{QColor("#7E929C"), QColor("#849589"),
- QColor("#A1957D"), QColor("#71889A")};
+ const QList transformColors{QColor("#C8C7BF"), QColor("#C8C7BF"),
+ QColor("#C8C7BF"), QColor("#C8C7BF")};
for (int index = 0; index < transformNames.size(); ++index) {
- auto *button = new QToolButton(toolbar);
+ auto *button = new styling::ToolButton(toolbar);
button->setObjectName("viewportModeButton");
button->setToolButtonStyle(Qt::ToolButtonIconOnly);
button->setCheckable(true);
@@ -145,13 +147,13 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
}
tools->addSpacing(10);
- spaceButton = new QToolButton(toolbar);
+ spaceButton = new styling::ToolButton(toolbar);
spaceButton->setObjectName("viewportOptionButton");
spaceButton->setIcon(styling::icon(styling::Icon::Globe, "#7E929C"));
spaceButton->setToolTip("World transform space · Shift+T");
tools->addWidget(spaceButton);
- cameraButton = new QToolButton(toolbar);
+ cameraButton = new styling::ToolButton(toolbar);
cameraButton->setObjectName("viewportOptionButton");
cameraButton->setIcon(styling::icon(styling::Icon::Camera, "#9E897D"));
cameraButton->setCheckable(true);
@@ -204,7 +206,7 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
styling::Icon::CubeTransparent,
styling::Icon::DotsNine};
for (int index = 0; index < shadingNames.size(); ++index) {
- auto *button = new QToolButton(toolbar);
+ auto *button = new styling::ToolButton(toolbar);
button->setObjectName("viewportShadingButton");
button->setToolButtonStyle(pathTracingProject
? Qt::ToolButtonTextBesideIcon
@@ -225,7 +227,7 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
}
}
- auto *fpsButton = new QToolButton(toolbar);
+ auto *fpsButton = new styling::ToolButton(toolbar);
fpsButton->setObjectName("viewportOptionButton");
fpsButton->setIcon(styling::icon(styling::Icon::Monitor, "#849589"));
fpsButton->setCheckable(true);
@@ -241,12 +243,12 @@ ViewportTools::ViewportTools(ViewportPanel *viewport,
viewportHost = new ViewportHost(viewport, cameraAspect, this);
layout->addWidget(viewportHost, 1);
shortcutHint =
- new QLabel("Tab Frame · Num 0 Camera · Shift+Middle/Right Pan · "
- "Middle/Right Orbit · G Move · R Rotate · S Scale · X "
- "Delete",
- this);
+ new QLabel("Orbit Middle drag Pan Shift + drag Frame Tab", this);
shortcutHint->setObjectName("viewportShortcutHint");
shortcutHint->setTextInteractionFlags(Qt::NoTextInteraction);
+ shortcutHint->setContentsMargins(12, 5, 12, 5);
+ shortcutHint->setToolTip("Tab Frame · Num 0 Camera · Shift+Middle/Right Pan · "
+ "Middle/Right Orbit · G Move · R Rotate · S Scale · X Delete");
layout->addWidget(shortcutHint);
connect(playButton, &QToolButton::clicked, viewport,
diff --git a/editor/views/general/contentBrowser.cpp b/editor/views/general/contentBrowser.cpp
index e2ecbd1e..323c92dc 100644
--- a/editor/views/general/contentBrowser.cpp
+++ b/editor/views/general/contentBrowser.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
/*
* contentBrowser.cpp
* As part of the Atlas project
@@ -215,7 +217,7 @@ ContentBrowserPanel::ContentBrowserPanel(const QString &projectFile,
}
auto *layout = new QVBoxLayout(this);
- layout->setContentsMargins(4, 4, 4, 4);
+ layout->setContentsMargins(6, 6, 6, 6);
layout->setSpacing(4);
auto *toolbar = new QWidget(this);
@@ -224,17 +226,17 @@ ContentBrowserPanel::ContentBrowserPanel(const QString &projectFile,
toolbarLayout->setContentsMargins(0, 0, 0, 0);
toolbarLayout->setSpacing(4);
- backButton = new QToolButton(toolbar);
+ backButton = new styling::ToolButton(toolbar);
backButton->setObjectName("browserNavigationButton");
backButton->setIcon(
styling::icon(styling::Icon::ArrowLeft, "#AAB4C4"));
backButton->setToolTip("Back");
- forwardButton = new QToolButton(toolbar);
+ forwardButton = new styling::ToolButton(toolbar);
forwardButton->setObjectName("browserNavigationButton");
forwardButton->setIcon(
styling::icon(styling::Icon::ArrowRight, "#AAB4C4"));
forwardButton->setToolTip("Forward");
- upButton = new QToolButton(toolbar);
+ upButton = new styling::ToolButton(toolbar);
upButton->setObjectName("browserNavigationButton");
upButton->setIcon(styling::icon(styling::Icon::ArrowUp, "#AAB4C4"));
upButton->setToolTip("Parent Folder");
@@ -245,24 +247,24 @@ ContentBrowserPanel::ContentBrowserPanel(const QString &projectFile,
searchField = new QLineEdit(toolbar);
searchField->setObjectName("contentSearchField");
- searchField->setPlaceholderText("Search");
+ searchField->setPlaceholderText("Filter assets…");
searchField->setClearButtonEnabled(true);
searchField->setMaximumWidth(180);
- createButton = new QToolButton(toolbar);
+ createButton = new styling::ToolButton(toolbar);
createButton->setObjectName("panelAddButton");
createButton->setIcon(styling::icon(styling::Icon::Plus, "#8498A8"));
createButton->setText("Create");
createButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
createButton->setPopupMode(QToolButton::InstantPopup);
- revealButton = new QToolButton(toolbar);
+ revealButton = new styling::ToolButton(toolbar);
revealButton->setObjectName("browserRevealButton");
revealButton->setIcon(
styling::icon(styling::Icon::FolderOpen, "#7E929C"));
revealButton->setToolTip("Reveal in Finder");
- moreButton = new QToolButton(toolbar);
+ moreButton = new styling::ToolButton(toolbar);
moreButton->setObjectName("panelMoreButton");
moreButton->setIcon(
styling::icon(styling::Icon::DotsVertical, "#8490A4"));
@@ -301,10 +303,10 @@ ContentBrowserPanel::ContentBrowserPanel(const QString &projectFile,
gridView->setWrapping(true);
gridView->setResizeMode(QListView::Adjust);
gridView->setMovement(QListView::Static);
- gridView->setGridSize(QSize(154, 118));
- gridView->setIconSize(QSize(50, 50));
+ gridView->setGridSize(QSize(128, 106));
+ gridView->setIconSize(QSize(42, 42));
gridView->setWordWrap(true);
- gridView->setTextElideMode(Qt::ElideNone);
+ gridView->setTextElideMode(Qt::ElideMiddle);
gridView->setSelectionMode(QAbstractItemView::ExtendedSelection);
gridView->setDragEnabled(true);
gridView->setDragDropMode(QAbstractItemView::DragOnly);
diff --git a/editor/views/general/inputActionsDialog.cpp b/editor/views/general/inputActionsDialog.cpp
index bb06ccf8..fed06db5 100644
--- a/editor/views/general/inputActionsDialog.cpp
+++ b/editor/views/general/inputActionsDialog.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include
#include
@@ -178,6 +180,7 @@ void InputActionsDialog::setupUi() {
root->setSpacing(12);
auto *heading = new QLabel("Controller Actions", this);
+ heading->setObjectName("dialogHeroTitle");
QFont headingFont = heading->font();
headingFont.setPointSizeF(18);
headingFont.setWeight(QFont::DemiBold);
@@ -207,7 +210,7 @@ void InputActionsDialog::setupUi() {
sidebarLayout->addWidget(actionList, 1);
auto *sidebarButtons = new QHBoxLayout();
- auto *addButton = new QPushButton("Add", sidebar);
+ auto *addButton = new styling::Button("Add", sidebar);
auto *addMenu = new QMenu(addButton);
addMenu->addAction("Button", this,
[this] { addAction(ActionKind::Button); });
@@ -216,8 +219,8 @@ void InputActionsDialog::setupUi() {
addMenu->addAction("2D Axis", this,
[this] { addAction(ActionKind::Axis2D); });
addButton->setMenu(addMenu);
- duplicateButton = new QPushButton("Duplicate", sidebar);
- removeButton = new QPushButton("Remove", sidebar);
+ duplicateButton = new styling::Button("Duplicate", sidebar);
+ removeButton = new styling::Button("Remove", sidebar);
sidebarButtons->addWidget(addButton);
sidebarButtons->addWidget(duplicateButton);
sidebarButtons->addWidget(removeButton);
@@ -261,8 +264,8 @@ void InputActionsDialog::setupUi() {
buttonBindings->setSelectionMode(QAbstractItemView::SingleSelection);
buttonLayout->addWidget(buttonBindings);
auto *bindingButtons = new QHBoxLayout();
- auto *addBindingButton = new QPushButton("Add Binding", buttonPage);
- auto *removeBindingButton = new QPushButton("Remove Binding", buttonPage);
+ auto *addBindingButton = new styling::Button("Add Binding", buttonPage);
+ auto *removeBindingButton = new styling::Button("Remove Binding", buttonPage);
bindingButtons->addWidget(addBindingButton);
bindingButtons->addWidget(removeBindingButton);
bindingButtons->addStretch();
diff --git a/editor/views/general/projectBrowser.cpp b/editor/views/general/projectBrowser.cpp
index ace9a885..1c43c1b7 100644
--- a/editor/views/general/projectBrowser.cpp
+++ b/editor/views/general/projectBrowser.cpp
@@ -1,3 +1,5 @@
+#include "editor/styling/workbench.h"
+
#include
#include
@@ -14,6 +16,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -173,7 +177,7 @@ class CreateProjectDialog : public QDialog {
}
locationField->setText(defaultLocation);
locationLayout->addWidget(locationField, 1);
- auto *browse = new QPushButton("Browse…", this);
+ auto *browse = new styling::Button("Browse…", this);
browse->setProperty("secondary", true);
browse->setIcon(styling::icon(styling::Icon::FolderOpen, "#7E929C"));
locationLayout->addWidget(browse);
@@ -188,10 +192,10 @@ class CreateProjectDialog : public QDialog {
auto *actions = new QHBoxLayout();
actions->addStretch();
- auto *cancel = new QPushButton("Cancel", this);
+ auto *cancel = new styling::Button("Cancel", this);
cancel->setProperty("secondary", true);
actions->addWidget(cancel);
- createButton = new QPushButton("Create project", this);
+ createButton = new styling::Button("Create project", this);
createButton->setObjectName("primaryAction");
createButton->setIcon(
styling::icon(styling::Icon::RocketLaunch, "#FFFFFF"));
@@ -269,12 +273,12 @@ class ProjectRow : public QFrame {
auto *copy = new QVBoxLayout();
copy->setSpacing(3);
- auto *title = new QLabel(project.name, this);
+ auto *title = new styling::ElidedLabel(project.name, this);
title->setObjectName("projectName");
copy->addWidget(title);
- auto *path = new QLabel(project.directory, this);
+ auto *path = new styling::ElidedLabel(project.directory, this);
path->setObjectName("projectPath");
- path->setTextInteractionFlags(Qt::TextSelectableByMouse);
+
copy->addWidget(path);
layout->addLayout(copy, 1);
@@ -283,7 +287,7 @@ class ProjectRow : public QFrame {
layout->addWidget(renderer);
auto *date =
- new QLabel(project.lastModified.isValid()
+ new QLabel(project.available && project.lastModified.isValid()
? project.lastModified.toString("d MMM yyyy")
: QStringLiteral("Unavailable"),
this);
@@ -291,7 +295,7 @@ class ProjectRow : public QFrame {
date->setMinimumWidth(90);
layout->addWidget(date);
- moreButton = new QToolButton(this);
+ moreButton = new styling::ToolButton(this);
moreButton->setObjectName("projectMoreButton");
moreButton->setIcon(
styling::icon(styling::Icon::DotsVertical, "#8490A4"));
@@ -318,32 +322,23 @@ void ProjectBrowser::setupUi() {
auto *root = new QWidget(this);
root->setObjectName("projectBrowserRoot");
setCentralWidget(root);
- auto *rootLayout = new QHBoxLayout(root);
- rootLayout->setContentsMargins(0, 0, 0, 0);
- rootLayout->setSpacing(0);
+ auto *rootLayout = new QVBoxLayout(root);
+ rootLayout->setContentsMargins(10, 10, 10, 10);
+ rootLayout->setSpacing(10);
auto *sidebar = new QFrame(root);
sidebar->setObjectName("projectSidebar");
- sidebar->setFixedWidth(224);
- auto *sidebarLayout = new QVBoxLayout(sidebar);
- sidebarLayout->setContentsMargins(22, 26, 22, 22);
+ sidebar->setFixedHeight(70);
+ auto *sidebarLayout = new QHBoxLayout(sidebar);
+ sidebarLayout->setContentsMargins(18, 8, 18, 8);
sidebarLayout->setSpacing(18);
auto *brandLayout = new QHBoxLayout();
brandLayout->setSpacing(11);
auto *brandIcon = new QLabel(sidebar);
brandIcon->setFixedSize(38, 38);
-#ifdef ATLAS_DEBUG_BUILD
- brandIcon->setPixmap(
- QPixmap(":/editor/assets/Icon-iOS-Default-1024x1024@1x.png")
- .scaled(brandIcon->size(), Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#else
- brandIcon->setPixmap(
- QPixmap(":/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png")
- .scaled(brandIcon->size(), Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#endif
+ brandIcon->setPixmap(styling::brandMark(brandIcon->size()));
+
brandLayout->addWidget(brandIcon);
auto *brandCopy = new QVBoxLayout();
brandCopy->setSpacing(0);
@@ -357,19 +352,17 @@ void ProjectBrowser::setupUi() {
brandLayout->addStretch();
sidebarLayout->addLayout(brandLayout);
- auto *projectsNav = new QPushButton("Projects", sidebar);
- projectsNav->setObjectName("projectNavSelected");
- projectsNav->setIcon(styling::icon(styling::Icon::SquaresFour, "#8498A8"));
- projectsNav->setEnabled(false);
- sidebarLayout->addWidget(projectsNav);
sidebarLayout->addStretch();
+ auto *sidebarCaption = new QLabel("Your next world starts here.", sidebar);
+ sidebarCaption->setObjectName("projectSidebarCaption");
+ sidebarLayout->addWidget(sidebarCaption);
rootLayout->addWidget(sidebar);
auto *content = new QWidget(root);
content->setObjectName("projectBrowserContent");
auto *contentLayout = new QVBoxLayout(content);
- contentLayout->setContentsMargins(34, 30, 34, 30);
+ contentLayout->setContentsMargins(38, 32, 38, 24);
contentLayout->setSpacing(20);
auto *headingLayout = new QHBoxLayout();
@@ -384,11 +377,11 @@ void ProjectBrowser::setupUi() {
headingCopy->addWidget(subtitle);
headingLayout->addLayout(headingCopy, 1);
- auto *openButton = new QPushButton("Open existing", content);
+ auto *openButton = new styling::Button("Open existing", content);
openButton->setProperty("secondary", true);
openButton->setIcon(styling::icon(styling::Icon::FolderOpen, "#7E929C"));
headingLayout->addWidget(openButton);
- auto *createButton = new QPushButton("New project", content);
+ auto *createButton = new styling::Button("New project", content);
createButton->setObjectName("primaryAction");
createButton->setIcon(styling::icon(styling::Icon::Plus, "#FFFFFF"));
headingLayout->addWidget(createButton);
@@ -398,12 +391,16 @@ void ProjectBrowser::setupUi() {
searchField->setObjectName("projectSearch");
searchField->setPlaceholderText("Search projects");
searchField->setClearButtonEnabled(true);
+ searchField->addAction(styling::icon(styling::Icon::MagnifyingGlass), QLineEdit::LeadingPosition);
contentLayout->addWidget(searchField);
+ auto *sectionLabel = new QLabel("Recent projects", content);
+ sectionLabel->setObjectName("projectSectionLabel");
+ contentLayout->addWidget(sectionLabel);
projectStack = new QStackedWidget(content);
projectList = new QListWidget(projectStack);
projectList->setObjectName("projectList");
- projectList->setSpacing(8);
+ projectList->setSpacing(3);
projectList->setSelectionMode(QAbstractItemView::SingleSelection);
projectList->setContextMenuPolicy(Qt::CustomContextMenu);
projectList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
@@ -426,6 +423,9 @@ void ProjectBrowser::setupUi() {
emptyLayout->addStretch();
projectStack->addWidget(empty);
contentLayout->addWidget(projectStack, 1);
+ auto *listHint = new QLabel("Double-click a project to open it · Return to continue", content);
+ listHint->setObjectName("projectListHint");
+ contentLayout->addWidget(listHint);
rootLayout->addWidget(content, 1);
connect(createButton, &QPushButton::clicked, this,
@@ -434,6 +434,23 @@ void ProjectBrowser::setupUi() {
&ProjectBrowser::openExistingProject);
connect(searchField, &QLineEdit::textChanged, this,
&ProjectBrowser::filterProjects);
+ connect(projectList, &QListWidget::currentItemChanged, this,
+ [this](QListWidgetItem *current, QListWidgetItem *previous) {
+ for (auto *item : {previous, current}) {
+ if (item == nullptr)
+ continue;
+ auto *row = projectList->itemWidget(item);
+ if (row == nullptr)
+ continue;
+ row->setProperty("selected", item == current);
+ row->style()->unpolish(row);
+ row->style()->polish(row);
+ row->update();
+ }
+ });
+ auto *openShortcut = new QShortcut(QKeySequence(Qt::Key_Return), projectList);
+ openShortcut->setContext(Qt::WidgetWithChildrenShortcut);
+ connect(openShortcut, &QShortcut::activated, this, &ProjectBrowser::openSelectedProject);
connect(projectList, &QListWidget::itemDoubleClicked, this,
[this] { openSelectedProject(); });
connect(projectList, &QListWidget::customContextMenuRequested, this,
@@ -447,7 +464,7 @@ void ProjectBrowser::reloadProjects() {
auto *item = new QListWidgetItem(projectList);
item->setData(ProjectPathRole, project.projectFile);
item->setData(ProjectAvailableRole, project.available);
- item->setSizeHint(QSize(0, 76));
+ item->setSizeHint(QSize(0, 82));
auto *row = new ProjectRow(project, projectList);
projectList->setItemWidget(item, row);
connect(row->optionsButton(), &QToolButton::clicked, this,
diff --git a/editor/views/general/splashScreen.cpp b/editor/views/general/splashScreen.cpp
index 0868f40b..facf4750 100644
--- a/editor/views/general/splashScreen.cpp
+++ b/editor/views/general/splashScreen.cpp
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
@@ -23,11 +24,11 @@ SplashScreen::SplashScreen(QWidget *parent)
setAttribute(Qt::WA_TranslucentBackground);
setModal(true);
setObjectName("atlasSplash");
- setFixedSize(708, 252);
+ setFixedSize(640, 280);
auto *card = new QFrame(this);
card->setObjectName("splashCard");
- card->setGeometry(0, 0, 708, 252);
+ card->setGeometry(0, 0, 640, 280);
auto *shadow = new QGraphicsDropShadowEffect(card);
shadow->setBlurRadius(20.0);
shadow->setOffset(0.0, 5.0);
@@ -36,41 +37,28 @@ SplashScreen::SplashScreen(QWidget *parent)
auto *icon = new QLabel(card);
icon->setObjectName("splashIcon");
- icon->setGeometry(30, 38, 108, 108);
-#ifdef ATLAS_DEBUG_BUILD
- icon->setPixmap(QPixmap(":/editor/assets/Icon-iOS-Default-1024x1024@1x.png")
- .scaled(icon->size(), Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#else
- icon->setPixmap(
- QPixmap(":/editor/assets/iconFile-iOS-Dark-1024x1024@1x.png")
- .scaled(icon->size(), Qt::KeepAspectRatio,
- Qt::SmoothTransformation));
-#endif
+ icon->setGeometry(30, 44, 104, 104);
+ icon->setPixmap(styling::brandMark(icon->size()));
auto *title = new QLabel(card);
title->setObjectName("splashTitle");
- title->setGeometry(164, 42, 514, 44);
+ title->setGeometry(158, 44, 444, 48);
QFont titleFont = title->font();
titleFont.setLetterSpacing(QFont::AbsoluteSpacing, -0.3);
titleFont.setKerning(true);
-#ifdef ATLAS_RELEASE_BUILD
title->setText("Atlas Engine");
-#else
- title->setText("Atlas Engine (Development)");
title->setFont(titleFont);
-#endif
title->setWordWrap(false);
title->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
auto *version = new QLabel(card);
version->setObjectName("splashVersion");
- version->setGeometry(164, 86, 500, 28);
+ version->setGeometry(160, 100, 440, 24);
#ifdef ATLAS_RELEASE_BUILD
version->setText(QStringLiteral(ATLAS_VERSION));
#else
- version->setText(QStringLiteral("%1 (build %2)")
+ version->setText(QStringLiteral("%1 · Development %2")
.arg(QStringLiteral(ATLAS_VERSION),
QStringLiteral(ATLAS_BUILD_STRING)));
#endif
@@ -78,85 +66,28 @@ SplashScreen::SplashScreen(QWidget *parent)
auto *company = new QLabel("by neutral software", card);
company->setObjectName("splashCompany");
- company->setGeometry(164, 114, 400, 22);
+ company->setGeometry(160, 128, 440, 22);
company->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
statusLabel = new QLabel("Loading the engine…", card);
statusLabel->setObjectName("splashStatus");
- statusLabel->setGeometry(164, 151, 500, 22);
+ statusLabel->setGeometry(36, 198, 568, 24);
statusLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
auto *progress = new QProgressBar(card);
progress->setObjectName("splashProgress");
- progress->setGeometry(164, 181, 500, 5);
+ progress->setGeometry(36, 232, 568, 4);
progress->setRange(0, 0);
progress->setTextVisible(false);
#ifndef ATLAS_RELEASE_BUILD
- auto *warning = new QLabel(
- "As this software is in its development version issues may be found "
- "with the experience. If you meant to use the traditional version "
- "please access: https://atlasengine.org to get the official builds. "
- "In development versions, the engine may require you to have a "
- "runtime already installed therefore, make sure that you have an "
- "appropriate runtime in your system that works with this version.",
- card);
+ auto *warning = new QLabel("Development build · atlasengine.org", card);
warning->setObjectName("splashWarning");
- warning->setGeometry(40, 199, 628, 44);
+ warning->setGeometry(36, 246, 568, 20);
warning->setWordWrap(true);
warning->setAlignment(Qt::AlignLeft | Qt::AlignTop);
#endif
- setStyleSheet(R"(
-#atlasSplash {
- background: transparent;
-}
-#splashCard {
- background: #202224;
- border: 1px solid #494D52;
- border-radius: 18px;
-}
-#splashTitle {
- background: transparent;
- color: #F5F7FA;
- font-size: 34px;
- font-weight: 750;
-}
-#splashVersion {
- background: transparent;
- color: #8498A8;
- font-size: 14px;
- font-weight: 700;
-}
-#splashCompany {
- background: transparent;
- color: #7F8B9D;
- font-family: "Manrope";
- font-size: 12px;
- font-weight: 650;
-}
-#splashStatus {
- background: transparent;
- color: #B7C1CF;
- font-size: 10px;
- font-weight: 550;
-}
-#splashProgress {
- background: #34373A;
- border: none;
- border-radius: 2px;
-}
-#splashProgress::chunk {
- background: #71889A;
- border-radius: 2px;
-}
-#splashWarning {
- background: transparent;
- color: #68758A;
- font-size: 9px;
- font-weight: 450;
-}
-)");
}
void SplashScreen::start(const QString &statusText) {
diff --git a/include/atlas/runtime/context.h b/include/atlas/runtime/context.h
index a5f789f0..319e530a 100644
--- a/include/atlas/runtime/context.h
+++ b/include/atlas/runtime/context.h
@@ -89,6 +89,7 @@ class Context {
bool cameraAutomaticMoving = false;
bool editorCameraFocused = false;
bool editorRuntime = false;
+ bool editorPathTracingPreview = true;
bool materialPreviewRuntime = false;
float materialPreviewYaw = 0.0f;
float materialPreviewPitch = 0.0f;
diff --git a/include/editor/core/themes.h b/include/editor/core/themes.h
index 451ecf9b..7915d3f7 100644
--- a/include/editor/core/themes.h
+++ b/include/editor/core/themes.h
@@ -7,154 +7,60 @@
inline constexpr const char* DARK_THEME =
"* {\n"
" font-family: \"SF Pro Text\", \"Inter\", \"Segoe UI\", \"Arial\";\n"
-" font-size: 11px;\n"
-" color: #D6D6D6;\n"
-" selection-background-color: #4772B3;\n"
-" selection-color: #FFFFFF;\n"
+" font-size: 13px;\n"
+" color: #C5C5BE;\n"
+" selection-background-color: #353532;\n"
+" selection-color: #F1F1EC;\n"
"}\n"
"\n"
"QWidget {\n"
-" background-color: #1C1C1C;\n"
-" color: #D6D6D6;\n"
+" background: #191918;\n"
"}\n"
"\n"
"QMainWindow,\n"
"QDialog,\n"
-"QFrame {\n"
-" background-color: #1C1C1C;\n"
+"#editorFrame,\n"
+"#projectBrowserRoot {\n"
+" background: #121211;\n"
"}\n"
"\n"
-"QLabel {\n"
+"QLabel,\n"
+"QCheckBox,\n"
+"QRadioButton,\n"
+"QToolButton,\n"
+"QPushButton {\n"
" background: transparent;\n"
"}\n"
"\n"
"QLabel:disabled {\n"
-" color: #566174;\n"
-"}\n"
-"\n"
-"QToolTip {\n"
-" background-color: #303030;\n"
-" color: #F7F9FC;\n"
-" border: 1px solid #505050;\n"
-" border-radius: 4px;\n"
-" padding: 4px 6px;\n"
-"}\n"
-"\n"
-"QGroupBox {\n"
-" background-color: #242424;\n"
-" border: 1px solid #3B3B3B;\n"
-" border-radius: 4px;\n"
-" margin-top: 13px;\n"
-" padding: 7px;\n"
-" color: #F1F4F8;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"QGroupBox::title {\n"
-" subcontrol-origin: margin;\n"
-" subcontrol-position: top left;\n"
-" left: 9px;\n"
-" padding: 0 6px;\n"
-" color: #AEB8C8;\n"
-" background-color: #242424;\n"
-"}\n"
-"\n"
-"QScrollArea,\n"
-"QAbstractScrollArea {\n"
-" background-color: #202020;\n"
-" border: none;\n"
-"}\n"
-"\n"
-"QAbstractScrollArea::corner {\n"
-" background-color: #202020;\n"
-"}\n"
-"\n"
-"QScrollBar:vertical {\n"
-" background-color: transparent;\n"
-" width: 9px;\n"
-" margin: 2px;\n"
-" border: none;\n"
-"}\n"
-"\n"
-"QScrollBar:horizontal {\n"
-" background-color: transparent;\n"
-" height: 9px;\n"
-" margin: 2px;\n"
-" border: none;\n"
-"}\n"
-"\n"
-"QScrollBar::handle:vertical,\n"
-"QScrollBar::handle:horizontal {\n"
-" background-color: #4A4A4A;\n"
-" border-radius: 4px;\n"
-" min-height: 30px;\n"
-" min-width: 30px;\n"
-"}\n"
-"\n"
-"QScrollBar::handle:vertical:hover,\n"
-"QScrollBar::handle:horizontal:hover {\n"
-" background-color: #666666;\n"
+" color: #62625D;\n"
"}\n"
"\n"
-"QScrollBar::add-line,\n"
-"QScrollBar::sub-line,\n"
-"QScrollBar::add-page,\n"
-"QScrollBar::sub-page {\n"
-" background: none;\n"
-" border: none;\n"
-" width: 0;\n"
-" height: 0;\n"
+"QLabel[muted=\"true\"] {\n"
+" color: #92928B;\n"
"}\n"
"\n"
"QPushButton,\n"
"QToolButton {\n"
-" background-color: #303030;\n"
-" border: 1px solid #464646;\n"
-" border-radius: 3px;\n"
-" padding: 3px 8px;\n"
-" color: #D8D8D8;\n"
-" min-height: 22px;\n"
-" font-weight: 500;\n"
+" border: none;\n"
+" border-radius: 7px;\n"
+" padding: 5px 10px;\n"
+" min-height: 24px;\n"
"}\n"
"\n"
"QPushButton:hover,\n"
"QToolButton:hover {\n"
-" background-color: #3A3A3A;\n"
-" border-color: #606060;\n"
-"}\n"
-"\n"
-"QPushButton:pressed,\n"
-"QToolButton:pressed {\n"
-" background-color: #242424;\n"
-" border-color: #4772B3;\n"
+" background: #292928;\n"
"}\n"
"\n"
"QPushButton:checked,\n"
"QToolButton:checked {\n"
-" background-color: #3B5F8A;\n"
-" border-color: #5D8BC0;\n"
-" color: #FFFFFF;\n"
-"}\n"
-"\n"
-"QPushButton:default,\n"
-"#primaryAction {\n"
-" background-color: #4772B3;\n"
-" border-color: #6791C9;\n"
-" color: #FFFFFF;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"QPushButton:default:hover,\n"
-"#primaryAction:hover {\n"
-" background-color: #5682C2;\n"
-" border-color: #7AA1D4;\n"
+" background: #30302E;\n"
"}\n"
"\n"
"QPushButton:disabled,\n"
"QToolButton:disabled {\n"
-" background-color: #242424;\n"
-" border-color: #333333;\n"
-" color: #686868;\n"
+" color: #646460;\n"
"}\n"
"\n"
"QToolButton::menu-indicator {\n"
@@ -163,1015 +69,670 @@ inline constexpr const char* DARK_THEME =
"\n"
"QLineEdit,\n"
"QTextEdit,\n"
-"QPlainTextEdit,\n"
+"QPlainTextEdit {\n"
+" background: #20201F;\n"
+" border: 1px solid transparent;\n"
+" border-radius: 6px;\n"
+" padding: 7px 9px;\n"
+" selection-background-color: #42423E;\n"
+"}\n"
+"\n"
+"QLineEdit:hover,\n"
+"QTextEdit:hover,\n"
+"QPlainTextEdit:hover {\n"
+" background: #242423;\n"
+"}\n"
+"\n"
+"QLineEdit:focus,\n"
+"QTextEdit:focus,\n"
+"QPlainTextEdit:focus {\n"
+" border-color: #53534D;\n"
+"}\n"
+"\n"
+"QLineEdit:disabled,\n"
+"QTextEdit:disabled,\n"
+"QPlainTextEdit:disabled {\n"
+" color: #666660;\n"
+"}\n"
+"\n"
"QComboBox,\n"
"QSpinBox,\n"
"QDoubleSpinBox,\n"
"QDateEdit,\n"
"QTimeEdit,\n"
"QDateTimeEdit {\n"
-" background-color: #181818;\n"
-" border: 1px solid #3D3D3D;\n"
-" border-radius: 3px;\n"
-" padding: 3px 7px;\n"
-" color: #E2E2E2;\n"
-" min-height: 22px;\n"
+" background: #252524;\n"
+" border: 1px solid transparent;\n"
+" border-radius: 5px;\n"
+" min-height: 24px;\n"
+" padding: 3px 8px;\n"
+" color: #D3D3CC;\n"
"}\n"
"\n"
-"QLineEdit:hover,\n"
-"QTextEdit:hover,\n"
-"QPlainTextEdit:hover,\n"
"QComboBox:hover,\n"
"QSpinBox:hover,\n"
"QDoubleSpinBox:hover {\n"
-" border-color: #5A5A5A;\n"
+" background: #2B2B29;\n"
"}\n"
"\n"
-"QLineEdit:focus,\n"
-"QTextEdit:focus,\n"
-"QPlainTextEdit:focus,\n"
"QComboBox:focus,\n"
"QSpinBox:focus,\n"
"QDoubleSpinBox:focus {\n"
-" background-color: #222222;\n"
-" border-color: #5D8BC0;\n"
+" border-color: #666660;\n"
"}\n"
"\n"
-"QLineEdit:disabled,\n"
-"QTextEdit:disabled,\n"
"QComboBox:disabled,\n"
"QSpinBox:disabled,\n"
"QDoubleSpinBox:disabled {\n"
-" background-color: #202020;\n"
-" border-color: #303030;\n"
-" color: #666666;\n"
+" color: #666660;\n"
"}\n"
"\n"
"QComboBox {\n"
-" padding-right: 24px;\n"
+" padding-right: 28px;\n"
"}\n"
"\n"
"QComboBox::drop-down {\n"
-" subcontrol-origin: padding;\n"
-" subcontrol-position: top right;\n"
-" width: 22px;\n"
-" border-left: 1px solid #3B3B3B;\n"
+" width: 26px;\n"
+" border: none;\n"
"}\n"
"\n"
-"QComboBox QAbstractItemView {\n"
-" background-color: #292929;\n"
-" border: 1px solid #4B4B4B;\n"
-" border-radius: 4px;\n"
-" padding: 3px;\n"
-" selection-background-color: #3B5F8A;\n"
+"QComboBox::down-arrow,\n"
+"QAbstractSpinBox::down-arrow {\n"
+" image: url(:/editor/assets/chevron-down.svg);\n"
+" width: 12px;\n"
+" height: 12px;\n"
+"}\n"
+"\n"
+"QAbstractSpinBox::up-arrow {\n"
+" image: url(:/editor/assets/chevron-up.svg);\n"
+" width: 12px;\n"
+" height: 12px;\n"
"}\n"
"\n"
"QAbstractSpinBox::up-button,\n"
"QAbstractSpinBox::down-button {\n"
-" background-color: #292929;\n"
+" background: transparent;\n"
" border: none;\n"
-" width: 16px;\n"
+" width: 18px;\n"
"}\n"
"\n"
-"QAbstractSpinBox::up-button:hover,\n"
-"QAbstractSpinBox::down-button:hover {\n"
-" background-color: #3E3E3E;\n"
+"QComboBox QAbstractItemView {\n"
+" background: #222221;\n"
+" border: 1px solid #393936;\n"
+" border-radius: 8px;\n"
+" padding: 5px;\n"
"}\n"
"\n"
"QCheckBox,\n"
"QRadioButton {\n"
-" spacing: 7px;\n"
-" color: #C9D1DE;\n"
+" spacing: 9px;\n"
"}\n"
"\n"
-"QCheckBox::indicator,\n"
-"QRadioButton::indicator {\n"
-" width: 15px;\n"
-" height: 15px;\n"
-" background-color: #171717;\n"
-" border: 1px solid #555555;\n"
-" border-radius: 3px;\n"
+"QCheckBox::indicator {\n"
+" width: 16px;\n"
+" height: 16px;\n"
+" border: 1px solid #55554F;\n"
+" border-radius: 4px;\n"
+" background: #232322;\n"
"}\n"
"\n"
-"QCheckBox::indicator:hover,\n"
-"QRadioButton::indicator:hover {\n"
-" border-color: #777777;\n"
+"QCheckBox::indicator:hover {\n"
+" border-color: #999991;\n"
+"}\n"
+"\n"
+"QCheckBox::indicator:checked {\n"
+" image: url(:/editor/assets/check.svg);\n"
+" background: #74746C;\n"
+" border-color: #999991;\n"
+"}\n"
+"\n"
+"QCheckBox::indicator:indeterminate {\n"
+" background: #999991;\n"
+" border: 4px solid #44443F;\n"
+"}\n"
+"\n"
+"QRadioButton::indicator {\n"
+" width: 16px;\n"
+" height: 16px;\n"
+" background: #232322;\n"
+" border: 1px solid #55554F;\n"
+" border-radius: 9px;\n"
"}\n"
"\n"
-"QCheckBox::indicator:checked,\n"
"QRadioButton::indicator:checked {\n"
-" background-color: #4772B3;\n"
-" border-color: #6D98CE;\n"
+" width: 8px;\n"
+" height: 8px;\n"
+" background: #DDDDD5;\n"
+" border: 5px solid #55554F;\n"
+" border-radius: 9px;\n"
"}\n"
"\n"
"QSlider::groove:horizontal {\n"
-" background-color: #353535;\n"
-" height: 4px;\n"
-" border-radius: 2px;\n"
+" height: 3px;\n"
+" background: #343431;\n"
+" border-radius: 1px;\n"
+"}\n"
+"\n"
+"QSlider::sub-page:horizontal {\n"
+" background: #93938A;\n"
+" border-radius: 1px;\n"
"}\n"
"\n"
"QSlider::handle:horizontal {\n"
-" background-color: #5D8BC0;\n"
-" border: 2px solid #A0B9D7;\n"
-" width: 12px;\n"
-" margin: -5px 0;\n"
-" border-radius: 7px;\n"
+" background: #D5D5CD;\n"
+" border: none;\n"
+" width: 10px;\n"
+" margin: -4px 0;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
"QProgressBar {\n"
-" background-color: #262626;\n"
-" border: 1px solid #424242;\n"
+" background: #292927;\n"
+" border: none;\n"
" border-radius: 3px;\n"
-" height: 8px;\n"
+" min-height: 6px;\n"
" text-align: center;\n"
+" color: #F1F1EC;\n"
"}\n"
"\n"
"QProgressBar::chunk {\n"
-" background-color: #4772B3;\n"
+" background: #76766D;\n"
+" border-radius: 3px;\n"
+"}\n"
+"\n"
+"QScrollArea,\n"
+"QAbstractScrollArea {\n"
+" background: #191918;\n"
+" border: none;\n"
+"}\n"
+"\n"
+"QAbstractScrollArea::corner {\n"
+" background: transparent;\n"
+"}\n"
+"\n"
+"QScrollBar:vertical {\n"
+" background: transparent;\n"
+" border: none;\n"
+" width: 8px;\n"
+" margin: 3px 1px;\n"
+"}\n"
+"\n"
+"QScrollBar:horizontal {\n"
+" background: transparent;\n"
+" border: none;\n"
+" height: 8px;\n"
+" margin: 1px 3px;\n"
+"}\n"
+"\n"
+"QScrollBar::handle:vertical,\n"
+"QScrollBar::handle:horizontal {\n"
+" background: #3B3B36;\n"
" border-radius: 3px;\n"
+" min-height: 32px;\n"
+" min-width: 32px;\n"
+"}\n"
+"\n"
+"QScrollBar::handle:vertical:hover,\n"
+"QScrollBar::handle:horizontal:hover {\n"
+" background: #606059;\n"
+"}\n"
+"\n"
+"QScrollBar::add-line,\n"
+"QScrollBar::sub-line,\n"
+"QScrollBar::add-page,\n"
+"QScrollBar::sub-page {\n"
+" border: none;\n"
+" background: transparent;\n"
+" width: 0;\n"
+" height: 0;\n"
"}\n"
"\n"
"QTreeView,\n"
"QListView,\n"
-"QListWidget,\n"
-"QTableView,\n"
-"QTableWidget {\n"
-" background-color: #202020;\n"
-" alternate-background-color: #242424;\n"
+"QTableView {\n"
+" background: #191918;\n"
" border: none;\n"
-" color: #DCE3EC;\n"
+" outline: none;\n"
+" alternate-background-color: #1D1D1C;\n"
" show-decoration-selected: 1;\n"
"}\n"
"\n"
"QTreeView::item,\n"
"QListView::item,\n"
-"QListWidget::item,\n"
-"QTableView::item,\n"
-"QTableWidget::item {\n"
-" border: 1px solid transparent;\n"
-" border-radius: 2px;\n"
-" padding: 3px 5px;\n"
-"}\n"
-"\n"
-"QTreeView::item:hover,\n"
-"QListView::item:hover,\n"
-"QListWidget::item:hover,\n"
-"QTableView::item:hover,\n"
-"QTableWidget::item:hover {\n"
-" background-color: #303030;\n"
-" border-color: #464646;\n"
+"QTableView::item {\n"
+" border: none;\n"
+" padding: 5px 8px;\n"
"}\n"
"\n"
"QTreeView::item:selected,\n"
"QListView::item:selected,\n"
-"QListWidget::item:selected,\n"
-"QTableView::item:selected,\n"
-"QTableWidget::item:selected {\n"
-" background-color: #3B5F8A;\n"
-" border-color: #5D8BC0;\n"
-" color: #FFFFFF;\n"
+"QTableView::item:selected {\n"
+" background: #30302E;\n"
+" color: #F1F1EC;\n"
"}\n"
"\n"
-"QHeaderView {\n"
-" background-color: #202020;\n"
+"QHeaderView::section {\n"
+" background: #191918;\n"
+" border: none;\n"
+" border-bottom: 1px solid #2B2B28;\n"
+" color: #92928B;\n"
+" padding: 9px;\n"
+" font-weight: 400;\n"
"}\n"
"\n"
-"QHeaderView::section {\n"
-" background-color: #292929;\n"
+"QGroupBox {\n"
+" background: transparent;\n"
" border: none;\n"
-" border-right: 1px solid #404040;\n"
-" border-bottom: 1px solid #404040;\n"
-" padding: 5px 7px;\n"
-" color: #98A4B7;\n"
-" font-weight: 600;\n"
+" border-top: 1px solid #2B2B28;\n"
+" margin-top: 26px;\n"
+" padding: 14px 2px 6px 2px;\n"
+" font-weight: 500;\n"
+"}\n"
+"\n"
+"QGroupBox::title {\n"
+" subcontrol-origin: margin;\n"
+" subcontrol-position: top left;\n"
+" padding: 0;\n"
+" color: #DDDDD6;\n"
"}\n"
"\n"
"QTabWidget::pane {\n"
-" background-color: #202020;\n"
-" border: 1px solid #3B3B3B;\n"
-" border-radius: 0;\n"
+" background: #191918;\n"
+" border: none;\n"
+"}\n"
+"\n"
+"QTabBar {\n"
+" background: transparent;\n"
"}\n"
"\n"
"QTabBar::tab {\n"
-" background-color: #252525;\n"
+" background: transparent;\n"
" border: none;\n"
-" border-right: 1px solid #393939;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-" color: #7F8B9D;\n"
-" min-width: 88px;\n"
-" padding: 5px 10px;\n"
-" margin: 1px 0;\n"
-" border-radius: 0;\n"
+" color: #92928B;\n"
+" padding: 9px 16px;\n"
+" margin: 4px 3px;\n"
+" border-radius: 6px;\n"
"}\n"
"\n"
-"QTabBar::tab:hover {\n"
-" background-color: #303030;\n"
-" color: #C8D1DF;\n"
+"QTabBar::tab:selected {\n"
+" background: #2B2B29;\n"
+" color: #EAEAE3;\n"
"}\n"
"\n"
-"QTabBar::tab:selected {\n"
-" background-color: #333333;\n"
-" color: #F2F5F9;\n"
-" border-bottom: 2px solid #5D8BC0;\n"
+"QTabBar::tab:hover {\n"
+" color: #EAEAE3;\n"
"}\n"
"\n"
-"QMenuBar#atlasMenuBar {\n"
-" background-color: #181818;\n"
-" border-bottom: 1px solid #303030;\n"
-" padding: 1px 6px;\n"
+"QMenuBar {\n"
+" background: #121211;\n"
+" border: none;\n"
+" padding: 3px 10px;\n"
"}\n"
"\n"
-"QMenuBar#atlasMenuBar::item {\n"
+"QMenuBar::item {\n"
" background: transparent;\n"
-" color: #B8C2D0;\n"
" padding: 5px 9px;\n"
-" border-radius: 3px;\n"
"}\n"
"\n"
-"QMenuBar#atlasMenuBar::item:selected,\n"
-"QMenuBar#atlasMenuBar::item:pressed {\n"
-" background-color: #343434;\n"
-" color: #FFFFFF;\n"
+"QMenuBar::item:selected {\n"
+" background: #2B2B29;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
"QMenu {\n"
-" background-color: #292929;\n"
-" border: 1px solid #515151;\n"
-" border-radius: 4px;\n"
-" padding: 4px;\n"
+" background: #20201F;\n"
+" border: 1px solid #393936;\n"
+" border-radius: 8px;\n"
+" padding: 6px;\n"
"}\n"
"\n"
"QMenu::item {\n"
" background: transparent;\n"
-" border-radius: 2px;\n"
-" padding: 6px 32px 6px 9px;\n"
-" color: #DCE3EC;\n"
+" padding: 9px 34px 9px 12px;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
"QMenu::item:selected {\n"
-" background-color: #3B5F8A;\n"
-" color: #FFFFFF;\n"
+" background: #33332F;\n"
"}\n"
"\n"
"QMenu::item:disabled {\n"
-" color: #596477;\n"
+" color: #64645E;\n"
"}\n"
"\n"
"QMenu::separator {\n"
-" background-color: #424242;\n"
+" background: #343431;\n"
" height: 1px;\n"
-" margin: 5px 8px;\n"
+" margin: 6px 10px;\n"
"}\n"
"\n"
-"QSplitter::handle {\n"
-" background-color: #111111;\n"
-"}\n"
-"\n"
-"QSplitter::handle:horizontal {\n"
-" width: 4px;\n"
+"QToolTip {\n"
+" background: #292927;\n"
+" color: #E1E1DA;\n"
+" border: 1px solid #44443E;\n"
+" border-radius: 5px;\n"
+" padding: 6px 9px;\n"
"}\n"
"\n"
-"QSplitter::handle:vertical {\n"
-" height: 4px;\n"
+"QSplitter::handle {\n"
+" background: #121211;\n"
"}\n"
"\n"
"QSplitter::handle:hover {\n"
-" background-color: #5D8BC0;\n"
+" background: #41413C;\n"
"}\n"
"\n"
"QStatusBar {\n"
-" background-color: #181818;\n"
-" border-top: 1px solid #303030;\n"
-" color: #8490A4;\n"
+" background: #121211;\n"
+" color: #888882;\n"
+" border: none;\n"
+" padding: 3px 14px;\n"
+" min-height: 24px;\n"
+" font-size: 11px;\n"
+"}\n"
+"\n"
+"QStatusBar::item {\n"
+" border: none;\n"
"}\n"
"\n"
-"#atlasStatusBar {\n"
-" min-height: 23px;\n"
-" padding: 0 6px;\n"
+"#workspaceBar,\n"
+"#workspaceChrome,\n"
+"#workspaceIdentity,\n"
+"#workspaceIdentityText,\n"
+"#workspaceActivity,\n"
+"#workspaceUtilities {\n"
+" background: #121211;\n"
+" border: none;\n"
"}\n"
"\n"
-"#statusRuntimeIcon {\n"
+"#workspaceBar {\n"
" padding: 0;\n"
+" spacing: 0;\n"
"}\n"
"\n"
-"#statusRuntime {\n"
-" background: transparent;\n"
-" border-right: 1px solid #343434;\n"
+"#workspaceProject {\n"
+" color: #D7D7D0;\n"
+" font-size: 13px;\n"
"}\n"
"\n"
-"#statusRuntimeText {\n"
-" color: #9BA79F;\n"
-" font-size: 10px;\n"
+"#workspaceSwitcher,\n"
+"#workspaceSurface,\n"
+"#workspaceHeading,\n"
+"#editorWorkspaceStack {\n"
+" background: #191918;\n"
+" border: none;\n"
"}\n"
"\n"
-"#statusRenderer {\n"
-" background-color: #292929;\n"
-" border: 1px solid #454545;\n"
-" border-radius: 3px;\n"
-" color: #B6BCB8;\n"
-" font-size: 9px;\n"
-" font-weight: 700;\n"
-" padding: 2px 6px;\n"
+"#workspaceHeading {\n"
+" border-bottom: 1px solid #282825;\n"
"}\n"
"\n"
-"#statusVersion {\n"
-" color: #68758A;\n"
-" font-size: 9px;\n"
-" padding: 0 6px;\n"
+"#workspaceSwitcher {\n"
+" padding: 0;\n"
"}\n"
"\n"
-"#workspaceBar {\n"
-" background-color: #202020;\n"
+"#workspaceMark {\n"
+" background: transparent;\n"
" border: none;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-" spacing: 4px;\n"
-" padding: 3px 6px 3px 0;\n"
-" min-height: 38px;\n"
"}\n"
"\n"
-"#workspaceIdentity {\n"
+"#workspaceContextPath,\n"
+"#statusVersion,\n"
+"#statusRenderer,\n"
+"#statusRuntimeText,\n"
+"#viewportFpsLabel,\n"
+"#viewportShortcutHint {\n"
" background: transparent;\n"
-" border-right: 1px solid #424242;\n"
+" color: #898982;\n"
+" font-size: 11px;\n"
+" border: none;\n"
"}\n"
"\n"
-"#workspaceMark {\n"
-" background-color: #292929;\n"
-" border: 1px solid #3F3F3F;\n"
-" border-radius: 4px;\n"
-" padding: 3px;\n"
+"#statusRuntime {\n"
+" background: transparent;\n"
"}\n"
"\n"
-"#workspaceIdentityText {\n"
-" background: transparent;\n"
+"#sceneTabs {\n"
+" background: #191918;\n"
+" border: none;\n"
"}\n"
"\n"
-"#workspaceBrand {\n"
-" color: #8C8C8C;\n"
-" font-size: 8px;\n"
-" font-weight: 750;\n"
+"#sceneTabs::tab {\n"
+" padding: 9px 14px;\n"
+" min-width: 92px;\n"
"}\n"
"\n"
-"#workspaceProject {\n"
-" color: #EFEFEF;\n"
-" font-size: 12px;\n"
-" font-weight: 650;\n"
+"#viewportTools {\n"
+" background: #191918;\n"
"}\n"
"\n"
-"#workspaceSwitcher {\n"
-" background-color: #181818;\n"
-" border: 1px solid #383838;\n"
-" border-radius: 4px;\n"
-" margin-left: 7px;\n"
+"#viewportToolbar,\n"
+"#panelToolbar,\n"
+"#materialEditorHeader,\n"
+"#postProcessingToolbar,\n"
+"#workspaceToolbar {\n"
+" background: #191918;\n"
+" border: none;\n"
"}\n"
"\n"
-"#workspaceModeButton {\n"
-" background-color: #222222;\n"
-" border: 1px solid transparent;\n"
-" border-radius: 3px;\n"
-" color: #A0A0A0;\n"
-" padding: 3px 9px;\n"
-" min-height: 22px;\n"
+"#hierarchySearch,\n"
+"#contentSearchField {\n"
+" background: #222221;\n"
+" padding: 6px 9px;\n"
"}\n"
"\n"
-"#workspaceModeButton:hover {\n"
-" background-color: #333333;\n"
-" color: #E2E2E2;\n"
+"#contentPathField {\n"
+" background: transparent;\n"
+" border: none;\n"
+" color: #A7A7A0;\n"
"}\n"
"\n"
-"#workspaceModeButton:checked {\n"
-" background-color: #3B5F8A;\n"
-" border-color: #5D8BC0;\n"
-" color: #FFFFFF;\n"
+"#inspectorScroll,\n"
+"#inspectorContent,\n"
+"#materialEditorBody,\n"
+"#postProcessingBody,\n"
+"#environmentPages,\n"
+"#environmentWorkspace,\n"
+"#environmentPage {\n"
+" background: #191918;\n"
+" border: none;\n"
"}\n"
"\n"
-"#workspaceCommandButton,\n"
-"#workspaceUtilityButton,\n"
-"#workspaceBuildButton,\n"
-"#workspaceLaunchButton {\n"
-" min-width: 42px;\n"
-" padding: 3px 9px;\n"
-" margin-left: 2px;\n"
-" min-height: 24px;\n"
-"}\n"
-"\n"
-"#workspaceCommandButton,\n"
-"#workspaceUtilityButton,\n"
-"#workspaceBuildButton {\n"
-" background-color: #292929;\n"
-" border-color: #444444;\n"
-"}\n"
-"\n"
-"#workspaceLaunchButton {\n"
-" background-color: #3F684F;\n"
-" border-color: #5A8B6B;\n"
-" color: #FFFFFF;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"#workspaceCommandButton:hover,\n"
-"#workspaceUtilityButton:hover,\n"
-"#workspaceBuildButton:hover,\n"
-"#workspaceLaunchButton:hover {\n"
-" background-color: #3A3A3A;\n"
-" border-color: #606060;\n"
-"}\n"
-"\n"
-"#workspaceLaunchButton:hover {\n"
-" background-color: #4E7B5E;\n"
-" border-color: #6B9B79;\n"
-"}\n"
-"\n"
-"#workspaceContextBar {\n"
-" background-color: #292929;\n"
-" border: none;\n"
-" border-bottom: 1px solid #3C3C3C;\n"
-" spacing: 2px;\n"
-" padding: 1px 5px 1px 0;\n"
-" min-height: 27px;\n"
-"}\n"
-"\n"
-"#workspaceBreadcrumb {\n"
-" background: transparent;\n"
-" border-right: 1px solid #414141;\n"
-"}\n"
-"\n"
-"#workspaceContextIcon {\n"
+"#inspectorHeader {\n"
" background: transparent;\n"
-"}\n"
-"\n"
-"#workspaceContextTitle {\n"
-" color: #E0E0E0;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"#workspaceContextPath {\n"
-" color: #7F7F7F;\n"
-"}\n"
-"\n"
-"#workspacePanelButton {\n"
-" background-color: transparent;\n"
-" border-color: transparent;\n"
-" color: #8F8F8F;\n"
-" padding: 2px 7px;\n"
-" min-height: 20px;\n"
-"}\n"
-"\n"
-"#workspacePanelButton:hover {\n"
-" background-color: #363636;\n"
-" color: #DADADA;\n"
-"}\n"
-"\n"
-"#workspacePanelButton:checked {\n"
-" background-color: #333333;\n"
-" border-color: #4A4A4A;\n"
-" color: #EAEAEA;\n"
-"}\n"
-"\n"
-"#sceneTabs {\n"
-" background-color: #181818;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-"}\n"
-"\n"
-"#sceneTabs::tab {\n"
-" background-color: #242424;\n"
-" border-right: 1px solid #3A3A3A;\n"
-" color: #7F8B9D;\n"
-" min-width: 112px;\n"
-" padding: 5px 10px;\n"
-" margin: 0;\n"
-" border-radius: 0;\n"
-"}\n"
-"\n"
-"#sceneTabs::tab:selected {\n"
-" background-color: #333333;\n"
-" color: #F3F6FA;\n"
-" border-bottom: 2px solid #5D8BC0;\n"
-"}\n"
-"\n"
-"#viewportTools {\n"
-" background-color: #151515;\n"
-"}\n"
-"\n"
-"#viewportToolbar {\n"
-" background-color: #292929;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-"}\n"
-"\n"
-"#viewportPlaybackButton,\n"
-"#viewportModeButton,\n"
-"#viewportOptionButton,\n"
-"#viewportShadingButton {\n"
-" background-color: #292C2F;\n"
-" border-color: #414549;\n"
-" min-width: 25px;\n"
-" min-height: 22px;\n"
-" padding: 3px 5px;\n"
-"}\n"
-"\n"
-"#viewportPlaybackButton:hover,\n"
-"#viewportModeButton:hover,\n"
-"#viewportOptionButton:hover,\n"
-"#viewportShadingButton:hover {\n"
-" background-color: #363A3E;\n"
-" border-color: #5A5F65;\n"
-"}\n"
-"\n"
-"#viewportModeButton:checked,\n"
-"#viewportShadingButton:checked {\n"
-" background-color: #3A4248;\n"
-" border-color: #6F7B84;\n"
-"}\n"
-"\n"
-"#viewportFpsLabel {\n"
-" color: #9CA5A0;\n"
-" font-size: 10px;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"#viewportShortcutHint {\n"
-" background-color: #141517;\n"
-" border-top: 1px solid #303236;\n"
-" color: #68758A;\n"
-" font-size: 10px;\n"
-" padding: 3px 7px;\n"
-"}\n"
-"\n"
-"#panelToolbar,\n"
-"#materialEditorHeader,\n"
-"#postProcessingToolbar,\n"
-"#workspaceToolbar {\n"
-" background-color: #292929;\n"
-" border-bottom: 1px solid #404040;\n"
-" padding: 2px;\n"
-"}\n"
-"\n"
-"#panelAddButton,\n"
-"#materialSaveButton,\n"
-"#workspaceApplyButton {\n"
-" background-color: #333333;\n"
-" border-color: #4C4C4C;\n"
-" color: #D8DBDE;\n"
-"}\n"
-"\n"
-"#panelMoreButton,\n"
-"#browserNavigationButton,\n"
-"#browserRevealButton {\n"
-" background-color: transparent;\n"
-" border-color: transparent;\n"
-" min-width: 24px;\n"
-"}\n"
-"\n"
-"#panelMoreButton:hover,\n"
-"#browserNavigationButton:hover,\n"
-"#browserRevealButton:hover {\n"
-" background-color: #34373A;\n"
-" border-color: #484C50;\n"
-"}\n"
-"\n"
-"#contentPathField {\n"
-" background-color: #1B1D1F;\n"
-" color: #8490A4;\n"
-" font-size: 11px;\n"
-"}\n"
-"\n"
-"#contentSearchField {\n"
-" min-width: 130px;\n"
-"}\n"
-"\n"
-"QTreeView#hierarchyTree {\n"
-" background-color: #202020;\n"
-" border-top: 1px solid #303030;\n"
-" padding: 3px 2px;\n"
-"}\n"
-"\n"
-"QTreeView#hierarchyTree::item {\n"
-" min-height: 22px;\n"
-" padding: 1px 6px;\n"
-"}\n"
-"\n"
-"QTreeView#hierarchyTree::item:hover {\n"
-" background-color: #303030;\n"
-" border-color: #444444;\n"
-"}\n"
-"\n"
-"QTreeView#hierarchyTree::item:selected {\n"
-" background-color: #3B5F8A;\n"
-" border-color: #5D8BC0;\n"
-" color: #FFFFFF;\n"
-"}\n"
-"\n"
-"QListView#contentGrid {\n"
-" background-color: #1C1C1C;\n"
-" border-top: 1px solid #303030;\n"
-" padding: 5px;\n"
-"}\n"
-"\n"
-"QListView#contentGrid::item {\n"
-" background-color: #252525;\n"
-" border: 1px solid #363636;\n"
-" border-radius: 4px;\n"
-" padding: 6px;\n"
-" color: #BCC6D4;\n"
-"}\n"
-"\n"
-"QListView#contentGrid::item:hover {\n"
-" background-color: #303030;\n"
-" border-color: #505050;\n"
-"}\n"
-"\n"
-"QListView#contentGrid::item:selected {\n"
-" background-color: #3B5F8A;\n"
-" border-color: #5D8BC0;\n"
-" color: #FFFFFF;\n"
-"}\n"
-"\n"
-"QScrollArea#inspectorScroll,\n"
-"#inspectorContent,\n"
-"#materialEditorBody,\n"
-"#postProcessingBody {\n"
-" background-color: #202020;\n"
" border: none;\n"
-"}\n"
-"\n"
-"#inspectorHeader {\n"
-" background-color: #292929;\n"
-" border: 1px solid #414141;\n"
-" border-radius: 4px;\n"
-" padding: 5px;\n"
+" padding: 0;\n"
"}\n"
"\n"
"#inspectorObjectIcon {\n"
-" background-color: #343434;\n"
-" border: 1px solid #4E4E4E;\n"
-" border-radius: 4px;\n"
-" padding: 4px;\n"
+" background: transparent;\n"
+" border: none;\n"
"}\n"
"\n"
"#inspectorNameField {\n"
" background: transparent;\n"
" border: 1px solid transparent;\n"
-" color: #F3F6FA;\n"
-" font-size: 14px;\n"
-" font-weight: 700;\n"
+" color: #EAEAE3;\n"
+" font-size: 18px;\n"
+" font-weight: 500;\n"
+" padding: 2px 0;\n"
"}\n"
"\n"
-"#inspectorNameField:hover,\n"
"#inspectorNameField:focus {\n"
-" background-color: #202020;\n"
-" border-color: #5A5A5A;\n"
+" border-color: #55554F;\n"
"}\n"
"\n"
-"#inspectorTypeLabel {\n"
-" color: #7E8A9E;\n"
-" font-size: 10px;\n"
-" font-weight: 600;\n"
+"#inspectorTypeLabel,\n"
+"#inspectorPropertyLabel,\n"
+"#materialTexturePath,\n"
+"#materialEditorStatus,\n"
+"#postProcessingStatus,\n"
+"#workspaceStatus,\n"
+"#workspaceAutoApply {\n"
+" color: #93938C;\n"
+" font-size: 12px;\n"
"}\n"
"\n"
"#inspectorComponent {\n"
-" background-color: #242424;\n"
-" border: 1px solid #3D3D3D;\n"
-" border-radius: 3px;\n"
-" margin-top: 2px;\n"
-"}\n"
-"\n"
-"#inspectorComponentHeaderRow {\n"
-" background-color: #2D2D2D;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-" border-radius: 3px 3px 0 0;\n"
-"}\n"
-"\n"
-"#inspectorComponentHeader {\n"
" background: transparent;\n"
" border: none;\n"
-" color: #E8ECF2;\n"
-" font-weight: 650;\n"
-" text-align: left;\n"
-" padding: 4px 7px;\n"
-"}\n"
-"\n"
-"#inspectorComponentHeader:hover {\n"
-" background-color: #383838;\n"
+" border-top: 1px solid #2C2C29;\n"
+" border-radius: 0;\n"
"}\n"
"\n"
-"#inspectorComponentRemoveButton {\n"
+"#inspectorComponentHeaderRow,\n"
+"#inspectorComponentBody,\n"
+"#inspectorPropertyRow,\n"
+"#inspectorNestedGroup,\n"
+"#inspectorAudioControls {\n"
" background: transparent;\n"
" border: none;\n"
-" min-width: 22px;\n"
-"}\n"
-"\n"
-"#inspectorComponentRemoveButton:hover {\n"
-" background-color: #3A3031;\n"
-" border: 1px solid #695556;\n"
-"}\n"
-"\n"
-"#inspectorComponentBody {\n"
-" background-color: #242424;\n"
-" padding: 4px;\n"
-"}\n"
-"\n"
-"#inspectorPropertyRow {\n"
-" background: transparent;\n"
-" min-height: 27px;\n"
-"}\n"
-"\n"
-"#inspectorPropertyLabel {\n"
-" color: #929EB0;\n"
-" font-size: 11px;\n"
"}\n"
"\n"
"#inspectorVectorField,\n"
-"#inspectorColorField,\n"
-"#inspectorNumericField {\n"
-" background-color: #181818;\n"
-" border: 1px solid #3D3D3D;\n"
-" border-radius: 3px;\n"
+"#inspectorNumericField,\n"
+"#inspectorColorField {\n"
+" background: #252524;\n"
+" border: none;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
"#inspectorVectorField QDoubleSpinBox,\n"
"#inspectorNumericField QDoubleSpinBox {\n"
" background: transparent;\n"
" border: none;\n"
+" padding: 4px 2px;\n"
"}\n"
"\n"
"#inspectorAxisX,\n"
"#inspectorAxisY,\n"
"#inspectorAxisZ {\n"
-" border-radius: 2px;\n"
-" color: #F1F1F1;\n"
-" font-size: 9px;\n"
-" font-weight: 750;\n"
-" padding: 2px 5px;\n"
-"}\n"
-"\n"
-"#inspectorAxisX {\n"
-" background-color: #874747;\n"
-"}\n"
-"\n"
-"#inspectorAxisY {\n"
-" background-color: #477451;\n"
-"}\n"
-"\n"
-"#inspectorAxisZ {\n"
-" background-color: #435E86;\n"
-"}\n"
-"\n"
-"#inspectorSyncButton,\n"
-"#inspectorArrayButton {\n"
" background: transparent;\n"
-" border-color: transparent;\n"
-" min-width: 22px;\n"
+" font-size: 10px;\n"
+" padding: 0 3px;\n"
"}\n"
"\n"
-"#inspectorSyncButton[matched=\"true\"] {\n"
-" background-color: #343936;\n"
-" border-color: #555F59;\n"
-" color: #B6BEB9;\n"
-"}\n"
+"#inspectorAxisX { color: #CA9290; }\n"
+"#inspectorAxisY { color: #9AB696; }\n"
+"#inspectorAxisZ { color: #91A9C7; }\n"
"\n"
"#inspectorColorSwatch {\n"
-" background-color: #292929;\n"
-" border: 1px solid #4D4D4D;\n"
-" border-radius: 3px;\n"
+" border: 1px solid #45453F;\n"
+" border-radius: 4px;\n"
" padding: 2px;\n"
"}\n"
"\n"
"#inspectorColorText {\n"
-" color: #9CA8BA;\n"
-" font-family: \"Menlo\";\n"
-" font-size: 10px;\n"
-"}\n"
-"\n"
-"#inspectorNestedGroup {\n"
-" background-color: #202020;\n"
-" border: 1px solid #383838;\n"
-" border-radius: 3px;\n"
-" margin: 3px 0;\n"
-" padding: 5px;\n"
+" color: #B0B0A8;\n"
+" font-family: \"SF Mono\", \"Menlo\", \"Consolas\";\n"
+" font-size: 11px;\n"
"}\n"
"\n"
"#inspectorNestedTitle,\n"
-"#inspectorArrayTitle {\n"
-" color: #AEB8C8;\n"
-" font-weight: 650;\n"
+"#inspectorArrayTitle,\n"
+"#materialTextureLabel {\n"
+" color: #C9C9C1;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
"#inspectorEmptyTitle,\n"
"#materialEditorEmpty,\n"
"#postProcessingEmpty {\n"
-" color: #C4CDDA;\n"
-" font-size: 14px;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"#inspectorEmptyHint {\n"
-" color: #728096;\n"
-"}\n"
-"\n"
-"#inspectorOpenAssetButton,\n"
-"#inspectorAddComponentButton {\n"
-" background-color: #292929;\n"
-" border: 1px dashed #5A5A5A;\n"
-" color: #C7D0DD;\n"
-" padding: 6px;\n"
-"}\n"
-"\n"
-"#inspectorAddComponentButton:hover {\n"
-" background-color: #363636;\n"
-" border-color: #666666;\n"
-" color: #FFFFFF;\n"
+" color: #C7C7BF;\n"
+" font-size: 15px;\n"
+" font-weight: 400;\n"
"}\n"
"\n"
-"#inspectorAudioControls {\n"
-" background-color: #202020;\n"
-" border-radius: 3px;\n"
+"#inspectorEmptyHint,\n"
+"#environmentPageSubtitle,\n"
+"#dialogHeroSubtitle {\n"
+" color: #92928B;\n"
"}\n"
"\n"
"#materialEditorTitle,\n"
"#postProcessingTitle,\n"
"#postProcessingSectionTitle,\n"
-"#inspectorCameraTitle,\n"
-"#workspaceTitle {\n"
-" color: #F3F6FA;\n"
+"#workspaceTitle,\n"
+"#inspectorCameraTitle {\n"
+" color: #D9D9D2;\n"
" font-size: 13px;\n"
-" font-weight: 700;\n"
-"}\n"
-"\n"
-"#materialEditorStatus,\n"
-"#postProcessingStatus,\n"
-"#workspaceStatus,\n"
-"#workspaceAutoApply {\n"
-" color: #7E8A9E;\n"
-" font-size: 10px;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
"#materialPreview {\n"
-" background-color: #151515;\n"
-" border: 1px solid #444444;\n"
-" border-radius: 4px;\n"
-"}\n"
-"\n"
-"#materialColorButton {\n"
-" background-color: #292929;\n"
-" border-color: #454545;\n"
-" border-radius: 3px;\n"
-" color: #C9CDD0;\n"
-" text-align: left;\n"
-" padding: 4px 8px;\n"
-"}\n"
-"\n"
-"#materialColorButton:hover {\n"
-" background-color: #34383B;\n"
-" border-color: #5A5F65;\n"
+" background: #151514;\n"
+" border: none;\n"
+" border-radius: 8px;\n"
"}\n"
"\n"
"#materialTextureSlot {\n"
-" background-color: #252525;\n"
-" border: 1px solid #404040;\n"
-" border-radius: 4px;\n"
-" padding: 4px;\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 6px 0;\n"
"}\n"
"\n"
"#materialTexturePreview {\n"
-" background-color: #1A1A1A;\n"
-" border: 1px solid #494949;\n"
-" border-radius: 3px;\n"
-" color: #9E897D;\n"
-" font-weight: 750;\n"
-"}\n"
-"\n"
-"#materialTextureLabel {\n"
-" color: #D6DDE7;\n"
-" font-weight: 650;\n"
-"}\n"
-"\n"
-"#materialTexturePath {\n"
-" color: #7D899C;\n"
-"}\n"
-"\n"
-"#environmentPages,\n"
-"#environmentWorkspace,\n"
-"#environmentPage {\n"
-" background-color: #202020;\n"
+" background: #242423;\n"
" border: none;\n"
+" border-radius: 6px;\n"
"}\n"
"\n"
-"QListWidget#environmentCategories {\n"
-" background-color: #1B1B1B;\n"
-" border-right: 1px solid #3B3B3B;\n"
-" padding: 5px;\n"
-"}\n"
-"\n"
-"QListWidget#environmentCategories::item {\n"
-" padding: 6px 8px;\n"
-" margin: 2px 0;\n"
-"}\n"
-"\n"
-"QListWidget#environmentCategories::item:selected {\n"
-" background-color: #3B5F8A;\n"
-" border-left: 2px solid #5D8BC0;\n"
+"#environmentCategories {\n"
+" background: #191918;\n"
+" border: none;\n"
+" padding: 8px;\n"
"}\n"
"\n"
"#environmentPageTitle {\n"
-" color: #F3F6FA;\n"
-" font-size: 17px;\n"
-" font-weight: 750;\n"
-"}\n"
-"\n"
-"#environmentPageSubtitle {\n"
-" color: #778499;\n"
-"}\n"
-"\n"
-"QGroupBox#environmentSection {\n"
-" background-color: #242424;\n"
-" border-color: #3B3B3B;\n"
-"}\n"
-"\n"
-"ads--CDockContainerWidget {\n"
-" background-color: #111111;\n"
-"}\n"
-"\n"
-"ads--CDockContainerWidget > QSplitter {\n"
-" background-color: #111111;\n"
+" color: #E7E7E0;\n"
+" font-size: 22px;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
+"ads--CDockContainerWidget,\n"
+"ads--CDockContainerWidget > QSplitter,\n"
"ads--CDockContainerWidget ads--CDockSplitter::handle {\n"
-" background-color: #111111;\n"
-"}\n"
-"\n"
-"ads--CDockContainerWidget ads--CDockSplitter::handle:hover {\n"
-" background-color: #5D8BC0;\n"
-"}\n"
-"\n"
-"ads--CDockAreaWidget {\n"
-" background-color: #202020;\n"
-" border: 1px solid #343434;\n"
+" background: #121211;\n"
"}\n"
"\n"
+"ads--CDockAreaWidget,\n"
"ads--CDockAreaWidget[focused=\"true\"] {\n"
-" border-color: #4A6382;\n"
-"}\n"
-"\n"
-"ads--CDockAreaTitleBar {\n"
-" background-color: #292929;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-" min-height: 25px;\n"
+" background: #191918;\n"
+" border: none;\n"
+" border-radius: 9px;\n"
"}\n"
"\n"
+"ads--CDockAreaTitleBar,\n"
"ads--CDockAreaWidget[focused=\"true\"] ads--CDockAreaTitleBar {\n"
-" background-color: #2D2D2D;\n"
+" background: #191918;\n"
+" border: none;\n"
+" min-height: 40px;\n"
"}\n"
"\n"
"#tabsContainerWidget {\n"
-" background-color: transparent;\n"
-"}\n"
-"\n"
-"ads--CTitleBarButton {\n"
" background: transparent;\n"
-" border: none;\n"
-" border-radius: 2px;\n"
-" min-width: 22px;\n"
-" min-height: 22px;\n"
-" padding: 2px;\n"
-"}\n"
-"\n"
-"ads--CTitleBarButton:hover {\n"
-" background-color: #404040;\n"
-"}\n"
-"\n"
-"ads--CDockWidgetTab {\n"
-" background-color: #292929;\n"
-" border: none;\n"
-" border-right: 1px solid #3A3A3A;\n"
-" border-bottom: 1px solid #3B3B3B;\n"
-" padding: 1px 5px;\n"
-" margin: 1px 0;\n"
-" border-radius: 0;\n"
-"}\n"
-"\n"
-"ads--CDockWidgetTab:hover {\n"
-" background-color: #333333;\n"
-"}\n"
-"\n"
-"ads--CDockWidgetTab[activeTab=\"true\"] {\n"
-" background-color: #333333;\n"
-" border-bottom: 2px solid #5D8BC0;\n"
"}\n"
"\n"
+"ads--CDockWidgetTab,\n"
+"ads--CDockWidgetTab[activeTab=\"true\"],\n"
"ads--CDockWidgetTab[focused=\"true\"] {\n"
-" background-color: #303030;\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 3px 10px;\n"
+" margin: 3px;\n"
"}\n"
"\n"
"ads--CDockWidgetTab #dockWidgetTabLabel {\n"
-" color: #7F8B9D;\n"
-" font-size: 11px;\n"
-" padding: 4px 2px;\n"
+" color: #A1A19A;\n"
+" font-size: 13px;\n"
+" padding: 4px 0;\n"
"}\n"
"\n"
-"ads--CDockWidgetTab[activeTab=\"true\"] #dockWidgetTabLabel,\n"
-"ads--CDockWidgetTab[focused=\"true\"] #dockWidgetTabLabel {\n"
-" color: #F1F4F8;\n"
+"ads--CDockWidgetTab[activeTab=\"true\"] #dockWidgetTabLabel {\n"
+" color: #DADAD3;\n"
"}\n"
"\n"
+"ads--CTitleBarButton,\n"
"#tabCloseButton,\n"
"#dockAreaCloseButton,\n"
"#detachGroupButton,\n"
@@ -1180,305 +741,338 @@ inline constexpr const char* DARK_THEME =
"#tabsMenuButton {\n"
" background: transparent;\n"
" border: none;\n"
-" min-width: 20px;\n"
-" min-height: 20px;\n"
+" padding: 4px;\n"
+" min-width: 18px;\n"
+" min-height: 18px;\n"
"}\n"
"\n"
-"#tabCloseButton:hover,\n"
-"#dockAreaCloseButton:hover,\n"
-"#detachGroupButton:hover,\n"
-"#dockAreaAutoHideButton:hover,\n"
-"#dockAreaMinimizeButton:hover,\n"
-"#tabsMenuButton:hover {\n"
-" background-color: #424549;\n"
+"ads--CTitleBarButton:hover,\n"
+"#tabCloseButton:hover {\n"
+" background: #2B2B29;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
"ads--CDockWidget {\n"
-" background-color: #202020;\n"
+" background: #191918;\n"
"}\n"
"\n"
"ads--CAutoHideSideBar,\n"
"#sideTabsContainerWidget {\n"
-" background-color: #141517;\n"
+" background: #121211;\n"
"}\n"
"\n"
"ads--CAutoHideTab {\n"
-" background-color: #202224;\n"
-" border: 1px solid #404448;\n"
-" color: #7F8B9D;\n"
-" padding: 4px;\n"
-" border-radius: 8px;\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 7px;\n"
"}\n"
"\n"
-"ads--CAutoHideTab:hover,\n"
-"ads--CAutoHideTab[activeTab=\"true\"] {\n"
-" background-color: #393F44;\n"
-" border-color: #66737C;\n"
-" color: #FFFFFF;\n"
+"#projectSidebar {\n"
+" background: #121211;\n"
+" border: none;\n"
"}\n"
"\n"
-"#projectBrowserRoot,\n"
"#projectBrowserContent {\n"
-" background-color: #18191B;\n"
-"}\n"
-"\n"
-"#projectSidebar {\n"
-" background-color: #151618;\n"
-" border-right: 1px solid #303236;\n"
+" background: #191918;\n"
+" border: none;\n"
+" border-radius: 10px;\n"
"}\n"
"\n"
"#projectBrand {\n"
-" color: #F5F7FA;\n"
+" color: #E7E7E0;\n"
" font-size: 16px;\n"
-" font-weight: 750;\n"
-"}\n"
-"\n"
-"#projectSidebarVersion {\n"
-" color: #68758A;\n"
-" font-size: 10px;\n"
-" font-weight: 600;\n"
-"}\n"
-"\n"
-"#projectNavSelected {\n"
-" background-color: #34383C;\n"
-" border: 1px solid #51575C;\n"
-" border-left: 3px solid #79868F;\n"
-" border-radius: 10px;\n"
-" color: #DCE9FA;\n"
-" padding: 6px 9px;\n"
-" text-align: left;\n"
-"}\n"
-"\n"
-"#projectNavSelected:disabled {\n"
-" color: #DCE9FA;\n"
-"}\n"
-"\n"
-"#projectBrowserTitle,\n"
-"#dialogTitle {\n"
-" color: #F4F6FA;\n"
-" font-size: 24px;\n"
-" font-weight: 750;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
+"#projectSidebarVersion,\n"
+"#projectSidebarCaption,\n"
+"#projectPath,\n"
+"#projectDate,\n"
"#projectBrowserSubtitle,\n"
"#dialogSubtitle,\n"
"#emptyStateSubtitle,\n"
"#templateDescription {\n"
-" color: #7F8B9D;\n"
+" color: #92928B;\n"
+" font-size: 12px;\n"
"}\n"
"\n"
-"#projectSearch {\n"
-" background-color: #202224;\n"
-" border: 1px solid #43474B;\n"
-" border-radius: 11px;\n"
-" padding: 7px 9px;\n"
-" font-size: 13px;\n"
+"#projectBrowserTitle,\n"
+"#dialogTitle {\n"
+" color: #EAEAE4;\n"
+" font-size: 28px;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
-"#projectSearch:focus {\n"
-" border-color: #71808A;\n"
+"#projectSearch {\n"
+" background: #222221;\n"
+" padding: 10px 12px;\n"
"}\n"
"\n"
"#projectList {\n"
-" background-color: transparent;\n"
+" background: transparent;\n"
" border: none;\n"
"}\n"
"\n"
-"#projectList::item {\n"
+"#projectRow {\n"
" background: transparent;\n"
" border: none;\n"
-" padding: 0;\n"
+" border-radius: 7px;\n"
"}\n"
"\n"
-"#projectRow {\n"
-" background-color: #242628;\n"
-" border: 1px solid #3B3E41;\n"
-" border-radius: 13px;\n"
+"#projectRow:hover {\n"
+" background: #242423;\n"
"}\n"
"\n"
-"#projectRow:hover {\n"
-" background-color: #2C2F32;\n"
-" border-color: #565B61;\n"
+"#projectRow[selected=\"true\"] {\n"
+" background: #30302E;\n"
"}\n"
"\n"
-"#projectRow[available=\"false\"] {\n"
-" background-color: #202224;\n"
-" border-color: #303235;\n"
+"#projectName {\n"
+" color: #DEDED7;\n"
+" font-size: 14px;\n"
+" font-weight: 400;\n"
"}\n"
"\n"
"#projectIcon,\n"
"#templateIcon {\n"
-" background-color: #303337;\n"
-" border: 1px solid #484C50;\n"
-" border-radius: 10px;\n"
+" background: transparent;\n"
+" border: none;\n"
"}\n"
"\n"
-"#projectName {\n"
-" color: #EEF2F7;\n"
-" font-size: 14px;\n"
-" font-weight: 700;\n"
+"#rendererBadge {\n"
+" background: #262624;\n"
+" border: none;\n"
+" border-radius: 4px;\n"
+" color: #ABABA2;\n"
+" font-size: 10px;\n"
+" padding: 4px 7px;\n"
"}\n"
"\n"
-"#projectPath,\n"
-"#projectDate {\n"
-" color: #768398;\n"
-" font-size: 10px;\n"
+"#projectEmptyState {\n"
+" background: transparent;\n"
+" border: none;\n"
"}\n"
"\n"
-"#rendererBadge {\n"
-" background-color: #2C302E;\n"
-" border: 1px solid #494F4B;\n"
+"#emptyStateTitle {\n"
+" color: #CFCFC7;\n"
+" font-size: 20px;\n"
+" font-weight: 400;\n"
+"}\n"
+"\n"
+"QFrame[templateCard=\"true\"] {\n"
+" background: #20201F;\n"
+" border: 1px solid transparent;\n"
" border-radius: 8px;\n"
-" color: #B4BBB6;\n"
-" padding: 3px 7px;\n"
-" font-size: 9px;\n"
-" font-weight: 700;\n"
"}\n"
"\n"
-"#projectMoreButton {\n"
-" background: transparent;\n"
-" border-color: transparent;\n"
+"QFrame[templateCard=\"true\"][selected=\"true\"] {\n"
+" background: #2A2A28;\n"
+" border-color: #66665F;\n"
"}\n"
"\n"
-"#projectMoreButton:hover {\n"
-" background-color: #3E4246;\n"
-" border-color: #51565B;\n"
+"#templateOption,\n"
+"#fieldLabel {\n"
+" color: #BDBDB5;\n"
+" font-weight: 400;\n"
"}\n"
"\n"
-"#projectEmptyState {\n"
-" background-color: #1E2022;\n"
-" border: 1px dashed #484C51;\n"
-" border-radius: 14px;\n"
+"#dialogError {\n"
+" color: #D69C95;\n"
+" font-size: 12px;\n"
"}\n"
"\n"
-"#emptyStateTitle {\n"
-" color: #CDD5E1;\n"
-" font-size: 16px;\n"
-" font-weight: 700;\n"
+"#dialogHero {\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 2px;\n"
+"}\n"
+"\n"
+"#dialogHeroIcon {\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 4px;\n"
"}\n"
"\n"
-"#createProjectDialog {\n"
-" background-color: #1E2022;\n"
+"#dialogHeroTitle {\n"
+" color: #E3E3DB;\n"
+" font-size: 22px;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
-"QFrame[templateCard=\"true\"] {\n"
-" background-color: #242628;\n"
-" border: 1px solid #42464A;\n"
-" border-radius: 13px;\n"
+"#exportSummary {\n"
+" background: #1D1D1C;\n"
+" border: none;\n"
+" border-radius: 6px;\n"
+" color: #9C9C94;\n"
+" padding: 12px;\n"
"}\n"
"\n"
-"QFrame[templateCard=\"true\"]:hover {\n"
-" background-color: #2B2E31;\n"
-" border-color: #5A5F65;\n"
+"#exportLog,\n"
+"#runtimeErrors {\n"
+" background: #161615;\n"
+" border: none;\n"
+" padding: 12px;\n"
+" font-family: \"SF Mono\", \"Menlo\", \"Consolas\";\n"
+" font-size: 12px;\n"
+" color: #C3BAB1;\n"
"}\n"
"\n"
-"QFrame[templateCard=\"true\"][selected=\"true\"] {\n"
-" background-color: #393F44;\n"
-" border-color: #66737C;\n"
+"#commandPaletteDialog,\n"
+"#globalSearchDialog {\n"
+" background: #191918;\n"
+" border: 1px solid #373733;\n"
+" border-radius: 10px;\n"
"}\n"
"\n"
-"#templateOption {\n"
-" color: #E7ECF3;\n"
-" font-weight: 650;\n"
+"#commandPaletteSearch,\n"
+"#globalSearchField {\n"
+" background: transparent;\n"
+" border: none;\n"
+" border-bottom: 1px solid #30302C;\n"
+" border-radius: 0;\n"
+" padding: 15px 12px;\n"
+" font-size: 16px;\n"
"}\n"
"\n"
-"#fieldLabel {\n"
-" color: #AAB5C5;\n"
-" font-size: 11px;\n"
-" font-weight: 650;\n"
+"#commandPaletteList,\n"
+"#globalSearchResults {\n"
+" background: transparent;\n"
+" padding: 4px;\n"
"}\n"
"\n"
-"#dialogError {\n"
-" color: #FF7D8A;\n"
+"#paletteHint,\n"
+"#projectListHint {\n"
+" background: transparent;\n"
+" color: #7E7E77;\n"
" font-size: 11px;\n"
+" padding: 7px 12px;\n"
"}\n"
"\n"
-"QPushButton[secondary=\"true\"] {\n"
-" background-color: #292C2F;\n"
-" border-color: #494D52;\n"
+"#splashCard {\n"
+" background: #191918;\n"
+" border: 1px solid #343430;\n"
+" border-radius: 12px;\n"
"}\n"
"\n"
-"QPushButton[secondary=\"true\"]:hover {\n"
-" background-color: #363A3E;\n"
-" border-color: #5D6268;\n"
+"#atlasSplash,\n"
+"#splashIcon {\n"
+" background: transparent;\n"
"}\n"
"\n"
-"#projectSettingsDialog,\n"
-"#exportDialog {\n"
-" background-color: #18191B;\n"
+"#splashTitle {\n"
+" color: #ECECE6;\n"
+" font-size: 36px;\n"
+" font-weight: 500;\n"
"}\n"
"\n"
-"#dialogHero {\n"
-" background-color: #242628;\n"
-" border: 1px solid #42464A;\n"
-" border-radius: 13px;\n"
-" padding: 6px;\n"
+"#splashVersion,\n"
+"#splashCompany,\n"
+"#splashWarning {\n"
+" color: #91918A;\n"
+" font-size: 12px;\n"
"}\n"
"\n"
-"#dialogHeroIcon {\n"
-" background-color: #2B3034;\n"
-" border: 1px solid #50575C;\n"
-" border-radius: 10px;\n"
-" padding: 6px;\n"
+"#splashStatus {\n"
+" color: #BFBFB7;\n"
+" font-size: 12px;\n"
"}\n"
"\n"
-"#dialogHeroTitle {\n"
-" color: #F3F6FA;\n"
-" font-size: 17px;\n"
-" font-weight: 750;\n"
+"#splashProgress {\n"
+" background: #2C2C28;\n"
+" border: none;\n"
+" min-height: 0;\n"
+" border-radius: 2px;\n"
"}\n"
"\n"
-"#dialogHeroSubtitle,\n"
-"#exportSummary {\n"
-" color: #7F8B9D;\n"
+"#splashProgress::chunk {\n"
+" background: #BCBCB2;\n"
+" border-radius: 2px;\n"
"}\n"
"\n"
-"#exportSummary {\n"
-" background-color: #232527;\n"
-" border: 1px solid #3B3E42;\n"
-" border-radius: 10px;\n"
-" padding: 6px;\n"
+"QPushButton:default {\n"
+" background: #E5E5E1;\n"
+" color: #191918;\n"
"}\n"
"\n"
-"#exportLog {\n"
-" background-color: #141517;\n"
-" border-color: #404448;\n"
-" color: #B7BDBC;\n"
-" font-family: \"Menlo\";\n"
-" font-size: 10px;\n"
+"#projectSectionLabel {\n"
+" color: #82827B;\n"
+" font-size: 12px;\n"
+" padding: 3px 10px;\n"
"}\n"
"\n"
-"#commandPaletteDialog,\n"
-"#globalSearchDialog {\n"
-" background-color: #202224;\n"
-" border: 1px solid #5A5F65;\n"
-" border-radius: 14px;\n"
+"#searchPreviewPane {\n"
+" background: #171716;\n"
+" border: none;\n"
+" border-left: 1px solid #30302C;\n"
"}\n"
"\n"
-"#commandPaletteSearch,\n"
-"#globalSearchField {\n"
-" background-color: #1A1C1E;\n"
-" border: 1px solid #505459;\n"
-" border-radius: 11px;\n"
-" padding: 7px 9px;\n"
-" font-size: 14px;\n"
+"#searchPreviewText {\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 0;\n"
+" font-family: \"SF Mono\", \"Menlo\", \"Consolas\";\n"
+" font-size: 12px;\n"
+" color: #B6B6AF;\n"
"}\n"
"\n"
-"#commandPaletteSearch:focus,\n"
-"#globalSearchField:focus {\n"
-" border-color: #71808A;\n"
+"#projectRow[available=\"false\"] #projectName {\n"
+" color: #82827B;\n"
"}\n"
"\n"
-"#commandPaletteList,\n"
-"#globalSearchResults {\n"
-" background-color: #202224;\n"
+"QAbstractSpinBox QLineEdit {\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 0;\n"
+" min-height: 0;\n"
+"}\n"
+"\n"
+"#inspectorVectorField {\n"
+" background: transparent;\n"
" border: none;\n"
+"}\n"
+"\n"
+"#inspectorAxisField {\n"
+" background: #252524;\n"
+" border: 1px solid transparent;\n"
+" border-radius: 6px;\n"
+"}\n"
+"\n"
+"#inspectorAxisField:hover {\n"
+" background: #2C2C29;\n"
+" border-color: #44443F;\n"
+"}\n"
+"\n"
+"#inspectorAxisField QDoubleSpinBox {\n"
+" background: transparent;\n"
+" border: none;\n"
+" padding: 5px 2px;\n"
+" min-height: 24px;\n"
+"}\n"
+"\n"
+"#inspectorNumberField,\n"
+"#inspectorNameField,\n"
+"#inspectorColorText {\n"
+" min-height: 26px;\n"
+"}\n"
+"\n"
+"#inspectorAxisX,\n"
+"#inspectorAxisY,\n"
+"#inspectorAxisZ {\n"
+" padding: 0;\n"
+" font-size: 11px;\n"
+"}\n"
+"\n"
+"QTabBar::close-button {\n"
+" image: url(:/editor/assets/close.svg);\n"
+" width: 14px;\n"
+" height: 14px;\n"
" padding: 5px;\n"
+" border-radius: 5px;\n"
"}\n"
"\n"
-"#commandPaletteList::item,\n"
-"#globalSearchResults::item {\n"
-" min-height: 30px;\n"
-" padding: 6px 8px;\n"
+"QTabBar::close-button:hover,\n"
+"#tabCloseButton:hover,\n"
+"#dockAreaCloseButton:hover {\n"
+" background: #343431;\n"
"}\n"
;
diff --git a/include/editor/styling/icons.h b/include/editor/styling/icons.h
index 784290bb..2fce2117 100644
--- a/include/editor/styling/icons.h
+++ b/include/editor/styling/icons.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
namespace styling {
@@ -85,7 +86,8 @@ enum class Icon {
};
bool loadIconFont();
-QIcon icon(Icon icon, const QColor &color = QColor("#AAB4C4"));
+QPixmap brandMark(const QSize &size);
+QIcon icon(Icon icon, const QColor &color = QColor("#B4B3AB"));
QIcon colorSwatch(const QColor &color, const QSize &size = QSize(18, 18));
}
diff --git a/include/editor/styling/workbench.h b/include/editor/styling/workbench.h
new file mode 100644
index 00000000..3b79ef66
--- /dev/null
+++ b/include/editor/styling/workbench.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class QApplication;
+
+namespace styling {
+
+inline constexpr int SecondaryTextRole = Qt::UserRole + 42;
+
+class Button : public QPushButton {
+public:
+ using QPushButton::QPushButton;
+ QSize sizeHint() const override;
+protected:
+ void paintEvent(QPaintEvent *) override;
+};
+
+class ToolButton : public QToolButton {
+public:
+ explicit ToolButton(QWidget *parent = nullptr);
+ QSize sizeHint() const override;
+protected:
+ void paintEvent(QPaintEvent *) override;
+};
+
+class ItemDelegate : public QStyledItemDelegate {
+public:
+ explicit ItemDelegate(QObject *parent = nullptr);
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+};
+
+class TreeView : public QTreeView {
+public:
+ using QTreeView::QTreeView;
+protected:
+ void drawBranches(QPainter *painter, const QRect &rect,
+ const QModelIndex &index) const override;
+};
+
+class ElidedLabel : public QLabel {
+public:
+ explicit ElidedLabel(const QString &text, QWidget *parent = nullptr);
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
+protected:
+ void paintEvent(QPaintEvent *) override;
+};
+
+class WorkspaceStack : public QStackedWidget {
+public:
+ explicit WorkspaceStack(QWidget *parent = nullptr);
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
+};
+
+void installWorkbench(QApplication &app);
+
+}
diff --git a/include/editor/widgets/scrubbableSpinBox.h b/include/editor/widgets/scrubbableSpinBox.h
index 463c68d0..50dcf856 100644
--- a/include/editor/widgets/scrubbableSpinBox.h
+++ b/include/editor/widgets/scrubbableSpinBox.h
@@ -16,6 +16,19 @@ class FlexibleDoubleSpinBox : public QDoubleSpinBox {
: QDoubleSpinBox(parent) {}
protected:
+ QString textFromValue(double value) const override {
+ QString text = QDoubleSpinBox::textFromValue(value);
+ const QString decimal = locale().decimalPoint();
+ if (text.contains(decimal)) {
+ const QChar zero = locale().zeroDigit().at(0);
+ while (text.endsWith(zero))
+ text.chop(1);
+ if (text.endsWith(decimal))
+ text.chop(decimal.size());
+ }
+ return text;
+ }
+
double valueFromText(const QString &text) const override {
return QDoubleSpinBox::valueFromText(normalizedText(text));
}
diff --git a/runtime/lib/context.cpp b/runtime/lib/context.cpp
index 9f334c13..6c9593e5 100644
--- a/runtime/lib/context.cpp
+++ b/runtime/lib/context.cpp
@@ -4927,6 +4927,7 @@ bool Context::setEditorShadingMode(int mode) {
}
bool Context::setEditorPathTracingPreview(bool enabled) {
+ editorPathTracingPreview = enabled;
if (window == nullptr || !editorRuntime) {
return false;
}
diff --git a/runtime/lib/runtime.cpp b/runtime/lib/runtime.cpp
index 61dc9127..0a384a4c 100644
--- a/runtime/lib/runtime.cpp
+++ b/runtime/lib/runtime.cpp
@@ -63,4 +63,10 @@ void RuntimeScene::initialize(Window &window) {
}
runtimeContext->loadMainScene(window);
+#ifdef METAL
+ if (runtimeContext->editorRuntime &&
+ runtimeContext->config.renderer == "pathtracing") {
+ window.setEditorPathTracingPreview(runtimeContext->editorPathTracingPreview);
+ }
+#endif
}
diff --git a/scripts/package_app.py b/scripts/package_app.py
index bc5dd9c8..dcaefbfc 100755
--- a/scripts/package_app.py
+++ b/scripts/package_app.py
@@ -28,13 +28,11 @@ def require(name, override=None):
return Path(candidate)
-def compile_icon(config, artwork, output_directory, work_directory, deployment_target):
+def compile_icon(icon_source, output_directory, work_directory, deployment_target):
source = work_directory / "AtlasEngine.icon"
if source.exists():
shutil.rmtree(source)
- (source / "Assets").mkdir(parents=True)
- shutil.copy2(config, source / "icon.json")
- shutil.copy2(artwork, source / "Assets" / "atlas_ball_bright.png")
+ shutil.copytree(icon_source, source)
if output_directory.exists():
shutil.rmtree(output_directory)
output_directory.mkdir(parents=True)
@@ -292,19 +290,17 @@ def main():
app_name = "Atlas Engine.app"
built_app = build_directory / "bin" / app_name
packaged_app = dist_directory / app_name
- icon_config = (
+ icon_source = (
root
/ "editor"
/ "assets"
- / ("AtlasEngine.icon.json" if args.release else "AtlasEngineDev.icon.json")
+ / ("AtlasEngine.icon" if args.release else "AtlasEngineDev.icon")
)
- icon_artwork = root / "editor" / "assets" / "atlas_ball_bright.png"
assets_directory.mkdir(parents=True, exist_ok=True)
dist_directory.mkdir(parents=True, exist_ok=True)
icon, icon_assets = compile_icon(
- icon_config,
- icon_artwork,
+ icon_source,
assets_directory / "compiled-icon",
assets_directory,
deployment_target,