コード例 #1
0
    def load_conf(self) -> None:
        """Load configuration from our config file."""
        try:
            if self.can_resize_x:
                width = int(GEN_OPTS['win_state'][self.win_name + '_width'])
            else:
                width = self.winfo_reqwidth()
            if self.can_resize_y:
                height = int(GEN_OPTS['win_state'][self.win_name + '_height'])
            else:
                height = self.winfo_reqheight()
            self.deiconify()

            self.geometry('{!s}x{!s}'.format(width, height))
            self.sizefrom('user')

            self.relX = int(GEN_OPTS['win_state'][self.win_name + '_x'])
            self.relY = int(GEN_OPTS['win_state'][self.win_name + '_y'])

            self.follow_main()
            self.positionfrom('user')
        except (ValueError, KeyError):
            pass
        if not GEN_OPTS.get_bool('win_state', self.win_name + '_visible', True):
            self.after(150, self.hide_win)

        # Prevent this until here, so the <config> event won't erase our
        #  settings
        self.can_save = True
コード例 #2
0
ファイル: optionWindow.py プロジェクト: Coolasp1e/BEE2.4
 def load_opt():
     """Load the checkbox's values."""
     var.set(GEN_OPTS.get_bool(
         section,
         item,
         default,
     ))
コード例 #3
0
 def load_opt():
     """Load the checkbox's values."""
     var.set(GEN_OPTS.get_bool(
         section,
         item,
         default,
     ))
コード例 #4
0
ファイル: backup.py プロジェクト: SnowedFox/BEE2.4
def init_backup_settings() -> None:
    """Initialise the auto-backup settings widget."""
    from BEE2_config import GEN_OPTS
    check_var = tk.IntVar(
        value=GEN_OPTS.get_bool('General', 'enable_auto_backup'))
    count_value = GEN_OPTS.get_int('General', 'auto_backup_count', 0)
    back_dir = GEN_OPTS.get_val('Directories', 'backup_loc', 'backups/')

    def check_callback():
        GEN_OPTS['General']['enable_auto_backup'] = srctools.bool_as_int(
            check_var.get())

    def count_callback():
        GEN_OPTS['General']['auto_backup_count'] = str(count.value)

    def directory_callback(path):
        GEN_OPTS['Directories']['backup_loc'] = path

    UI['auto_frame'] = frame = ttk.LabelFrame(window, )
    UI['auto_enable'] = enable_check = ttk.Checkbutton(
        frame,
        text=_('Automatic Backup After Export'),
        variable=check_var,
        command=check_callback,
    )

    frame['labelwidget'] = enable_check
    frame.grid(row=2, column=0, columnspan=3)

    dir_frame = ttk.Frame(frame, )
    dir_frame.grid(row=0, column=0)

    ttk.Label(
        dir_frame,
        text='Directory',
    ).grid(row=0, column=0)

    UI['auto_dir'] = tk_tools.FileField(
        dir_frame,
        loc=back_dir,
        is_dir=True,
        callback=directory_callback,
    )
    UI['auto_dir'].grid(row=1, column=0)

    count_frame = ttk.Frame(frame, )
    count_frame.grid(row=0, column=1)
    ttk.Label(
        count_frame,
        text=_('Keep (Per Game):'),
    ).grid(row=0, column=0)

    count = tk_tools.ttk_Spinbox(
        count_frame,
        range=range(50),
        command=count_callback,
    )
    count.grid(row=1, column=0)
    count.value = count_value
コード例 #5
0
ファイル: gameMan.py プロジェクト: seagemgames/BEE2.4
    def clean_editor_models(self, items: Iterable[editoritems.Item]) -> None:
        """The game is limited to having 1024 models loaded at once.

        Editor models are always being loaded, so we need to keep the number
        small. Go through editoritems, and disable (by renaming to .mdl_dis)
        unused ones.
        """
        # If set, force them all to be present.
        force_on = GEN_OPTS.get_bool('Debug', 'force_all_editor_models')

        used_models = {
            str(mdl.with_suffix('')).casefold()
            for item in items for subtype in item.subtypes
            for mdl in subtype.models
        }

        mdl_count = 0

        for mdl_folder in [
                self.abs_path('bee2/models/props_map_editor/'),
                self.abs_path('bee2_dev/models/props_map_editor/'),
        ]:
            if not os.path.exists(mdl_folder):
                continue
            for file in os.listdir(mdl_folder):
                if not file.endswith(('.mdl', '.mdl_dis')):
                    continue

                mdl_count += 1

                file_no_ext, ext = os.path.splitext(file)
                if force_on or file_no_ext.casefold() in used_models:
                    new_ext = '.mdl'
                else:
                    new_ext = '.mdl_dis'

                if new_ext != ext:
                    try:
                        os.remove(
                            os.path.join(mdl_folder, file_no_ext + new_ext))
                    except FileNotFoundError:
                        pass
                    os.rename(
                        os.path.join(mdl_folder, file_no_ext + ext),
                        os.path.join(mdl_folder, file_no_ext + new_ext),
                    )

        if mdl_count != 0:
            LOGGER.info(
                '{}/{} ({:.0%}) editor models used.',
                len(used_models),
                mdl_count,
                len(used_models) / mdl_count,
            )
        else:
            LOGGER.warning('No custom editor models!')
コード例 #6
0
ファイル: StyleVarPane.py プロジェクト: Stendec-UA/BEE2.4
def add_vars(data):
    """
    Add the given stylevars to our list.

    """
    global var_list
    var_list = sorted(data, key=operator.attrgetter('id'))

    for var in var_list:
        var.default = GEN_OPTS.get_bool('StyleVar', var.id, var.default)
コード例 #7
0
ファイル: StyleVarPane.py プロジェクト: GiovanH/BEE2.4
def add_vars(data):
    """
    Add the given stylevars to our list.

    """
    global var_list
    var_list = sorted(data, key=operator.attrgetter('id'))

    for var in var_list:
        var.default = GEN_OPTS.get_bool('StyleVar', var.id, var.default)
コード例 #8
0
    def clean_editor_models(self, editoritems: Property):
        """The game is limited to having 1024 models loaded at once.

        Editor models are always being loaded, so we need to keep the number
        small. Go through editoritems, and disable (by renaming to .mdl_dis)
        unused ones.
        """
        # If set, force them all to be present.
        force_on = GEN_OPTS.get_bool('Debug', 'force_all_editor_models')

        used_models = {
            mdl.value.rsplit('.', 1)[0].casefold()
            for mdl in editoritems.find_all(
                'Item',
                'Editor',
                'Subtype',
                'Model',
                'ModelName',
            )
        }

        mdl_count = 0

        for mdl_folder in [
                self.abs_path('bee2/models/props_map_editor/'),
                self.abs_path('bee2_dev/models/props_map_editor/'),
        ]:
            if not os.path.exists(mdl_folder):
                continue
            for file in os.listdir(mdl_folder):
                if not file.endswith(('.mdl', '.mdl_dis')):
                    continue

                mdl_count += 1

                file_no_ext, ext = os.path.splitext(file)
                if force_on or file_no_ext.casefold() in used_models:
                    new_ext = '.mdl'
                else:
                    new_ext = '.mdl_dis'

                if new_ext != ext:
                    try:
                        os.remove(
                            os.path.join(mdl_folder, file_no_ext + new_ext))
                    except FileNotFoundError:
                        pass
                    os.rename(
                        os.path.join(mdl_folder, file_no_ext + ext),
                        os.path.join(mdl_folder, file_no_ext + new_ext),
                    )

        LOGGER.info('{}/{} editor models used.', len(used_models), mdl_count)
コード例 #9
0
def add_vars(style_vars, styles):
    """
    Add the given stylevars to our list.

    """
    VAR_LIST.clear()
    VAR_LIST.extend(sorted(style_vars, key=operator.attrgetter('id')))

    for var in VAR_LIST:  # type: packageLoader.StyleVar
        var.enabled = GEN_OPTS.get_bool('StyleVar', var.id, var.default)

    for style in styles:
        STYLES[style.id] = style
コード例 #10
0
ファイル: StyleVarPane.py プロジェクト: GLiTcH2/BEE2.4
def add_vars(style_vars, styles):
    """
    Add the given stylevars to our list.

    """
    VAR_LIST.clear()
    VAR_LIST.extend(
        sorted(style_vars, key=operator.attrgetter('id'))
    )

    for var in VAR_LIST:  # type: packageLoader.StyleVar
        var.enabled = GEN_OPTS.get_bool('StyleVar', var.id, var.default)

    for style in styles:
        STYLES[style.id] = style
コード例 #11
0
    def cache_invalid(self):
        """Check to see if the cache is valid."""
        if GEN_OPTS.get_bool('General', 'preserve_bee2_resource_dir'):
            # Skipped always
            return False

        # Check lengths, to ensure we re-extract if packages were removed.
        if len(packageLoader.packages) != len(self.mod_times):
            LOGGER.info('Need to extract - package counts inconsistent!')
            return True

        if any(
                pack.is_stale(self.mod_times.get(pack_id.casefold(), 0))
                for pack_id, pack in packageLoader.packages.items()):
            return True
コード例 #12
0
ファイル: backup.py プロジェクト: SnowedFox/BEE2.4
def auto_backup(game: 'gameMan.Game', loader: loadScreen.LoadScreen):
    """Perform an automatic backup for the given game.

    We do this seperately since we don't need to read the property files.
    """
    from BEE2_config import GEN_OPTS
    if not GEN_OPTS.get_bool('General', 'enable_auto_backup'):
        # Don't backup!
        loader.skip_stage(AUTO_BACKUP_STAGE)
        return

    folder = find_puzzles(game)
    if not folder:
        loader.skip_stage(AUTO_BACKUP_STAGE)
        return

    # Keep this many previous
    extra_back_count = GEN_OPTS.get_int('General', 'auto_backup_count', 0)

    to_backup = os.listdir(folder)
    backup_dir = GEN_OPTS.get_val('Directories', 'backup_loc', 'backups/')

    os.makedirs(backup_dir, exist_ok=True)

    # A version of the name stripped of special characters
    # Allowed: a-z, A-Z, 0-9, '_-.'
    safe_name = srctools.whitelist(
        game.name,
        valid_chars=BACKUP_CHARS,
    )

    loader.set_length(AUTO_BACKUP_STAGE, len(to_backup))

    if extra_back_count:
        back_files = [AUTO_BACKUP_FILE.format(game=safe_name, ind='')] + [
            AUTO_BACKUP_FILE.format(game=safe_name, ind='_' + str(i + 1))
            for i in range(extra_back_count)
        ]
        # Move each file over by 1 index, ignoring missing ones
        # We need to reverse to ensure we don't overwrite any zips
        for old_name, new_name in reversed(
                list(zip(back_files, back_files[1:]))):
            LOGGER.info(
                'Moving: {old} -> {new}',
                old=old_name,
                new=new_name,
            )
            old_name = os.path.join(backup_dir, old_name)
            new_name = os.path.join(backup_dir, new_name)
            try:
                os.remove(new_name)
            except FileNotFoundError:
                pass  # We're overwriting this anyway
            try:
                os.rename(old_name, new_name)
            except FileNotFoundError:
                pass

    final_backup = os.path.join(
        backup_dir,
        AUTO_BACKUP_FILE.format(game=safe_name, ind=''),
    )
    LOGGER.info('Writing backup to "{}"', final_backup)
    with open(final_backup, 'wb') as f:
        with ZipFile(f, mode='w', compression=ZIP_LZMA) as zip_file:
            for file in to_backup:
                zip_file.write(
                    os.path.join(folder, file),
                    file,
                    ZIP_LZMA,
                )
                loader.step(AUTO_BACKUP_STAGE)
コード例 #13
0
ファイル: gameMan.py プロジェクト: seagemgames/BEE2.4
    def export(
        self,
        style: packages.Style,
        selected_objects: dict,
        should_refresh=False,
    ) -> Tuple[bool, bool]:
        """Generate the editoritems.txt and vbsp_config.

        - If no backup is present, the original editoritems is backed up.
        - For each object type, run its .export() function with the given
        - item.
        - Styles are a special case.
        """

        LOGGER.info('-' * 20)
        LOGGER.info('Exporting Items and Style for "{}"!', self.name)

        LOGGER.info('Style = {}', style.id)
        for obj, selected in selected_objects.items():
            # Skip the massive dict in items
            if obj == 'Item':
                selected = selected[0]
            LOGGER.info('{} = {}', obj, selected)

        # VBSP, VRAD, editoritems
        export_screen.set_length('BACK', len(FILES_TO_BACKUP))
        # files in compiler/
        try:
            num_compiler_files = sum(
                1 for file in utils.install_path('compiler').rglob('*'))
        except FileNotFoundError:
            num_compiler_files = 0

        if self.steamID == utils.STEAM_IDS['APERTURE TAG']:
            # Coop paint gun instance
            num_compiler_files += 1

        if num_compiler_files == 0:
            LOGGER.warning('No compiler files!')
            export_screen.skip_stage('COMP')
        else:
            export_screen.set_length('COMP', num_compiler_files)

        LOGGER.info('Should refresh: {}', should_refresh)
        if should_refresh:
            # Check to ensure the cache needs to be copied over..
            should_refresh = self.cache_invalid()
            if should_refresh:
                LOGGER.info("Cache invalid - copying..")
            else:
                LOGGER.info("Skipped copying cache!")

        # Each object type
        # Editoritems
        # VBSP_config
        # Instance list
        # Editor models.
        # FGD file
        # Gameinfo
        export_screen.set_length('EXP', len(packages.OBJ_TYPES) + 6)

        # Do this before setting music and resources,
        # those can take time to compute.
        export_screen.show()
        try:

            if should_refresh:
                # Count the files.
                export_screen.set_length(
                    'RES',
                    sum(1 for file in res_system.walk_folder_repeat()),
                )
            else:
                export_screen.skip_stage('RES')
                export_screen.skip_stage('MUS')

            # Make the folders we need to copy files to, if desired.
            os.makedirs(self.abs_path('bin/bee2/'), exist_ok=True)

            # Start off with the style's data.
            vbsp_config = Property(None, [])
            vbsp_config += style.config.copy()

            all_items = style.items.copy()
            renderables = style.renderables.copy()

            export_screen.step('EXP')

            vpk_success = True

            # Export each object type.
            for obj_name, obj_data in packages.OBJ_TYPES.items():
                if obj_name == 'Style':
                    continue  # Done above already

                LOGGER.info('Exporting "{}"', obj_name)
                selected = selected_objects.get(obj_name, None)

                try:
                    obj_data.cls.export(
                        packages.ExportData(
                            game=self,
                            selected=selected,
                            all_items=all_items,
                            renderables=renderables,
                            vbsp_conf=vbsp_config,
                            selected_style=style,
                        ))
                except packages.NoVPKExport:
                    # Raised by StyleVPK to indicate it failed to copy.
                    vpk_success = False

                export_screen.step('EXP')

            vbsp_config.set_key(('Options', 'Game_ID'), self.steamID)
            vbsp_config.set_key(
                ('Options', 'dev_mode'),
                srctools.bool_as_int(optionWindow.DEV_MODE.get()))

            # If there are multiple of these blocks, merge them together.
            # They will end up in this order.
            vbsp_config.merge_children(
                'Textures',
                'Fizzlers',
                'Options',
                'StyleVars',
                'DropperItems',
                'Conditions',
                'Quotes',
                'PackTriggers',
            )

            for name, file, ext in FILES_TO_BACKUP:
                item_path = self.abs_path(file + ext)
                backup_path = self.abs_path(file + '_original' + ext)

                if not os.path.isfile(item_path):
                    # We can't backup at all.
                    should_backup = False
                elif name == 'Editoritems':
                    should_backup = not os.path.isfile(backup_path)
                else:
                    # Always backup the non-_original file, it'd be newer.
                    # But only if it's Valves - not our own.
                    should_backup = should_backup_app(item_path)
                    backup_is_good = should_backup_app(backup_path)
                    LOGGER.info(
                        '{}{}: normal={}, backup={}',
                        file,
                        ext,
                        'Valve' if should_backup else 'BEE2',
                        'Valve' if backup_is_good else 'BEE2',
                    )

                    if not should_backup and not backup_is_good:
                        # It's a BEE2 application, we have a problem.
                        # Both the real and backup are bad, we need to get a
                        # new one.
                        try:
                            os.remove(backup_path)
                        except FileNotFoundError:
                            pass
                        try:
                            os.remove(item_path)
                        except FileNotFoundError:
                            pass

                        export_screen.reset()
                        if messagebox.askokcancel(
                                title=_('BEE2 - Export Failed!'),
                                message=_(
                                    'Compiler file {file} missing. '
                                    'Exit Steam applications, then press OK '
                                    'to verify your game cache. You can then '
                                    'export again.').format(file=file + ext, ),
                                master=TK_ROOT,
                        ):
                            webbrowser.open('steam://validate/' +
                                            str(self.steamID))
                        return False, vpk_success

                if should_backup:
                    LOGGER.info('Backing up original {}!', name)
                    shutil.copy(item_path, backup_path)
                export_screen.step('BACK')

            # Backup puzzles, if desired
            backup.auto_backup(selected_game, export_screen)

            # Special-case: implement the UnlockDefault stlylevar here,
            # so all items are modified.
            if selected_objects['StyleVar']['UnlockDefault']:
                LOGGER.info('Unlocking Items!')
                for i, item in enumerate(all_items):
                    # If the Unlock Default Items stylevar is enabled, we
                    # want to force the corridors and obs room to be
                    # deletable and copyable
                    # Also add DESIRES_UP, so they place in the correct orientation
                    if item.id in _UNLOCK_ITEMS:
                        all_items[i] = copy.copy(item)
                        item.deletable = item.copiable = True
                        item.facing = editoritems.DesiredFacing.UP

            LOGGER.info('Editing Gameinfo...')
            self.edit_gameinfo(True)
            export_screen.step('EXP')

            if not GEN_OPTS.get_bool('General', 'preserve_bee2_resource_dir'):
                LOGGER.info('Adding ents to FGD.')
                self.edit_fgd(True)
            export_screen.step('EXP')

            # AtomicWriter writes to a temporary file, then renames in one step.
            # This ensures editoritems won't be half-written.
            LOGGER.info('Writing Editoritems script...')
            with srctools.AtomicWriter(
                    self.abs_path('portal2_dlc2/scripts/editoritems.txt')
            ) as editor_file:
                editoritems.Item.export(editor_file, all_items, renderables)
            export_screen.step('EXP')

            LOGGER.info('Writing Editoritems database...')
            with open(self.abs_path('bin/bee2/editor.bin'), 'wb') as inst_file:
                pick = pickletools.optimize(pickle.dumps(all_items))
                inst_file.write(pick)
            export_screen.step('EXP')

            LOGGER.info('Writing VBSP Config!')
            os.makedirs(self.abs_path('bin/bee2/'), exist_ok=True)
            with open(self.abs_path('bin/bee2/vbsp_config.cfg'),
                      'w',
                      encoding='utf8') as vbsp_file:
                for line in vbsp_config.export():
                    vbsp_file.write(line)
            export_screen.step('EXP')

            if num_compiler_files > 0:
                LOGGER.info('Copying Custom Compiler!')
                compiler_src = utils.install_path('compiler')
                for comp_file in compiler_src.rglob('*'):
                    # Ignore folders.
                    if comp_file.is_dir():
                        continue

                    dest = self.abs_path('bin' /
                                         comp_file.relative_to(compiler_src))

                    LOGGER.info('\t* {} -> {}', comp_file, dest)

                    folder = Path(dest).parent
                    if not folder.exists():
                        folder.mkdir(parents=True, exist_ok=True)

                    try:
                        if os.path.isfile(dest):
                            # First try and give ourselves write-permission,
                            # if it's set read-only.
                            utils.unset_readonly(dest)
                        shutil.copy(comp_file, dest)
                    except PermissionError:
                        # We might not have permissions, if the compiler is currently
                        # running.
                        export_screen.reset()
                        messagebox.showerror(
                            title=_('BEE2 - Export Failed!'),
                            message=_('Copying compiler file {file} failed. '
                                      'Ensure {game} is not running.').format(
                                          file=comp_file,
                                          game=self.name,
                                      ),
                            master=TK_ROOT,
                        )
                        return False, vpk_success
                    export_screen.step('COMP')

            if should_refresh:
                LOGGER.info('Copying Resources!')
                music_files = self.copy_mod_music()
                self.refresh_cache(music_files)

            LOGGER.info('Optimizing editor models...')
            self.clean_editor_models(all_items)
            export_screen.step('EXP')

            self.generate_fizzler_sides(vbsp_config)

            if self.steamID == utils.STEAM_IDS['APERTURE TAG']:
                os.makedirs(self.abs_path('sdk_content/maps/instances/bee2/'),
                            exist_ok=True)
                with open(
                        self.abs_path(
                            'sdk_content/maps/instances/bee2/tag_coop_gun.vmf'
                        ), 'w') as f:
                    TAG_COOP_INST_VMF.export(f)

            export_screen.reset()  # Hide loading screen, we're done
            return True, vpk_success
        except loadScreen.Cancelled:
            return False, False
コード例 #14
0
ファイル: music_conf.py プロジェクト: seagemgames/BEE2.4
def make_widgets(frame: ttk.LabelFrame, pane: SubPane) -> SelectorWin:
    """Generate the UI components, and return the base window."""

    def for_channel(channel: MusicChannel) -> List[SelItem]:
        """Get the items needed for a specific channel."""
        music_list = []
        for music in Music.all():
            if music.provides_channel(channel):
                selitem = SEL_ITEMS[music.id].copy()
                selitem.snd_sample = music.get_sample(channel)
                music_list.append(selitem)
        return music_list

    # This gets overwritten when making windows.
    last_selected = {
        channel: GEN_OPTS.get_val(
            'Last_Selected',
            'music_' + channel.name.casefold(),
            '<NONE>',
        ) for channel in MusicChannel
    }

    base_win = WINDOWS[MusicChannel.BASE] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.BASE),
        title=_('Select Background Music - Base'),
        desc=_('This controls the background music used for a map. Expand '
               'the dropdown to set tracks for specific test elements.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music to the map at all. Testing Element-specific '
                    'music may still be added.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.BASE],
        attributes=[
            SelAttr.bool('SPEED', _('Propulsion Gel SFX')),
            SelAttr.bool('BOUNCE', _('Repulsion Gel SFX')),
            SelAttr.bool('TBEAM', _('Excursion Funnel Music')),
            SelAttr.bool('TBEAM_SYNC', _('Synced Funnel Music')),
        ],
    )

    WINDOWS[MusicChannel.TBEAM] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.TBEAM),
        title=_('Select Excursion Funnel Music'),
        desc=_('Set the music used while inside Excursion Funnels.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Have no music playing when inside funnels.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.TBEAM],
        attributes=[
            SelAttr.bool('TBEAM_SYNC', _('Synced Funnel Music')),
        ],
    )

    WINDOWS[MusicChannel.BOUNCE] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.BOUNCE),
        title=_('Select Repulsion Gel Music'),
        desc=_('Select the music played when players jump on Repulsion Gel.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music when jumping on Repulsion Gel.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.BOUNCE],
    )

    WINDOWS[MusicChannel.SPEED] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.SPEED),
        title=_('Select Propulsion Gel Music'),
        desc=_('Select music played when players have large amounts of horizontal velocity.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music while running fast.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.SPEED],
    )

    assert set(WINDOWS.keys()) == set(MusicChannel), "Extra channels?"

    # Widgets we want to remove when collapsing.
    exp_widgets = []  # type: List[tkinter.Widget]

    def toggle_btn_enter(event=None):
        toggle_btn['text'] = BTN_EXPAND_HOVER if is_collapsed else BTN_CONTRACT_HOVER

    def toggle_btn_exit(event=None):
        toggle_btn['text'] = BTN_EXPAND if is_collapsed else BTN_CONTRACT

    def set_collapsed():
        """Configure for the collapsed state."""
        global is_collapsed
        is_collapsed = True
        GEN_OPTS['Last_Selected']['music_collapsed'] = '1'
        base_lbl['text'] = _('Music: ')
        toggle_btn_exit()

        # Set all music to the children - so those are used.
        set_suggested(WINDOWS[MusicChannel.BASE].chosen_id, sel_item=True)

        for wid in exp_widgets:
            wid.grid_remove()

    def set_expanded():
        """Configure for the expanded state."""
        global is_collapsed
        is_collapsed = False
        GEN_OPTS['Last_Selected']['music_collapsed'] = '0'
        base_lbl['text'] = _('Base: ')
        toggle_btn_exit()
        for wid in exp_widgets:
            wid.grid()
        pane.update_idletasks()
        pane.move()

    def toggle(event=None):
        if is_collapsed:
            set_expanded()
        else:
            set_collapsed()
        pane.update_idletasks()
        pane.move()

    frame.columnconfigure(2, weight=1)

    base_lbl = ttk.Label(frame)
    base_lbl.grid(row=0, column=1)

    toggle_btn = ttk.Label(frame, text=' ')
    toggle_btn.bind('<Enter>', toggle_btn_enter)
    toggle_btn.bind('<Leave>', toggle_btn_exit)
    toggle_btn.bind('<ButtonPress-1>', toggle)
    toggle_btn.grid(row=0, column=0)

    for row, channel in enumerate(MusicChannel):
        btn = WINDOWS[channel].widget(frame)
        if row:
            exp_widgets.append(btn)
        btn.grid(row=row, column=2, sticky='EW')

    for row, text in enumerate([
        _('Funnel:'),
        _('Bounce:'),
        _('Speed:'),
    ], start=1):
        label = ttk.Label(frame, text=text)
        exp_widgets.append(label)
        label.grid(row=row, column=1, sticky='EW')

    if GEN_OPTS.get_bool('Last_Selected', 'music_collapsed', True):
        set_collapsed()
    else:
        set_expanded()

    for channel, win in WINDOWS.items():
        win.sel_item_id(last_selected[channel])

    return base_win
コード例 #15
0
        # Warn if a file is missing that a packfile refers to
        'log_incorrect_packfile': '0',

        # Show the log window on startup
        'show_log_win': '0',
        # The lowest level which will be shown.
        'window_log_level': 'INFO',
    },
}

GEN_OPTS.load()
GEN_OPTS.set_defaults(DEFAULT_SETTINGS)

LOGGER.debug('Starting loading screen...')
loadScreen.main_loader.set_length('UI', 14)
loadScreen.set_force_ontop(GEN_OPTS.get_bool('General', 'splash_stay_ontop'))
loadScreen.show_main_loader(GEN_OPTS.get_bool('General', 'compact_splash'))

# OS X starts behind other windows, fix that.
if utils.MAC:
    TK_ROOT.lift()

logWindow.init(GEN_OPTS.get_bool('Debug', 'show_log_win'),
               GEN_OPTS['Debug']['window_log_level'])

LOGGER.debug('Loading settings...')

UI.load_settings()

gameMan.load()
gameMan.set_game_by_name(GEN_OPTS.get_val('Last_Selected', 'Game', ''), )
コード例 #16
0
ファイル: BEE2.py プロジェクト: mariovct/BEE2.4
        # The lowest level which will be shown.
        'window_log_level': 'INFO',
    },
}

loadScreen.main_loader.set_length('UI', 15)
loadScreen.main_loader.show()

# OS X starts behind other windows, fix that.
if utils.MAC:
    TK_ROOT.lift()

GEN_OPTS.load()
GEN_OPTS.set_defaults(DEFAULT_SETTINGS)

logWindow.init(GEN_OPTS.get_bool('Debug', 'show_log_win'),
               GEN_OPTS['Debug']['window_log_level'])

UI.load_settings()

gameMan.load()
gameMan.set_game_by_name(GEN_OPTS.get_val('Last_Selected', 'Game', ''), )
gameMan.scan_music_locs()

LOGGER.info('Loading Packages...')
pack_data, package_sys = packageLoader.load_packages(
    GEN_OPTS['Directories']['package'],
    log_item_fallbacks=GEN_OPTS.get_bool('Debug', 'log_item_fallbacks'),
    log_missing_styles=GEN_OPTS.get_bool('Debug', 'log_missing_styles'),
    log_missing_ent_count=GEN_OPTS.get_bool('Debug', 'log_missing_ent_count'),
    log_incorrect_packfile=GEN_OPTS.get_bool('Debug',
コード例 #17
0
ファイル: music_conf.py プロジェクト: BenVlodgi/BEE2.4
def make_widgets(frame: ttk.LabelFrame, pane: SubPane) -> SelectorWin:
    """Generate the UI components, and return the base window."""

    def for_channel(channel: MusicChannel) -> List[SelItem]:
        """Get the items needed for a specific channel."""
        music_list = []
        for music in Music.all():
            if music.provides_channel(channel):
                selitem = SEL_ITEMS[music.id].copy()
                selitem.snd_sample = music.get_sample(channel)
                music_list.append(selitem)
        return music_list

    # This gets overwritten when making windows.
    last_selected = {
        channel: GEN_OPTS.get_val(
            'Last_Selected',
            'music_' + channel.name.casefold(),
            '<NONE>',
        ) for channel in MusicChannel
    }

    base_win = WINDOWS[MusicChannel.BASE] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.BASE),
        title=_('Select Background Music - Base'),
        desc=_('This controls the background music used for a map. Expand '
               'the dropdown to set tracks for specific test elements.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music to the map at all. Testing Element-specific '
                    'music may still be added.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.BASE],
        attributes=[
            SelAttr.bool('SPEED', _('Propulsion Gel SFX')),
            SelAttr.bool('BOUNCE', _('Repulsion Gel SFX')),
            SelAttr.bool('TBEAM', _('Excursion Funnel Music')),
            SelAttr.bool('TBEAM_SYNC', _('Synced Funnel Music')),
        ],
    )

    WINDOWS[MusicChannel.TBEAM] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.TBEAM),
        title=_('Select Excursion Funnel Music'),
        desc=_('Set the music used while inside Excursion Funnels.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Have no music playing when inside funnels.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.TBEAM],
        attributes=[
            SelAttr.bool('TBEAM_SYNC', _('Synced Funnel Music')),
        ],
    )

    WINDOWS[MusicChannel.BOUNCE] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.BOUNCE),
        title=_('Select Repulsion Gel Music'),
        desc=_('Select the music played when players jump on Repulsion Gel.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music when jumping on Repulsion Gel.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.BOUNCE],
    )

    WINDOWS[MusicChannel.SPEED] = SelectorWin(
        TK_ROOT,
        for_channel(MusicChannel.SPEED),
        title=_('Select Propulsion Gel Music'),
        desc=_('Select music played when players have large amounts of horizontal velocity.'),
        has_none=True,
        sound_sys=filesystem,
        none_desc=_('Add no music while running fast.'),
        callback=selwin_callback,
        callback_params=[MusicChannel.SPEED],
    )

    assert set(WINDOWS.keys()) == set(MusicChannel), "Extra channels?"

    # Widgets we want to remove when collapsing.
    exp_widgets = []  # type: List[tkinter.Widget]

    def toggle_btn_enter(event=None):
        toggle_btn['text'] = BTN_EXPAND_HOVER if is_collapsed else BTN_CONTRACT_HOVER

    def toggle_btn_exit(event=None):
        toggle_btn['text'] = BTN_EXPAND if is_collapsed else BTN_CONTRACT

    def set_collapsed():
        """Configure for the collapsed state."""
        global is_collapsed
        is_collapsed = True
        GEN_OPTS['Last_Selected']['music_collapsed'] = '1'
        base_lbl['text'] = _('Music: ')
        toggle_btn_exit()

        # Set all music to the children - so those are used.
        set_suggested(WINDOWS[MusicChannel.BASE].chosen_id, sel_item=True)

        for wid in exp_widgets:
            wid.grid_remove()

    def set_expanded():
        """Configure for the expanded state."""
        global is_collapsed
        is_collapsed = False
        GEN_OPTS['Last_Selected']['music_collapsed'] = '0'
        base_lbl['text'] = _('Base: ')
        toggle_btn_exit()
        for wid in exp_widgets:
            wid.grid()
        pane.update_idletasks()
        pane.move()

    def toggle(event=None):
        if is_collapsed:
            set_expanded()
        else:
            set_collapsed()
        pane.update_idletasks()
        pane.move()

    frame.columnconfigure(2, weight=1)

    base_lbl = ttk.Label(frame)
    base_lbl.grid(row=0, column=1)

    toggle_btn = ttk.Label(frame, text=' ')
    toggle_btn.bind('<Enter>', toggle_btn_enter)
    toggle_btn.bind('<Leave>', toggle_btn_exit)
    toggle_btn.bind('<ButtonPress-1>', toggle)
    toggle_btn.grid(row=0, column=0)

    for row, channel in enumerate(MusicChannel):
        btn = WINDOWS[channel].widget(frame)
        if row:
            exp_widgets.append(btn)
        btn.grid(row=row, column=2, sticky='EW')

    for row, text in enumerate([
        _('Funnel:'),
        _('Bounce:'),
        _('Speed:'),
    ], start=1):
        label = ttk.Label(frame, text=text)
        exp_widgets.append(label)
        label.grid(row=row, column=1, sticky='EW')

    if GEN_OPTS.get_bool('Last_Selected', 'music_collapsed', True):
        set_collapsed()
    else:
        set_expanded()

    for channel, win in WINDOWS.items():
        win.sel_item_id(last_selected[channel])

    return base_win
コード例 #18
0
ファイル: StyleVarPane.py プロジェクト: Stendec-UA/BEE2.4
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title="Style Properties",
        name="style",
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png("icons/win_stylevar"),
        tool_col=3,
    )

    UI["style_can"] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI["style_can"].grid(sticky="NSEW")
    window.rowconfigure(0, weight=1)

    UI["style_scroll"] = ttk.Scrollbar(window, orient=VERTICAL, command=UI["style_can"].yview)
    UI["style_scroll"].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI["style_can"]["yscrollcommand"] = UI["style_scroll"].set
    canvas_frame = ttk.Frame(UI["style_can"])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky="EW")

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky="EW")

    ttk.Separator(canvas_frame, orient=HORIZONTAL).grid(row=2, sticky="EW", pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky="EW")

    UI["stylevar_chosen_none"] = ttk.Label(frm_chosen, text="No Options!", font="TkMenuFont", justify="center")
    UI["stylevar_other_none"] = ttk.Label(frm_other, text="None!", font="TkMenuFont", justify="center")

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(value=GEN_OPTS.get_bool("StyleVar", var.id, var.enabled))
        checkbox_special[var.id] = ttk.Checkbutton(
            frame_all, variable=tk_vars[var.id], text=var.name, command=functools.partial(set_stylevar, var.id)
        )
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        if var.desc:
            tooltip.add_tooltip(checkbox_special[var.id], var.desc)

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {"variable": tk_vars[var.id], "text": var.name, "command": functools.partial(set_stylevar, var.id)}
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        if var.desc:
            tooltip.add_tooltip(checkbox_chosen[var.id], var.desc)
            tooltip.add_tooltip(checkbox_other[var.id], var.desc)

    UI["style_can"].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI["style_can"].update_idletasks()
    UI["style_can"].config(scrollregion=UI["style_can"].bbox(ALL), width=canvas_frame.winfo_reqwidth())
    ttk.Sizegrip(window, cursor=utils.CURSORS["stretch_vert"]).grid(row=1, column=0)

    UI["style_can"].bind("<Configure>", flow_stylevar)

    # Scroll globally even if canvas is not selected.
    if utils.WIN:
        window.bind("<MouseWheel>", lambda e: scroll(int(-1 * (e.delta / 120))))
    elif utils.MAC:
        window.bind("<Button-4>", lambda e: scroll(1))
        window.bind("<Button-5>", lambda e: scroll(-1))
コード例 #19
0
async def init_app():
    """Initialise the application."""
    GEN_OPTS.load()
    GEN_OPTS.set_defaults(DEFAULT_SETTINGS)

    # Special case, load in this early so it applies.
    utils.DEV_MODE = GEN_OPTS.get_bool('Debug', 'development_mode')
    DEV_MODE.set(utils.DEV_MODE)

    LOGGER.debug('Starting loading screen...')
    loadScreen.main_loader.set_length('UI', 16)
    loadScreen.set_force_ontop(
        GEN_OPTS.get_bool('General', 'splash_stay_ontop'))
    loadScreen.show_main_loader(GEN_OPTS.get_bool('General', 'compact_splash'))

    # OS X starts behind other windows, fix that.
    if utils.MAC:
        TK_ROOT.lift()

    logWindow.HANDLER.set_visible(GEN_OPTS.get_bool('Debug', 'show_log_win'))
    logWindow.HANDLER.setLevel(GEN_OPTS['Debug']['window_log_level'])

    LOGGER.debug('Loading settings...')

    UI.load_settings()

    gameMan.load()
    gameMan.set_game_by_name(GEN_OPTS.get_val('Last_Selected', 'Game', ''), )
    gameMan.scan_music_locs()

    LOGGER.info('Loading Packages...')
    package_sys = await packages.load_packages(
        list(get_package_locs()),
        loader=loadScreen.main_loader,
        log_item_fallbacks=GEN_OPTS.get_bool('Debug', 'log_item_fallbacks'),
        log_missing_styles=GEN_OPTS.get_bool('Debug', 'log_missing_styles'),
        log_missing_ent_count=GEN_OPTS.get_bool('Debug',
                                                'log_missing_ent_count'),
        log_incorrect_packfile=GEN_OPTS.get_bool('Debug',
                                                 'log_incorrect_packfile'),
        has_tag_music=gameMan.MUSIC_TAG_LOC is not None,
        has_mel_music=gameMan.MUSIC_MEL_VPK is not None,
    )
    loadScreen.main_loader.step('UI', 'pre_ui')
    APP_NURSERY.start_soon(img.init, package_sys)
    APP_NURSERY.start_soon(sound.sound_task)

    # Load filesystems into various modules
    music_conf.load_filesystems(package_sys.values())
    gameMan.load_filesystems(package_sys.values())
    UI.load_packages()
    loadScreen.main_loader.step('UI', 'package_load')
    LOGGER.info('Done!')

    # Check games for Portal 2's basemodui.txt file, so we can translate items.
    LOGGER.info('Loading Item Translations...')
    for game in gameMan.all_games:
        game.init_trans()

    LOGGER.info('Initialising UI...')
    await UI.init_windows()  # create all windows
    LOGGER.info('UI initialised!')

    loadScreen.main_loader.destroy()
    # Delay this until the loop has actually run.
    # Directly run TK_ROOT.lift() in TCL, instead
    # of building a callable.
    TK_ROOT.tk.call('after', 10, 'raise', TK_ROOT)
コード例 #20
0
ファイル: StyleVarPane.py プロジェクト: GLiTcH2/BEE2.4
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
        )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], window)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
        ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
        )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
        )

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.default)
        )
        checkbox_special[var.id] = ttk.Checkbutton(
            frame_all,
            variable=tk_vars[var.id],
            text=var.name,
            command=functools.partial(set_stylevar, var.id)
            )
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        tooltip.add_tooltip(
            checkbox_special[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
            }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        desc = make_desc(var)
        tooltip.add_tooltip(
            checkbox_chosen[var.id],
            desc,
        )
        tooltip.add_tooltip(
            checkbox_other[var.id],
            desc,
        )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)
コード例 #21
0
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title=_('Style Properties'),
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
    )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set

    utils.add_mousewheel(UI['style_can'], window)

    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text=_("All:"))
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text=_("Selected Style:"))
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
    ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text=_("Other Styles:"))
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text=_('No Options!'),
        font='TkMenuFont',
        justify='center',
    )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text=_('None!'),
        font='TkMenuFont',
        justify='center',
    )

    all_pos = 0
    for all_pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.default))
        checkbox_all[var.id] = ttk.Checkbutton(frame_all,
                                               variable=tk_vars[var.id],
                                               text=var.name,
                                               command=functools.partial(
                                                   set_stylevar, var.id))
        checkbox_all[var.id].grid(row=all_pos, column=0, sticky="W", padx=3)

        tooltip.add_tooltip(
            checkbox_all[var.id],
            make_desc(var, is_hardcoded=True),
        )

    for var in VAR_LIST:
        tk_vars[var.id] = IntVar(value=var.enabled)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
        }
        desc = make_desc(var)
        if var.applies_to_all():
            # Available in all styles - put with the hardcoded variables.
            all_pos += 1

            checkbox_all[var.id] = check = ttk.Checkbutton(frame_all, **args)
            check.grid(row=all_pos, column=0, sticky="W", padx=3)
            tooltip.add_tooltip(check, desc)
        else:
            # Swap between checkboxes depending on style.
            checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
            checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )

    if utils.USE_SIZEGRIP:
        ttk.Sizegrip(
            window,
            cursor=utils.CURSORS['stretch_vert'],
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)
コード例 #22
0
ファイル: StyleVarPane.py プロジェクト: GiovanH/BEE2.4
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=2,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
        )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set
    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
        ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
        )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
        )

    for pos, (var_id, name, default) in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var_id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var_id, default)
        )
        checkbox_special[var_id] = ttk.Checkbutton(
            frame_all,
            variable=tk_vars[var_id],
            text=name,
            command=functools.partial(set_stylevar, var_id)
            )
        checkbox_special[var_id].grid(row=pos, column=0, sticky="W", padx=3)

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
            }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
        )
    ttk.Sizegrip(
        window,
        cursor="sb_v_double_arrow",
        ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    # Scroll globally even if canvas is not selected.
    window.bind(
        "<MouseWheel>",
        lambda e: scroll(int(-1*(e.delta/120))),
        )
    window.bind(
        "<Button-4>",
        lambda e: scroll(1),
        )
    window.bind(
        "<Button-5>",
        lambda e: scroll(-1),
        )
コード例 #23
0
ファイル: StyleVarPane.py プロジェクト: Stendec-UA/BEE2.4
def make_pane(tool_frame):
    """Create the styleVar pane.

    """
    global window
    window = SubPane(
        TK_ROOT,
        options=GEN_OPTS,
        title='Style Properties',
        name='style',
        resize_y=True,
        tool_frame=tool_frame,
        tool_img=png.png('icons/win_stylevar'),
        tool_col=3,
    )

    UI['style_can'] = Canvas(window, highlightthickness=0)
    # need to use a canvas to allow scrolling
    UI['style_can'].grid(sticky='NSEW')
    window.rowconfigure(0, weight=1)

    UI['style_scroll'] = ttk.Scrollbar(
        window,
        orient=VERTICAL,
        command=UI['style_can'].yview,
    )
    UI['style_scroll'].grid(column=1, row=0, rowspan=2, sticky="NS")
    UI['style_can']['yscrollcommand'] = UI['style_scroll'].set
    canvas_frame = ttk.Frame(UI['style_can'])

    frame_all = ttk.Labelframe(canvas_frame, text="All:")
    frame_all.grid(row=0, sticky='EW')

    frm_chosen = ttk.Labelframe(canvas_frame, text="Selected Style:")
    frm_chosen.grid(row=1, sticky='EW')

    ttk.Separator(
        canvas_frame,
        orient=HORIZONTAL,
    ).grid(row=2, sticky='EW', pady=(10, 5))

    frm_other = ttk.Labelframe(canvas_frame, text="Other Styles:")
    frm_other.grid(row=3, sticky='EW')

    UI['stylevar_chosen_none'] = ttk.Label(
        frm_chosen,
        text='No Options!',
        font='TkMenuFont',
        justify='center',
    )
    UI['stylevar_other_none'] = ttk.Label(
        frm_other,
        text='None!',
        font='TkMenuFont',
        justify='center',
    )

    for pos, var in enumerate(styleOptions):
        # Add the special stylevars which apply to all styles
        tk_vars[var.id] = IntVar(
            value=GEN_OPTS.get_bool('StyleVar', var.id, var.enabled))
        checkbox_special[var.id] = ttk.Checkbutton(frame_all,
                                                   variable=tk_vars[var.id],
                                                   text=var.name,
                                                   command=functools.partial(
                                                       set_stylevar, var.id))
        checkbox_special[var.id].grid(row=pos, column=0, sticky="W", padx=3)

        if var.desc:
            tooltip.add_tooltip(
                checkbox_special[var.id],
                var.desc,
            )

    for var in var_list:
        tk_vars[var.id] = IntVar(value=var.default)
        args = {
            'variable': tk_vars[var.id],
            'text': var.name,
            'command': functools.partial(set_stylevar, var.id)
        }
        checkbox_chosen[var.id] = ttk.Checkbutton(frm_chosen, **args)
        checkbox_other[var.id] = ttk.Checkbutton(frm_other, **args)
        if var.desc:
            tooltip.add_tooltip(
                checkbox_chosen[var.id],
                var.desc,
            )
            tooltip.add_tooltip(
                checkbox_other[var.id],
                var.desc,
            )

    UI['style_can'].create_window(0, 0, window=canvas_frame, anchor="nw")
    UI['style_can'].update_idletasks()
    UI['style_can'].config(
        scrollregion=UI['style_can'].bbox(ALL),
        width=canvas_frame.winfo_reqwidth(),
    )
    ttk.Sizegrip(
        window,
        cursor=utils.CURSORS['stretch_vert'],
    ).grid(row=1, column=0)

    UI['style_can'].bind('<Configure>', flow_stylevar)

    # Scroll globally even if canvas is not selected.
    if utils.WIN:
        window.bind(
            "<MouseWheel>",
            lambda e: scroll(int(-1 * (e.delta / 120))),
        )
    elif utils.MAC:
        window.bind(
            "<Button-4>",
            lambda e: scroll(1),
        )
        window.bind(
            "<Button-5>",
            lambda e: scroll(-1),
        )
コード例 #24
0
ファイル: BEE2.py プロジェクト: Reactorcore21/BEE2.4
        'log_missing_ent_count': '0',
        # Warn if a file is missing that a packfile refers to
        'log_incorrect_packfile': '0',

        # Show the log window on startup
        'show_log_win': '0',
        # The lowest level which will be shown.
        'window_log_level': 'INFO',
    },
}

GEN_OPTS.load()
GEN_OPTS.set_defaults(DEFAULT_SETTINGS)

loadScreen.main_loader.set_length('UI', 14)
loadScreen.show_main_loader(GEN_OPTS.get_bool('General', 'compact_splash'))

# OS X starts behind other windows, fix that.
if utils.MAC:
    TK_ROOT.lift()

logWindow.init(
    GEN_OPTS.get_bool('Debug', 'show_log_win'),
    GEN_OPTS['Debug']['window_log_level']
)

UI.load_settings()

gameMan.load()
gameMan.set_game_by_name(
    GEN_OPTS.get_val('Last_Selected', 'Game', ''),
コード例 #25
0
ファイル: backup.py プロジェクト: Coolasp1e/BEE2.4
def auto_backup(game: 'gameMan.Game', loader: LoadScreen):
    """Perform an automatic backup for the given game.

    We do this seperately since we don't need to read the property files.
    """
    from BEE2_config import GEN_OPTS
    if not GEN_OPTS.get_bool('General', 'enable_auto_backup'):
        # Don't backup!
        loader.skip_stage(AUTO_BACKUP_STAGE)
        return

    folder = find_puzzles(game)
    if not folder:
        loader.skip_stage(AUTO_BACKUP_STAGE)
        return

    # Keep this many previous
    extra_back_count = GEN_OPTS.get_int('General', 'auto_backup_count', 0)

    to_backup = os.listdir(folder)
    backup_dir = GEN_OPTS.get_val('Directories', 'backup_loc', 'backups/')

    os.makedirs(backup_dir, exist_ok=True)

    # A version of the name stripped of special characters
    # Allowed: a-z, A-Z, 0-9, '_-.'
    safe_name = utils.whitelist(
        game.name,
        valid_chars=BACKUP_CHARS,
    )

    loader.set_length(AUTO_BACKUP_STAGE, len(to_backup))

    if extra_back_count:
        back_files = [
            AUTO_BACKUP_FILE.format(game=safe_name, ind='')
        ] + [
            AUTO_BACKUP_FILE.format(game=safe_name, ind='_'+str(i+1))
            for i in range(extra_back_count)
        ]
        # Move each file over by 1 index, ignoring missing ones
        # We need to reverse to ensure we don't overwrite any zips
        for old_name, new_name in reversed(
                list(zip(back_files, back_files[1:]))
                ):
            LOGGER.info(
                'Moving: {old} -> {new}',
                old=old_name,
                new=new_name,
            )
            old_name = os.path.join(backup_dir, old_name)
            new_name = os.path.join(backup_dir, new_name)
            try:
                os.remove(new_name)
            except FileNotFoundError:
                pass  # We're overwriting this anyway
            try:
                os.rename(old_name, new_name)
            except FileNotFoundError:
                pass

    final_backup = os.path.join(
        backup_dir,
        AUTO_BACKUP_FILE.format(game=safe_name, ind=''),
    )
    LOGGER.info('Writing backup to "{}"', final_backup)
    with open(final_backup, 'wb') as f:
        with ZipFile(f, mode='w', compression=ZIP_LZMA) as zip_file:
            for file in to_backup:
                zip_file.write(
                    os.path.join(folder, file),
                    file,
                    ZIP_LZMA,
                )
                loader.step(AUTO_BACKUP_STAGE)
コード例 #26
0
ファイル: backup.py プロジェクト: Coolasp1e/BEE2.4
def init_backup_settings():
    """Initialise the auto-backup settings widget."""
    from BEE2_config import GEN_OPTS
    check_var = tk.IntVar(
        value=GEN_OPTS.get_bool('General', 'enable_auto_backup')
    )
    count_value = GEN_OPTS.get_int('General', 'auto_backup_count', 0)
    back_dir = GEN_OPTS.get_val('Directories', 'backup_loc', 'backups/')

    def check_callback():
        GEN_OPTS['General']['enable_auto_backup'] = utils.bool_as_int(
            check_var.get()
        )

    def count_callback():
        GEN_OPTS['General']['auto_backup_count'] = str(count.value)

    def directory_callback(path):
        GEN_OPTS['Directories']['backup_loc'] = path

    UI['auto_frame'] = frame = ttk.LabelFrame(
        window,
    )
    UI['auto_enable'] = enable_check = ttk.Checkbutton(
        frame,
        text='Automatic Backup After Export',
        variable=check_var,
        command=check_callback,
    )

    frame['labelwidget'] = enable_check
    frame.grid(row=2, column=0, columnspan=3)

    dir_frame = ttk.Frame(
        frame,
    )
    dir_frame.grid(row=0, column=0)

    ttk.Label(
        dir_frame,
        text='Directory',
    ).grid(row=0, column=0)

    UI['auto_dir'] = tk_tools.FileField(
        dir_frame,
        loc=back_dir,
        is_dir=True,
        callback=directory_callback,
    )
    UI['auto_dir'].grid(row=1, column=0)

    count_frame = ttk.Frame(
        frame,
    )
    count_frame.grid(row=0, column=1)
    ttk.Label(
        count_frame,
        text='Keep (Per Game):'
    ).grid(row=0, column=0)

    count = tk_tools.ttk_Spinbox(
        count_frame,
        range=range(50),
        command=count_callback,
    )
    count.grid(row=1, column=0)
    count.value = count_value