feat: EU-styled floating icon positioned near game UI
- Floating icon now matches Entropia Universe aesthetic - Dark blue/gray background with subtle border - Positioned at top-left (250, 10) near other game icons - Click vs drag detection (5px threshold) - Hover effect with lighter border - Subtle blue glow effect
This commit is contained in:
parent
d74de07110
commit
b00792726d
|
|
@ -1,64 +1,80 @@
|
||||||
"""
|
"""
|
||||||
EU-Utility - Floating Icon
|
EU-Utility - Floating Icon
|
||||||
|
|
||||||
A draggable floating button for easy access in-game.
|
In-game floating button styled to match Entropia Universe UI.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication
|
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication
|
||||||
from PyQt6.QtCore import Qt, QPoint, pyqtSignal
|
from PyQt6.QtCore import Qt, QPoint, pyqtSignal, QSize
|
||||||
from PyQt6.QtGui import QMouseEvent, QEnterEvent, QPainter, QBrush, QColor
|
from PyQt6.QtGui import QMouseEvent, QEnterEvent, QFont, QGraphicsDropShadowEffect, QColor
|
||||||
|
|
||||||
|
|
||||||
class FloatingIcon(QWidget):
|
class FloatingIcon(QWidget):
|
||||||
"""Draggable floating icon for in-game use."""
|
"""Draggable floating icon that matches Entropia Universe UI."""
|
||||||
|
|
||||||
clicked = pyqtSignal()
|
clicked = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
# Frameless, always on top
|
# Frameless, always on top, click-through when not interacting
|
||||||
self.setWindowFlags(
|
self.setWindowFlags(
|
||||||
Qt.WindowType.FramelessWindowHint |
|
Qt.WindowType.FramelessWindowHint |
|
||||||
Qt.WindowType.WindowStaysOnTopHint |
|
Qt.WindowType.WindowStaysOnTopHint |
|
||||||
Qt.WindowType.Tool |
|
Qt.WindowType.Tool
|
||||||
Qt.WindowType.WindowTransparentForInput
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
self.setFixedSize(48, 48)
|
self.setFixedSize(42, 42)
|
||||||
|
|
||||||
# Position - top left with offset
|
# Position - near top-left game icons (offset from corner)
|
||||||
screen = QApplication.primaryScreen().geometry()
|
screen = QApplication.primaryScreen().geometry()
|
||||||
self.move(10, 10)
|
# Position near other game UI elements (top left area)
|
||||||
|
self.move(250, 10)
|
||||||
|
|
||||||
self.dragging = False
|
self.dragging = False
|
||||||
self.drag_position = QPoint()
|
self.drag_position = QPoint()
|
||||||
|
self.click_threshold = 5 # pixels
|
||||||
|
self.click_start_pos = QPoint()
|
||||||
|
|
||||||
self._setup_ui()
|
self._setup_ui()
|
||||||
|
|
||||||
def _setup_ui(self):
|
def _setup_ui(self):
|
||||||
"""Setup the floating icon."""
|
"""Setup the floating icon with EU-style."""
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
layout.setSpacing(0)
|
||||||
|
|
||||||
self.icon_label = QLabel("⚡")
|
self.icon_label = QLabel("⚡")
|
||||||
self.icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
self.icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
self.icon_label.setFixedSize(42, 42)
|
||||||
|
|
||||||
|
# EU-style: dark background with subtle border, hexagonal or square with rounded corners
|
||||||
|
# Matching the game's dark blue/gray aesthetic
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
background-color: rgba(30, 30, 30, 200);
|
background-color: rgba(20, 25, 35, 220);
|
||||||
border-radius: 24px;
|
border-radius: 8px;
|
||||||
border: 2px solid rgba(74, 158, 255, 150);
|
border: 1px solid rgba(100, 150, 200, 80);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
# Add subtle glow effect
|
||||||
|
shadow = QGraphicsDropShadowEffect()
|
||||||
|
shadow.setBlurRadius(10)
|
||||||
|
shadow.setColor(QColor(74, 158, 255, 100))
|
||||||
|
shadow.setOffset(0, 0)
|
||||||
|
self.icon_label.setGraphicsEffect(shadow)
|
||||||
|
|
||||||
layout.addWidget(self.icon_label)
|
layout.addWidget(self.icon_label)
|
||||||
|
|
||||||
def mousePressEvent(self, event: QMouseEvent):
|
def mousePressEvent(self, event: QMouseEvent):
|
||||||
"""Handle mouse press."""
|
"""Handle mouse press."""
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
if event.button() == Qt.MouseButton.LeftButton:
|
||||||
self.dragging = True
|
self.dragging = True
|
||||||
self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
self.click_start_pos = event.globalPosition().toPoint()
|
||||||
|
self.drag_position = self.click_start_pos - self.frameGeometry().topLeft()
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def mouseMoveEvent(self, event: QMouseEvent):
|
def mouseMoveEvent(self, event: QMouseEvent):
|
||||||
|
|
@ -69,35 +85,45 @@ class FloatingIcon(QWidget):
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event: QMouseEvent):
|
def mouseReleaseEvent(self, event: QMouseEvent):
|
||||||
"""Handle mouse release."""
|
"""Handle mouse release - detect click vs drag."""
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
if event.button() == Qt.MouseButton.LeftButton:
|
||||||
self.dragging = False
|
release_pos = event.globalPosition().toPoint()
|
||||||
# If didn't move much, treat as click
|
distance = (release_pos - self.click_start_pos).manhattanLength()
|
||||||
event.accept()
|
|
||||||
|
|
||||||
def mouseDoubleClickEvent(self, event: QMouseEvent):
|
self.dragging = False
|
||||||
"""Handle double click."""
|
|
||||||
|
# If moved less than threshold, treat as click
|
||||||
|
if distance < self.click_threshold:
|
||||||
self.clicked.emit()
|
self.clicked.emit()
|
||||||
|
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def enterEvent(self, event: QEnterEvent):
|
def enterEvent(self, event: QEnterEvent):
|
||||||
"""Mouse entered - highlight."""
|
"""Mouse entered - highlight like EU UI."""
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
background-color: rgba(74, 158, 255, 200);
|
background-color: rgba(40, 55, 75, 240);
|
||||||
border-radius: 24px;
|
border-radius: 8px;
|
||||||
border: 2px solid rgba(255, 255, 255, 200);
|
border: 1px solid rgba(100, 180, 255, 150);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
# Change cursor to indicate clickable
|
||||||
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
|
||||||
def leaveEvent(self, event):
|
def leaveEvent(self, event):
|
||||||
"""Mouse left - normal."""
|
"""Mouse left - normal EU style."""
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 24px;
|
font-size: 20px;
|
||||||
background-color: rgba(30, 30, 30, 200);
|
background-color: rgba(20, 25, 35, 220);
|
||||||
border-radius: 24px;
|
border-radius: 8px;
|
||||||
border: 2px solid rgba(74, 158, 255, 150);
|
border: 1px solid rgba(100, 150, 200, 80);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
self.setCursor(Qt.CursorShape.ArrowCursor)
|
||||||
|
|
||||||
|
def show_tooltip(self):
|
||||||
|
"""Show tooltip near icon."""
|
||||||
|
# Could implement a custom tooltip here
|
||||||
|
pass
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue