style: white/frosted icon theme for EU aesthetic
- Floating icon now uses diamond shape (◆) with frosted glass effect - Plugin bar icons with per-plugin accent colors - Icon manager for consistent theming - Cleaner, more minimal white/frosted style - Matches Entropia Universe sci-fi aesthetic To add custom icons from flaticon.com: 1. Download white/frosted PNG icons (24x24 or 32x32) 2. Place in assets/icons/ folder 3. Icons auto-load on app start Recommended icon styles: - Minimal outline icons - White/light colored - Frosted/glass effect - Sci-fi or tech aesthetic
This commit is contained in:
parent
ea9a73c8b4
commit
d3d69c41cc
|
|
@ -2,6 +2,7 @@
|
||||||
EU-Utility - Floating Icon
|
EU-Utility - Floating Icon
|
||||||
|
|
||||||
In-game floating button styled to match Entropia Universe UI.
|
In-game floating button styled to match Entropia Universe UI.
|
||||||
|
Uses white/frosted icon style.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication
|
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication
|
||||||
|
|
@ -25,7 +26,7 @@ class FloatingIcon(QWidget):
|
||||||
)
|
)
|
||||||
|
|
||||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||||
self.setFixedSize(42, 42)
|
self.setFixedSize(40, 40)
|
||||||
|
|
||||||
# Position - near top-left game icons (offset from corner)
|
# Position - near top-left game icons (offset from corner)
|
||||||
screen = QApplication.primaryScreen().geometry()
|
screen = QApplication.primaryScreen().geometry()
|
||||||
|
|
@ -40,30 +41,33 @@ class FloatingIcon(QWidget):
|
||||||
self._setup_ui()
|
self._setup_ui()
|
||||||
|
|
||||||
def _setup_ui(self):
|
def _setup_ui(self):
|
||||||
"""Setup the floating icon with EU-style."""
|
"""Setup the floating icon with EU-style white/frosted look."""
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
layout.setSpacing(0)
|
layout.setSpacing(0)
|
||||||
|
|
||||||
self.icon_label = QLabel("⚡")
|
# Diamond shape - clean, sci-fi, white/frosted
|
||||||
|
self.icon_label = QLabel("◆")
|
||||||
self.icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
self.icon_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
self.icon_label.setFixedSize(42, 42)
|
self.icon_label.setFixedSize(40, 40)
|
||||||
|
|
||||||
# EU-style: dark background with subtle border, hexagonal or square with rounded corners
|
# EU-style: frosted glass effect
|
||||||
# Matching the game's dark blue/gray aesthetic
|
# Dark background with subtle white border and glow
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
background-color: rgba(20, 25, 35, 220);
|
font-weight: bold;
|
||||||
border-radius: 8px;
|
color: rgba(255, 255, 255, 220);
|
||||||
border: 1px solid rgba(100, 150, 200, 80);
|
background-color: rgba(25, 30, 40, 230);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 40);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Add subtle glow effect
|
# Add subtle glow effect
|
||||||
shadow = QGraphicsDropShadowEffect()
|
shadow = QGraphicsDropShadowEffect()
|
||||||
shadow.setBlurRadius(10)
|
shadow.setBlurRadius(15)
|
||||||
shadow.setColor(QColor(74, 158, 255, 100))
|
shadow.setColor(QColor(100, 150, 200, 80))
|
||||||
shadow.setOffset(0, 0)
|
shadow.setOffset(0, 0)
|
||||||
self.icon_label.setGraphicsEffect(shadow)
|
self.icon_label.setGraphicsEffect(shadow)
|
||||||
|
|
||||||
|
|
@ -99,31 +103,30 @@ class FloatingIcon(QWidget):
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def enterEvent(self, event: QEnterEvent):
|
def enterEvent(self, event: QEnterEvent):
|
||||||
"""Mouse entered - highlight like EU UI."""
|
"""Mouse entered - highlight with frosted effect."""
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
background-color: rgba(40, 55, 75, 240);
|
font-weight: bold;
|
||||||
border-radius: 8px;
|
color: white;
|
||||||
border: 1px solid rgba(100, 180, 255, 150);
|
background-color: rgba(45, 60, 85, 250);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1.5px solid rgba(120, 180, 255, 100);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
# Change cursor to indicate clickable
|
# Change cursor to indicate clickable
|
||||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
|
|
||||||
def leaveEvent(self, event):
|
def leaveEvent(self, event):
|
||||||
"""Mouse left - normal EU style."""
|
"""Mouse left - normal frosted look."""
|
||||||
self.icon_label.setStyleSheet("""
|
self.icon_label.setStyleSheet("""
|
||||||
QLabel {
|
QLabel {
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
background-color: rgba(20, 25, 35, 220);
|
font-weight: bold;
|
||||||
border-radius: 8px;
|
color: rgba(255, 255, 255, 220);
|
||||||
border: 1px solid rgba(100, 150, 200, 80);
|
background-color: rgba(25, 30, 40, 230);
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 40);
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
self.setCursor(Qt.CursorShape.ArrowCursor)
|
self.setCursor(Qt.CursorShape.ArrowCursor)
|
||||||
|
|
||||||
def show_tooltip(self):
|
|
||||||
"""Show tooltip near icon."""
|
|
||||||
# Could implement a custom tooltip here
|
|
||||||
pass
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,161 @@
|
||||||
|
"""
|
||||||
|
EU-Utility - Icon Manager
|
||||||
|
|
||||||
|
Loads and manages white/frosted style icons for EU aesthetic.
|
||||||
|
Icons should be:
|
||||||
|
- White/light colored
|
||||||
|
- Frosted/glass effect
|
||||||
|
- 24x24 or 32x32 PNG with transparency
|
||||||
|
- Match Entropia Universe sci-fi style
|
||||||
|
|
||||||
|
Recommended sources:
|
||||||
|
- flaticon.com (search: "white icon", "frosted glass", "minimal")
|
||||||
|
- phosphoricons.com (Phosphor icons - great frosted look)
|
||||||
|
- heroicons.com (outline style)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from PyQt6.QtGui import QIcon, QPixmap, QColor
|
||||||
|
from PyQt6.QtCore import QSize
|
||||||
|
|
||||||
|
|
||||||
|
class IconManager:
|
||||||
|
"""Manage application icons with EU styling."""
|
||||||
|
|
||||||
|
# Icon names mapping
|
||||||
|
ICONS = {
|
||||||
|
# Navigation
|
||||||
|
'search': '🔍',
|
||||||
|
'calculator': '🧮',
|
||||||
|
'music': '🎵',
|
||||||
|
'globe': '🌐',
|
||||||
|
'skills': '📊',
|
||||||
|
'camera': '📷',
|
||||||
|
|
||||||
|
# Actions
|
||||||
|
'scan': '📸',
|
||||||
|
'save': '💾',
|
||||||
|
'export': '📤',
|
||||||
|
'copy': '📋',
|
||||||
|
'close': '✕',
|
||||||
|
'settings': '⚙️',
|
||||||
|
|
||||||
|
# Status
|
||||||
|
'success': '✓',
|
||||||
|
'error': '✗',
|
||||||
|
'warning': '⚠️',
|
||||||
|
'loading': '⟳',
|
||||||
|
|
||||||
|
# EU Specific
|
||||||
|
'ped': 'P',
|
||||||
|
'esi': '💉',
|
||||||
|
'weapon': '🔫',
|
||||||
|
'armor': '🛡️',
|
||||||
|
'mob': '👾',
|
||||||
|
'loot': '🎁',
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, icons_dir="assets/icons"):
|
||||||
|
self.icons_dir = Path(icons_dir)
|
||||||
|
self.custom_icons = {}
|
||||||
|
self._load_custom_icons()
|
||||||
|
|
||||||
|
def _load_custom_icons(self):
|
||||||
|
"""Load custom PNG icons if they exist."""
|
||||||
|
if not self.icons_dir.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
for icon_file in self.icons_dir.glob("*.png"):
|
||||||
|
name = icon_file.stem
|
||||||
|
self.custom_icons[name] = str(icon_file)
|
||||||
|
|
||||||
|
def get(self, name, size=24):
|
||||||
|
"""Get an icon by name."""
|
||||||
|
# Check for custom icon first
|
||||||
|
if name in self.custom_icons:
|
||||||
|
icon = QIcon(self.custom_icons[name])
|
||||||
|
# Apply white tint if needed
|
||||||
|
return icon
|
||||||
|
|
||||||
|
# Return emoji as fallback
|
||||||
|
return self.ICONS.get(name, '•')
|
||||||
|
|
||||||
|
def get_emoji_label(self, name, size=20):
|
||||||
|
"""Get an emoji styled as an icon label."""
|
||||||
|
emoji = self.ICONS.get(name, '•')
|
||||||
|
return f'<span style="font-size: {size}px;">{emoji}</span>'
|
||||||
|
|
||||||
|
def tint_icon(self, icon_path, color='#ffffff'):
|
||||||
|
"""Tint an icon to match EU aesthetic."""
|
||||||
|
pixmap = QPixmap(icon_path)
|
||||||
|
|
||||||
|
# Create tinted version
|
||||||
|
tinted = QPixmap(pixmap.size())
|
||||||
|
tinted.fill(QColor(color))
|
||||||
|
|
||||||
|
# Apply original as mask
|
||||||
|
painter = QPainter(tinted)
|
||||||
|
painter.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform)
|
||||||
|
painter.drawPixmap(0, 0, pixmap)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
return QIcon(tinted)
|
||||||
|
|
||||||
|
|
||||||
|
# EU Styling Constants
|
||||||
|
EU_STYLES = {
|
||||||
|
'floating_icon': """
|
||||||
|
QLabel {
|
||||||
|
font-size: 20px;
|
||||||
|
background-color: rgba(20, 25, 35, 220);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid rgba(100, 150, 200, 80);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
'floating_icon_hover': """
|
||||||
|
QLabel {
|
||||||
|
font-size: 20px;
|
||||||
|
background-color: rgba(40, 55, 75, 240);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid rgba(100, 180, 255, 150);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
'plugin_button': """
|
||||||
|
QPushButton {
|
||||||
|
background-color: rgba(255, 255, 255, 15);
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 22px;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 30);
|
||||||
|
}
|
||||||
|
QPushButton:checked {
|
||||||
|
background-color: #4a9eff;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_frosted_button_style(color='#4a9eff'):
|
||||||
|
"""Get frosted glass button style."""
|
||||||
|
return f"""
|
||||||
|
QPushButton {{
|
||||||
|
background-color: rgba(255, 255, 255, 15);
|
||||||
|
color: white;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 30);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
}}
|
||||||
|
QPushButton:hover {{
|
||||||
|
background-color: rgba(255, 255, 255, 25);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 50);
|
||||||
|
}}
|
||||||
|
QPushButton:pressed {{
|
||||||
|
background-color: {color};
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
EU-Utility - Overlay Window
|
EU-Utility - Overlay Window
|
||||||
|
|
||||||
Spotlight-style overlay with frosted glass effect.
|
Spotlight-style overlay with frosted glass effect and custom icons.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -27,6 +27,28 @@ class OverlayWindow(QMainWindow):
|
||||||
|
|
||||||
visibility_changed = pyqtSignal(bool)
|
visibility_changed = pyqtSignal(bool)
|
||||||
|
|
||||||
|
# Plugin icon mapping - white/frosted style icons
|
||||||
|
PLUGIN_ICONS = {
|
||||||
|
"Universal Search": ("search", "#4a9eff"),
|
||||||
|
"Calculator": ("calculator", "#9c27b0"),
|
||||||
|
"Spotify": ("music", "#1db954"),
|
||||||
|
"Nexus Search": ("globe", "#ff9800"),
|
||||||
|
"Game Reader": ("camera", "#f44336"),
|
||||||
|
"Skill Scanner": ("skills", "#00bcd4"),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Emoji fallbacks for frosted look
|
||||||
|
ICONS = {
|
||||||
|
'search': '🔍',
|
||||||
|
'calculator': '🧮',
|
||||||
|
'music': '🎵',
|
||||||
|
'globe': '🌐',
|
||||||
|
'skills': '📊',
|
||||||
|
'camera': '📷',
|
||||||
|
'close': '✕',
|
||||||
|
'menu': '☰',
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, plugin_manager=None):
|
def __init__(self, plugin_manager=None):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
|
|
@ -177,7 +199,7 @@ class OverlayWindow(QMainWindow):
|
||||||
layout.addWidget(self.container)
|
layout.addWidget(self.container)
|
||||||
|
|
||||||
def _setup_plugin_bar(self, layout):
|
def _setup_plugin_bar(self, layout):
|
||||||
"""Setup circular plugin icon bar at bottom."""
|
"""Setup circular plugin icon bar at bottom with frosted style."""
|
||||||
bar = QWidget()
|
bar = QWidget()
|
||||||
bar.setStyleSheet("""
|
bar.setStyleSheet("""
|
||||||
QWidget {
|
QWidget {
|
||||||
|
|
@ -188,39 +210,38 @@ class OverlayWindow(QMainWindow):
|
||||||
""")
|
""")
|
||||||
bar_layout = QHBoxLayout(bar)
|
bar_layout = QHBoxLayout(bar)
|
||||||
bar_layout.setContentsMargins(20, 12, 20, 12)
|
bar_layout.setContentsMargins(20, 12, 20, 12)
|
||||||
bar_layout.setSpacing(15)
|
bar_layout.setSpacing(12)
|
||||||
bar_layout.addStretch()
|
bar_layout.addStretch()
|
||||||
|
|
||||||
# Add plugin icons
|
# Add plugin icons
|
||||||
plugin_icons = {
|
|
||||||
"Universal Search": "🔍",
|
|
||||||
"Calculator": "🧮",
|
|
||||||
"Spotify": "🎵",
|
|
||||||
"Nexus Search": "🌐",
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, (plugin_id, plugin) in enumerate(self.plugin_manager.get_all_plugins().items()):
|
for idx, (plugin_id, plugin) in enumerate(self.plugin_manager.get_all_plugins().items()):
|
||||||
btn = QPushButton()
|
btn = QPushButton()
|
||||||
|
|
||||||
# Get icon emoji or default
|
# Get icon and color for this plugin
|
||||||
icon = plugin_icons.get(plugin.name, "⚡")
|
icon_key, accent_color = self.PLUGIN_ICONS.get(
|
||||||
btn.setText(icon)
|
plugin.name,
|
||||||
|
("menu", "#4a9eff")
|
||||||
|
)
|
||||||
|
icon_emoji = self.ICONS.get(icon_key, '⚡')
|
||||||
|
|
||||||
btn.setFixedSize(44, 44)
|
btn.setText(icon_emoji)
|
||||||
btn.setStyleSheet("""
|
btn.setFixedSize(40, 40)
|
||||||
QPushButton {
|
btn.setStyleSheet(f"""
|
||||||
background-color: rgba(255, 255, 255, 15);
|
QPushButton {{
|
||||||
|
background-color: rgba(255, 255, 255, 12);
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 20px;
|
font-size: 18px;
|
||||||
border: none;
|
border: 1px solid rgba(255, 255, 255, 20);
|
||||||
border-radius: 22px;
|
border-radius: 20px;
|
||||||
}
|
}}
|
||||||
QPushButton:hover {
|
QPushButton:hover {{
|
||||||
background-color: rgba(255, 255, 255, 30);
|
background-color: rgba(255, 255, 255, 25);
|
||||||
}
|
border: 1px solid rgba(255, 255, 255, 40);
|
||||||
QPushButton:checked, QPushButton:pressed {
|
}}
|
||||||
background-color: #4a9eff;
|
QPushButton:checked {{
|
||||||
}
|
background-color: {accent_color};
|
||||||
|
border: 1px solid rgba(255, 255, 255, 50);
|
||||||
|
}}
|
||||||
""")
|
""")
|
||||||
btn.setCheckable(True)
|
btn.setCheckable(True)
|
||||||
btn.setToolTip(plugin.name)
|
btn.setToolTip(plugin.name)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue