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)
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)
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)
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)
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')
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()
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
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()
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)
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)
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)
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")
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()