Skip to content

Commit

Permalink
Merge pull request #381 from gymnast86/tracker-touchups
Browse files Browse the repository at this point in the history
Tracker Touchups
  • Loading branch information
CovenEsme authored Jun 19, 2024
2 parents 7d2aea6 + 46c4e01 commit 2b12e18
Show file tree
Hide file tree
Showing 41 changed files with 474 additions and 223 deletions.
Binary file removed assets/tracker/bottle1.png
Binary file not shown.
Binary file removed assets/tracker/bottle2.png
Binary file not shown.
Binary file removed assets/tracker/bottle3.png
Binary file not shown.
Binary file removed assets/tracker/bottle4.png
Binary file not shown.
Binary file removed assets/tracker/bottle5.png
Binary file not shown.
Binary file removed assets/tracker/pouch1.png
Binary file not shown.
Binary file removed assets/tracker/pouch2.png
Binary file not shown.
Binary file removed assets/tracker/pouch3.png
Binary file not shown.
Binary file removed assets/tracker/pouch4.png
Binary file not shown.
Binary file removed assets/tracker/pouch5.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_10.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_15.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_20.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_25.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_30.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_35.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_40.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_45.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_5.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_50.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_55.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_60.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_65.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_70.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_75.png
Binary file not shown.
Binary file removed assets/tracker/sidequests/crystal_80.png
Diff not rendered.
Binary file removed assets/tracker/songs/song_of_the_hero_1.png
Diff not rendered.
Binary file removed assets/tracker/songs/song_of_the_hero_2.png
Diff not rendered.
Binary file removed assets/tracker/songs/song_of_the_hero_3.png
Diff not rendered.
Binary file removed assets/tracker/songs/song_of_the_hero_4.png
Diff not rendered.
Binary file removed assets/tracker/wallets/extra_wallet_1.png
Diff not rendered.
Binary file removed assets/tracker/wallets/extra_wallet_2.png
Diff not rendered.
Binary file removed assets/tracker/wallets/extra_wallet_3.png
Diff not rendered.
92 changes: 92 additions & 0 deletions gui/components/outlined_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Shamelessly stolen from https://stackoverflow.com/questions/64290561/qlabel-correct-positioning-for-text-outline

import math
from PySide6.QtWidgets import *
from PySide6.QtCore import *
from PySide6.QtGui import *


class OutlinedLabel(QLabel):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.w = 1 / 10
self.mode = True
self.setBrush(Qt.white)
self.setPen(Qt.black)

def scaledOutlineMode(self):
return self.mode

def setScaledOutlineMode(self, state):
self.mode = state

def outlineThickness(self):
return self.w * self.font().pointSize() if self.mode else self.w

def setOutlineThickness(self, value):
self.w = value

def setBrush(self, brush):
if not isinstance(brush, QBrush):
brush = QBrush(brush)
self.brush = brush

def setPen(self, pen):
if not isinstance(pen, QPen):
pen = QPen(pen)
pen.setJoinStyle(Qt.RoundJoin)
self.pen = pen

def sizeHint(self):
w = math.ceil(self.outlineThickness() * 2)
return super().sizeHint() + QSize(w, w)

def minimumSizeHint(self):
w = math.ceil(self.outlineThickness() * 2)
return super().minimumSizeHint() + QSize(w, w)

def paintEvent(self, event):
w = self.outlineThickness()
rect = self.rect()
metrics = QFontMetrics(self.font())
tr = metrics.boundingRect(self.text()).adjusted(0, 0, w, w)
if self.indent() == -1:
if self.frameWidth():
indent = (metrics.boundingRect("x").width() + w * 2) / 2
else:
indent = w
else:
indent = self.indent()

if self.alignment() & Qt.AlignLeft:
x = rect.left() + indent - min(metrics.leftBearing(self.text()[0]), 0)
elif self.alignment() & Qt.AlignRight:
x = rect.x() + rect.width() - indent - tr.width()
else:
x = (rect.width() - tr.width()) / 2

if self.alignment() & Qt.AlignTop:
y = rect.top() + indent + metrics.ascent()
elif self.alignment() & Qt.AlignBottom:
y = rect.y() + rect.height() - indent - metrics.descent()
else:
y = (rect.height() + metrics.ascent() - metrics.descent()) / 2

path = QPainterPath()
path.addText(x, y, self.font(), self.text())
qp = QPainter(self)
qp.setRenderHint(QPainter.Antialiasing)

self.pen.setWidthF(w * 2)
qp.strokePath(path, self.pen)
if self.brush.style() not in [
Qt.BrushStyle.NoBrush,
Qt.BrushStyle.SolidPattern,
Qt.BrushStyle.LinearGradientPattern,
Qt.BrushStyle.ConicalGradientPattern,
Qt.BrushStyle.RadialGradientPattern,
Qt.BrushStyle.TexturePattern,
]:
qp.fillPath(path, self.palette().window())
qp.fillPath(path, self.brush)
62 changes: 55 additions & 7 deletions gui/components/tracker_inventory_button.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
from PySide6.QtWidgets import QLabel, QSizePolicy, QToolTip
from PySide6.QtGui import (
QCursor,
QMouseEvent,
QPaintEvent,
QPainter,
QPixmap,
)
from PySide6.QtGui import *
from PySide6 import QtCore
from PySide6.QtCore import QEvent, QPoint, Signal


from filepathconstants import TRACKER_ASSETS_PATH
from constants.guiconstants import TRACKER_TOOLTIP_STYLESHEET
from gui.components.outlined_label import OutlinedLabel

from logic.world import World, Counter, Location
from logic.item import Item

import math


class TrackerInventoryButton(QLabel):

Expand All @@ -38,6 +35,10 @@ def __init__(
self.sphere_tracked_items: dict[Location, str] = {}
self.inventory: Counter[Item]
self.allow_sphere_tracking: bool = False
self.number_label: OutlinedLabel = None
self.label_offset_x_ratio: float = 0
self.label_offset_y_ratio: float = 0
self.label_scale: float = 1.0
assert len(self.items) == len(self.filenames)

self.setSizePolicy(
Expand Down Expand Up @@ -73,6 +74,17 @@ def update_icon(self) -> None:

self.update() # Calls paintEvent

def create_number_label(self) -> None:
self.number_label = OutlinedLabel(self)
self.number_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)

def set_label_offset_ratios(self, x: float, y: float) -> None:
self.label_offset_x_ratio = x
self.label_offset_y_ratio = y

def set_label_scale(self, scale: float) -> None:
self.label_scale = scale

def paintEvent(self, arg__1: QPaintEvent) -> None:

# Paint the appropriate image scaled to fit inside
Expand All @@ -92,6 +104,42 @@ def paintEvent(self, arg__1: QPaintEvent) -> None:
offset = int((new_height - self.height()) / -2)
painter.drawPixmap(0, offset, self.width(), new_height, self.pixmap)

# Adjust the label if it exists
if self.number_label is not None:
# Keep the font size reasonable. e scales well for whatever reason
pt_size = (min(self.width(), self.height()) // math.e) * self.label_scale
self.number_label.setStyleSheet(f"font-size: {pt_size}pt;")
# If count is 0, don't display the number
if self.state == 0:
self.number_label.setBrush(Qt.transparent)
self.number_label.setPen(Qt.transparent)
# If the count is maxed, set the number as green
elif self.state == len(self.items) - 1:
self.number_label.setBrush(Qt.green)
self.number_label.setPen(Qt.black)
# Otherwise, set it as white
else:
self.number_label.setBrush(Qt.white)
self.number_label.setPen(Qt.black)
# Set the proper text
self.number_label.setText(str(self.state))

# Now we have to do some math to properly center the number regardless of font
font = self.number_label.font()
font.setPointSize(pt_size)
# This is the *font* width of the characters in the string added together
number_advance = QFontMetrics(font).horizontalAdvance(str(self.state))
# This is the *actual* pixel width of the individual number string
number_width = QFontMetrics(font).boundingRect(str(self.state)).width()
# Keep the label centered and adjusted by the offset
x_offset = int(self.label_offset_x_ratio * self.width()) + int(
self.width() / 2 - (number_advance - number_width / 2)
)
y_offset = int(self.label_offset_y_ratio * self.height())
self.number_label.setGeometry(
x_offset - 10, 9 + y_offset, number_advance + 20, self.height() - 20
)

return super().paintEvent(arg__1)

def get_current_item(self) -> Item:
Expand Down
27 changes: 24 additions & 3 deletions gui/dialogs/fi_question_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,35 @@ class FiQuestionDialog:
def __init__(self, parent):
self.parent = parent

def show_dialog(self, title: str, text: str):
# x_button_is_separate makes sure that clicking the x button or hitting ESC returns the Cancel
# value instead of the same value as the No value.
def show_dialog(
self,
title: str,
text: str,
yes_text: str = "",
no_text: str = "",
x_button_is_separate=False,
):
dialog = QMessageBox(self.parent)
dialog.setTextFormat(Qt.TextFormat.RichText)
dialog.setWindowIcon(QIcon(FI_ICON_PATH.as_posix()))
dialog.setIconPixmap(QPixmap(FI_ICON_PATH.as_posix()))
dialog.setWindowTitle(title)
dialog.setText(text)

dialog_yes_button = dialog.addButton(QMessageBox.StandardButton.Yes)
dialog_no_button = dialog.addButton(QMessageBox.StandardButton.No)
self.dialog_yes_button = dialog.addButton(QMessageBox.StandardButton.Yes)
self.dialog_no_button = dialog.addButton(QMessageBox.StandardButton.No)

if x_button_is_separate:
self.dialog_cancel_button = dialog.addButton(
QMessageBox.StandardButton.Cancel
)
self.dialog_cancel_button.setHidden(True)

if yes_text:
self.dialog_yes_button.setText(yes_text)
if no_text:
self.dialog_no_button.setText(no_text)

return dialog.exec()
9 changes: 8 additions & 1 deletion gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from types import TracebackType

from PySide6.QtCore import QEvent, Qt, QSize, QUrl
from PySide6.QtGui import QDesktopServices, QIcon, QMouseEvent, QPixmap
from PySide6.QtGui import QDesktopServices, QIcon, QMouseEvent, QPixmap, QCloseEvent
from PySide6.QtWidgets import (
QApplication,
QMessageBox,
Expand Down Expand Up @@ -248,6 +248,13 @@ def thread_error(self, exception: str, traceback: str):
else:
error_from_str(exception, traceback)

def closeEvent(self, event: QCloseEvent) -> None:
# Autosave tracker on window close if it's active
# This guarantees that the notes will be properly saved
if self.tracker.started:
self.tracker.autosave_tracker()
event.accept()


def start_gui(app: QApplication):
try:
Expand Down
Loading

0 comments on commit 2b12e18

Please sign in to comment.