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
|
||||
|
||||
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.QtCore import Qt, QPoint, pyqtSignal
|
||||
from PyQt6.QtGui import QMouseEvent, QEnterEvent, QPainter, QBrush, QColor
|
||||
from PyQt6.QtCore import Qt, QPoint, pyqtSignal, QSize
|
||||
from PyQt6.QtGui import QMouseEvent, QEnterEvent, QFont, QGraphicsDropShadowEffect, QColor
|
||||
|
||||
|
||||
class FloatingIcon(QWidget):
|
||||
"""Draggable floating icon for in-game use."""
|
||||
"""Draggable floating icon that matches Entropia Universe UI."""
|
||||
|
||||
clicked = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
# Frameless, always on top
|
||||
# Frameless, always on top, click-through when not interacting
|
||||
self.setWindowFlags(
|
||||
Qt.WindowType.FramelessWindowHint |
|
||||
Qt.WindowType.WindowStaysOnTopHint |
|
||||
Qt.WindowType.Tool |
|
||||
Qt.WindowType.WindowTransparentForInput
|
||||
Qt.WindowType.Tool
|
||||
)
|
||||
|
||||
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()
|
||||
self.move(10, 10)
|
||||
# Position near other game UI elements (top left area)
|
||||
self.move(250, 10)
|
||||
|
||||
self.dragging = False
|
||||
self.drag_position = QPoint()
|
||||
self.click_threshold = 5 # pixels
|
||||
self.click_start_pos = QPoint()
|
||||
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""Setup the floating icon."""
|
||||
"""Setup the floating icon with EU-style."""
|
||||
layout = QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(0)
|
||||
|
||||
self.icon_label = QLabel("⚡")
|
||||
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("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
background-color: rgba(30, 30, 30, 200);
|
||||
border-radius: 24px;
|
||||
border: 2px solid rgba(74, 158, 255, 150);
|
||||
font-size: 20px;
|
||||
background-color: rgba(20, 25, 35, 220);
|
||||
border-radius: 8px;
|
||||
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)
|
||||
|
||||
def mousePressEvent(self, event: QMouseEvent):
|
||||
"""Handle mouse press."""
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
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()
|
||||
|
||||
def mouseMoveEvent(self, event: QMouseEvent):
|
||||
|
|
@ -69,35 +85,45 @@ class FloatingIcon(QWidget):
|
|||
event.accept()
|
||||
|
||||
def mouseReleaseEvent(self, event: QMouseEvent):
|
||||
"""Handle mouse release."""
|
||||
"""Handle mouse release - detect click vs drag."""
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self.dragging = False
|
||||
# If didn't move much, treat as click
|
||||
event.accept()
|
||||
release_pos = event.globalPosition().toPoint()
|
||||
distance = (release_pos - self.click_start_pos).manhattanLength()
|
||||
|
||||
def mouseDoubleClickEvent(self, event: QMouseEvent):
|
||||
"""Handle double click."""
|
||||
self.dragging = False
|
||||
|
||||
# If moved less than threshold, treat as click
|
||||
if distance < self.click_threshold:
|
||||
self.clicked.emit()
|
||||
|
||||
event.accept()
|
||||
|
||||
def enterEvent(self, event: QEnterEvent):
|
||||
"""Mouse entered - highlight."""
|
||||
"""Mouse entered - highlight like EU UI."""
|
||||
self.icon_label.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
background-color: rgba(74, 158, 255, 200);
|
||||
border-radius: 24px;
|
||||
border: 2px solid rgba(255, 255, 255, 200);
|
||||
font-size: 20px;
|
||||
background-color: rgba(40, 55, 75, 240);
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(100, 180, 255, 150);
|
||||
}
|
||||
""")
|
||||
# Change cursor to indicate clickable
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
|
||||
def leaveEvent(self, event):
|
||||
"""Mouse left - normal."""
|
||||
"""Mouse left - normal EU style."""
|
||||
self.icon_label.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 24px;
|
||||
background-color: rgba(30, 30, 30, 200);
|
||||
border-radius: 24px;
|
||||
border: 2px solid rgba(74, 158, 255, 150);
|
||||
font-size: 20px;
|
||||
background-color: rgba(20, 25, 35, 220);
|
||||
border-radius: 8px;
|
||||
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