Add more gui config
This commit is contained in:
parent
241c5c16d6
commit
156ac2b5b7
7 changed files with 298 additions and 67 deletions
70
gui/engine_config_tab.py
Normal file
70
gui/engine_config_tab.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Unified Game Engine Configuration Tab.
|
||||
|
||||
This tab dynamically shows the appropriate engine-specific configuration UI
|
||||
based on signals from the Translation tab (engine selection).
|
||||
|
||||
Currently supports:
|
||||
- RPG Maker MV/MZ
|
||||
- RPG Maker Ace
|
||||
- Wolf RPG
|
||||
|
||||
Easily extensible: add new engine widget + mapping entry.
|
||||
"""
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QStackedLayout, QLabel
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from gui.rpgmaker_tab import RPGMakerTab
|
||||
from gui.wolf_tab import WolfTab
|
||||
|
||||
|
||||
class EngineConfigTab(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._init_widgets()
|
||||
|
||||
def _init_widgets(self):
|
||||
layout = QVBoxLayout()
|
||||
self.setLayout(layout)
|
||||
|
||||
self.stack = QStackedLayout()
|
||||
layout.addLayout(self.stack)
|
||||
|
||||
# Engine widgets
|
||||
self.mv_widget = RPGMakerTab("MVMZ")
|
||||
self.ace_widget = RPGMakerTab("ACE")
|
||||
self.wolf_widget = WolfTab()
|
||||
|
||||
# Placeholder when no engine selected
|
||||
self.placeholder = QLabel("Select a game engine in the Translation tab to configure its options.")
|
||||
self.placeholder.setAlignment(Qt.AlignCenter)
|
||||
self.placeholder.setStyleSheet("color:#888; padding:40px;")
|
||||
|
||||
# Add to stack
|
||||
self.widget_map = {
|
||||
"mvmz": self.mv_widget,
|
||||
"ace": self.ace_widget,
|
||||
"wolf": self.wolf_widget,
|
||||
}
|
||||
self.stack.addWidget(self.placeholder) # index 0
|
||||
for w in self.widget_map.values():
|
||||
self.stack.addWidget(w)
|
||||
|
||||
self.current_engine = None
|
||||
self.show_placeholder()
|
||||
|
||||
def show_placeholder(self):
|
||||
self.stack.setCurrentIndex(0)
|
||||
self.current_engine = None
|
||||
|
||||
def show_engine(self, engine: str):
|
||||
engine = (engine or "").lower()
|
||||
widget = self.widget_map.get(engine)
|
||||
if not widget:
|
||||
self.show_placeholder()
|
||||
return
|
||||
# Find the widget's index in stack
|
||||
for i in range(self.stack.count()):
|
||||
if self.stack.widget(i) is widget:
|
||||
self.stack.setCurrentIndex(i)
|
||||
self.current_engine = engine
|
||||
break
|
||||
31
gui/main.py
31
gui/main.py
|
|
@ -18,7 +18,7 @@ from PyQt5.QtGui import QIcon, QFont, QPixmap, QScreen
|
|||
|
||||
# Import configuration widgets
|
||||
from gui.config_tab import ConfigTab
|
||||
from gui.rpgmaker_tab import RPGMakerTab
|
||||
from gui.engine_config_tab import EngineConfigTab
|
||||
from gui.log_viewer import LogViewer
|
||||
from gui.file_manager import FileManager
|
||||
from gui.translation_tab import TranslationTab
|
||||
|
|
@ -170,11 +170,32 @@ class DazedMTLGUI(QMainWindow):
|
|||
|
||||
# Translation Execution Tab (includes file management)
|
||||
self.translation_tab = TranslationTab(self)
|
||||
try:
|
||||
self.translation_tab.engine_changed.connect(self.show_engine_tab)
|
||||
except Exception:
|
||||
pass
|
||||
self.tab_widget.addTab(self.translation_tab, "Translation")
|
||||
|
||||
# RPG Maker MV/MZ Tab
|
||||
self.rpgmaker_tab = RPGMakerTab()
|
||||
self.tab_widget.addTab(self.rpgmaker_tab, "RPG Maker MV/MZ")
|
||||
|
||||
# Unified Engine Configuration Tab
|
||||
self.engine_config_tab = EngineConfigTab()
|
||||
self.tab_widget.addTab(self.engine_config_tab, "Engine Config")
|
||||
# Default to MV/MZ config on first load
|
||||
try:
|
||||
self.show_engine_tab("mvmz")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def show_engine_tab(self, engine: str):
|
||||
"""Select engine config tab and display appropriate engine sub-widget."""
|
||||
try:
|
||||
# Switch to Engine Config tab
|
||||
for i in range(self.tab_widget.count()):
|
||||
if self.tab_widget.tabText(i) == "Engine Config":
|
||||
self.tab_widget.setCurrentIndex(i)
|
||||
break
|
||||
self.engine_config_tab.show_engine(engine)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def on_config_changed(self):
|
||||
"""Handle configuration changes."""
|
||||
|
|
|
|||
|
|
@ -19,7 +19,11 @@ except ImportError:
|
|||
|
||||
|
||||
class RPGMakerTab(QWidget):
|
||||
"""RPG Maker MV/MZ configuration tab."""
|
||||
"""RPG Maker MV/MZ & Ace configuration tab.
|
||||
|
||||
This widget now supports both MV/MZ and Ace engines. Pass engine="ACE" to
|
||||
target rpgmakerace.py; otherwise it will default to MV/MZ (rpgmakermvmz.py).
|
||||
"""
|
||||
|
||||
# Default configuration values for RPG Maker MV/MZ
|
||||
DEFAULT_CONFIG = {
|
||||
|
|
@ -141,8 +145,9 @@ class RPGMakerTab(QWidget):
|
|||
|
||||
config_changed = pyqtSignal()
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, engine: str = "MVMZ"):
|
||||
super().__init__()
|
||||
self.engine = engine.upper()
|
||||
self.config_integration = ConfigIntegration() if ConfigIntegration else None
|
||||
self.init_ui()
|
||||
self.connect_auto_apply() # Connect auto-apply before setting defaults
|
||||
|
|
@ -158,10 +163,11 @@ class RPGMakerTab(QWidget):
|
|||
scroll_layout = QVBoxLayout()
|
||||
|
||||
# Title and description
|
||||
title_label = QLabel("RPG Maker MV/MZ Translation Settings")
|
||||
title = "RPG Maker MV/MZ" if self.engine != "ACE" else "RPG Maker Ace"
|
||||
title_label = QLabel(f"{title} Translation Settings")
|
||||
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #007acc;")
|
||||
scroll_layout.addWidget(title_label)
|
||||
|
||||
|
||||
description_label = QLabel(
|
||||
"Configure which RPG Maker event codes to translate and additional options. "
|
||||
"Each code represents a specific type of game content."
|
||||
|
|
@ -618,12 +624,12 @@ class RPGMakerTab(QWidget):
|
|||
return is_valid
|
||||
|
||||
def apply_to_module(self, show_messages=False):
|
||||
"""Apply current configuration to the rpgmakermvmz.py module."""
|
||||
"""Apply current configuration to the correct RPG Maker module (MV/MZ or Ace)."""
|
||||
try:
|
||||
config = self.get_config()
|
||||
|
||||
# Direct file modification approach (completely silent)
|
||||
module_path = Path(__file__).parent.parent / "modules" / "rpgmakermvmz.py"
|
||||
# Select module filename based on engine
|
||||
module_filename = "rpgmakermvmz.py" if self.engine != "ACE" else "rpgmakerace.py"
|
||||
module_path = Path(__file__).parent.parent / "modules" / module_filename
|
||||
|
||||
if not module_path.exists():
|
||||
if show_messages:
|
||||
|
|
@ -662,7 +668,7 @@ class RPGMakerTab(QWidget):
|
|||
QMessageBox.information(
|
||||
self,
|
||||
"Success",
|
||||
"Configuration has been applied to modules/rpgmakermvmz.py\n\n"
|
||||
f"Configuration has been applied to modules/{module_filename}\n\n"
|
||||
"The module will now use these settings when running translations."
|
||||
)
|
||||
|
||||
|
|
@ -673,16 +679,18 @@ class RPGMakerTab(QWidget):
|
|||
self.config_changed.emit()
|
||||
|
||||
def load_from_module(self):
|
||||
"""Load configuration from the actual module file."""
|
||||
"""Load configuration from the actual module file based on engine."""
|
||||
if not self.config_integration:
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
config = self.config_integration.read_current_config()
|
||||
module_filename = "rpgmakermvmz.py" if self.engine != "ACE" else "rpgmakerace.py"
|
||||
module_path = Path("modules") / module_filename
|
||||
config = self.config_integration.read_current_config(module_path)
|
||||
if config:
|
||||
self.set_config(config)
|
||||
QMessageBox.information(self, "Success", "Configuration loaded from module file")
|
||||
QMessageBox.information(self, "Success", f"Configuration loaded from {module_filename}")
|
||||
else:
|
||||
QMessageBox.warning(self, "Warning", "No configuration found in module file")
|
||||
QMessageBox.warning(self, "Warning", f"No configuration found in {module_filename}")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Error", f"Failed to load from module:\n{str(e)}")
|
||||
|
|
|
|||
|
|
@ -441,7 +441,12 @@ except Exception as e:
|
|||
|
||||
|
||||
class TranslationTab(QWidget):
|
||||
"""Simple translation tab with file management and console log."""
|
||||
"""Simple translation tab with file management and console log.
|
||||
|
||||
Emits engine_changed(str) when the selected module implies a different
|
||||
engine configuration tab should be displayed.
|
||||
"""
|
||||
engine_changed = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
|
@ -471,13 +476,13 @@ class TranslationTab(QWidget):
|
|||
def setup_ui(self):
|
||||
"""Set up the user interface."""
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(15) # Add consistent spacing
|
||||
|
||||
layout.setSpacing(15)
|
||||
|
||||
# Title
|
||||
title_label = QLabel("Translation")
|
||||
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #007acc; margin-bottom: 5px;")
|
||||
layout.addWidget(title_label)
|
||||
|
||||
|
||||
# Description
|
||||
desc_label = QLabel(
|
||||
"Manage your files and run translations. Add files to 'files' folder, select module, then click translate."
|
||||
|
|
@ -485,54 +490,42 @@ class TranslationTab(QWidget):
|
|||
desc_label.setWordWrap(True)
|
||||
desc_label.setStyleSheet("color: #cccccc; margin-bottom: 15px;")
|
||||
layout.addWidget(desc_label)
|
||||
|
||||
# Module selection section
|
||||
|
||||
# Module selection
|
||||
module_group = QGroupBox("Translation Settings")
|
||||
module_group.setStyleSheet("QGroupBox { font-weight: bold; color: #007acc; margin-top: 10px; }")
|
||||
module_layout = QVBoxLayout()
|
||||
|
||||
# Module selector
|
||||
module_selector_layout = QHBoxLayout()
|
||||
module_label = QLabel("Game Engine:")
|
||||
module_selector_layout.addWidget(module_label)
|
||||
|
||||
selector_layout = QHBoxLayout()
|
||||
selector_layout.addWidget(QLabel("Game Engine:"))
|
||||
self.module_combo = QComboBox()
|
||||
module_selector_layout.addWidget(self.module_combo)
|
||||
|
||||
# Estimate checkbox
|
||||
self.module_combo.currentTextChanged.connect(self._on_module_changed)
|
||||
selector_layout.addWidget(self.module_combo)
|
||||
self.estimate_checkbox = QCheckBox("Estimate only (don't translate)")
|
||||
module_selector_layout.addWidget(self.estimate_checkbox)
|
||||
|
||||
module_layout.addLayout(module_selector_layout)
|
||||
selector_layout.addWidget(self.estimate_checkbox)
|
||||
module_layout.addLayout(selector_layout)
|
||||
module_group.setLayout(module_layout)
|
||||
layout.addWidget(module_group)
|
||||
|
||||
# File management section at the top
|
||||
file_management_splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# Input files
|
||||
|
||||
# File management splitter
|
||||
file_splitter = QSplitter(Qt.Horizontal)
|
||||
input_widget = self.create_input_files_widget()
|
||||
file_management_splitter.addWidget(input_widget)
|
||||
|
||||
# Output files
|
||||
file_splitter.addWidget(input_widget)
|
||||
output_widget = self.create_output_files_widget()
|
||||
file_management_splitter.addWidget(output_widget)
|
||||
|
||||
# Set proportional sizes instead of fixed pixel sizes
|
||||
file_management_splitter.setStretchFactor(0, 1)
|
||||
file_management_splitter.setStretchFactor(1, 1)
|
||||
layout.addWidget(file_management_splitter)
|
||||
|
||||
# Console log at the bottom
|
||||
file_splitter.addWidget(output_widget)
|
||||
file_splitter.setStretchFactor(0, 1)
|
||||
file_splitter.setStretchFactor(1, 1)
|
||||
layout.addWidget(file_splitter)
|
||||
|
||||
# Log
|
||||
log_widget = self.create_log_widget()
|
||||
layout.addWidget(log_widget)
|
||||
|
||||
# Modules list
|
||||
self.setup_module_list()
|
||||
|
||||
# Translation button
|
||||
|
||||
# Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addStretch()
|
||||
|
||||
self.translate_button = QPushButton("Start Translation")
|
||||
self.translate_button.clicked.connect(self.start_translation)
|
||||
self.translate_button.setStyleSheet("""
|
||||
|
|
@ -549,7 +542,6 @@ class TranslationTab(QWidget):
|
|||
}
|
||||
""")
|
||||
button_layout.addWidget(self.translate_button)
|
||||
|
||||
self.stop_button = QPushButton("Stop Translation")
|
||||
self.stop_button.clicked.connect(self.stop_translation)
|
||||
self.stop_button.setEnabled(False)
|
||||
|
|
@ -567,10 +559,8 @@ class TranslationTab(QWidget):
|
|||
}
|
||||
""")
|
||||
button_layout.addWidget(self.stop_button)
|
||||
|
||||
button_layout.addStretch()
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def setup_module_list(self):
|
||||
|
|
@ -617,6 +607,8 @@ class TranslationTab(QWidget):
|
|||
for module in self.modules:
|
||||
extensions = ", ".join(module[1])
|
||||
self.module_combo.addItem(f"{module[0]} ({extensions})")
|
||||
if self.module_combo.count():
|
||||
self._on_module_changed(self.module_combo.currentText())
|
||||
|
||||
except Exception as e:
|
||||
# Store error for later logging since log_display might not exist yet
|
||||
|
|
@ -624,6 +616,16 @@ class TranslationTab(QWidget):
|
|||
# Add a default option
|
||||
self.module_combo.addItem("RPG Maker MV/MZ (.json)")
|
||||
self.modules = [["RPG Maker MV/MZ", [".json"], None]]
|
||||
self._on_module_changed(self.module_combo.currentText())
|
||||
|
||||
def _on_module_changed(self, text: str):
|
||||
lowered = text.lower()
|
||||
if "ace" in lowered:
|
||||
self.engine_changed.emit("ace")
|
||||
elif "wolf" in lowered and "wolf rpg 2" not in lowered:
|
||||
self.engine_changed.emit("wolf")
|
||||
elif "mv/mz" in lowered:
|
||||
self.engine_changed.emit("mvmz")
|
||||
|
||||
def create_input_files_widget(self):
|
||||
"""Create the input files widget."""
|
||||
|
|
|
|||
126
gui/wolf_tab.py
Normal file
126
gui/wolf_tab.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
"""Wolf RPG configuration tab (basic initial implementation).
|
||||
|
||||
Provides toggles for a subset of flags in wolf.py so users can enable/disable
|
||||
what gets translated. This can be expanded later.
|
||||
"""
|
||||
from pathlib import Path
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QGroupBox, QCheckBox, QPushButton, QMessageBox, QLabel, QHBoxLayout, QScrollArea
|
||||
)
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
import re
|
||||
|
||||
class WolfTab(QWidget):
|
||||
config_changed = pyqtSignal()
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
# Dialogue/choices
|
||||
"CODE101": True,
|
||||
"CODE102": True,
|
||||
# Picture
|
||||
"CODE150": True,
|
||||
# Strings / variables
|
||||
"CODE122": True,
|
||||
# Other
|
||||
"CODE210": True,
|
||||
"CODE300": True,
|
||||
"CODE250": True,
|
||||
# Database flags
|
||||
"SCENARIOFLAG": True,
|
||||
"OPTIONSFLAG": True,
|
||||
"NPCFLAG": True,
|
||||
"DBNAMEFLAG": True,
|
||||
"DBVALUEFLAG": True,
|
||||
"ITEMFLAG": True,
|
||||
"STATEFLAG": True,
|
||||
"ENEMYFLAG": True,
|
||||
"ARMORFLAG": True,
|
||||
"WEAPONFLAG": True,
|
||||
"SKILLFLAG": True,
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.init_ui()
|
||||
self.reset_to_defaults()
|
||||
|
||||
def init_ui(self):
|
||||
main_layout = QVBoxLayout()
|
||||
scroll = QScrollArea()
|
||||
content = QWidget()
|
||||
v = QVBoxLayout()
|
||||
|
||||
title = QLabel("Wolf RPG Settings")
|
||||
title.setStyleSheet("font-size:16px;font-weight:bold;color:#007acc")
|
||||
v.addWidget(title)
|
||||
desc = QLabel("Toggle which parts of Wolf RPG data are translated. This is a minimal first pass; more options can be added later.")
|
||||
desc.setWordWrap(True)
|
||||
desc.setStyleSheet("color:#cccccc")
|
||||
v.addWidget(desc)
|
||||
|
||||
# Groups
|
||||
self.checkboxes = {}
|
||||
self.add_group(v, "Dialogue / Choices", ["CODE101", "CODE102"])
|
||||
self.add_group(v, "Pictures / Variables", ["CODE150", "CODE122"])
|
||||
self.add_group(v, "Other Event Codes", ["CODE210", "CODE300", "CODE250"])
|
||||
self.add_group(v, "Database Sections", [
|
||||
"SCENARIOFLAG", "OPTIONSFLAG", "NPCFLAG", "DBNAMEFLAG", "DBVALUEFLAG",
|
||||
"ITEMFLAG", "STATEFLAG", "ENEMYFLAG", "ARMORFLAG", "WEAPONFLAG", "SKILLFLAG"
|
||||
])
|
||||
|
||||
# Buttons
|
||||
btn_row = QHBoxLayout()
|
||||
self.reset_btn = QPushButton("Reset")
|
||||
self.reset_btn.clicked.connect(self.reset_to_defaults)
|
||||
self.apply_btn = QPushButton("Apply Now")
|
||||
self.apply_btn.clicked.connect(self.apply_to_module)
|
||||
btn_row.addWidget(self.reset_btn)
|
||||
btn_row.addWidget(self.apply_btn)
|
||||
btn_row.addStretch()
|
||||
v.addLayout(btn_row)
|
||||
|
||||
content.setLayout(v)
|
||||
scroll.setWidget(content)
|
||||
scroll.setWidgetResizable(True)
|
||||
main_layout.addWidget(scroll)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def add_group(self, parent_layout, title, keys):
|
||||
box = QGroupBox(title)
|
||||
v = QVBoxLayout()
|
||||
for k in keys:
|
||||
cb = QCheckBox(k)
|
||||
cb.stateChanged.connect(lambda _=None: self.apply_to_module(False))
|
||||
v.addWidget(cb)
|
||||
self.checkboxes[k] = cb
|
||||
box.setLayout(v)
|
||||
parent_layout.addWidget(box)
|
||||
|
||||
def get_config(self):
|
||||
return {k: cb.isChecked() for k, cb in self.checkboxes.items()}
|
||||
|
||||
def reset_to_defaults(self):
|
||||
for k, val in self.DEFAULT_CONFIG.items():
|
||||
if k in self.checkboxes:
|
||||
self.checkboxes[k].setChecked(val)
|
||||
self.apply_to_module()
|
||||
|
||||
def apply_to_module(self, show_message=False):
|
||||
module_path = Path(__file__).parent.parent / 'modules' / 'wolf.py'
|
||||
if not module_path.exists():
|
||||
if show_message:
|
||||
QMessageBox.critical(self, 'Error', 'wolf.py not found in modules directory.')
|
||||
return
|
||||
try:
|
||||
content = module_path.read_text(encoding='utf-8')
|
||||
for key, value in self.get_config().items():
|
||||
pattern = rf'^{key}\s*=\s*.*$'
|
||||
content = re.sub(pattern, f'{key} = {value}', content, flags=re.MULTILINE)
|
||||
module_path.write_text(content, encoding='utf-8')
|
||||
self.config_changed.emit()
|
||||
if show_message:
|
||||
QMessageBox.information(self, 'Applied', 'Wolf configuration applied to wolf.py')
|
||||
except Exception as e:
|
||||
if show_message:
|
||||
QMessageBox.critical(self, 'Error', f'Failed to apply settings: {e}')
|
||||
|
||||
|
|
@ -75,12 +75,12 @@ TRANSLATION_CONFIG = TranslationConfig(
|
|||
LEAVE = False
|
||||
|
||||
# Config (Default)
|
||||
FIRSTLINESPEAKERS = False # If 1st line of 401 is a speaker, set to True (False)
|
||||
FACENAME101 = False # Find Speakers in 101 Codes based on Face Name (False)
|
||||
NAMES = False # Output a list of all the character names found (False)
|
||||
BRFLAG = False # If the game uses <br> instead (False)
|
||||
FIXTEXTWRAP = True # Overwrites textwrap (True)
|
||||
IGNORETLTEXT = False # Ignores all translated text. (False)
|
||||
FIRSTLINESPEAKERS = False
|
||||
FACENAME101 = False
|
||||
NAMES = False
|
||||
BRFLAG = False
|
||||
FIXTEXTWRAP = True
|
||||
IGNORETLTEXT = False
|
||||
|
||||
# Dialogue / Scroll / Choices (Main Codes)
|
||||
CODE401 = True
|
||||
|
|
@ -88,8 +88,8 @@ CODE405 = True
|
|||
CODE102 = True
|
||||
|
||||
# Optional
|
||||
CODE101 = False # Turn this one on when names exist in 101
|
||||
CODE408 = False # Warning, translates comments and can inflate costs.
|
||||
CODE101 = False
|
||||
CODE408 = False
|
||||
|
||||
# Variables
|
||||
CODE122 = False
|
||||
|
|
|
|||
4
start.py
Normal file
4
start.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import modules.main
|
||||
|
||||
if __name__ == "__main__":
|
||||
modules.main.main()
|
||||
Loading…
Reference in a new issue