예제 #1
0
def cmd_metagen(args):
    if not os.path.isfile(args.project_file):
        error_project_not_found(args.project_file)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    exe_path = os.path.join(crypath.get_engine_path(), 'Tools/rc/rc.exe')
    if not os.path.isfile(exe_path):
        error_engine_tool_not_found(exe_path)

    job_path = os.path.join(crypath.get_engine_path(),
                            'Tools/cryassets/rcjob_cryassets.xml')
    if not os.path.isfile(job_path):
        error_engine_tool_not_found(job_path)

    project_path = os.path.dirname(os.path.abspath(args.project_file))
    asset_dir = project.asset_dir()
    asset_path = os.path.normpath(os.path.join(project_path, asset_dir))

    subcmd = (exe_path, ('/job=' + job_path), ('/src=' + asset_path))

    print_subprocess(subcmd)
    subprocess.Popen(subcmd)
예제 #2
0
def cmd_edit(args):
    if not os.path.isfile(args.project_file):
        error_project_not_found(args.project_file)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    exe_path = os.path.join(crypath.get_engine_path(), 'bin',
                            args.platform, 'Sandbox.exe')
    if not os.path.isfile(exe_path):
        error_engine_tool_not_found(exe_path)

    # ---

    subcmd = (
        exe_path,
        '-project',
        os.path.abspath(args.project_file)
    )

    print_subprocess(subcmd)
    subprocess.Popen(subcmd)
예제 #3
0
def cmd_projgen(args, open_cmake=False):
    if not os.path.isfile(args.project_file):
        error_project_not_found(args.project_file)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    project_path = os.path.abspath(os.path.dirname(args.project_file))
    engine_path = crypath.get_engine_path()

    cmakelists_dir = project.cmakelists_dir()

    if not cmakelists_dir:
        error_code_folder_not_specified()

    code_directory = os.path.join(project_path, cmakelists_dir)

    # Generate solutions
    crysolutiongenerator.generate_solution(args.project_file, code_directory,
                                           engine_path)

    # Skip on Crytek build agents
    if args.buildmachine:
        return

    cmakelists_path = os.path.join(os.path.join(project_path, cmakelists_dir),
                                   'CMakeLists.txt')

    # Generate the Solution
    if code_directory is not None and os.path.isfile(cmakelists_path):
        generate_project_solution(project_path, code_directory, open_cmake)
예제 #4
0
def cmd_build(args):
    if not os.path.isfile(args.project_file):
        error_project_not_found(args.project_file)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    cmake_path = crypath.get_cmake_exe_path()
    if cmake_path is None:
        error_cmake_not_found()

    # --- cmake
    if project.cmakelists_dir() is not None:
        project_path = os.path.dirname(os.path.abspath(args.project_file))
        solution_dir = get_project_solution_dir(project_path)
        if 'win32' in solution_dir:
            error_platform_deprecated('win32')
        subcmd = (cmake_path, '--build', solution_dir, '--config', args.config)

        print_subprocess(subcmd)
        errcode = subprocess.call(subcmd, cwd=project_path)
        if errcode != 0:
            sys.exit(errcode)
예제 #5
0
def create_config(project_file, export_path, config_path, config_type):
    """
    Create the config file which contains the cryproject file,
    and generates the system.cfg.
    """
    project_name = "game.cryproject"
    alt_project_name = "game.crygame"
    dst_file = os.path.join(export_path, project_name)

    # Replace GUIDs with binary names
    project = cryproject.CryProject()
    try:
        project.load(project_file)
    except Exception:
        print("Unable to read project file %s" % (project_file))
        raise

    engine_id = project.engine_id()
    plugins = project.plugins_list()
    new_plugins = []
    if plugins:
        for it in plugins:
            platforms = it.get("platforms")
            if platforms:
                current_platform = CONFIGURATION_PLATFORM_LOOKUP[config_type]
                if current_platform not in platforms:
                    continue

            if it.get("guid", '') != '':
                plugin = cryplugin.CryPlugin()
                plugin.load(cryplugin.find(engine_id, it["guid"]))

                serialized_plugins = serialize_plugin_for_config(
                    plugin, engine_id, config_path)

                for it2 in serialized_plugins:
                    new_plugins.append(it2)
            else:
                new_plugins.append(it)

        project.set_plugin_list(new_plugins)

    project.save(dst_file)

    use_config = True
    # If possible put the project file in a pak. Otherwise rename the
    # project file's extension to crygame so it won't show all the
    # cryproject options on right-click.
    if create_config_pak(export_path, dst_file) and os.path.isfile(dst_file):
        os.remove(dst_file)
    else:
        os.rename(dst_file, os.path.join(export_path, alt_project_name))
        use_config = False

    with open(os.path.join(export_path, 'system.cfg'), 'w') as file_handle:
        if not use_config:
            file_handle.write('sys_project={}\n'.format(alt_project_name))
        file_handle.write('sys_asserts=0\n')
        file_handle.write('sys_float_exceptions = 0\n')
예제 #6
0
def cmd_require(args):
    registry = cryregistry.load()
    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    plugin_dependencies = {}
    require_getall(registry, project.require_list(), plugin_dependencies)
    plugin_list = require_sortedlist(plugin_dependencies)
    plugin_list = cryregistry.filter_plugin(registry, plugin_list)

    project_path = os.path.dirname(args.project_file)
    plugin_path = os.path.join(project_path, 'cryext.txt')
    if os.path.isfile(plugin_path):
        os.remove(plugin_path)

    plugin_file = open(plugin_path, 'w')
    for k in plugin_list:
        project_file = cryregistry.project_file(registry, k)
        project_path = os.path.dirname(project_file)
        project = cryproject.CryProject()
        try:
            project.load(project_file)
        except Exception:
            error_project_json_decode(args.project_file)

        (m_extensionName,
         shared_path) = cryproject.shared_tuple(project, args.platform,
                                                args.config)
        asset_dir = project.asset_dir()

        m_extensionBinaryPath = os.path.normpath(
            os.path.join(project_path, shared_path))
        m_extensionAssetDirectory = os.path.normpath(
            os.path.join(project_path, asset_dir)) if asset_dir else ''
        m_extensionClassName = 'EngineExtension_%s' % os.path.splitext(
            os.path.basename(m_extensionBinaryPath))[0]

        line = ';'.join((m_extensionName, m_extensionClassName,
                         m_extensionBinaryPath, m_extensionAssetDirectory))
        plugin_file.write(line + os.linesep)

    plugin_file.close()
예제 #7
0
def switch_engine(project_file, engine_id, silent):
    """
    Switch the engine of the selected project to the specified engine.
    By setting silent to True, no permissions will be asked from the user
    and warnings are not given.
    """
    project = cryproject.CryProject()
    try:
        project.load(project_file)
    except Exception:
        print("Unable to read project file %s" % (project_file))
        raise

    if project.engine_id() != engine_id:
        if not silent and HAS_WIN_MODULES:
            message = ('Changing the version of the engine can cause the '
                       'project to become unstable. Do you want to create a '
                       'backup before switching the engine?')
            result = MESSAGEBOX(
                None, message, 'Changing engine version',
                win32con.MB_YESNOCANCEL | win32con.MB_ICONWARNING)

            if result == win32con.IDCANCEL:
                # Return 1 to indicate that changing the engine is
                # canceled by the user.
                return 1

            if result == win32con.IDYES:
                create_backup(project_file)

        try:
            project.set_engine_id(engine_id)
            project.save(project_file)
        except Exception:
            # Catch every exception and print it to the console.
            # This way the command can be debugged in the console but
            # the normal user will not be overwhelmed with technical stuff.
            exception_info = sys.exc_info()[0]
            print(repr(exception_info))
            message = 'An error occurred while changing the engine version. ' \
                      'Is the project file read-only?'
            if not silent and HAS_WIN_MODULES:
                MESSAGEBOX(None, message, 'An error occurred',
                           win32con.MB_OK | win32con.MB_ICONERROR)
            else:
                sys.stderr.write(message)
            return 1

        if not silent and HAS_WIN_MODULES:
            message = 'The engine version has changed and this has caused ' \
                      'the code to become incompatible. Please generate the ' \
                      'solution, fix any errors in the code and rebuild the ' \
                      'project before launching it.'
            MESSAGEBOX(None, message, 'Rebuild required',
                       win32con.MB_OK | win32con.MB_ICONWARNING)

    return 0
예제 #8
0
def cmd_switch(args):
    """
    Command to switch the project to another engine. By specifying an
    engine version the project will instantly switch to that engine.
    Otherwise a GUI is shown where the user can select the engine version.
    """
    if not os.path.isfile(args.project_file):
        error_project_not_found(args)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args)

    # If the engine version is already specified than set it and return early.
    if args.engine_id is not None:
        sys.exit(switch_engine(args.project_file, args.engine_id, args.silent))

    engine_list = []
    engine_version = []

    engines = cryregistry.load_engines()
    for (engine_id, engine_data) in engines.items():
        engine_file = engine_data['uri']

        info = engine_data.get('info', {})
        name = info.get('name', os.path.dirname(engine_file))
        version = info.get('version')
        if version is not None:
            engine_version.append((version, name, engine_id))
        else:
            engine_list.append((name, engine_id))

    engine_version.sort()
    engine_version.reverse()
    engine_list.sort()

    engine_list = list(map(lambda a: (a[2], a[1]), engine_version)) + list(
        map(lambda a: (a[1], a[0]), engine_list))

    engine_id = project.engine_id()

    found = 0
    for i in range(len(engine_list)):
        (id_, name) = engine_list[i]
        if id_ == engine_id:
            found = i
            break

    app = CrySwitch(args.project_file, engine_list, found)
    app.mainloop()
예제 #9
0
def require_getall(registry, require_list, result):

    for k in require_list:
        if k in result:
            continue

        project_file = cryregistry.project_file(registry, k)
        project = cryproject.CryProject()
        try:
            project.load(project_file)
            result[k] = project.require_list()
        except Exception:
            error_project_json_decode(project_file)
예제 #10
0
def cmd_run_project(args, sys_argv=sys.argv[1:]):
    """
    Runs the command on the project, by invoking it on the cryrun.exe
    that is used by the engine the project is registered to.
    """
    if not os.path.isfile(args.project_file):
        error_project_not_found(args)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args)

    engine_id = project.engine_id()
    engine_path = ""

    # Start by checking for the ability to specifying use of the local engine
    if engine_id is '.':
        engine_path = os.path.dirname(args.project_file)
    else:
        # Now check the registry
        engine_registry = cryregistry.load_engines()
        engine_path = cryregistry.engine_path(engine_registry, engine_id)
        if engine_path is None:
            error_engine_path_not_found(args, engine_id)

    if getattr(sys, 'frozen', False):
        subcmd = [get_cryrun_path(engine_path)]
    else:
        subcmd = [get_python_path(), get_cryrun_path(engine_path)]

    if not os.path.isfile(subcmd[-1]):
        error_engine_tool_not_found(args, subcmd[-1])

    subcmd.extend(sys_argv)

    print_subprocess(subcmd)
    try:
        subprocess.run(subcmd,
                       stdout=None,
                       stderr=None,
                       check=True,
                       universal_newlines=True)
    except subprocess.CalledProcessError as e:
        error_subprocess_error(
            args,
            "Encountered an error while running command '{}'!".format(e.cmd),
            e.returncode)
예제 #11
0
def cmd_cmake_gui(args):
    if not os.path.isfile(args.project_file):
        error_project_not_found(args.project_file)

    project = cryproject.CryProject()
    try:
        project.load(args.project_file)
    except Exception:
        error_project_json_decode(args.project_file)

    # --- cpp
    cmakelists_dir = project.cmakelists_dir()
    if cmakelists_dir is not None:
        project_path = os.path.abspath(os.path.dirname(args.project_file))
        source_path = os.path.join(project_path, cmakelists_dir)
        solution_dir = get_project_solution_dir(project_path)
        if solution_dir is None:
            args.buildmachine = False
            cmd_projgen(args, True)
        elif 'win32' in solution_dir:
            error_platform_deprecated('win32')
        else:
            solution_path = os.path.join(project_path, solution_dir)
            open_cmake_gui(source_path, solution_path)
예제 #12
0
def run(project_file, backup_location, silent):
    """
    Entry point for setting up the process to create a backup of a project.
    """
    # Path to the project file as created by the launcher - engine and
    # project path are derivable from this.

    project = cryproject.CryProject()
    try:
        project.load(project_file)
    except Exception:
        print("Unable to read project file %s" % (project_file))
        raise

    # The path the folder that contains the .cryproject file.
    project_path = os.path.normpath(os.path.dirname(project_file))
    project_path_long = LONG_PATH_PREFIX + project_path

    project_file_name = os.path.basename(project_file)

    # Path to which the game is to be exported.
    head, tail = os.path.split(project_path)
    if backup_location and is_pathname_valid(backup_location):
        export_path = backup_location
    else:
        export_path = os.path.join(head, '{}_backup'.format(tail))

    while not silent:
        export_path = backup_project_gui.configure_backup(export_path)
        if not export_path:
            # If no valid path is selected it's most likely because
            # the user closed the window, so close this as well.
            return 1

        export_path = os.path.normpath(export_path)
        temp_project_file = os.path.join(export_path, project_file_name)
        if os.path.isfile(temp_project_file) and os.path.samefile(
                temp_project_file, project_file):
            message = "The backup directory cannot be the same as the " \
                "current project directory!"
            if HAS_WIN_MODULES:
                MESSAGEBOX(None, message, 'Invalid folder selected!',
                           win32con.MB_OK | win32con.MB_ICONWARNING)
            else:
                print(message)
            continue

        if HAS_WIN_MODULES and os.path.isdir(export_path) and os.listdir(
                export_path):
            message = ('The directory "{}" is not empty. '
                       'Continuing to write the backup to this location can '
                       'cause data loss!\nAre you sure you wish to continue?'
                       ).format(export_path)

            mb_kind = win32con.MB_OKCANCEL | win32con.MB_ICONWARNING
            if MESSAGEBOX(None, message, 'Overwrite existing folder',
                          mb_kind) == win32con.IDCANCEL:
                continue
        break

    export_path_long = LONG_PATH_PREFIX + export_path

    if not silent:
        print("Creating a backup of project {}".format(project.name()))
        print("Backup is saved to: {}".format(export_path))

    task_list = []

    task_list.append(("Copying code folder...", copy_code, project,
                      project_path_long, export_path_long, silent))
    task_list.append(("Copying project binaries...", copy_binaries, project,
                      project_path, export_path, silent))
    task_list.append(("Copying game assets...", copy_assets, project,
                      project_path_long, export_path_long, silent))
    task_list.append(("Copying shared libraries...", copy_libs, project,
                      project_path_long, export_path_long))
    task_list.append(("Copying config files...", copy_configs,
                      project_path_long, export_path_long, project_file_name))

    i = 0
    count = len(task_list)
    for task in task_list:
        description = task[0]
        if not silent:
            print(description)
            set_title("{}% {}".format(int(get_percentage(i, count)),
                                      description))
        task[1](*task[2:])
        i += 1

    if not silent:
        set_title("100% Backup created successfully")
        message = "Backup created successfully"
        if HAS_WIN_MODULES:
            MESSAGEBOX(None, message, 'Backup created',
                       win32con.MB_OK | win32con.MB_ICONINFORMATION)
        else:
            print(message)
            input("Press Enter to exit")
예제 #13
0
def run(project_file):
    """
    Entry point for setting up the process to release a packaged build.
    """
    # Path to the project file as created by the launcher
    # Engine and project path are derivable from this.
    project = cryproject.CryProject()
    try:
        project.load(project_file)
    except Exception:
        print("Unable to read project file %s" % (project_file))
        raise

    # The path the folder that contains the .cryproject file.
    project_path = os.path.normpath(os.path.dirname(project_file))
    project_path_long = LONG_PATH_PREFIX + project_path

    # The path to the engine that is being used by the project.
    engine_path = crypath.get_engine_path()
    engine_path_long = LONG_PATH_PREFIX + engine_path

    # Path to which the game is to be exported.
    export_path = os.path.join(
        project_path, '{}_package'.format(project.name()))

    configurations = get_available_configurations(engine_path)
    if not configurations:
        print("Unable to find a valid engine configuration. Make sure to "
              "build your engine to the following locations.")
        for key, value in DEFAULT_CONFIGURATIONS:
            print("Configuration: {} \n Location: {}".format(key, value))
        print("Press Enter to exit")
        input()
        return

    # configuration is returned as
    # (export_path, config_name, config_bin_folder, include_symbols)
    configuration = release_project_gui.configure_build(
        export_path, configurations)
    if not configuration:
        # No configuration selected. Most likely because the user closed
        # the window, so close this as well.
        return

    export_path = os.path.normpath(configuration[0])
    export_path_long = LONG_PATH_PREFIX + export_path
    config_type = configuration[1]
    bin_path = os.path.normpath(configuration[2])
    include_symbols = configuration[3]
    bit_type = CONFIGURATION_BUILD_TARGET_LOOKUP[config_type]

    print("Packaging project {}".format(project.name()))
    print("Configuration: {}".format(config_type))
    print("Debug symbols are {}".format(
        "included" if include_symbols else "excluded"))
    print("Building to: {}".format(export_path))

    task_list = []

    if os.path.exists(export_path_long):
        task_list.append(("Deleting previous build...",
                          delete_previous_build, export_path_long))

    task_list.append(("Packaging custom engine assets...",
                      package_engine_assets, engine_path, export_path))
    task_list.append(("Copying default engine assets...",
                      copy_engine_assets, engine_path_long, export_path_long))
    task_list.append(("Copying engine binaries...", copy_engine_binaries,
                      engine_path_long, export_path_long, bin_path,
                      include_symbols))

    if requires_mono(project, project_path_long):
        task_list.append((
            "Copying mono files...", copy_mono_files, engine_path_long,
            export_path_long))

    task_list.append((
        "Copying game binaries...", copy_project_plugins, project,
        project_path, export_path, bin_path, config_type, include_symbols))
    task_list.append((
        "Copying shared libraries...", copy_libs,
        project, project_path, export_path, bin_path, bit_type, include_symbols))
    task_list.append((
        "Copying existing game asset packages...",
        copy_assets, project, project_path_long, export_path_long))
    task_list.append((
        "Packaging game assets...", package_assets,
        project, engine_path, project_path, export_path))
    task_list.append((
        "Cleaning up temp folders...",
        delete_temp_folders, engine_path_long, project_path_long))
    task_list.append((
        "Creating config files...", create_config, project_file, export_path,
        bin_path, config_type))

    i = 0
    count = len(task_list)
    for task in task_list:
        description = task[0]
        print(description)
        set_title("{}% {}".format(int(get_percentage(i, count)), description))
        task[1](*task[2:])
        i += 1

    set_title("100% Build packaged successfully")
    print("Build packaged successfully")
    print("Press Enter to exit")
    input()