Example #1
0
def move_app_to_collated_dir():
    source = doset(mac=Build.dir_dist / 'AudioQuake.app',
                   windows=Build.dir_dist / 'AudioQuake')

    destination = doset(mac=Build.dir_dist_collated,
                        windows=Build.dir_dist_collated)

    if source.is_dir() and destination.is_dir():
        shutil.move(str(source), str(destination))
    else:
        raise Exception(
            f'Either "{source}" or "{destination}" is not a directory!')
Example #2
0
	def __init__(self, parent, game_controller):
		wx.Panel.__init__(self, parent)
		sizer = wx.BoxSizer(wx.VERTICAL)

		# Playing the game

		game_modes = {
			"Play Quake": game_controller.launch_quake,
			"Play Open Quartz": game_controller.launch_open_quartz,
			"Tutorial":
				lambda: game_controller.launch_tutorial(high_contrast=False),
			"Tutorial (high-contrast maps)":
				lambda: game_controller.launch_tutorial(high_contrast=True)
		}

		for title, action in game_modes.items():
			add_launch_button(self, sizer, title, action)

		# Listing key bindings

		add_widget(sizer, wx.StaticLine(self, -1))

		keys_button = wx.Button(self, -1, 'List key bindings')

		def show_bindings(event):
			bindings_html = format_bindings_as_html()
			modal_html_page(self, 'Key bindings', bindings_html)

		keys_button.Bind(wx.EVT_BUTTON, show_bindings)
		add_widget(sizer, keys_button)

		# Server stuff

		add_widget(sizer, wx.StaticLine(self, -1))

		server_stuff = {
			"Dedicated server": doset(
				mac=start_server_mac,
				windows=lambda evt: start_server_windows(self),
				set_only=True),
			"Remote console": doset(
				mac=lambda evt: run_apple_script(dirs.gubbins / 'rcon'),
				windows=lambda evt:
					run_win_console([dirs.gubbins / 'rcon.exe']),
				set_only=True)
		}

		for title, action in server_stuff.items():
			add_cli_tool_button(self, sizer, title, action)

		sizer.SetSizeHints(self)
		self.SetSizer(sizer)
Example #3
0
def run(args, errorcheck=True, verbose=False, quiet=False, throw=False):
	"""Run a builder program

	args       - the program to run, including command-line arguments
	errorcheck - whether to monitor for CalledProcessErrors at all
	verbose    - whether to print the stdout from the program
	quiet      - whether to print anything to stdout (overrides 'verbose')
	throw      - whether to raise a CalledProcessError if encountered"""
	try:
		use_shell = doset(mac=False, windows=True)
		res = subprocess.run(
			args, capture_output=True, check=errorcheck, shell=use_shell)
		# We may not be doing strict error-checking (e.g. for vis) but still
		# want to know when it didn't work
		if not quiet and verbose:
			print(res.stdout.decode())
		elif res.returncode != 0 and not quiet:
			print('Ignored error from', args[0].name)
	except subprocess.CalledProcessError as error:
		if throw:
			details = error.output.decode().splitlines()[-1]
			raise LDLError(error.cmd[0].name + ': ' + details)
		elif not quiet:
			print('Error from', error.cmd[0].name)
			if verbose:
				print(error.output.decode())
Example #4
0
def run(args, errorcheck=True, verbose=False, quiet=False, throw=False):
    """Run a builder program

	args       - the program to run, including command-line arguments
	errorcheck - whether to monitor for CalledProcessErrors at all
	verbose    - whether to print the stdout from the program
	quiet      - whether to print anything to stdout (overrides 'verbose')
	throw      - whether to raise a CalledProcessError if encountered"""
    try:
        use_shell = doset(mac=False, windows=True)
        res = subprocess.run(args,
                             capture_output=True,
                             check=errorcheck,
                             shell=use_shell)
        # We may not be doing strict error-checking (e.g. for vis) but still
        # want to know when it didn't work
        if not quiet and verbose:
            print(res.stdout.decode())
        elif res.returncode != 0 and not quiet:
            print('Ignored error from', args[0].name)
    except subprocess.CalledProcessError as error:
        if throw:
            program = error.cmd[0].name
            details = doset(
                mac=lambda: error.output.decode().splitlines()[-1],
                windows=(
                    'Details are unavailable on Windows. This may be due to '
                    'the path to the WAD file containing the textures being '
                    'too long for the map tools, in which case moving the '
                    'AudioQuake+LDL folder closer to the root of your drive '
                    'can address this.'))
            message = doset(mac=f'{program}: {details}',
                            windows=f'{program} reported an error. {details}')

            if 'Token too large on line ' in message:
                message += (
                    '\n\nThis error is caused by the path to the WAD file '
                    'that contains the textures for the map being too long. '
                    'You can address it by moving the AudioQuake+LDL folder '
                    'closer to the root of your drive, shortening the path.')

            raise LDLError(message)
        elif not quiet:
            print('Error from', error.cmd[0].name)
            if verbose:
                print(error.output.decode())
Example #5
0
def make_zip():
    program_name = 'AudioQuake+LDL'
    platform_name = doset(mac='Mac', windows='Windows')
    archive_name = f'{program_name}_{version_string}_{platform_name}'
    # TODO: I think that unlinking first is needed, as it seems like otherwise
    #       things may only be added to the archive...
    #       https://github.com/python/cpython/blob/b2a91e0c9ee18b50cc86b21211c2258520a9f5d0/Lib/shutil.py#L935
    (Build.dir_dist / f'{archive_name}.zip').unlink(missing_ok=True)
    shutil.make_archive(Build.dir_dist / archive_name, 'zip',
                        Build.dir_dist_collated)
Example #6
0
def build_giants():
	check_platform()
	stuff = 'ZQuake, ZQCC, gamecode and Quake map tools'

	print('Building', stuff + '...')

	print('Compiling zquake')
	doset(
		mac=compile_zquake,
		windows=compile_zquake_windows)

	print('Compiling zqcc')
	doset(
		mac=compile_zqcc,
		windows=compile_zqcc_windows)

	print('Compiling gamecode')
	compile_gamecode()

	print('Renaming qutils files to lower-case')
	rename_qutils()

	print('Patching the Quake map tools')
	patch_map_tools_all()
	doset_only(windows=patch_map_tools_windows)

	print('Compiling the Quake map tools')
	doset(
		mac=compile_map_tools,
		windows=compile_map_tools_windows)

	print('Completed building', stuff + '.')
Example #7
0
def platform_appropriate_grouping(parent, label):
    """On macOS (Catalina and Big Sur) the focus order with VoiceOver is a bit
	weird with StaticBoxSizer labels coming after so many of the controls
	within. Therefore on macOS we'll just use a sizer and some text, but on
	Windows we can use a StaticBoxSizer."""
    def mac_gropuing():
        group = wx.BoxSizer(wx.VERTICAL)
        add_widget(
            group,
            wx.StaticText(parent, -1, label, style=wx.ALIGN_CENTRE_HORIZONTAL))
        return group

    return doset(mac=mac_gropuing,
                 windows=wx.StaticBoxSizer(wx.VERTICAL, parent, label))
Example #8
0
    def __init__(self, parent, title, game_controller):
        flags = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)
        wx.Frame.__init__(self, parent, title=title, style=flags)

        sizer = wx.BoxSizer(wx.VERTICAL)

        notebook = doset(mac=lambda: wx.Notebook(self),
                         windows=lambda: wx.Listbook(self))

        tab_play = PlayTab(notebook, game_controller)
        tab_help = HelpTab(notebook)
        tab_customise = CustomiseTab(notebook, game_controller)
        tab_mod = ModTab(notebook, game_controller)
        tab_map = MapTab(notebook, game_controller)

        notebook.AddPage(tab_play, "Play")
        notebook.AddPage(tab_help, "Help")
        notebook.AddPage(tab_customise, "Customise")
        notebook.AddPage(tab_mod, "Mod")
        notebook.AddPage(tab_map, "Map")

        sizer.Add(notebook, 1, wx.EXPAND)
        sizer.SetSizeHints(self)  # doesn't seem to be needed?
        self.SetSizer(sizer)

        def set_up_menu_bar():
            menubar = wx.MenuBar()
            wx.MenuBar.MacSetCommonMenuBar(menubar)

        doset_only(mac=set_up_menu_bar)

        # TODO: If Quit on the Menu Bar is used and the engine is running, the
        # app gets the beachball until the engine is quat and then it quits.
        # Sounds like the only solution is to somehow quit Quake.
        def OnClose(event):
            if game_controller.quit():
                self.Destroy()
            else:
                if event.CanVeto():
                    event.Veto()
                    Warn(self, "Can't quit whilst Quake is still running.")
                else:
                    self.Destroy()  # has no effect as Quake still running

        self.Bind(wx.EVT_CLOSE, OnClose)
Example #9
0
 def __init__(self, args, on_error):
     threading.Thread.__init__(self)
     self._engine = doset(mac=dirs.engines / 'zquake-glsdl',
                          windows=dirs.engines / 'zquake-gl.exe')
     self._command_line = (self._engine, ) + args
     self._on_error = on_error
Example #10
0
others are kept outside (because they'll be modified). The launcher could be
running from within an Application (Mac) or folder (Windows)."""
from pathlib import Path
import sys

from buildlib import doset, Build  # TODO: somehow not need Build?

_inited = False
_adjust_config_dir_to_be_root = False

if not _inited:
	if hasattr(sys, '_MEIPASS'):
		# Running from frozen app bundle/dir
		launcher_dir = Path(getattr(sys, '_MEIPASS'))
		root_dir = doset(
			mac=launcher_dir.parent.parent.parent,
			windows=launcher_dir.parent)
	else:
		# Did we already run a build, and thus can use the data already there?
		collated = Path(__file__).parent.parent / 'dist' / 'collated'
		if collated.is_dir():
			# Using latest .py code, but already-prepared frozen assets
			launcher_dir = doset(
				mac=collated / 'AudioQuake.app' / 'Contents' / 'MacOS',
				windows=collated / Build.dir_windows_app)
			root_dir = collated
		else:
			# Using latest .py code and no frozen assets (this won't work
			# terribly much :-))
			launcher_dir = root_dir = Path(__file__).resolve().parent.parent
			# Set a flag to later adjust the config path because that's where
Example #11
0
def opener(openee):
    doset(mac=lambda: check_call(['open', openee]),
          windows=lambda: startfile(openee))
Example #12
0
"""AudioQuake & LDL Launcher - Customise tab"""
# FIXME: enforce min and max resolutions
from buildlib import doset
import launcherlib.config as config

RESOLUTIONS = [
    '640x400 (16:10)',  # Default on macOS
    '640x480 (4:3)',  # Default on Windows
    '800x600 (4:3)',
    '1152x720 (16:10)',
    '1280x720 (16:9)',
    '1024x768 (4:3)'
]

DEFAULT_RESOLUTION_INDEX = doset(mac=0, windows=1)

RESOLUTIONS[DEFAULT_RESOLUTION_INDEX] += ' [default]'


def width_and_height(resolution_string):
    """Given a string, extract the width and height of the corresponding
	resolution

	Raises ValueError if the string doesn't describe a resolution"""
    if ' ' in resolution_string:
        dimensions = resolution_string.split(' ')[0]
    else:
        dimensions = resolution_string
    xstr, ystr = dimensions.split('x')  # may raise ValueError
    return xstr, ystr
Example #13
0
 def __init__(self):
     doset(mac=self._init_mac, windows=self._init_windows)
Example #14
0
def make_zip():
    program_name = 'AudioQuake+LDL'
    platform_name = doset(mac='Mac', windows='Windows')
    archive_name = f'{program_name}_{version_string}_{platform_name}'
    shutil.make_archive(Build.dir_dist / archive_name, 'zip',
                        Build.dir_dist_collated)
Example #15
0
def copy_in_rcon():
    rcon_bin = doset(mac='rcon', windows='rcon.exe')

    shutil.copy(Build.dir_dist_rcon / rcon_bin, Build.dir_aq_exe_internals)