def _select_template(self,
                         sim_info: SimInfo,
                         on_close: Callable[[], None] = None):
        self.log.format_with_message('Opening dialog.', sim=sim_info)

        def _on_close() -> None:
            self.log.debug('Slider Template dialog closed.')
            if on_close is not None:
                on_close()

        option_dialog = CommonChooseObjectOptionDialog(
            CSFStringId.SELECTED_TEMPLATE,
            CSFStringId.PLEASE_SELECT_A_TEMPLATE,
            mod_identity=self.mod_identity,
            on_close=_on_close,
            per_page=400)

        self.log.debug('Opening Customize Slider dialog.')

        def _on_chosen(_: str, _chosen_template: CSFSliderTemplate):
            if _chosen_template is None:
                self.log.debug('No template name entered, dialog closed.')
                _on_close()
                return
            self.log.format_with_message(
                'Template name entered.',
                template_name=_chosen_template.template_name)
            CSFSliderTemplateDialog._SELECTED_TEMPLATE = _chosen_template
            _on_close()

        for (template_name,
             template) in self._template_utils.template_library.items():
            template: CSFSliderTemplate = template
            option_dialog.add_option(
                CommonDialogObjectOption(
                    template_name,
                    template,
                    CommonDialogOptionContext(
                        template.display_name,
                        0,
                        icon=CommonIconUtils.load_filled_circle_icon() if
                        CSFSliderTemplateDialog._SELECTED_TEMPLATE == template
                        else CommonIconUtils.load_unfilled_circle_icon(),
                    ),
                    on_chosen=_on_chosen))

        if not option_dialog.has_options():

            def _on_acknowledge(_) -> None:
                _on_close()

            CommonOkDialog(CSFStringId.NO_TEMPLATES_DETECTED_NAME,
                           CSFStringId.NO_TEMPLATES_DETECTED_DESCRIPTION,
                           mod_identity=self.mod_identity).show(
                               on_acknowledged=_on_acknowledge)
            return

        option_dialog.show(sim_info=sim_info)
def _common_testing_show_multi_pane_choose_option_dialog(
        _connection: int = None):
    output = sims4.commands.CheatOutput(_connection)
    output('Showing test multi pane choose option dialog.')

    def _on_option_chosen_in_dialog_one(option_identifier: str, choice: str):
        output('Chose option in dialog one {} with value: {}.'.format(
            pformat(option_identifier), pformat(choice)))

    def _on_option_chosen_in_dialog_two(option_identifier: str, choice: str):
        output('Chose option in dialog two {} with value: {}.'.format(
            pformat(option_identifier), pformat(choice)))

    def _on_submit(chosen_options: Dict[int, Any]):
        output('Chosen options from all dialogs {}.'.format(
            pformat(chosen_options)))

    try:
        # LocalizedStrings within other LocalizedStrings
        title_tokens = (CommonLocalizationUtils.create_localized_string(
            CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
            text_color=CommonLocalizedStringColor.GREEN), )
        description_tokens = (CommonLocalizationUtils.create_localized_string(
            CommonStringId.TESTING_TEST_TEXT_WITH_SIM_FIRST_AND_LAST_NAME,
            tokens=(CommonSimUtils.get_active_sim_info(), ),
            text_color=CommonLocalizedStringColor.BLUE), )

        sub_dialog_one = CommonChooseObjectOptionDialog(
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            title_tokens=title_tokens,
            description_tokens=description_tokens,
            per_page=2)

        sub_dialog_one.add_option(
            CommonDialogObjectOption(
                'Option 1',
                'Value 1',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_ONE,
                    icon=CommonIconUtils.load_checked_square_icon()),
                on_chosen=_on_option_chosen_in_dialog_one))

        sub_dialog_one.add_option(
            CommonDialogObjectOption(
                'Option 2',
                'Value 2',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen_in_dialog_one))

        sub_dialog_one.add_option(
            CommonDialogObjectOption(
                'Option 3',
                'Value 3',
                CommonDialogOptionContext(
                    CommonLocalizationUtils.create_localized_string('Value 3'),
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen_in_dialog_one))

        sub_dialog_two = CommonChooseObjectOptionDialog(
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            title_tokens=title_tokens,
            description_tokens=description_tokens,
            per_page=2)

        sub_dialog_two.add_option(
            CommonDialogObjectOption(
                'Option 4',
                'Value 4',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_ONE,
                    icon=CommonIconUtils.load_checked_square_icon()),
                on_chosen=_on_option_chosen_in_dialog_two))

        sub_dialog_two.add_option(
            CommonDialogObjectOption(
                'Option 5',
                'Value 5',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen_in_dialog_two))

        sub_dialog_two.add_option(
            CommonDialogObjectOption(
                'Option 6',
                'Value 6',
                CommonDialogOptionContext(
                    CommonLocalizationUtils.create_localized_string('Value 3'),
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen_in_dialog_two))

        option_dialog = CommonMultiPaneChooseOptionDialog(
            ModInfo.get_identity(),
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            title_tokens=title_tokens,
            description_tokens=description_tokens)

        option_dialog.add_sub_dialog(sub_dialog_one)
        option_dialog.add_sub_dialog(sub_dialog_two)

        option_dialog.show(on_submit=_on_submit,
                           sim_info=CommonSimUtils.get_active_sim_info())
    except Exception as ex:
        CommonExceptionHandler.log_exception(ModInfo.get_identity(),
                                             'Failed to show dialog',
                                             exception=ex)
        output('Failed to show dialog, please locate your exception log file.')
    output('Done showing.')
예제 #3
0
def _common_testing_show_choose_objects_option_dialog(_connection: int = None):
    output = sims4.commands.CheatOutput(_connection)
    output('Showing test choose objects option dialog.')

    def _on_option_chosen(option_identifier: str, choice: str):
        output('Chose option {} with value: {}.'.format(
            pformat(option_identifier), pformat(choice)))

    def _on_submit(choices: Tuple[str]):
        output('Chose options {}.'.format(pformat(choices)))

    try:
        # LocalizedStrings within other LocalizedStrings
        title_tokens = (CommonLocalizationUtils.create_localized_string(
            CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
            text_color=CommonLocalizedStringColor.GREEN), )
        description_tokens = (CommonLocalizationUtils.create_localized_string(
            CommonStringId.TESTING_TEST_TEXT_WITH_SIM_FIRST_AND_LAST_NAME,
            tokens=(CommonSimUtils.get_active_sim_info(), ),
            text_color=CommonLocalizedStringColor.BLUE), )
        option_dialog = CommonChooseObjectsOptionDialog(
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            CommonStringId.TESTING_TEST_TEXT_WITH_STRING_TOKEN,
            title_tokens=title_tokens,
            description_tokens=description_tokens,
            per_page=2)

        from sims4communitylib.utils.common_icon_utils import CommonIconUtils

        option_dialog.add_option(
            CommonDialogObjectOption(
                'Option 1',
                'Value 1',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_ONE,
                    icon=CommonIconUtils.load_checked_square_icon()),
                on_chosen=_on_option_chosen))

        option_dialog.add_option(
            CommonDialogObjectOption(
                'Option 2',
                'Value 2',
                CommonDialogOptionContext(
                    CommonStringId.TESTING_SOME_TEXT_FOR_TESTING,
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen))

        option_dialog.add_option(
            CommonDialogObjectOption(
                'Option 3',
                'Value 3',
                CommonDialogOptionContext(
                    CommonLocalizationUtils.create_localized_string('Value 3'),
                    CommonStringId.TESTING_TEST_BUTTON_TWO,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()),
                on_chosen=_on_option_chosen))

        option_dialog.show(on_submit=_on_submit,
                           sim_info=CommonSimUtils.get_active_sim_info(),
                           min_selectable=1,
                           max_selectable=2)
    except Exception as ex:
        CommonExceptionHandler.log_exception(ModInfo.get_identity(),
                                             'Failed to show dialog',
                                             exception=ex)
        output('Failed to show dialog, please locate your exception log file.')
    output('Done showing.')
예제 #4
0
 def _add_row(self, option: CommonDialogObjectOption):
     self._internal_dialog.add_row(option.as_row(len(self._options)),
                                   always_visible=option.always_visible)
    def _view_template(self,
                       sim_info: SimInfo,
                       on_close: Callable[[], None] = None):
        self.log.format_with_message('Opening view template dialog.',
                                     sim=sim_info)

        def _on_close() -> None:
            self.log.debug('Slider Template dialog closed.')
            if on_close is not None:
                on_close()

        def _reopen() -> None:
            self._view_template(sim_info, on_close=on_close)

        if CSFSliderTemplateDialog._SELECTED_TEMPLATE is None:

            def _on_acknowledge(_) -> None:
                _on_close()

            CommonOkDialog(CSFStringId.NO_TEMPLATE_SELECTED,
                           CSFStringId.PLEASE_SELECT_A_TEMPLATE,
                           mod_identity=self.mod_identity).show(
                               on_acknowledged=_on_acknowledge)
            return

        option_dialog = CommonChooseObjectOptionDialog(
            CSFStringId.VIEW_TEMPLATE_NAME,
            CSFStringId.VIEW_TEMPLATE_DESCRIPTION,
            mod_identity=self.mod_identity,
            on_close=_on_close,
            per_page=400)

        for (slider,
             amount) in CSFSliderTemplateDialog._SELECTED_TEMPLATE.get_sliders(
                 sim_info):
            slider: CSFSlider = slider
            option_dialog.add_option(
                CommonDialogObjectOption(
                    slider.unique_identifier,
                    slider,
                    CommonDialogOptionContext(
                        0,
                        CSFStringId.STRING_PLUS_STRING,
                        description_tokens=(
                            slider.display_name,
                            str(amount),
                        ),
                        icon=CommonIconUtils.load_arrow_right_icon(),
                        is_enabled=False),
                    on_chosen=lambda *_, **__: _reopen()))

        if not option_dialog.has_options():

            def _on_acknowledge(_) -> None:
                _on_close()

            CommonOkDialog(CSFStringId.NO_SLIDERS_DETECTED_NAME,
                           CSFStringId.NO_SLIDERS_DETECTED_DESCRIPTION,
                           mod_identity=self.mod_identity).show(
                               on_acknowledged=_on_acknowledge)
            return

        option_dialog.show(sim_info=sim_info)
예제 #6
0
    def open(self) -> None:
        """ Open the dialog for customizing a sims outfit. """
        self.log.format_with_message('Opening customize outfit dialog.', sim=CommonSimNameUtils.get_full_name(self._sim_info))

        def _on_close() -> None:
            if self._on_close is not None:
                self._on_close()

        def _reopen_dialog() -> None:
            option_dialog.show(sim_info=self._sim_info, page=option_dialog.current_page)

        outfit_parts = OCCASPartQueryUtils().get_cas_parts_for_sim(self._sim_info)
        if not outfit_parts:
            CommonOkDialog(
                OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
                OCStringId.OC_NO_OUTFIT_PARTS_FOUND,
                mod_identity=self.mod_identity
            ).show(on_acknowledged=_on_close)
            return

        option_dialog = CommonChooseObjectOptionDialog(
            OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
            0,
            on_close=_on_close,
            mod_identity=self.mod_identity
        )

        def _on_option_chosen(option_identifier: str, choice: _OutfitPartsBy):
            self.log.debug('Opening Outfit Parts: {}'.format(option_identifier))
            self._open_outfit_parts_by(choice, outfit_parts, on_close=_reopen_dialog)

        option_dialog.add_option(
            CommonDialogObjectOption(
                'By Tag',
                _OutfitPartsBy.TAG,
                CommonDialogOptionContext(
                    OCStringId.OC_FILTER_BY_TAG,
                    0,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()
                ),
                on_chosen=_on_option_chosen
            )
        )

        option_dialog.add_option(
            CommonDialogObjectOption(
                'By Outfit Slot',
                _OutfitPartsBy.OUTFIT_SLOT,
                CommonDialogOptionContext(
                    OCStringId.OC_FILTER_BY_OUTFIT_SLOT,
                    0,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()
                ),
                on_chosen=_on_option_chosen
            )
        )

        option_dialog.add_option(
            CommonDialogObjectOption(
                'By Author',
                _OutfitPartsBy.AUTHOR,
                CommonDialogOptionContext(
                    OCStringId.OC_FILTER_BY_AUTHOR,
                    0,
                    icon=CommonIconUtils.load_arrow_navigate_into_icon()
                ),
                on_chosen=_on_option_chosen
            )
        )

        option_dialog.show(sim_info=self._sim_info)
예제 #7
0
    def _open_body_type_selection(self, outfit_part: OCOutfitPart, outfit_io: CommonSimOutfitIO, on_close_callback: Callable[[], None]=None):
        def _on_close() -> None:
            if on_close_callback is not None:
                on_close_callback()

        def _reopen_dialog() -> None:
            self._open_body_type_selection(outfit_part, outfit_io, on_close_callback=on_close_callback)

        def _on_option_chosen(option_identifier: str, picked_body_type: BodyType):
            self.log.debug('Chose body type: {}'.format(option_identifier))
            if outfit_io.is_cas_part_attached(outfit_part.part_id):
                outfit_io.detach_cas_part(outfit_part.part_id)
            outfit_io.attach_cas_part(outfit_part.part_id, body_type=picked_body_type)
            outfit_io.apply()
            _reopen_dialog()

        def _on_remove_chosen() -> None:
            if outfit_io.is_cas_part_attached(outfit_part.part_id):
                outfit_io.detach_cas_part(outfit_part.part_id)
            outfit_io.apply()
            _reopen_dialog()

        option_dialog = CommonChooseObjectOptionDialog(
            OCStringId.OC_CHOOSE_BODY_LOCATION,
            OCStringId.OC_WHERE_SHOULD_IT_BE_WORN_AT,
            mod_identity=self.mod_identity,
            per_page=25,
            on_close=_on_close
        )

        if CommonCASUtils.has_cas_part_attached(self._sim_info, outfit_part.part_id, body_type=None):
            option_dialog.add_option(
                CommonDialogActionOption(
                    CommonDialogOptionContext(
                        OCStringId.OC_REMOVE,
                        0,
                        icon=CommonIconUtils.load_x_icon(),
                        tooltip_text_identifier=OCStringId.OC_REMOVE
                    ),
                    on_chosen=_on_remove_chosen,
                    always_visible=True
                )
            )

        default_body_type = CommonCASUtils.get_body_type_of_cas_part(outfit_part.part_id)
        option_dialog.add_option(
            CommonDialogObjectOption(
                'Default',
                default_body_type,
                CommonDialogOptionContext(
                    OCStringId.OC_DEFAULT_VALUE,
                    0,
                    title_tokens=(str(default_body_type).replace('BodyType.', ''),),
                    icon=CommonIconUtils.load_arrow_right_icon()
                ),
                on_chosen=_on_option_chosen
            )
        )

        sorted_body_types = sorted(BodyType.values, key=lambda bt: str(bt))

        for body_type in sorted_body_types:
            if body_type == BodyType.NONE or body_type == default_body_type:
                continue

            cas_part_id = CommonCASUtils.get_cas_part_id_at_body_type(self._sim_info, body_type)
            if cas_part_id != -1:
                cas_part_id_at_body_type = str(cas_part_id)
            else:
                cas_part_id_at_body_type = OCStringId.OC_NONE

            name = CommonLocalizationUtils.create_localized_string(OCStringId.OC_LOCATION, tokens=(str(body_type).replace('BodyType.', ''),))
            row_description = CommonLocalizationUtils.create_localized_string(OCStringId.OC_CURRENT, tokens=(cas_part_id_at_body_type,))
            if cas_part_id == outfit_part.part_id:
                name = CommonLocalizationUtils.colorize(name, text_color=CommonLocalizedStringColor.GREEN)
                row_description = CommonLocalizationUtils.colorize(row_description, text_color=CommonLocalizedStringColor.GREEN)

            option_dialog.add_option(
                CommonDialogObjectOption(
                    str(body_type),
                    body_type,
                    CommonDialogOptionContext(
                        name,
                        row_description,
                        icon=CommonIconUtils.load_arrow_right_icon(),
                        tooltip_text_identifier=name
                    ),
                    on_chosen=_on_option_chosen
                )
            )

        option_dialog.show(sim_info=self._sim_info)
예제 #8
0
    def _open_cas_part_selector(self, outfit_parts: Tuple[OCOutfitPart], tag: str, on_close_callback: Callable[[], None]=None, current_page: int=1):
        self.log.format_with_message('Opening with outfit parts.', outfit_parts=outfit_parts)

        def _on_close() -> None:
            if on_close_callback is not None:
                on_close_callback()

        def _reopen_dialog() -> None:
            self._open_cas_part_selector(outfit_parts, tag, on_close_callback=on_close_callback, current_page=option_dialog.current_page)

        option_dialog = CommonChooseObjectOptionDialog(
            OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
            0,
            mod_identity=self.mod_identity,
            on_close=_on_close
        )

        outfit_io = CommonSimOutfitIO(self._sim_info, mod_identity=self.mod_identity)

        def _on_option_chosen(option_identifier: str, picked_outfit_part: OCOutfitPart):
            self.log.debug('Chose outfit part: {}'.format(option_identifier))
            self._open_body_type_selection(picked_outfit_part, outfit_io, on_close_callback=_reopen_dialog)

        def _on_remove_chosen() -> None:
            OCOutfitPartUtils.remove_outfit_parts(self._sim_info, outfit_parts)
            _reopen_dialog()

        def _no_outfit_parts_found() -> None:
            CommonOkDialog(
                OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
                OCStringId.OC_NO_OUTFIT_PARTS_FOUND
            ).show(on_acknowledged=_on_close)

        if not outfit_parts:
            _no_outfit_parts_found()
            return

        sorted_outfit_parts = sorted(outfit_parts, key=lambda item: item.raw_display_name)

        option_dialog.add_option(
            CommonDialogActionOption(
                CommonDialogOptionContext(
                    OCStringId.OC_REMOVE_ALL,
                    0,
                    icon=CommonIconUtils.load_x_icon(),
                    tooltip_text_identifier=OCStringId.OC_REMOVE_ALL,
                ),
                on_chosen=_on_remove_chosen,
                always_visible=True
            )
        )

        for outfit_part in sorted_outfit_parts:
            if tag not in outfit_part.tag_list:
                continue
            part_id = outfit_part.part_id
            author = outfit_part.author
            icon = CommonIconUtils._load_icon(outfit_part.icon_id) or CommonIconUtils.load_question_mark_icon()
            outfit_part_name = outfit_part.display_name
            # If outfit part is already equipped
            if outfit_io.is_cas_part_attached(part_id):
                outfit_part_name = CommonLocalizationUtils.create_localized_string(CommonStringId.TEXT_WITH_GREEN_COLOR, tokens=(outfit_part_name,))

            option_dialog.add_option(
                CommonDialogObjectOption(
                    str(part_id),
                    outfit_part,
                    CommonDialogOptionContext(
                        outfit_part_name,
                        OCStringId.OC_AUTHOR,
                        description_tokens=(author,),
                        icon=icon,
                    ),
                    on_chosen=_on_option_chosen
                )
            )

        # noinspection PyTypeChecker
        option_dialog.show(
            sim_info=self._sim_info,
            picker_type=UiObjectPicker.UiObjectPickerObjectPickerType.OBJECT,
            page=current_page
        )
예제 #9
0
    def _open_outfit_parts_by(self, outfit_parts_by: _OutfitPartsBy, outfit_parts: Tuple[OCOutfitPart], on_close: Callable[[], None]):
        self.log.format_with_message('Opening outfit parts by', outfit_parts_by=outfit_parts_by)

        def _on_close() -> None:
            on_close()

        option_dialog = CommonChooseObjectOptionDialog(
            OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
            0,
            on_close=_on_close,
            mod_identity=self.mod_identity
        )

        def _reopen_dialog() -> None:
            option_dialog.show(sim_info=self._sim_info, page=option_dialog.current_page)

        def _on_option_chosen(option_identifier: str, chosen: Tuple[OCOutfitPart]):
            self.log.debug('Opening Outfit Parts By: {}'.format(option_identifier))
            self._open_with_outfit_parts(chosen, on_close_callback=_reopen_dialog)

        def _no_outfit_parts_found() -> None:
            CommonOkDialog(
                OCStringId.OC_CUSTOMIZE_OUTFIT_OC,
                OCStringId.OC_NO_OUTFIT_PARTS_FOUND,
                mod_identity=self.mod_identity
            ).show(on_acknowledged=_on_close)

        if outfit_parts_by == _OutfitPartsBy.NONE:
            self.log.debug('outfit_parts_by was NONE')
            _no_outfit_parts_found()
            return

        self.log.format_with_message('Creating outfit parts by', outfit_parts_by=outfit_parts_by)
        if len(outfit_parts) == 0:
            self.log.debug('No outfit parts found!')
            _no_outfit_parts_found()
            return

        sorted_outfit_parts = sorted(outfit_parts, key=lambda op: op.raw_display_name)
        if not sorted_outfit_parts:
            self.log.debug('Failed to sort outfit parts by name')
            _no_outfit_parts_found()
            return

        self.log.format_with_message('Outfit parts sorted.', sorted_outfit_parts=sorted_outfit_parts)

        outfit_parts_by_value_dict = {}
        for outfit_part in sorted_outfit_parts:
            outfit_part: OCOutfitPart = outfit_part
            self.log.format_with_message('Looking at outfit part.', outfit_part=outfit_part)
            if not CommonCASUtils.is_cas_part_loaded(outfit_part.part_id):
                self.log.debug('Outfit part not loaded.')
                continue
            keys = self._get_outfit_part_key(outfit_part, outfit_parts_by=outfit_parts_by)
            if keys is None:
                self.log.debug('No key found.')
                continue
            for key in keys:
                str_key = str(key)
                by_value = outfit_parts_by_value_dict.get(str_key, list())
                by_value.append(outfit_part)
                outfit_parts_by_value_dict[str_key] = by_value
            self.log.debug('Outfit part loaded.')

        if len(outfit_parts_by_value_dict) == 0:
            self.log.format_with_message('No outfit parts found with outfit parts by!', outfit_parts_by=outfit_parts_by, outfit_parts_by_value_dict=outfit_parts_by_value_dict)
            self.log.debug('No outfit parts found!')
            _no_outfit_parts_found()
            return

        self.log.format_with_message('Finished filtering outfit parts.', outfit_parts_by_value_dict=outfit_parts_by_value_dict)

        sorted_keys = sorted(outfit_parts_by_value_dict.keys())
        self.log.format(sorted_keys=sorted_keys)
        for key in sorted_keys:
            self.log.format_with_message('Building key', key=key)
            outfit_parts_by_value: List[OCOutfitPart] = outfit_parts_by_value_dict[key]
            if len(outfit_parts_by_value) == 0:
                self.log.debug('No parts found in key.')
                continue
            outfit_parts_count = str(len(outfit_parts_by_value))
            self.log.format_with_message('Found outfit parts', count=outfit_parts_count)
            option_dialog.add_option(
                CommonDialogObjectOption(
                    key,
                    tuple(outfit_parts_by_value),
                    CommonDialogOptionContext(
                        key,
                        OCStringId.OC_OUTFIT_PARTS_COUNT,
                        description_tokens=(outfit_parts_count,),
                        icon=CommonIconUtils.load_arrow_navigate_into_icon()
                    ),
                    on_chosen=_on_option_chosen
                )
            )

        if not option_dialog.has_options():
            self.log.debug('No options found in dialog.')
            _no_outfit_parts_found()
            return

        self.log.debug('Showing dialog.')

        option_dialog.show(sim_info=self._sim_info)