def _add_persist_option(self, check: QtWidgets.QCheckBox, attribute_name: str): def persist(value: bool): with self._editor as editor: editor.set_configuration_field(attribute_name, value) signal_handling.on_checked(check, persist)
def __init__(self, editor: PresetEditor): super().__init__(editor) self.setupUi(self) self.energy_tank_capacity_spin_box.valueChanged.connect( self._persist_tank_capacity) signal_handling.on_checked(self.immediate_energy_parts_check, self._persist_immediate_energy_parts)
def _create_check_for_source_elevator(self, location: Teleporter): area = self.game_description.world_list.area_by_area_location(location.area_location) name = randovania.games.prime.echoes_teleporters.CUSTOM_NAMES_FOR_ELEVATORS.get(area.area_asset_id) if name is None: name = self.game_description.world_list.area_name(area) check = QtWidgets.QCheckBox(self.elevators_source_group) check.setText(name) check.area_location = location signal_handling.on_checked(check, functools.partial(self._on_elevator_source_check_changed, location)) return check
def __init__(self, editor: PresetEditor, game_description: GameDescription) -> None: super().__init__(editor) self.setupUi(self) # Game-specific Settings game_settings = self.game_specific_widgets if game_settings is not None: for w in game_settings: self.game_specific_layout.addWidget(w) else: self.game_specific_group.setVisible(False) # Item Placement signal_handling.on_checked(self.multi_pickup_placement_check, self._persist_multi_pickup_placement) signal_handling.on_checked(self.multi_pickup_new_weighting_check, self._persist_multi_pickup_new_weighting) signal_handling.on_checked(self.check_major_minor, self._persist_major_minor) signal_handling.on_checked(self.local_first_progression_check, self._persist_local_first_progression) # Logic Settings self.dangerous_combo.setItemData(0, LayoutLogicalResourceAction.RANDOMLY) self.dangerous_combo.setItemData( 1, LayoutLogicalResourceAction.LAST_RESORT) signal_handling.on_combo(self.dangerous_combo, self._on_dangerous_changed) signal_handling.on_checked(self.trick_level_minimal_logic_check, self._on_trick_level_minimal_logic_check) for w in [ self.trick_level_minimal_logic_check, self.trick_level_minimal_logic_label, self.minimal_logic_line ]: w.setVisible(game_description.minimal_logic is not None) if game_description.minimal_logic is not None: self.trick_level_minimal_logic_label.setText( self.trick_level_minimal_logic_label.text().format( game_specific_text=game_description.minimal_logic. description)) # Damage strictness self.damage_strictness_combo.setItemData(0, LayoutDamageStrictness.STRICT) self.damage_strictness_combo.setItemData(1, LayoutDamageStrictness.MEDIUM) self.damage_strictness_combo.setItemData( 2, LayoutDamageStrictness.LENIENT) self.damage_strictness_combo.currentIndexChanged.connect( self._on_update_damage_strictness)
def _create_check_for_source_elevator(self, location: NodeIdentifier): name = elevators.get_elevator_or_area_name( self.game_enum, self.game_description.world_list, location.area_location, True) check = QtWidgets.QCheckBox(self.elevators_source_group) check.setText(name) check.area_location = location signal_handling.on_checked( check, functools.partial(self._on_elevator_source_check_changed, location)) return check
def __init__(self, editor: PresetEditor, game: GameDescription): super().__init__(editor) self.setupUi(self) self.game_description = game self.elevator_layout.setAlignment(QtCore.Qt.AlignTop) for value in enum_lib.iterate_enum(TeleporterShuffleMode): self.elevators_combo.addItem(value.long_name, value) self.elevators_combo.currentIndexChanged.connect( self._update_elevator_mode) signal_handling.on_checked(self.skip_final_bosses_check, self._update_require_final_bosses) signal_handling.on_checked(self.elevators_allow_unvisited_names_check, self._update_allow_unvisited_names) # Elevator Source self._create_source_elevators() # Elevator Target self._elevator_target_for_world, self._elevator_target_for_area = self.create_area_list_selection( self.elevators_target_group, self.elevators_target_layout, TeleporterTargetList.areas_list(self.game_enum), self._on_elevator_target_check_changed, ) if self.game_enum != RandovaniaGame.METROID_PRIME_ECHOES: self.elevators_help_sound_bug_label.setVisible(False) self.elevators_allow_unvisited_names_check.setVisible(False) self.elevators_line_3.setVisible(False) self.elevators_help_list_label.setVisible(False) if self.game_enum == RandovaniaGame.METROID_PRIME: self.skip_final_bosses_check.setText( "Go directly to credits from Artifact Temple") self.skip_final_bosses_label.setText("""<html><head/><body> <p>Change the teleport in Artifact Temple to go directly to the credits, skipping the final bosses.</p> <p>This changes the requirements to <span style=" font-weight:600;">not need the final bosses</span>, turning certain items optional such as Plasma Beam.</p></body></html> """) elif self.game_enum != RandovaniaGame.METROID_PRIME_ECHOES: self.skip_final_bosses_check.setVisible(False) self.skip_final_bosses_label.setVisible(False) elif self.game_enum == RandovaniaGame.METROID_PRIME_CORRUPTION: self.elevators_description_label.setText( self.elevators_description_label.text().replace( "elevator", "teleporter"))
def _setup_general_widgets(self): # Item Data for i, value in enumerate(PickupModelStyle): self.pickup_model_combo.setItemData(i, value) for i, value in enumerate(PickupModelDataSource): self.pickup_data_source_combo.setItemData(i, value) # TODO: implement the LOCATION data source self.pickup_data_source_combo.removeItem(self.pickup_data_source_combo.findData(PickupModelDataSource.LOCATION)) self.pickup_model_combo.currentIndexChanged.connect( self._persist_enum(self.pickup_model_combo, "pickup_model_style")) self.pickup_data_source_combo.currentIndexChanged.connect( self._persist_enum(self.pickup_data_source_combo, "pickup_model_data_source")) signal_handling.on_checked(self.multi_pickup_placement_check, self._persist_multi_pickup_placement)
def __init__(self, editor: PresetEditor, game_enum: RandovaniaGame): super().__init__(editor) self.setupUi(self) self.game_enum = game_enum self.energy_tank_capacity_spin_box.valueChanged.connect( self._persist_tank_capacity) signal_handling.on_checked(self.dangerous_tank_check, self._persist_dangerous_tank) if self.game_enum == RandovaniaGame.METROID_PRIME_ECHOES: config_fields = { field.name: field for field in dataclasses.fields(EchoesConfiguration) } self.varia_suit_spin_box.setMinimum( config_fields["varia_suit_damage"].metadata["min"]) self.varia_suit_spin_box.setMaximum( config_fields["varia_suit_damage"].metadata["max"]) self.dark_suit_spin_box.setMinimum( config_fields["dark_suit_damage"].metadata["min"]) self.dark_suit_spin_box.setMaximum( config_fields["dark_suit_damage"].metadata["max"]) signal_handling.on_checked(self.safe_zone_logic_heal_check, self._persist_safe_zone_logic_heal) self.safe_zone_regen_spin.valueChanged.connect( self._persist_safe_zone_regen) self.varia_suit_spin_box.valueChanged.connect( self._persist_float("varia_suit_damage")) self.dark_suit_spin_box.valueChanged.connect( self._persist_float("dark_suit_damage")) else: self.dark_aether_box.setVisible(False) self.safe_zone_box.setVisible(False) self.dangerous_tank_check.setVisible(False) if self.game_enum == RandovaniaGame.METROID_PRIME: config_fields = { field.name: field for field in dataclasses.fields(PrimeConfiguration) } self.heated_damage_spin.setMinimum( config_fields["heat_damage"].metadata["min"]) self.heated_damage_spin.setMaximum( config_fields["heat_damage"].metadata["max"]) signal_handling.on_checked(self.progressive_damage_reduction_check, self._persist_progressive_damage) signal_handling.on_checked( self.heated_damage_varia_check, self._persist_heat_protection_only_varia) self.heated_damage_spin.valueChanged.connect( self._persist_float("heat_damage")) else: self.progressive_damage_reduction_check.setVisible(False) self.heated_damage_box.setVisible(False)
def setup_damage_elements(self): self.damage_strictness_combo.setItemData(0, LayoutDamageStrictness.STRICT) self.damage_strictness_combo.setItemData(1, LayoutDamageStrictness.MEDIUM) self.damage_strictness_combo.setItemData(2, LayoutDamageStrictness.LENIENT) self.damage_strictness_combo.options_field_name = "layout_configuration_damage_strictness" self.damage_strictness_combo.currentIndexChanged.connect(functools.partial(_update_options_by_value, self._editor, self.damage_strictness_combo)) def _persist_float(attribute_name: str): def persist(value: float): with self._editor as options: options.set_configuration_field(attribute_name, value) return persist self.energy_tank_capacity_spin_box.valueChanged.connect(self._persist_tank_capacity) signal_handling.on_checked(self.dangerous_tank_check, self._persist_dangerous_tank) if self.game_enum == RandovaniaGame.PRIME2: config_fields = { field.name: field for field in dataclasses.fields(EchoesConfiguration) } self.varia_suit_spin_box.setMinimum(config_fields["varia_suit_damage"].metadata["min"]) self.varia_suit_spin_box.setMaximum(config_fields["varia_suit_damage"].metadata["max"]) self.dark_suit_spin_box.setMinimum(config_fields["dark_suit_damage"].metadata["min"]) self.dark_suit_spin_box.setMaximum(config_fields["dark_suit_damage"].metadata["max"]) signal_handling.on_checked(self.safe_zone_logic_heal_check, self._persist_safe_zone_logic_heal) self.safe_zone_regen_spin.valueChanged.connect(self._persist_safe_zone_regen) self.varia_suit_spin_box.valueChanged.connect(_persist_float("varia_suit_damage")) self.dark_suit_spin_box.valueChanged.connect(_persist_float("dark_suit_damage")) else: self.dark_aether_box.setVisible(False) self.safe_zone_box.setVisible(False) if self.game_enum == RandovaniaGame.PRIME1: config_fields = { field.name: field for field in dataclasses.fields(PrimeConfiguration) } self.heated_damage_spin.setMinimum(config_fields["heat_damage"].metadata["min"]) self.heated_damage_spin.setMaximum(config_fields["heat_damage"].metadata["max"]) signal_handling.on_checked(self.progressive_damage_reduction_check, self._persist_progressive_damage) signal_handling.on_checked(self.heated_damage_varia_check, self._persist_heat_protection_only_varia) self.heated_damage_spin.valueChanged.connect(_persist_float("heat_damage")) else: self.progressive_damage_reduction_check.setVisible(False) self.heated_damage_box.setVisible(False)
def add_group(name: str, desc: str, weaknesses: dict[DockWeakness, bool]): group = QtWidgets.QGroupBox() group.setObjectName(f"{name}_group {dock_type.short_name}") group.setTitle(desc) layout = QtWidgets.QVBoxLayout() group.setLayout(layout) for weakness, enabled in weaknesses.items(): check = QtWidgets.QCheckBox() check.setObjectName( f"{name}_check {dock_type.short_name} {weakness.name}") check.setText(weakness.long_name) check.setEnabled(enabled) signal_handling.on_checked( check, self._persist_weakness_setting(name, dock_type, weakness)) layout.addWidget(check) self.type_checks[dock_type][weakness][name] = check type_layout.addWidget(group)
def setup_elevator_elements(self): for value in iterate_enum(TeleporterShuffleMode): self.elevators_combo.addItem(value.long_name, value) self.elevators_combo.currentIndexChanged.connect(self._update_elevator_mode) signal_handling.on_checked(self.skip_final_bosses_check, self._update_require_final_bosses) signal_handling.on_checked(self.elevators_allow_unvisited_names_check, self._update_allow_unvisited_names) # Elevator Source self._create_source_elevators() # Elevator Target self._elevator_target_for_world, self._elevator_target_for_area = self._create_area_list_selection( self.elevators_target_group, self.elevators_target_layout, TeleporterTargetList.areas_list(self.game_enum), self._on_elevator_target_check_changed, ) if self.game_enum == RandovaniaGame.PRIME3: self.patches_tab_widget.setTabText(self.patches_tab_widget.indexOf(self.elevator_tab), "Teleporters") self.elevators_description_label.setText( self.elevators_description_label.text().replace("elevator", "teleporter") )
def __init__(self, editor: PresetEditor): super().__init__(editor) self.setupUi(self) self.description_label.setText(self.description_label.text().replace("color:#0000ff;", "")) # Signals self.cutscene_combo.setItemData(0, LayoutCutsceneMode.ORIGINAL) self.cutscene_combo.setItemData(1, LayoutCutsceneMode.COMPETITIVE) self.cutscene_combo.setItemData(2, LayoutCutsceneMode.MINOR) self.cutscene_combo.setItemData(3, LayoutCutsceneMode.MAJOR) signal_handling.on_combo(self.cutscene_combo, self._on_cutscene_changed) self.room_rando_combo.setItemData(0, RoomRandoMode.NONE) self.room_rando_combo.setItemData(1, RoomRandoMode.ONE_WAY) self.room_rando_combo.setItemData(2, RoomRandoMode.TWO_WAY) signal_handling.on_combo(self.room_rando_combo, self._on_room_rando_changed) for f in _FIELDS: self._add_persist_option(getattr(self, f"{f}_check"), f) signal_handling.on_checked(self.small_samus_check, self._on_small_samus_changed) signal_handling.on_checked(self.large_samus_check, self._on_large_samus_changed) self.superheated_slider.valueChanged.connect(self._on_slider_changed) self.submerged_slider.valueChanged.connect(self._on_slider_changed)
def connect_signals(self): super().connect_signals() self.music_type_combo.currentIndexChanged.connect(self._on_music_type_changed) self.mychar_left_button.clicked.connect(self._mychar_left) self.mychar_right_button.clicked.connect(self._mychar_right) signal_handling.on_checked(self.song_cs_check, self._cs_songs) signal_handling.on_checked(self.song_beta_check, self._beta_songs) signal_handling.on_checked(self.song_kero_check, self._kero_songs)
def __init__(self, parent: QtWidgets.QWidget, game: GameDescription): super().__init__(parent) set_default_window_icon(self) self.setWindowTitle("Layers") self.root_widget = QtWidgets.QScrollArea() self.root_layout = QtWidgets.QVBoxLayout(self.root_widget) self.root_widget.setWidgetResizable(True) self.setWidget(self.root_widget) self.contents_widget = QtWidgets.QWidget() self.contents_layout = QtWidgets.QVBoxLayout(self.contents_widget) self.root_widget.setWidget(self.contents_widget) self.title_label = QtWidgets.QLabel(self.contents_widget) self.title_label.setText("Select visible layers") self.contents_layout.addWidget(self.title_label) self.layer_checks = [] for layer in game.layers: self.layer_checks.append( layer_check := QtWidgets.QCheckBox(self.contents_widget)) layer_check.setText(layer) layer_check.setChecked(True) signal_handling.on_checked(layer_check, lambda it: self._notify_change()) self.contents_layout.addWidget(layer_check) self.add_layer_button = QtWidgets.QPushButton(self.contents_widget) self.add_layer_button.setText("Add new layer") self.add_layer_button.setEnabled(False) self.add_layer_button.setToolTip("Not implemented") self.contents_layout.addWidget(self.add_layer_button) self.tricks_box = QtWidgets.QGroupBox(self.contents_widget) self.tricks_box.setTitle("Simplify connections with:") self.contents_layout.addWidget(self.tricks_box) self.tricks_layout = QtWidgets.QVBoxLayout(self.tricks_box) self.tricks = {} for trick in sorted(game.resource_database.trick, key=lambda it: it.long_name): trick_layout = QtWidgets.QHBoxLayout() self.tricks_layout.addLayout(trick_layout) trick_check = QtWidgets.QCheckBox(self.tricks_box) trick_check.setText(trick.long_name) trick_layout.addWidget(trick_check) trick_combo = ScrollProtectedComboBox(self.tricks_box) trick_layout.addWidget(trick_combo) for trick_level in enum_lib.iterate_enum(LayoutTrickLevel): trick_combo.addItem(trick_level.long_name, userData=trick_level.as_number) signal_handling.on_combo(trick_combo, lambda it: self._notify_change()) trick_combo.setEnabled(False) signal_handling.on_checked(trick_check, trick_combo.setEnabled) signal_handling.on_checked(trick_check, lambda it: self._notify_change()) self.tricks[(trick, trick_check)] = trick_combo self.load_preset_button = QtWidgets.QPushButton(self.contents_widget) self.load_preset_button.setText("Configure with preset") self.load_preset_button.clicked.connect(self._on_load_preset_slot) self.contents_layout.addWidget(self.load_preset_button) self.vertical_spacer = QtWidgets.QSpacerItem( 20, 30, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.contents_layout.addItem(self.vertical_spacer)
def __init__(self, editor: PresetEditor, game_description: GameDescription, window_manager: WindowManager): super().__init__(editor) self.setupUi(self) self.game_description = game_description self._window_manager = window_manager self.trick_level_layout.setAlignment(QtCore.Qt.AlignTop) signal_handling.on_checked(self.underwater_abuse_check, self._on_underwater_abuse_check) self.underwater_abuse_label.linkActivated.connect( self._on_click_link_underwater_details) self.trick_difficulties_layout = QtWidgets.QGridLayout() self._slider_for_trick = {} tricks_in_use = trick_lib.used_tricks(self.game_description) size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) self.trick_level_line_1.setVisible( self.game_enum != RandovaniaGame.METROID_PRIME_CORRUPTION) self.underwater_abuse_label.setText( self.underwater_abuse_label.text().replace("color:#0000ff;", "")) if self.game_enum != RandovaniaGame.METROID_PRIME: for w in [ self.underwater_abuse_check, self.underwater_abuse_label ]: w.setVisible(False) self._create_difficulty_details_row() row = 2 for trick in sorted(self.game_description.resource_database.trick, key=lambda _trick: _trick.long_name): if trick not in tricks_in_use: continue if row > 1: self.trick_difficulties_layout.addItem( QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)) trick_label = QtWidgets.QLabel(self.trick_level_scroll_contents) trick_label.setSizePolicy(size_policy) trick_label.setWordWrap(True) trick_label.setFixedWidth(100) trick_label.setText(trick.long_name) self.trick_difficulties_layout.addWidget(trick_label, row, 1, 1, 1) slider_layout = QtWidgets.QGridLayout() slider_layout.setHorizontalSpacing(0) for i in range(12): slider_layout.setColumnStretch(i, 1) horizontal_slider = QtWidgets.QSlider( self.trick_level_scroll_contents) horizontal_slider.setMaximum(5) horizontal_slider.setPageStep(2) horizontal_slider.setOrientation(QtCore.Qt.Horizontal) horizontal_slider.setTickPosition(QtWidgets.QSlider.TicksBelow) horizontal_slider.setEnabled(False) horizontal_slider.valueChanged.connect( functools.partial(self._on_slide_trick_slider, trick)) self._slider_for_trick[trick] = horizontal_slider slider_layout.addWidget(horizontal_slider, 0, 1, 1, 10) used_difficulties = trick_lib.difficulties_for_trick( self.game_description, trick) for i, trick_level in enumerate( enum_lib.iterate_enum(LayoutTrickLevel)): if trick_level == LayoutTrickLevel.DISABLED or trick_level in used_difficulties: difficulty_label = QtWidgets.QLabel( self.trick_level_scroll_contents) difficulty_label.setAlignment(QtCore.Qt.AlignHCenter) difficulty_label.setText(trick_level.long_name) slider_layout.addWidget(difficulty_label, 1, 2 * i, 1, 2) self.trick_difficulties_layout.addLayout(slider_layout, row, 2, 1, 1) if self._window_manager is not None: tool_button = QtWidgets.QToolButton( self.trick_level_scroll_contents) tool_button.setText("?") tool_button.clicked.connect( functools.partial(self._open_trick_details_popup, trick)) self.trick_difficulties_layout.addWidget( tool_button, row, 3, 1, 1) row += 1 self.trick_level_layout.addLayout(self.trick_difficulties_layout)