mirror of
https://gitea.shironeko-all.duckdns.org/shironeko/Hytale-F2P-2.git
synced 2026-02-26 10:41:46 -03:00
Merge GPU preference feature branch to main branch version 2.0.2 for testing (#3)
* modernized UI for GPU Preference option * feat: auto-detect dedicated GPU on hybrid laptops (iGPU+dGPU) * feat: detailed GPU info in auto-detection feature on startup * feat: add GPU options for launcher - Add GPU preference setting (Auto/Integrated/Dedicated) - Implement Linux GPU selection with DRI_PRIME and NVIDIA env vars - Add GPU detection using Electron's app.getGPUInfo() - Update settings UI with GPU preference dropdown - Integrate GPU preference into game launch process * feat: auto-detect dedicated GPU on hybrid laptops (iGPU+dGPU) * added fallbacks to and option to use integrated GPU. * add package-lock and fix deps version * changed 'Nvidia' string to 'NVIDIA' * fix: selecting `dedicated` option while using nvidia GPU did not set its specific env variables * remove unused `CONFIG_FILE` variable on launcher core modules * fix: duplicated save-load gpu detection functions * move game option settings to the top, while custom java to the bottom * fix: settings-header margin-bottom from 3rem to 1rem and supress line-clamp warning
This commit is contained in:
@@ -365,6 +365,41 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-input-group">
|
||||
<label class="settings-input-label">GPU Preference</label>
|
||||
<div class="segmented-control">
|
||||
<input type="radio" id="gpu-auto" name="gpuPreference" value="auto" checked>
|
||||
<label for="gpu-auto">Auto</label>
|
||||
<input type="radio" id="gpu-integrated" name="gpuPreference" value="integrated">
|
||||
<label for="gpu-integrated">Integrated</label>
|
||||
<input type="radio" id="gpu-dedicated" name="gpuPreference" value="dedicated">
|
||||
<label for="gpu-dedicated">Dedicated</label>
|
||||
</div>
|
||||
<p class="settings-hint">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Select your preferred GPU (Linux: affects DRI_PRIME)
|
||||
</p>
|
||||
<div id="gpu-detection-info" class="gpu-detection-info"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h3 class="settings-section-title">
|
||||
<i class="fab fa-discord"></i>
|
||||
Discord Integration
|
||||
</h3>
|
||||
|
||||
<div class="settings-option">
|
||||
<label class="settings-checkbox">
|
||||
<input type="checkbox" id="discordRPCCheck" checked />
|
||||
<span class="checkmark"></span>
|
||||
<div class="checkbox-content">
|
||||
<div class="checkbox-title">Enable Discord Rich Presence</div>
|
||||
<div class="checkbox-description">Show your launcher activity on Discord</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
@@ -406,6 +441,48 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h3 class="settings-section-title">
|
||||
<i class="fas fa-coffee"></i>
|
||||
Java Runtime
|
||||
</h3>
|
||||
|
||||
<div class="settings-option">
|
||||
<label class="settings-checkbox">
|
||||
<input type="checkbox" id="customJavaCheck" />
|
||||
<span class="checkmark"></span>
|
||||
<div class="checkbox-content">
|
||||
<div class="checkbox-title">Use Custom Java Path</div>
|
||||
<div class="checkbox-description">Override the bundled Java runtime with your own installation</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="customJavaOptions" class="custom-java-options" style="display: none;">
|
||||
<div class="settings-input-group">
|
||||
<label class="settings-input-label">Java Executable Path</label>
|
||||
<div class="settings-input-with-button">
|
||||
<input
|
||||
type="text"
|
||||
id="customJavaPath"
|
||||
class="settings-input"
|
||||
placeholder="Select Java path..."
|
||||
readonly
|
||||
/>
|
||||
<button id="browseJavaBtn" class="settings-browse-btn">
|
||||
<i class="fas fa-folder-open"></i>
|
||||
Browse
|
||||
</button>
|
||||
</div>
|
||||
<p class="settings-hint">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Select the Java installation folder (supports Windows, Mac, Linux)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -211,6 +211,15 @@ export async function launch() {
|
||||
if (window.SettingsAPI && window.SettingsAPI.getCurrentJavaPath) {
|
||||
javaPath = window.SettingsAPI.getCurrentJavaPath();
|
||||
}
|
||||
|
||||
let gpuPreference = 'auto';
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.loadGpuPreference) {
|
||||
gpuPreference = await window.electronAPI.loadGpuPreference();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading GPU preference:', error);
|
||||
}
|
||||
|
||||
if (window.LauncherUI) window.LauncherUI.showProgress();
|
||||
isDownloading = true;
|
||||
@@ -223,8 +232,8 @@ export async function launch() {
|
||||
if (window.LauncherUI) window.LauncherUI.updateProgress({ message: 'Starting game...' });
|
||||
|
||||
if (window.electronAPI && window.electronAPI.launchGame) {
|
||||
const result = await window.electronAPI.launchGame(playerName, javaPath, '');
|
||||
|
||||
const result = await window.electronAPI.launchGame(playerName, javaPath, '', gpuPreference);
|
||||
|
||||
isDownloading = false;
|
||||
|
||||
if (window.LauncherUI) {
|
||||
|
||||
@@ -5,6 +5,7 @@ let customJavaPath;
|
||||
let browseJavaBtn;
|
||||
let settingsPlayerName;
|
||||
let discordRPCCheck;
|
||||
let gpuPreferenceRadios;
|
||||
|
||||
// UUID Management elements
|
||||
let currentUuidDisplay;
|
||||
@@ -142,6 +143,7 @@ function showCustomConfirm(message, title = 'Confirm Action', onConfirm, onCance
|
||||
document.addEventListener('keydown', handleEscape);
|
||||
}
|
||||
|
||||
|
||||
export function initSettings() {
|
||||
setupSettingsElements();
|
||||
loadAllSettings();
|
||||
@@ -154,6 +156,7 @@ function setupSettingsElements() {
|
||||
browseJavaBtn = document.getElementById('browseJavaBtn');
|
||||
settingsPlayerName = document.getElementById('settingsPlayerName');
|
||||
discordRPCCheck = document.getElementById('discordRPCCheck');
|
||||
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
|
||||
|
||||
// UUID Management elements
|
||||
currentUuidDisplay = document.getElementById('currentUuid');
|
||||
@@ -226,6 +229,15 @@ function setupSettingsElements() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (gpuPreferenceRadios) {
|
||||
gpuPreferenceRadios.forEach(radio => {
|
||||
radio.addEventListener('change', async () => {
|
||||
await saveGpuPreference();
|
||||
await updateGpuLabel();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleCustomJava() {
|
||||
@@ -361,11 +373,85 @@ async function loadPlayerName() {
|
||||
}
|
||||
}
|
||||
|
||||
async function saveGpuPreference() {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.saveGpuPreference && gpuPreferenceRadios) {
|
||||
const gpuPreference = Array.from(gpuPreferenceRadios).find(radio => radio.checked)?.value || 'auto';
|
||||
await window.electronAPI.saveGpuPreference(gpuPreference);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving GPU preference:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateGpuLabel() {
|
||||
const detectionInfo = document.getElementById('gpu-detection-info');
|
||||
if (!detectionInfo) return;
|
||||
|
||||
if (gpuPreferenceRadios) {
|
||||
const checked = Array.from(gpuPreferenceRadios).find(radio => radio.checked);
|
||||
if (checked) {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.getDetectedGpu) {
|
||||
const detected = await window.electronAPI.getDetectedGpu();
|
||||
if (checked.value === 'auto') {
|
||||
if (detected.dedicatedName) {
|
||||
detectionInfo.textContent = `dGPU detected, using ${detected.dedicatedName}`;
|
||||
} else {
|
||||
detectionInfo.textContent = `dGPU not detected, using iGPU (${detected.integratedName}) instead`;
|
||||
}
|
||||
detectionInfo.style.display = 'block';
|
||||
} else if (checked.value === 'integrated') {
|
||||
detectionInfo.textContent = `Detected: ${detected.integratedName}`;
|
||||
detectionInfo.style.display = 'block';
|
||||
} else if (checked.value === 'dedicated') {
|
||||
if (detected.dedicatedName) {
|
||||
detectionInfo.textContent = `Detected: ${detected.dedicatedName}`;
|
||||
} else {
|
||||
detectionInfo.textContent = `No dedicated GPU detected`;
|
||||
}
|
||||
detectionInfo.style.display = 'block';
|
||||
} else {
|
||||
detectionInfo.style.display = 'none';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error getting detected GPU:', error);
|
||||
detectionInfo.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
detectionInfo.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
detectionInfo.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGpuPreference() {
|
||||
try {
|
||||
if (window.electronAPI && window.electronAPI.loadGpuPreference && gpuPreferenceRadios) {
|
||||
const savedPreference = await window.electronAPI.loadGpuPreference();
|
||||
if (savedPreference) {
|
||||
for (const radio of gpuPreferenceRadios) {
|
||||
if (radio.value === savedPreference) {
|
||||
radio.checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await updateGpuLabel();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading GPU preference:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAllSettings() {
|
||||
await loadCustomJavaPath();
|
||||
await loadPlayerName();
|
||||
await loadCurrentUuid();
|
||||
await loadDiscordRPC();
|
||||
await loadGpuPreference();
|
||||
}
|
||||
|
||||
async function openGameLocation() {
|
||||
|
||||
@@ -1005,6 +1005,7 @@ body {
|
||||
transform: translateY(0.5rem);
|
||||
transition: all 0.3s ease 0.1s;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
@@ -1888,6 +1889,7 @@ body {
|
||||
line-height: 1.5;
|
||||
margin: 0.75rem 0;
|
||||
display: -webkit-box;
|
||||
line-clamp: 3;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
@@ -2675,6 +2677,7 @@ body {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
@@ -3095,6 +3098,7 @@ body {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
word-break: break-word;
|
||||
@@ -3758,7 +3762,7 @@ body {
|
||||
}
|
||||
|
||||
.settings-header {
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -4047,6 +4051,14 @@ body {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.gpu-detection-info {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-weight: 500;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#settings-page {
|
||||
opacity: 0;
|
||||
@@ -4078,7 +4090,53 @@ body {
|
||||
background: linear-gradient(135deg, #a855f7, #60a5fa);
|
||||
}
|
||||
|
||||
|
||||
.segmented-control {
|
||||
display: flex;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
backdrop-filter: blur(10px);
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.segmented-control input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
.segmented-control label {
|
||||
flex: 1;
|
||||
padding: 0.75rem 1rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
color: #d1d5db;
|
||||
font-size: 0.875rem;
|
||||
background: transparent;
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-weight: 500;
|
||||
}
|
||||
.segmented-control label:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
.segmented-control input[type="radio"]:checked + label {
|
||||
background: linear-gradient(135deg, #9333ea, #3b82f6);
|
||||
color: white;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.segmented-control label:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
}
|
||||
.segmented-control input[type="radio"]:checked + label:hover {
|
||||
background: linear-gradient(135deg, #7c3aed, #2563eb);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
.segmented-control:focus-within {
|
||||
border-color: rgba(147, 51, 234, 0.3);
|
||||
box-shadow: 0 0 20px rgba(147, 51, 234, 0.1);
|
||||
}
|
||||
|
||||
|
||||
#update-popup-overlay {
|
||||
|
||||
Reference in New Issue
Block a user