diff --git a/forms/colorinputwidget.ui b/forms/colorinputwidget.ui new file mode 100644 index 00000000..11f0bc25 --- /dev/null +++ b/forms/colorinputwidget.ui @@ -0,0 +1,310 @@ + + + ColorInputWidget + + + + 0 + 0 + 221 + 212 + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Red + + + + + + + Green + + + + + + + Blue + + + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + 31 + + + 4 + + + Qt::Orientation::Horizontal + + + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 255 + + + 8 + + + + + + + 255 + + + 8 + + + + + + + 255 + + + 8 + + + + + + + + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::Shadow::Raised + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Shape::NoFrame + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + # + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + + + + + + ... + + + + :/icons/pipette.ico:/icons/pipette.ico + + + + + + + + + + + + + diff --git a/forms/gridsettingsdialog.ui b/forms/gridsettingsdialog.ui new file mode 100644 index 00000000..75d31de1 --- /dev/null +++ b/forms/gridsettingsdialog.ui @@ -0,0 +1,275 @@ + + + GridSettingsDialog + + + + 0 + 0 + 331 + 467 + + + + Grid Settings + + + + + + true + + + + + 0 + 0 + 305 + 401 + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Color + + + + + + + false + + + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow + + + 0 + + + + + + + + 0 + 0 + + + + Style + + + + + + + Dimensions (in pixels) + + + + + + ... + + + + :/icons/link_broken.ico + :/icons/link.ico:/icons/link_broken.ico + + + true + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + 2 + + + 999 + + + + + + + Height + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + Width + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + 2 + + + 999 + + + + + + + + + + Offset (in pixels) + + + + + + Y + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + X + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + 0 + + + 999 + + + + + + + 0 + + + 999 + + + + + + + ... + + + + :/icons/link_broken.ico + :/icons/link.ico:/icons/link_broken.ico + + + true + + + true + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + true + + + + + + + + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults + + + + + + + + NoScrollSpinBox + QSpinBox +
noscrollspinbox.h
+
+ + NoScrollComboBox + QComboBox +
noscrollcombobox.h
+
+ + ColorInputWidget + QGroupBox +
colorinputwidget.h
+ 1 +
+
+ + + + +
diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index d4538dcb..60dc95e7 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3077,10 +3077,13 @@ + + + @@ -3312,7 +3315,7 @@ true - Player View Rectangle + Show Player View Rectangle <html><head/><body><p>Show the player's view rectangle on the map based on the cursor's position.</p></body></html> @@ -3329,7 +3332,7 @@ true - Cursor Tile Outline + Show Cursor Tile Outline C @@ -3428,7 +3431,26 @@ true - Dive/Emerge Map + Show Dive/Emerge Map + + + + + true + + + true + + + Show Grid + + + Ctrl+G + + + + + Grid Settings... diff --git a/forms/paletteeditor.ui b/forms/paletteeditor.ui index 1cd7c959..c1a4ee7a 100644 --- a/forms/paletteeditor.ui +++ b/forms/paletteeditor.ui @@ -7,7 +7,7 @@ 0 0 907 - 886 + 933 @@ -15,5039 +15,13 @@ - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Color 0 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 1 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 2 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 3 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 4 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 5 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 6 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 7 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 8 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 9 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 10 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 11 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 12 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 13 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 14 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - Color 15 - - - - - - - 32 - 32 - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Red - - - - - - - Green - - - - - - - Blue - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - 31 - - - 4 - - - Qt::Horizontal - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - 255 - - - 8 - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - # - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - ... - - - - :/icons/pipette.ico:/icons/pipette.ico - - - - - - - - - - - - - - - - + - QFrame::NoFrame + QFrame::Shape::NoFrame - QFrame::Raised + QFrame::Shadow::Raised @@ -5060,14 +34,14 @@ - Qt::StrongFocus + Qt::FocusPolicy::StrongFocus - Qt::Horizontal + Qt::Orientation::Horizontal @@ -5078,7 +52,7 @@ - + Bit Depth: @@ -5101,6 +75,40 @@ + + + + QFrame::Shape::NoFrame + + + true + + + + + 0 + 0 + 883 + 784 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + @@ -5109,7 +117,7 @@ 0 0 907 - 22 + 37 @@ -5137,10 +145,10 @@ Ctrl+Z - Qt::WindowShortcut + Qt::ShortcutContext::WindowShortcut - QAction::NormalPriority + QAction::Priority::NormalPriority @@ -5157,8 +165,6 @@ - - - + diff --git a/include/editor.h b/include/editor.h index 7ef5ba10..88eec307 100644 --- a/include/editor.h +++ b/include/editor.h @@ -23,6 +23,7 @@ #include "collisionpixmapitem.h" #include "mappixmapitem.h" #include "settings.h" +#include "gridsettings.h" #include "movablerect.h" #include "cursortilerect.h" #include "mapruler.h" @@ -48,6 +49,7 @@ public: QPointer project = nullptr; Map *map = nullptr; Settings *settings; + GridSettings gridSettings; void setProject(Project * project); void saveProject(); void save(); @@ -67,6 +69,7 @@ public: void displayMapConnections(); void displayMapBorder(); void displayMapGrid(); + void updateMapGrid(); void displayWildMonTables(); void updateMapBorder(); @@ -118,7 +121,7 @@ public: QPointer collision_item = nullptr; QGraphicsItemGroup *events_group = nullptr; QList borderItems; - QList gridLines; + QGraphicsItemGroup *mapGrid = nullptr; MovableRect *playerViewRect = nullptr; CursorTileRect *cursorMapTileRect = nullptr; MapRuler *map_ruler = nullptr; @@ -165,6 +168,7 @@ public slots: void maskNonVisibleConnectionTiles(); void onBorderMetatilesChanged(); void selectedEventIndexChanged(int index, Event::Group eventGroup); + void toggleGrid(bool); private: const QImage defaultCollisionImgSheet = QImage(":/images/collisions.png"); @@ -219,7 +223,6 @@ private slots: void onHoveredMapMovementPermissionCleared(); void onSelectedMetatilesChanged(); void onWheelZoom(int); - void onToggleGridClicked(bool); signals: void objectsChanged(); @@ -231,6 +234,7 @@ signals: void currentMetatilesSelectionChanged(); void mapRulerStatusChanged(const QString &); void tilesetUpdated(QString); + void gridToggled(bool); }; #endif // EDITOR_H diff --git a/include/mainwindow.h b/include/mainwindow.h index c2726efc..f2a31741 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -26,6 +26,7 @@ #include "shortcutseditor.h" #include "preferenceeditor.h" #include "projectsettingseditor.h" +#include "gridsettings.h" #include "customscriptseditor.h" #include "wildmonchart.h" #include "updatepromoter.h" @@ -302,6 +303,8 @@ private slots: void on_actionProject_Settings_triggered(); void on_actionCustom_Scripts_triggered(); void reloadScriptEngine(); + void on_actionShow_Grid_triggered(); + void on_actionGrid_Settings_triggered(); public: Ui::MainWindow *ui; @@ -316,6 +319,7 @@ private: QPointer newMapPrompt = nullptr; QPointer preferenceEditor = nullptr; QPointer projectSettingsEditor = nullptr; + QPointer gridSettingsDialog = nullptr; QPointer customScriptsEditor = nullptr; QPointer updatePromoter = nullptr; QPointer networkAccessManager = nullptr; diff --git a/include/ui/colorinputwidget.h b/include/ui/colorinputwidget.h new file mode 100644 index 00000000..cd871e0b --- /dev/null +++ b/include/ui/colorinputwidget.h @@ -0,0 +1,46 @@ +#ifndef COLORINPUTWIDGET_H +#define COLORINPUTWIDGET_H + +#include +#include + +namespace Ui { +class ColorInputWidget; +} + + +class ColorInputWidget : public QGroupBox { + Q_OBJECT +public: + explicit ColorInputWidget(QWidget *parent = nullptr); + explicit ColorInputWidget(const QString &title, QWidget *parent = nullptr); + ~ColorInputWidget(); + + void setColor(QRgb color); + QRgb color() const { return m_color; } + + bool setBitDepth(int bits); + int bitDepth() const { return m_bitDepth; } + +signals: + void colorChanged(QRgb color); + void bitDepthChanged(int bits); + void editingFinished(); + +private: + Ui::ColorInputWidget *ui; + + QRgb m_color = 0; + int m_bitDepth = 0; + + void init(); + void updateColorUi(); + void pickColor(); + void blockEditSignals(bool block); + + void setRgbFromSliders(); + void setRgbFromSpinners(); + void setRgbFromHexString(const QString &); +}; + +#endif // COLORINPUTWIDGET_H diff --git a/include/ui/gridsettings.h b/include/ui/gridsettings.h new file mode 100644 index 00000000..807a0685 --- /dev/null +++ b/include/ui/gridsettings.h @@ -0,0 +1,99 @@ +#ifndef GRIDSETTINGS_H +#define GRIDSETTINGS_H + +#include +#include + +class GridSettings { +public: + explicit GridSettings() {}; + ~GridSettings() {}; + + enum Style { + Solid, + LargeDashes, + SmallDashes, + Crosshairs, + Dots, + }; + + uint width = 16; + uint height = 16; + int offsetX = 0; + int offsetY = 0; + Style style = Style::Solid; + QColor color = Qt::black; + QVector getHorizontalDashPattern() const { return this->getDashPattern(this->width); } + QVector getVerticalDashPattern() const { return this->getDashPattern(this->height); } + + static QString getStyleName(Style style); + static GridSettings::Style getStyleFromName(const QString &name); +private: + static const QMap styleToName; + + QVector getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const; + QVector getDashPattern(uint length) const; +}; + +inline bool operator==(const GridSettings &a, const GridSettings &b) { + return a.width == b.width + && a.height == b.height + && a.offsetX == b.offsetX + && a.offsetY == b.offsetY + && a.style == b.style + && a.color == b.color; +} + +inline bool operator!=(const GridSettings &a, const GridSettings &b) { + return !(operator==(a, b)); +} + + + +namespace Ui { +class GridSettingsDialog; +} + +class GridSettingsDialog : public QDialog { + Q_OBJECT +public: + explicit GridSettingsDialog(QWidget *parent = nullptr); + explicit GridSettingsDialog(GridSettings *settings, QWidget *parent = nullptr); + ~GridSettingsDialog(); + + void setSettings(const GridSettings &settings); + GridSettings settings() const { return *m_settings; } + + void setDefaultSettings(const GridSettings &settings); + GridSettings defaultSettings() const { return m_defaultSettings; } + +signals: + void changedGridSettings(); + +private: + Ui::GridSettingsDialog *ui; + GridSettings *const m_settings; + const GridSettings m_originalSettings; + GridSettings m_defaultSettings; + bool m_dimensionsLinked = true; + bool m_offsetsLinked = true; + bool m_ownedSettings = false; + + void init(); + void updateInput(); + void setWidth(int value); + void setHeight(int value); + void setOffsetX(int value); + void setOffsetY(int value); + +private slots: + void dialogButtonClicked(QAbstractButton *button); + void on_spinBox_Width_valueChanged(int value); + void on_spinBox_Height_valueChanged(int value); + void on_spinBox_X_valueChanged(int value); + void on_spinBox_Y_valueChanged(int value); + void on_comboBox_Style_currentTextChanged(const QString &text); + void onColorChanged(QRgb color); +}; + +#endif // GRIDSETTINGS_H diff --git a/include/ui/paletteeditor.h b/include/ui/paletteeditor.h index 9b846d60..63581eb1 100644 --- a/include/ui/paletteeditor.h +++ b/include/ui/paletteeditor.h @@ -2,10 +2,8 @@ #define PALETTEEDITOR_H #include -#include -#include -#include -#include + +#include "colorinputwidget.h" #include "project.h" #include "history.h" @@ -32,43 +30,27 @@ public: private: Ui::PaletteEditor *ui; Project *project = nullptr; - - QList> sliders; - QList> spinners; - QList frames; - QList pickButtons; - QList hexEdits; + QList colorInputs; Tileset *primaryTileset; Tileset *secondaryTileset; QList> palettesHistory; - void refreshColorUis(); - void updateColorUi(int index, QRgb color); - void commitEditHistory(int paletteid); + Tileset* getTileset(int paletteId); + void refreshColorInputs(); + void commitEditHistory(); + void commitEditHistory(int paletteId); void restoreWindowState(); - void setSignalsEnabled(bool enabled); - void setColorsFromHistory(PaletteHistoryItem*, int); void closeEvent(QCloseEvent*); - void pickColor(int i); void setRgb(int index, QRgb rgb); - void setRgbFromSliders(int colorIndex); - void setRgbFromHexEdit(int colorIndex); - void setRgbFromSpinners(int colorIndex); + void setPalette(int paletteId, const QList &palette); void setBitDepth(int bits); int bitDepth = 24; - class HexCodeValidator : public QValidator { - virtual QValidator::State validate(QString &input, int &) const override { - input = input.toUpper(); - return QValidator::Acceptable; - } - }; - - HexCodeValidator *hexValidator = nullptr; + static const int numColors = 16; signals: void closed(); diff --git a/porymap.pro b/porymap.pro index f36f536f..6b7fc59d 100644 --- a/porymap.pro +++ b/porymap.pro @@ -51,6 +51,7 @@ SOURCES += src/core/block.cpp \ src/scriptapi/apiutility.cpp \ src/scriptapi/scripting.cpp \ src/ui/aboutporymap.cpp \ + src/ui/colorinputwidget.cpp \ src/ui/connectionslistitem.cpp \ src/ui/customscriptseditor.cpp \ src/ui/customscriptslistitem.cpp \ @@ -60,6 +61,7 @@ SOURCES += src/core/block.cpp \ src/ui/collisionpixmapitem.cpp \ src/ui/connectionpixmapitem.cpp \ src/ui/currentselectedmetatilespixmapitem.cpp \ + src/ui/gridsettings.cpp \ src/ui/newmapconnectiondialog.cpp \ src/ui/overlay.cpp \ src/ui/prefab.cpp \ @@ -157,6 +159,7 @@ HEADERS += include/core/block.h \ include/ui/collisionpixmapitem.h \ include/ui/connectionpixmapitem.h \ include/ui/currentselectedmetatilespixmapitem.h \ + include/ui/gridsettings.h \ include/ui/newmapconnectiondialog.h \ include/ui/prefabframe.h \ include/ui/projectsettingseditor.h \ @@ -173,6 +176,7 @@ HEADERS += include/core/block.h \ include/ui/prefabcreationdialog.h \ include/ui/regionmappixmapitem.h \ include/ui/citymappixmapitem.h \ + include/ui/colorinputwidget.h \ include/ui/mapsceneeventfilter.h \ include/ui/metatilelayersitem.h \ include/ui/metatileselector.h \ @@ -218,7 +222,9 @@ HEADERS += include/core/block.h \ include/ui/wildmonchart.h FORMS += forms/mainwindow.ui \ + forms/colorinputwidget.ui \ forms/connectionslistitem.ui \ + forms/gridsettingsdialog.ui \ forms/newmapconnectiondialog.ui \ forms/prefabcreationdialog.ui \ forms/prefabframe.ui \ diff --git a/resources/icons/link.ico b/resources/icons/link.ico new file mode 100755 index 00000000..b0c35b59 Binary files /dev/null and b/resources/icons/link.ico differ diff --git a/resources/icons/link_broken.ico b/resources/icons/link_broken.ico new file mode 100755 index 00000000..fd7774ed Binary files /dev/null and b/resources/icons/link_broken.ico differ diff --git a/resources/images.qrc b/resources/images.qrc index 73ed0620..26f51f42 100644 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -17,6 +17,8 @@ icons/folder_map.ico icons/folder.ico icons/help.ico + icons/link_broken.ico + icons/link.ico icons/map_edited.ico icons/map_opened.ico icons/map.ico diff --git a/src/editor.cpp b/src/editor.cpp index ad228d77..3929d1e3 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -47,6 +47,10 @@ Editor::Editor(Ui::MainWindow* ui) connect(ui->stackedWidget_WildMons, &QStackedWidget::currentChanged, [this] { emit wildMonTableOpened(getCurrentWildMonTable()); }); + + connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this, &Editor::openMapScripts); + connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this, &Editor::openProjectInTextEditor); + connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::toggleGrid); } Editor::~Editor() @@ -1842,40 +1846,69 @@ int Editor::getBorderDrawDistance(int dimension) { } } -void Editor::onToggleGridClicked(bool checked) { +void Editor::toggleGrid(bool checked) { + if (porymapConfig.showGrid == checked) + return; porymapConfig.showGrid = checked; + + // Synchronize action and checkbox + const QSignalBlocker b_Action(ui->actionShow_Grid); + const QSignalBlocker b_Checkbox(ui->checkBox_ToggleGrid); + ui->actionShow_Grid->setChecked(checked); + ui->checkBox_ToggleGrid->setChecked(checked); + + this->mapGrid->setVisible(checked); + if (ui->graphicsView_Map->scene()) ui->graphicsView_Map->scene()->update(); } void Editor::clearMapGrid() { - for (QGraphicsLineItem* item : gridLines) { - if (item) delete item; - } - gridLines.clear(); + delete this->mapGrid; + this->mapGrid = nullptr; } void Editor::displayMapGrid() { clearMapGrid(); - ui->checkBox_ToggleGrid->disconnect(); - int pixelWidth = map->getWidth() * 16; - int pixelHeight = map->getHeight() * 16; - for (int i = 0; i <= map->getWidth(); i++) { - int x = i * 16; - QGraphicsLineItem *line = new QGraphicsLineItem(x, 0, x, pixelHeight); - line->setVisible(ui->checkBox_ToggleGrid->isChecked()); - gridLines.append(line); - connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);}); + // Note: The grid lines are not added to the scene. They need to be drawn on top of the overlay + // elements of the scripting API, so they're painted manually in MapView::drawForeground. + this->mapGrid = new QGraphicsItemGroup(); + + const int pixelMapWidth = map->getWidth() * 16; + const int pixelMapHeight = map->getHeight() * 16; + + // The grid can be moved with a user-specified x/y offset. The grid's dash patterns will only wrap in full pattern increments, + // so we draw an additional row/column outside the map that can be revealed as the offset changes. + const int offsetX = (this->gridSettings.offsetX % this->gridSettings.width) - this->gridSettings.width; + const int offsetY = (this->gridSettings.offsetY % this->gridSettings.height) - this->gridSettings.height; + + QPen pen; + pen.setColor(this->gridSettings.color); + + // Create vertical lines + pen.setDashPattern(this->gridSettings.getVerticalDashPattern()); + for (int i = offsetX; i <= pixelMapWidth; i += this->gridSettings.width) { + auto line = new QGraphicsLineItem(i, offsetY, i, pixelMapHeight); + line->setPen(pen); + this->mapGrid->addToGroup(line); } - for (int j = 0; j <= map->getHeight(); j++) { - int y = j * 16; - QGraphicsLineItem *line = new QGraphicsLineItem(0, y, pixelWidth, y); - line->setVisible(ui->checkBox_ToggleGrid->isChecked()); - gridLines.append(line); - connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);}); + + // Create horizontal lines + pen.setDashPattern(this->gridSettings.getHorizontalDashPattern()); + for (int i = offsetY; i <= pixelMapHeight; i += this->gridSettings.height) { + auto line = new QGraphicsLineItem(offsetX, i, pixelMapWidth, i); + line->setPen(pen); + this->mapGrid->addToGroup(line); } - connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::onToggleGridClicked); + + this->mapGrid->setVisible(porymapConfig.showGrid); +} + +void Editor::updateMapGrid() { + displayMapGrid(); + if (ui->graphicsView_Map->scene()) + ui->graphicsView_Map->scene()->update(); } void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 588ce90f..93ed1dcb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -149,10 +149,6 @@ void MainWindow::initExtraShortcuts() { shortcutReset_Zoom->setObjectName("shortcutZoom_Reset"); shortcutReset_Zoom->setWhatsThis("Zoom Reset"); - auto *shortcutToggle_Grid = new Shortcut(QKeySequence("Ctrl+G"), ui->checkBox_ToggleGrid, SLOT(toggle())); - shortcutToggle_Grid->setObjectName("shortcutToggle_Grid"); - shortcutToggle_Grid->setWhatsThis("Toggle Grid"); - auto *shortcutDuplicate_Events = new Shortcut(QKeySequence("Ctrl+D"), this, SLOT(duplicate())); shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events"); shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)"); @@ -317,8 +313,6 @@ void MainWindow::initEditor() { connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); }); connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged); connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated); - connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts); - connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor); this->loadUserSettings(); @@ -465,27 +459,45 @@ void MainWindow::applyMapListFilter(QString filterText) } void MainWindow::loadUserSettings() { - const QSignalBlocker blocker1(ui->horizontalSlider_CollisionTransparency); - const QSignalBlocker blocker2(ui->slider_DiveEmergeMapOpacity); - const QSignalBlocker blocker3(ui->slider_DiveMapOpacity); - const QSignalBlocker blocker4(ui->slider_EmergeMapOpacity); - const QSignalBlocker blocker5(ui->horizontalSlider_MetatileZoom); - const QSignalBlocker blocker6(ui->horizontalSlider_CollisionZoom); - + // Better Cursors ui->actionBetter_Cursors->setChecked(porymapConfig.prettyCursors); this->editor->settings->betterCursors = porymapConfig.prettyCursors; + + // Player view rectangle ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.showPlayerView); this->editor->settings->playerViewRectEnabled = porymapConfig.showPlayerView; + + // Cursor tile outline ui->actionCursor_Tile_Outline->setChecked(porymapConfig.showCursorTile); this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile; + + // Border ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder); + + // Grid + const QSignalBlocker b_Grid(ui->checkBox_ToggleGrid); + ui->actionShow_Grid->setChecked(porymapConfig.showGrid); ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid); + + // Mirror connections ui->checkBox_MirrorConnections->setChecked(porymapConfig.mirrorConnectingMaps); + + // Collision opacity/transparency + const QSignalBlocker b_CollisionTransparency(ui->horizontalSlider_CollisionTransparency); this->editor->collisionOpacity = static_cast(porymapConfig.collisionOpacity) / 100; ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.collisionOpacity); + + // Dive map opacity/transparency + const QSignalBlocker b_DiveEmergeOpacity(ui->slider_DiveEmergeMapOpacity); + const QSignalBlocker b_DiveMapOpacity(ui->slider_DiveMapOpacity); + const QSignalBlocker b_EmergeMapOpacity(ui->slider_EmergeMapOpacity); ui->slider_DiveEmergeMapOpacity->setValue(porymapConfig.diveEmergeMapOpacity); ui->slider_DiveMapOpacity->setValue(porymapConfig.diveMapOpacity); ui->slider_EmergeMapOpacity->setValue(porymapConfig.emergeMapOpacity); + + // Zoom + const QSignalBlocker b_MetatileZoom(ui->horizontalSlider_MetatileZoom); + const QSignalBlocker b_CollisionZoom(ui->horizontalSlider_CollisionZoom); ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.metatilesZoom); ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom); @@ -1910,6 +1922,18 @@ void MainWindow::on_actionCursor_Tile_Outline_triggered() } } +void MainWindow::on_actionShow_Grid_triggered() { + this->editor->toggleGrid(ui->actionShow_Grid->isChecked()); +} + +void MainWindow::on_actionGrid_Settings_triggered() { + if (!this->gridSettingsDialog) { + this->gridSettingsDialog = new GridSettingsDialog(&this->editor->gridSettings, this); + connect(this->gridSettingsDialog, &GridSettingsDialog::changedGridSettings, this->editor, &Editor::updateMapGrid); + } + openSubWindow(this->gridSettingsDialog); +} + void MainWindow::on_actionShortcuts_triggered() { if (!shortcutsEditor) diff --git a/src/ui/colorinputwidget.cpp b/src/ui/colorinputwidget.cpp new file mode 100644 index 00000000..8b40be27 --- /dev/null +++ b/src/ui/colorinputwidget.cpp @@ -0,0 +1,229 @@ +#include "colorinputwidget.h" +#include "ui_colorinputwidget.h" +#include "colorpicker.h" + +#include + +class HexCodeValidator : public QValidator { + virtual QValidator::State validate(QString &input, int &) const override { + input = input.toUpper(); + return QValidator::Acceptable; + } +}; + +static inline int rgb5(int rgb) { return round(static_cast(rgb * 31) / 255.0); } +static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); } +static inline int gbaRed(int rgb) { return rgb & 0x1f; } +static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; } +static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; } + +ColorInputWidget::ColorInputWidget(QWidget *parent) : + QGroupBox(parent), + ui(new Ui::ColorInputWidget) +{ + init(); +} + +ColorInputWidget::ColorInputWidget(const QString &title, QWidget *parent) : + QGroupBox(title, parent), + ui(new Ui::ColorInputWidget) +{ + init(); +} + +void ColorInputWidget::init() { + ui->setupUi(this); + + // Connect color change signals + connect(ui->slider_Red, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + connect(ui->slider_Green, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + connect(ui->slider_Blue, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders); + + connect(ui->spinBox_Red, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + connect(ui->spinBox_Green, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + connect(ui->spinBox_Blue, QOverload::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners); + + static const HexCodeValidator hexValidator; + ui->lineEdit_Hex->setValidator(&hexValidator); + connect(ui->lineEdit_Hex, &QLineEdit::textEdited, this, &ColorInputWidget::setRgbFromHexString); + + // We have separate signals for when color input editing finishes. + // This is mostly useful for external commit histories, esp. for the sliders which can rapidly emit color change signals. + connect(ui->slider_Red, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + connect(ui->slider_Green, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + connect(ui->slider_Blue, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished); + + connect(ui->spinBox_Red, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + connect(ui->spinBox_Green, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + connect(ui->spinBox_Blue, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished); + + connect(ui->lineEdit_Hex, &QLineEdit::editingFinished, this, &ColorInputWidget::editingFinished); + + // Connect color picker + connect(ui->button_Eyedrop, &QToolButton::clicked, this, &ColorInputWidget::pickColor); + + setBitDepth(24); +} + +ColorInputWidget::~ColorInputWidget() { + delete ui; +} + +void ColorInputWidget::updateColorUi() { + blockEditSignals(true); + + int red = qRed(m_color); + int green = qGreen(m_color); + int blue = qBlue(m_color); + + if (m_bitDepth == 15) { + // Sliders + ui->slider_Red->setValue(rgb5(red)); + ui->slider_Green->setValue(rgb5(green)); + ui->slider_Blue->setValue(rgb5(blue)); + + // Hex + int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red); + ui->lineEdit_Hex->setText(QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper()); + + // Spinners + ui->spinBox_Red->setValue(rgb5(red)); + ui->spinBox_Green->setValue(rgb5(green)); + ui->spinBox_Blue->setValue(rgb5(blue)); + } else { + // Sliders + ui->slider_Red->setValue(red); + ui->slider_Green->setValue(green); + ui->slider_Blue->setValue(blue); + + // Hex + QColor color(red, green, blue); + ui->lineEdit_Hex->setText(color.name().remove(0, 1).toUpper()); + + // Spinners + ui->spinBox_Red->setValue(red); + ui->spinBox_Green->setValue(green); + ui->spinBox_Blue->setValue(blue); + } + + ui->frame_ColorDisplay->setStyleSheet(QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue)); + + blockEditSignals(false); +} + +void ColorInputWidget::blockEditSignals(bool block) { + ui->slider_Red->blockSignals(block); + ui->slider_Green->blockSignals(block); + ui->slider_Blue->blockSignals(block); + + ui->spinBox_Red->blockSignals(block); + ui->spinBox_Green->blockSignals(block); + ui->spinBox_Blue->blockSignals(block); + + ui->lineEdit_Hex->blockSignals(block); +} + +bool ColorInputWidget::setBitDepth(int bits) { + if (m_bitDepth == bits) + return true; + + int singleStep, pageStep, maximum; + QString hexInputMask; + if (bits == 15) { + singleStep = 1; + pageStep = 4; + maximum = 31; + hexInputMask = "HHHH"; + } else if (bits == 24) { + singleStep = 8; + pageStep = 24; + maximum = 255; + hexInputMask = "HHHHHH"; + } else { + // Unsupported bit depth + return false; + } + m_bitDepth = bits; + + blockEditSignals(true); + ui->slider_Red->setSingleStep(singleStep); + ui->slider_Green->setSingleStep(singleStep); + ui->slider_Blue->setSingleStep(singleStep); + ui->slider_Red->setPageStep(pageStep); + ui->slider_Green->setPageStep(pageStep); + ui->slider_Blue->setPageStep(pageStep); + ui->slider_Red->setMaximum(maximum); + ui->slider_Green->setMaximum(maximum); + ui->slider_Blue->setMaximum(maximum); + + ui->spinBox_Red->setSingleStep(singleStep); + ui->spinBox_Green->setSingleStep(singleStep); + ui->spinBox_Blue->setSingleStep(singleStep); + ui->spinBox_Red->setMaximum(maximum); + ui->spinBox_Green->setMaximum(maximum); + ui->spinBox_Blue->setMaximum(maximum); + + ui->lineEdit_Hex->setInputMask(hexInputMask); + ui->lineEdit_Hex->setMaxLength(hexInputMask.length()); + + updateColorUi(); + blockEditSignals(false); + emit bitDepthChanged(m_bitDepth); + return true; +} + +void ColorInputWidget::setColor(QRgb rgb) { + if (m_color == rgb) + return; + m_color = rgb; + updateColorUi(); + emit colorChanged(m_color); +} + +void ColorInputWidget::setRgbFromSliders() { + if (m_bitDepth == 15) { + setColor(qRgb(rgb8(ui->slider_Red->value()), + rgb8(ui->slider_Green->value()), + rgb8(ui->slider_Blue->value()))); + } else { + setColor(qRgb(ui->slider_Red->value(), + ui->slider_Green->value(), + ui->slider_Blue->value())); + } +} + +void ColorInputWidget::setRgbFromSpinners() { + if (m_bitDepth == 15) { + setColor(qRgb(rgb8(ui->spinBox_Red->value()), rgb8(ui->spinBox_Green->value()), rgb8(ui->spinBox_Blue->value()))); + } else { + setColor(qRgb(ui->spinBox_Red->value(), ui->spinBox_Green->value(), ui->spinBox_Blue->value())); + } +} + +void ColorInputWidget::setRgbFromHexString(const QString &text) { + if ((m_bitDepth == 24 && text.length() != 6) + || (m_bitDepth == 15 && text.length() != 4)) + return; + + bool ok = false; + int rgb = text.toInt(&ok, 16); + if (!ok) rgb = 0xFFFFFFFF; + + if (m_bitDepth == 15) { + int rc = gbaRed(rgb); + int gc = gbaGreen(rgb); + int bc = gbaBlue(rgb); + setColor(qRgb(rgb8(rc), rgb8(gc), rgb8(bc))); + } else { + setColor(qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb))); + } +} + +void ColorInputWidget::pickColor() { + ColorPicker picker(this); + if (picker.exec() == QDialog::Accepted) { + QColor c = picker.getColor(); + setColor(c.rgb()); + emit editingFinished(); + } +} diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index 1c86e004..f4de5074 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -31,10 +31,24 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) { if (!editor) return; QStyleOptionGraphicsItem option; - for (QGraphicsLineItem* line : editor->gridLines) { - if (line && line->isVisible()) - line->paint(painter, &option, this); + + // Draw elements of the map view that should always render on top of anything added by the user with the scripting API. + + // Draw map grid + if (editor->mapGrid && editor->mapGrid->isVisible()) { + painter->save(); + if (editor->map) { + // We're clipping here to hide parts of the grid that are outside the map. + const QRectF mapRect(-0.5, -0.5, editor->map->getWidth() * 16 + 1.5, editor->map->getHeight() * 16 + 1.5); + painter->setClipping(true); + painter->setClipRect(mapRect); + } + for (auto item : editor->mapGrid->childItems()) + item->paint(painter, &option, this); + painter->restore(); } + + // Draw cursor rectangles if (editor->playerViewRect && editor->playerViewRect->isVisible()) editor->playerViewRect->paint(painter, &option, this); if (editor->cursorMapTileRect && editor->cursorMapTileRect->isVisible()) diff --git a/src/ui/gridsettings.cpp b/src/ui/gridsettings.cpp new file mode 100644 index 00000000..b4e180af --- /dev/null +++ b/src/ui/gridsettings.cpp @@ -0,0 +1,230 @@ +#include "ui_gridsettingsdialog.h" +#include "gridsettings.h" + +// TODO: Save settings in config + +const QMap GridSettings::styleToName = { + {Style::Solid, "Solid"}, + {Style::LargeDashes, "Large Dashes"}, + {Style::SmallDashes, "Small Dashes"}, + {Style::Crosshairs, "Crosshairs"}, + {Style::Dots, "Dots"}, +}; + +QString GridSettings::getStyleName(GridSettings::Style style) { + return styleToName.value(style); +} + +GridSettings::Style GridSettings::getStyleFromName(const QString &name) { + return styleToName.key(name, GridSettings::Style::Solid); +} + +// We do some extra work here to A: try and center the dashes away from the intersections, and B: keep the dash pattern's total +// length equal to the length of a grid square. This keeps the patterns looking reasonable regardless of the grid size. +// Otherwise, the dashes can start to intersect in weird ways and create grid patterns that don't look like a rectangular grid. +QVector GridSettings::getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const { + const qreal minEdgesLength = 0.6*2; + if (length <= dashLength + minEdgesLength) + return {dashLength}; + + // Every dash after the first one needs to have room for a 'gapLength' segment. + const int numDashes = 1 + ((length - minEdgesLength) - dashLength) / (dashLength + gapLength); + + // Total length of the pattern excluding the centering edges. There are always 1 fewer gap segments than dashes. + const qreal mainLength = (dashLength * numDashes) + (gapLength * (numDashes-1)); + + const qreal edgeLength = (length - mainLength) / 2; + + // Fill the pattern + QVector pattern = {0, edgeLength}; + for (int i = 0; i < numDashes-1; i++) { + pattern.append(dashLength); + pattern.append(gapLength); + } + pattern.append(dashLength); + pattern.append(edgeLength); + + return pattern; +} + +QVector GridSettings::getDashPattern(uint length) const { + switch (this->style) { + + // Equivalent to setting Qt::PenStyle::Solid with no dash pattern. + case Style::Solid: return {1, 0}; + + // Roughly equivalent to Qt::PenStyle::DashLine but with centering. + case Style::LargeDashes: return getCenteredDashPattern(length, 3.0, 2.0); + + // Roughly equivalent to Qt::PenStyle::DotLine but with centering. + case Style::SmallDashes: return getCenteredDashPattern(length, 1.0, 2.5); + + // Dashes only at intersections, in the shape of a crosshair. + case Style::Crosshairs: { + const qreal crosshairLength = 2.0; + return {crosshairLength / 2, length - crosshairLength, crosshairLength / 2, 0}; + } + + // Dots only at intersections. + case Style::Dots: { + const qreal dotLength = 0.1; + return {dotLength, length - dotLength}; + } + + // Invalid + default: return {}; + } +} + + + +GridSettingsDialog::GridSettingsDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::GridSettingsDialog), + m_settings(new GridSettings), + m_originalSettings(*m_settings) +{ + m_ownedSettings = true; + init(); +} + +GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) : + QDialog(parent), + ui(new Ui::GridSettingsDialog), + m_settings(settings), + m_originalSettings(*settings) +{ + m_ownedSettings = false; + init(); +} + +void GridSettingsDialog::init() { + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + // Populate the styles combo box + const QSignalBlocker b_Style(ui->comboBox_Style); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Solid)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::LargeDashes)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::SmallDashes)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Crosshairs)); + ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Dots)); + + ui->button_LinkDimensions->setChecked(m_dimensionsLinked); + ui->button_LinkOffsets->setChecked(m_offsetsLinked); + + connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked); + connect(ui->button_LinkDimensions, &QAbstractButton::toggled, [this](bool on) { m_dimensionsLinked = on; }); + connect(ui->button_LinkOffsets, &QAbstractButton::toggled, [this](bool on) { m_offsetsLinked = on; }); + connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged); + + updateInput(); +} + +GridSettingsDialog::~GridSettingsDialog() { + delete ui; + if (m_ownedSettings) + delete m_settings; +} + +void GridSettingsDialog::setSettings(const GridSettings &settings) { + if (*m_settings == settings) + return; + *m_settings = settings; + updateInput(); + emit changedGridSettings(); +} + +void GridSettingsDialog::updateInput() { + setWidth(m_settings->width); + setHeight(m_settings->height); + setOffsetX(m_settings->offsetX); + setOffsetY(m_settings->offsetY); + + const QSignalBlocker b_Color(ui->colorInput); + ui->colorInput->setColor(m_settings->color.rgb()); + + const QSignalBlocker b_Style(ui->comboBox_Style); + ui->comboBox_Style->setCurrentText(GridSettings::getStyleName(m_settings->style)); +} + +void GridSettingsDialog::setWidth(int value) { + const QSignalBlocker b(ui->spinBox_Width); + ui->spinBox_Width->setValue(value); + m_settings->width = value; +} + +void GridSettingsDialog::setHeight(int value) { + const QSignalBlocker b(ui->spinBox_Height); + ui->spinBox_Height->setValue(value); + m_settings->height = value; +} + +void GridSettingsDialog::setOffsetX(int value) { + const QSignalBlocker b(ui->spinBox_X); + ui->spinBox_X->setValue(value); + m_settings->offsetX = value; +} + +void GridSettingsDialog::setOffsetY(int value) { + const QSignalBlocker b(ui->spinBox_Y); + ui->spinBox_Y->setValue(value); + m_settings->offsetY = value; +} + +void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) { + setWidth(value); + if (m_dimensionsLinked) + setHeight(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) { + setHeight(value); + if (m_dimensionsLinked) + setWidth(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_X_valueChanged(int value) { + setOffsetX(value); + if (m_offsetsLinked) + setOffsetY(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) { + setOffsetY(value); + if (m_offsetsLinked) + setOffsetX(value); + + emit changedGridSettings(); +} + +void GridSettingsDialog::on_comboBox_Style_currentTextChanged(const QString &text) { + m_settings->style = GridSettings::getStyleFromName(text); + emit changedGridSettings(); +} + +void GridSettingsDialog::onColorChanged(QRgb color) { + m_settings->color = QColor::fromRgb(color); + emit changedGridSettings(); +} + +void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) { + auto role = ui->buttonBox->buttonRole(button); + if (role == QDialogButtonBox::AcceptRole) { + // "OK" + close(); + } else if (role == QDialogButtonBox::RejectRole) { + // "Cancel" + setSettings(m_originalSettings); + close(); + } else if (role == QDialogButtonBox::ResetRole) { + // "Restore Defaults" + setSettings(m_defaultSettings); + } +} diff --git a/src/ui/paletteeditor.cpp b/src/ui/paletteeditor.cpp index 8dcd2a7a..393f3a6e 100644 --- a/src/ui/paletteeditor.cpp +++ b/src/ui/paletteeditor.cpp @@ -1,19 +1,12 @@ #include "paletteeditor.h" #include "ui_paletteeditor.h" -#include "colorpicker.h" #include "paletteutil.h" #include "config.h" #include "log.h" -#include #include #include -static inline int rgb5(int rgb) { return round(static_cast(rgb * 31) / 255.0); } -static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); } -static inline int gbaRed(int rgb) { return rgb & 0x1f; } -static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; } -static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; } PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId, QWidget *parent) : QMainWindow(parent), @@ -26,55 +19,14 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset this->ui->spinBox_PaletteId->setMinimum(0); this->ui->spinBox_PaletteId->setMaximum(Project::getNumPalettesTotal() - 1); - this->sliders.clear(); - for (int i = 0; i < 16; i++) { - QList rgbSliders; - rgbSliders.append(this->ui->container->findChild("slider_red_" + QString::number(i))); - rgbSliders.append(this->ui->container->findChild("slider_green_" + QString::number(i))); - rgbSliders.append(this->ui->container->findChild("slider_blue_" + QString::number(i))); - this->sliders.append(rgbSliders); - - connect(this->sliders[i][0], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - connect(this->sliders[i][1], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - connect(this->sliders[i][2], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); }); - } - - this->spinners.clear(); - for (int i = 0; i < 16; i++) { - QList rgbSpinners; - rgbSpinners.append(this->ui->container->findChild("spin_red_" + QString::number(i))); - rgbSpinners.append(this->ui->container->findChild("spin_green_" + QString::number(i))); - rgbSpinners.append(this->ui->container->findChild("spin_blue_" + QString::number(i))); - this->spinners.append(rgbSpinners); - - connect(this->spinners[i][0], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - connect(this->spinners[i][1], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - connect(this->spinners[i][2], QOverload::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); }); - } - - this->frames.clear(); - for (int i = 0; i < 16; i++) { - this->frames.append(this->ui->container->findChild("colorFrame_" + QString::number(i))); - this->frames[i]->setFrameStyle(QFrame::NoFrame); - } - - this->pickButtons.clear(); - for (int i = 0; i < 16; i++) { - this->pickButtons.append(this->ui->container->findChild("pick_" + QString::number(i))); - } - - this->hexValidator = new HexCodeValidator; - this->hexEdits.clear(); - for (int i = 0; i < 16; i++) { - this->hexEdits.append(this->ui->container->findChild("hex_" + QString::number(i))); - this->hexEdits[i]->setValidator(hexValidator); - } - - // Connect to function that will update color when hex edit is changed - for (int i = 0; i < this->hexEdits.length(); i++) { - connect(this->hexEdits[i], &QLineEdit::textEdited, [this, i](QString text){ - if ((this->bitDepth == 24 && text.length() == 6) || (this->bitDepth == 15 && text.length() == 4)) setRgbFromHexEdit(i); - }); + this->colorInputs.clear(); + const int numColorsPerRow = 4; + for (int i = 0; i < this->numColors; i++) { + auto colorInput = new ColorInputWidget(QString("Color %1").arg(i)); + connect(colorInput, &ColorInputWidget::colorChanged, [this, i](QRgb color) { setRgb(i, color); }); + connect(colorInput, &ColorInputWidget::editingFinished, [this] { commitEditHistory(); }); + this->colorInputs.append(colorInput); + ui->layout_Colors->addWidget(colorInput, i / numColorsPerRow, i % numColorsPerRow); } // Setup edit-undo history for each of the palettes. @@ -82,11 +34,6 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset this->palettesHistory.append(History()); } - // Connect the color picker's selection to the correct color index - for (int i = 0; i < 16; i++) { - connect(this->pickButtons[i], &QToolButton::clicked, [this, i](){ this->pickColor(i); }); - } - int bitDepth = porymapConfig.paletteEditorBitDepth; if (bitDepth == 15) { this->ui->bit_depth_15->setChecked(true); @@ -100,246 +47,87 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset connect(this->ui->bit_depth_24, &QRadioButton::toggled, [this](bool checked){ if (checked) this->setBitDepth(24); }); this->setPaletteId(paletteId); - this->commitEditHistory(this->ui->spinBox_PaletteId->value()); + this->commitEditHistory(); this->restoreWindowState(); } PaletteEditor::~PaletteEditor() { delete ui; - delete this->hexValidator; } -void PaletteEditor::updateColorUi(int colorIndex, QRgb rgb) { - setSignalsEnabled(false); - - int red = qRed(rgb); - int green = qGreen(rgb); - int blue = qBlue(rgb); - - if (this->bitDepth == 15) { - // sliders - this->sliders[colorIndex][0]->setValue(rgb5(red)); - this->sliders[colorIndex][1]->setValue(rgb5(green)); - this->sliders[colorIndex][2]->setValue(rgb5(blue)); - - // hex - int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red); - QString hexcode = QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper(); - this->hexEdits[colorIndex]->setText(hexcode); - - // spinners - this->spinners[colorIndex][0]->setValue(rgb5(red)); - this->spinners[colorIndex][1]->setValue(rgb5(green)); - this->spinners[colorIndex][2]->setValue(rgb5(blue)); - } else { - // sliders - this->sliders[colorIndex][0]->setValue(red); - this->sliders[colorIndex][1]->setValue(green); - this->sliders[colorIndex][2]->setValue(blue); - - // hex - QColor color(red, green, blue); - QString hexcode = color.name().remove(0, 1).toUpper(); - this->hexEdits[colorIndex]->setText(hexcode); - - // spinners - this->spinners[colorIndex][0]->setValue(red); - this->spinners[colorIndex][1]->setValue(green); - this->spinners[colorIndex][2]->setValue(blue); - } - - // frame - QString stylesheet = QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue); - this->frames[colorIndex]->setStyleSheet(stylesheet); - - setSignalsEnabled(true); -} - -void PaletteEditor::setSignalsEnabled(bool enabled) { - // spinners, sliders, hexbox - for (int i = 0; i < this->sliders.length(); i++) { - this->sliders.at(i).at(0)->blockSignals(!enabled); - this->sliders.at(i).at(1)->blockSignals(!enabled); - this->sliders.at(i).at(2)->blockSignals(!enabled); - } - - for (int i = 0; i < this->spinners.length(); i++) { - this->spinners.at(i).at(0)->blockSignals(!enabled); - this->spinners.at(i).at(1)->blockSignals(!enabled); - this->spinners.at(i).at(2)->blockSignals(!enabled); - } - - for (int i = 0; i < this->hexEdits.length(); i++) { - this->hexEdits.at(i)->blockSignals(!enabled); - } +Tileset* PaletteEditor::getTileset(int paletteId) { + return (paletteId < Project::getNumPalettesPrimary()) + ? this->primaryTileset + : this->secondaryTileset; } void PaletteEditor::setBitDepth(int bits) { - setSignalsEnabled(false); - switch (bits) { - case 15: - for (int i = 0; i < 16; i++) { - // sliders ranged [0, 31] with 1 single step and 4 page step - this->sliders[i][0]->setSingleStep(1); - this->sliders[i][1]->setSingleStep(1); - this->sliders[i][2]->setSingleStep(1); - this->sliders[i][0]->setPageStep(4); - this->sliders[i][1]->setPageStep(4); - this->sliders[i][2]->setPageStep(4); - this->sliders[i][0]->setMaximum(31); - this->sliders[i][1]->setMaximum(31); - this->sliders[i][2]->setMaximum(31); - - // spinners limited [0, 31] with 1 step - this->spinners[i][0]->setSingleStep(1); - this->spinners[i][1]->setSingleStep(1); - this->spinners[i][2]->setSingleStep(1); - this->spinners[i][0]->setMaximum(31); - this->spinners[i][1]->setMaximum(31); - this->spinners[i][2]->setMaximum(31); - - // hex box now 4 digits - this->hexEdits[i]->setInputMask("HHHH"); - this->hexEdits[i]->setMaxLength(4); - } - break; - case 24: - default: - for (int i = 0; i < 16; i++) { - // sliders ranged [0, 31] with 1 single step and 4 page step - this->sliders[i][0]->setSingleStep(8); - this->sliders[i][1]->setSingleStep(8); - this->sliders[i][2]->setSingleStep(8); - this->sliders[i][0]->setPageStep(24); - this->sliders[i][1]->setPageStep(24); - this->sliders[i][2]->setPageStep(24); - this->sliders[i][0]->setMaximum(255); - this->sliders[i][1]->setMaximum(255); - this->sliders[i][2]->setMaximum(255); - - // spinners limited [0, 31] with 1 step - this->spinners[i][0]->setSingleStep(8); - this->spinners[i][1]->setSingleStep(8); - this->spinners[i][2]->setSingleStep(8); - this->spinners[i][0]->setMaximum(255); - this->spinners[i][1]->setMaximum(255); - this->spinners[i][2]->setMaximum(255); - - // hex box now 4 digits - this->hexEdits[i]->setInputMask("HHHHHH"); - this->hexEdits[i]->setMaxLength(6); - } - break; - } this->bitDepth = bits; porymapConfig.paletteEditorBitDepth = bits; - refreshColorUis(); - setSignalsEnabled(true); + for (const auto &colorInput : this->colorInputs) { + colorInput->setBitDepth(bits); + } } void PaletteEditor::setRgb(int colorIndex, QRgb rgb) { - int paletteNum = this->ui->spinBox_PaletteId->value(); + const int paletteId = this->ui->spinBox_PaletteId->value(); - Tileset *tileset = paletteNum < Project::getNumPalettesPrimary() - ? this->primaryTileset - : this->secondaryTileset; - tileset->palettes[paletteNum][colorIndex] = rgb; - tileset->palettePreviews[paletteNum][colorIndex] = rgb; + Tileset *tileset = getTileset(paletteId); + tileset->palettes[paletteId][colorIndex] = rgb; + tileset->palettePreviews[paletteId][colorIndex] = rgb; - this->updateColorUi(colorIndex, rgb); - - this->commitEditHistory(paletteNum); - emit this->changedPaletteColor(); + emit changedPaletteColor(); } -void PaletteEditor::setRgbFromSliders(int colorIndex) { - if (this->bitDepth == 15) { - setRgb(colorIndex, qRgb(rgb8(this->sliders[colorIndex][0]->value()), - rgb8(this->sliders[colorIndex][1]->value()), - rgb8(this->sliders[colorIndex][2]->value()))); - } else { - setRgb(colorIndex, qRgb(this->sliders[colorIndex][0]->value(), - this->sliders[colorIndex][1]->value(), - this->sliders[colorIndex][2]->value())); +void PaletteEditor::setPalette(int paletteId, const QList &palette) { + Tileset *tileset = getTileset(paletteId); + for (int i = 0; i < this->numColors; i++) { + tileset->palettes[paletteId][i] = palette.at(i); + tileset->palettePreviews[paletteId][i] = palette.at(i); } + refreshColorInputs(); + emit changedPaletteColor(); } -void PaletteEditor::setRgbFromHexEdit(int colorIndex) { - QString text = this->hexEdits[colorIndex]->text(); - bool ok = false; - int rgb = text.toInt(&ok, 16); - if (!ok) rgb = 0xFFFFFFFF; - if (this->bitDepth == 15) { - int rc = gbaRed(rgb); - int gc = gbaGreen(rgb); - int bc = gbaBlue(rgb); - setRgb(colorIndex, qRgb(rgb8(rc), rgb8(gc), rgb8(bc))); - } else { - setRgb(colorIndex, qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb))); - } -} - -void PaletteEditor::setRgbFromSpinners(int colorIndex) { - if (this->bitDepth == 15) { - setRgb(colorIndex, qRgb(rgb8(this->spinners[colorIndex][0]->value()), - rgb8(this->spinners[colorIndex][1]->value()), - rgb8(this->spinners[colorIndex][2]->value()))); - } else { - setRgb(colorIndex, qRgb(this->spinners[colorIndex][0]->value(), - this->spinners[colorIndex][1]->value(), - this->spinners[colorIndex][2]->value())); - } -} - -void PaletteEditor::refreshColorUis() { - int paletteNum = this->ui->spinBox_PaletteId->value(); - for (int i = 0; i < 16; i++) { - QRgb color; - if (paletteNum < Project::getNumPalettesPrimary()) { - color = this->primaryTileset->palettes.at(paletteNum).at(i); - } else { - color = this->secondaryTileset->palettes.at(paletteNum).at(i); - } - - this->updateColorUi(i, color); +void PaletteEditor::refreshColorInputs() { + const int paletteId = ui->spinBox_PaletteId->value(); + Tileset *tileset = getTileset(paletteId); + for (int i = 0; i < this->numColors; i++) { + auto colorInput = this->colorInputs.at(i); + const QSignalBlocker b(colorInput); + colorInput->setColor(tileset->palettes.at(paletteId).at(i)); } } void PaletteEditor::setPaletteId(int paletteId) { - this->ui->spinBox_PaletteId->blockSignals(true); + const QSignalBlocker b(ui->spinBox_PaletteId); this->ui->spinBox_PaletteId->setValue(paletteId); - this->refreshColorUis(); - this->ui->spinBox_PaletteId->blockSignals(false); + this->refreshColorInputs(); } void PaletteEditor::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; - this->refreshColorUis(); -} - -void PaletteEditor::pickColor(int index) { - ColorPicker picker(this); - if (picker.exec() == QDialog::Accepted) { - QColor c = picker.getColor(); - this->setRgb(index, c.rgb()); - } - return; + this->refreshColorInputs(); } void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) { - this->refreshColorUis(); + this->refreshColorInputs(); if (!this->palettesHistory[paletteId].current()) { this->commitEditHistory(paletteId); } emit this->changedPalette(paletteId); } +void PaletteEditor::commitEditHistory() { + commitEditHistory(ui->spinBox_PaletteId->value()); +} + void PaletteEditor::commitEditHistory(int paletteId) { QList colors; - for (int i = 0; i < 16; i++) { - colors.append(qRgb(this->spinners[i][0]->value(), this->spinners[i][1]->value(), this->spinners[i][2]->value())); + for (int i = 0; i < this->numColors; i++) { + colors.append(this->colorInputs.at(i)->color()); } PaletteHistoryItem *commit = new PaletteHistoryItem(colors); this->palettesHistory[paletteId].push(commit); @@ -356,31 +144,16 @@ void PaletteEditor::on_actionUndo_triggered() { int paletteId = this->ui->spinBox_PaletteId->value(); PaletteHistoryItem *prev = this->palettesHistory[paletteId].back(); - this->setColorsFromHistory(prev, paletteId); + if (prev) + setPalette(paletteId, prev->colors); } void PaletteEditor::on_actionRedo_triggered() { int paletteId = this->ui->spinBox_PaletteId->value(); PaletteHistoryItem *next = this->palettesHistory[paletteId].next(); - this->setColorsFromHistory(next, paletteId); -} - -void PaletteEditor::setColorsFromHistory(PaletteHistoryItem *history, int paletteId) { - if (!history) return; - - for (int i = 0; i < 16; i++) { - if (paletteId < Project::getNumPalettesPrimary()) { - this->primaryTileset->palettes[paletteId][i] = history->colors.at(i); - this->primaryTileset->palettePreviews[paletteId][i] = history->colors.at(i); - } else { - this->secondaryTileset->palettes[paletteId][i] = history->colors.at(i); - this->secondaryTileset->palettePreviews[paletteId][i] = history->colors.at(i); - } - } - - this->refreshColorUis(); - emit this->changedPaletteColor(); + if (next) + setPalette(paletteId, next->colors); } void PaletteEditor::on_actionImport_Palette_triggered() @@ -407,10 +180,12 @@ void PaletteEditor::on_actionImport_Palette_triggered() return; } - if (palette.length() < 16) { + if (palette.length() < this->numColors) { QMessageBox msgBox(this); msgBox.setText("Failed to import palette."); - QString message = QString("The palette file has %1 colors, but it must have 16 colors.").arg(palette.length()); + QString message = QString("The palette file has %1 colors, but it must have %2 colors.") + .arg(palette.length()) + .arg(this->numColors); msgBox.setInformativeText(message); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setIcon(QMessageBox::Icon::Critical); @@ -418,20 +193,9 @@ void PaletteEditor::on_actionImport_Palette_triggered() return; } - int paletteId = this->ui->spinBox_PaletteId->value(); - for (int i = 0; i < 16; i++) { - if (paletteId < Project::getNumPalettesPrimary()) { - this->primaryTileset->palettes[paletteId][i] = palette.at(i); - this->primaryTileset->palettePreviews[paletteId][i] = palette.at(i); - } else { - this->secondaryTileset->palettes[paletteId][i] = palette.at(i); - this->secondaryTileset->palettePreviews[paletteId][i] = palette.at(i); - } - } - - this->refreshColorUis(); - this->commitEditHistory(paletteId); - emit this->changedPaletteColor(); + const int paletteId = ui->spinBox_PaletteId->value(); + setPalette(paletteId, palette); + commitEditHistory(paletteId); } void PaletteEditor::closeEvent(QCloseEvent*) {