From b00792726d031004d1f57daaa702379f06f0b956 Mon Sep 17 00:00:00 2001 From: LemonNexus Date: Fri, 13 Feb 2026 13:17:11 +0000 Subject: [PATCH] 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 --- projects/EU-Utility/core/floating_icon.py | 92 +++++++++++++++-------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/projects/EU-Utility/core/floating_icon.py b/projects/EU-Utility/core/floating_icon.py index e73bf2c..7fcc1c0 100644 --- a/projects/EU-Utility/core/floating_icon.py +++ b/projects/EU-Utility/core/floating_icon.py @@ -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: + release_pos = event.globalPosition().toPoint() + distance = (release_pos - self.click_start_pos).manhattanLength() + self.dragging = False - # If didn't move much, treat as click + + # If moved less than threshold, treat as click + if distance < self.click_threshold: + self.clicked.emit() + event.accept() - def mouseDoubleClickEvent(self, event: QMouseEvent): - """Handle double click.""" - 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