Add more gui config

This commit is contained in:
dazedanon 2025-09-10 15:22:24 -05:00
parent 241c5c16d6
commit 156ac2b5b7
7 changed files with 298 additions and 67 deletions

70
gui/engine_config_tab.py Normal file
View 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

View file

@ -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."""

View file

@ -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)}")

View file

@ -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
View 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}')

View file

@ -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
View file

@ -0,0 +1,4 @@
import modules.main
if __name__ == "__main__":
modules.main.main()