def on_compiled(mode): # build, play, play_viewport, publish log.clear() sdk_path = arm.utils.get_sdk_path() wrd = bpy.data.worlds['Arm'] # Launch project in new window if mode == 'play': if wrd.arm_play_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/html5' webbrowser.open(html5_app_path) elif wrd.arm_play_runtime == 'Krom': krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) args = [ krom_path, arm.utils.get_fp_build() + '/windowed/krom', arm.utils.get_fp_build() + '/windowed/krom-resources' ] # TODO: Krom sound freezes on MacOS if arm.utils.get_os() == 'mac': args.append('--nosound') if state.is_render: args.append('--nowindow') state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE) watch_play()
def play_project(in_viewport): global scripts_mtime wrd = bpy.data.worlds['Arm'] log.clear() # Store area if arm.utils.with_krom( ) and in_viewport and bpy.context.area != None and bpy.context.area.type == 'VIEW_3D': state.play_area = bpy.context.area state.target = runtime_to_target(in_viewport) # Build data build_project(is_play=True, in_viewport=in_viewport, target=state.target) state.in_viewport = in_viewport khajs_path = get_khajs_path(in_viewport, state.target) if not wrd.arm_cache_compiler or \ not os.path.isfile(khajs_path) or \ assets.khafile_defs_last != assets.khafile_defs or \ state.last_target != state.target or \ state.last_in_viewport != state.in_viewport or \ state.target == 'native': wrd.arm_recompile = True state.last_target = state.target state.last_in_viewport = state.in_viewport # Trait sources modified script_path = arm.utils.get_fp() + '/Sources/' + arm.utils.safestr( wrd.arm_project_package) if os.path.isdir(script_path): for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True): mtime = os.path.getmtime(fn) if scripts_mtime < mtime: scripts_mtime = mtime wrd.arm_recompile = True # New compile requred - traits changed if wrd.arm_recompile: # Unable to live-patch, stop player if state.krom_running: bpy.ops.arm.space_stop('EXEC_DEFAULT') return mode = 'play' if state.target == 'native': state.compileproc = compile_project(target_name='--run') elif state.target == 'krom': if in_viewport: mode = 'play_viewport' state.compileproc = compile_project(target_name='krom') else: # Browser state.compileproc = compile_project(target_name='html5') threading.Timer(0.1, watch_compile, [mode]).start() else: # kha.js up to date compile_project(target_name=state.target, patch=True)
def execute(self, context): area = bpy.context.area if area == None: area = state.play_area area.type = 'VIEW_3D' state.is_paused = False log.clear() return {'FINISHED'}
def on_compiled(mode): # build, play, play_viewport, publish log.clear() sdk_path = arm.utils.get_sdk_path() wrd = bpy.data.worlds['Arm'] # Print info if mode == 'publish': target_name = make_utils.get_kha_target(wrd.arm_project_target) print('Project published') files_path = arm.utils.get_fp() + '/build/' + target_name if target_name == 'html5': print('HTML5 files are located in ' + files_path) elif target_name == 'ios' or target_name == 'osx': # TODO: to macos print('XCode project files are located in ' + files_path + '-build') elif target_name == 'windows': print('VisualStudio 2015 project files are located in ' + files_path + '-build') elif target_name == 'android-native': print('Android Studio project files are located in ' + files_path + '-build/' + arm.utils.safefilename(wrd.arm_project_name)) else: print('Makefiles are located in ' + files_path + '-build') return # Launch project in new window elif mode =='play': if wrd.arm_play_runtime == 'Electron': electron_app_path = './build/electron.js' if arm.utils.get_os() == 'win': electron_path = sdk_path + 'win32/Kode Studio.exe' elif arm.utils.get_os() == 'mac': electron_path = sdk_path + 'Kode Studio.app/Contents/MacOS/Electron' else: electron_path = sdk_path + 'linux64/kodestudio' state.playproc = subprocess.Popen([electron_path, '--chromedebug', '--remote-debugging-port=9222', '--enable-logging', electron_app_path], stderr=subprocess.PIPE) watch_play() elif wrd.arm_play_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/build/html5' webbrowser.open(html5_app_path) elif wrd.arm_play_runtime == 'Krom': if arm.utils.get_os() == 'win': krom_location = sdk_path + '/win32/Krom/win32' krom_path = krom_location + '/Krom.exe' elif arm.utils.get_os() == 'mac': krom_location = sdk_path + '/Kode Studio.app/Contents/Krom/macos/Krom.app/Contents/MacOS' krom_path = krom_location + '/Krom' else: krom_location = sdk_path + '/linux64/Krom/linux' krom_path = krom_location + '/Krom' os.chdir(krom_location) state.playproc = subprocess.Popen([krom_path, arm.utils.get_fp() + '/build/window/krom', arm.utils.get_fp() + '/build/window/krom-resources', '--nosound'], stderr=subprocess.PIPE) watch_play()
def on_compiled(mode): # build, play, play_viewport, publish log.clear() sdk_path = arm.utils.get_sdk_path() wrd = bpy.data.worlds['Arm'] # Print info if mode == 'publish': target_name = make_utils.get_kha_target(wrd.arm_project_target) print('Project published') files_path = arm.utils.get_fp_build() + '/' + target_name if target_name == 'html5': print('HTML5 files are located in ' + files_path) elif target_name == 'ios' or target_name == 'osx': # TODO: to macos print('XCode project files are located in ' + files_path + '-build') elif target_name == 'windows': print('VisualStudio 2017 project files are located in ' + files_path + '-build') elif target_name == 'windowsapp': print('VisualStudio 2017 project files are located in ' + files_path + '-build') elif target_name == 'android-native': print('Android Studio project files are located in ' + files_path + '-build/' + arm.utils.safestr(wrd.arm_project_name)) else: print('Makefiles are located in ' + files_path + '-build') return # Launch project in new window elif mode == 'play': if wrd.arm_play_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/html5' webbrowser.open(html5_app_path) elif wrd.arm_play_runtime == 'Krom': krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) # os.chdir(arm.utils.get_fp_build()) args = [ krom_path, arm.utils.get_fp_build() + '/window/krom', arm.utils.get_fp_build() + '/window/krom-resources', '--nosound' ] if state.is_render: args.append('--nowindow') state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE) watch_play()
def watch_play(): if state.playproc == None: return line = b'' while state.playproc != None and state.playproc.poll() == None: char = state.playproc.stderr.read(1) # Read immediately one by one if char == b'\n': msg = str(line).split('"', 1) # Extract message if len(msg) > 1: trace = msg[1].rsplit('"', 1)[0] log.krom_trace(trace) line = b'' else: line += char state.playproc = None state.playproc_finished = True log.clear()
def play(is_viewport): global scripts_mtime global code_parsed wrd = bpy.data.worlds['Arm'] log.clear() build(target=runtime_to_target(is_viewport), is_play=True, is_viewport=is_viewport) khajs_path = get_khajs_path(is_viewport, state.target) if not wrd.arm_cache_compiler or \ not os.path.isfile(khajs_path) or \ assets.khafile_defs_last != assets.khafile_defs or \ state.last_target != state.target or \ state.last_is_viewport != state.is_viewport or \ state.target == 'native': wrd.arm_recompile = True state.last_target = state.target state.last_is_viewport = state.is_viewport # Trait sources modified state.mod_scripts = [] script_path = arm.utils.get_fp() + '/Sources/' + arm.utils.safestr( wrd.arm_project_package) if os.path.isdir(script_path): new_mtime = scripts_mtime for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True): mtime = os.path.getmtime(fn) if scripts_mtime < mtime: arm.utils.fetch_script_props(fn) # Trait props fn = fn.split('Sources/')[1] fn = fn[:-3] #.hx fn = fn.replace('/', '.') state.mod_scripts.append(fn) wrd.arm_recompile = True if new_mtime < mtime: new_mtime = mtime scripts_mtime = new_mtime if len(state.mod_scripts) > 0: # Trait props arm.utils.fetch_trait_props() compile(assets_only=(not wrd.arm_recompile))
def build_success(): log.clear() wrd = bpy.data.worlds['Arm'] if state.is_play: if wrd.arm_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run_tcp) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/debug/html5' webbrowser.open(html5_app_path) elif wrd.arm_runtime == 'Krom': if wrd.arm_live_patch: open(arm.utils.get_fp_build() + '/debug/krom/krom.patch', 'w').close() krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) cmd = [ krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources' ] if arm.utils.get_os() == 'win': cmd.append('--consolepid') cmd.append(str(os.getpid())) if wrd.arm_audio == 'Disabled': cmd.append('--nosound') if wrd.arm_verbose_output: print("Running: ", *cmd) state.proc_play = run_proc(cmd, play_done) elif state.is_publish: sdk_path = arm.utils.get_sdk_path() target_name = arm.utils.get_kha_target(state.target) files_path = os.path.join(arm.utils.get_fp_build(), target_name) if (target_name == 'html5' or target_name == 'krom') and wrd.arm_minify_js: # Minify JS minifier_path = sdk_path + '/lib/armory_tools/uglifyjs/bin/uglifyjs' if target_name == 'html5': jsfile = files_path + '/kha.js' else: jsfile = files_path + '/krom.js' args = [ arm.utils.get_node_path(), minifier_path, jsfile, '-o', jsfile ] proc = subprocess.Popen(args) proc.wait() if target_name == 'krom': # Copy Krom binaries if state.target == 'krom-windows': gapi = state.export_gapi ext = '' if gapi == 'direct3d11' else '_' + gapi krom_location = sdk_path + '/Krom/Krom' + ext + '.exe' shutil.copy(krom_location, files_path + '/Krom.exe') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.exe' os.rename(files_path + '/Krom.exe', files_path + '/' + krom_exe) elif state.target == 'krom-linux': krom_location = sdk_path + '/Krom/Krom' shutil.copy(krom_location, files_path) krom_exe = arm.utils.safestr(wrd.arm_project_name) os.rename(files_path + '/Krom', files_path + '/' + krom_exe) krom_exe = './' + krom_exe else: krom_location = sdk_path + '/Krom/Krom.app' shutil.copytree(krom_location, files_path + '/Krom.app') game_files = os.listdir(files_path) for f in game_files: f = files_path + '/' + f if os.path.isfile(f): shutil.move(f, files_path + '/Krom.app/Contents/MacOS') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.app' os.rename(files_path + '/Krom.app', files_path + '/' + krom_exe) # Rename ext = state.target.split('-')[-1] # krom-windows new_files_path = files_path + '-' + ext os.rename(files_path, new_files_path) files_path = new_files_path if target_name == 'html5': project_path = files_path print('Exported HTML5 package to ' + project_path) elif target_name.startswith('ios') or target_name.startswith( 'osx'): # TODO: to macos project_path = files_path + '-build' print('Exported XCode project to ' + project_path) elif target_name.startswith('windows'): project_path = files_path + '-build' vs_ver, vs_year, vs_name, vs_id = arm.utils.get_visual_studio_from_version( wrd.arm_project_win_list_vs) print('Exported ' + vs_name + ' project to ' + project_path) elif target_name.startswith('android'): project_name = arm.utils.safesrc(wrd.arm_project_name + '-' + wrd.arm_project_version) project_path = os.path.join(files_path + '-build', project_name) print('Exported Android Studio project to ' + project_path) elif target_name.startswith('krom'): project_path = files_path print('Exported Krom package to ' + project_path) else: project_path = files_path + '-build' print('Exported makefiles to ' + project_path) if arm.utils.get_arm_preferences().open_build_directory: arm.utils.open_folder(project_path) # Android build APK if target_name.startswith('android'): if (arm.utils.get_project_android_build_apk()) and (len( arm.utils.get_android_sdk_root_path()) > 0): print("\nBuilding APK") # Check settings path_sdk = arm.utils.get_android_sdk_root_path() if len(path_sdk) > 0: # Check Environment Variables - ANDROID_SDK_ROOT if os.getenv('ANDROID_SDK_ROOT') == None: # Set value from settings os.environ['ANDROID_SDK_ROOT'] = path_sdk else: project_path = '' # Build start if len(project_path) > 0: os.chdir(project_path) # set work folder if arm.utils.get_os_is_windows(): state.proc_publish_build = run_proc( os.path.join(project_path, "gradlew.bat assembleDebug"), done_gradlew_build) else: cmd = shlex.split( os.path.join(project_path, "gradlew assembleDebug")) state.proc_publish_build = run_proc( cmd, done_gradlew_build) else: print( '\nBuilding APK Warning: ANDROID_SDK_ROOT is not specified in environment variables and "Android SDK Path" setting is not specified in preferences: \n- If you specify an environment variable ANDROID_SDK_ROOT, then you need to restart Blender;\n- If you specify the setting "Android SDK Path" in the preferences, then repeat operation "Publish"' ) # HTML5 After Publish if target_name.startswith('html5'): if len(arm.utils.get_html5_copy_path()) > 0 and ( wrd.arm_project_html5_copy): project_name = arm.utils.safesrc(wrd.arm_project_name + '-' + wrd.arm_project_version) dst = os.path.join(arm.utils.get_html5_copy_path(), project_name) if os.path.exists(dst): shutil.rmtree(dst) try: shutil.copytree(project_path, dst) print("Copied files to " + dst) except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(project_path, dst) else: raise if len(arm.utils.get_link_web_server()) and ( wrd.arm_project_html5_start_browser): link_html5_app = arm.utils.get_link_web_server( ) + '/' + project_name print("Running a browser with a link " + link_html5_app) webbrowser.open(link_html5_app) # Windows After Publish if target_name.startswith('windows'): list_vs = [] err = '' # Print message project_name = arm.utils.safesrc(wrd.arm_project_name + '-' + wrd.arm_project_version) if int(wrd.arm_project_win_build) == 1: print('\nOpen in Visual Studio ' + os.path.join(project_path, project_name + '.sln"')) if int(wrd.arm_project_win_build) == 2: print('\nCompile project ' + os.path.join(project_path, project_name + '.vcxproj')) if int(wrd.arm_project_win_build) == 3: print('\nCompile and run project ' + os.path.join(project_path, project_name + '.vcxproj')) if int(wrd.arm_project_win_build) > 0: # Check Visual Studio list_vs, err = arm.utils.get_list_installed_vs( True, True, True) if len(err) > 0: print(err) return if len(list_vs) == 0: print('No Visual Studio found') return is_check = False for vs in list_vs: if vs[0] == wrd.arm_project_win_list_vs: is_check = True break if not is_check: vs_ver, vs_year, vs_name, vs_id = arm.utils.get_visual_studio_from_version( wrd.arm_project_win_list_vs) print(vs_name + ' not found.') print('The following are installed on the PC:') for vs in list_vs: print('- ' + vs[1] + ' (version ' + vs[3] + ')') return # Current VS vs_path = '' for vs in list_vs: if vs[0] == wrd.arm_project_win_list_vs: vs_path = vs[2] break # Open in Visual Studio if int(wrd.arm_project_win_build) == 1: cmd = os.path.join( 'start "' + vs_path, 'Common7', 'IDE', 'devenv.exe" "' + os.path.join(project_path, project_name + '.sln"')) subprocess.Popen(cmd, shell=True) # Compile if int(wrd.arm_project_win_build) > 1: bits = '64' if wrd.arm_project_win_build_arch == 'x64' else '32' # vcvars cmd = os.path.join(vs_path, 'VC', 'Auxiliary', 'Build', 'vcvars' + bits + '.bat') if not os.path.isfile(cmd): print('File "' + cmd + '" not found. Verify ' + vs_name + ' was installed correctly') log.error('Compile failed, check console') return state.proc_publish_build = run_proc(cmd, done_vs_vars)
def play_done(): state.proc_play = None state.redraw_ui = True log.clear()
def build(target, is_play=False, is_publish=False, is_export=False): global profile_time profile_time = time.time() state.target = target state.is_play = is_play state.is_publish = is_publish state.is_export = is_export # Save blend if arm.utils.get_save_on_build(): bpy.ops.wm.save_mainfile() log.clear(clear_warnings=True, clear_errors=True) # Set camera in active scene active_scene = arm.utils.get_active_scene() if active_scene.camera == None: for o in active_scene.objects: if o.type == 'CAMERA': active_scene.camera = o break # Get paths sdk_path = arm.utils.get_sdk_path() raw_shaders_path = sdk_path + '/armory/Shaders/' # Set dir fp = arm.utils.get_fp() os.chdir(fp) # Create directories wrd = bpy.data.worlds['Arm'] sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package) if not os.path.exists(sources_path): os.makedirs(sources_path) # Save external scripts edited inside Blender write_texts = False for text in bpy.data.texts: if text.filepath != '' and text.is_dirty: write_texts = True break if write_texts: area = bpy.context.area old_type = area.type area.type = 'TEXT_EDITOR' for text in bpy.data.texts: if text.filepath != '' and text.is_dirty and os.path.isfile( text.filepath): area.spaces[0].text = text bpy.ops.text.save() area.type = old_type # Save internal Haxe scripts for text in bpy.data.texts: if text.filepath == '' and text.name[-3:] == '.hx': with open( 'Sources/' + arm.utils.safestr(wrd.arm_project_package) + '/' + text.name, 'w') as f: f.write(text.as_string()) # Export data export_data(fp, sdk_path) if state.target == 'html5': w, h = arm.utils.get_render_resolution(arm.utils.get_active_scene()) write_data.write_indexhtml(w, h, is_publish) # Bundle files from include dir if os.path.isdir('include'): dest = '/html5/' if is_publish else '/debug/html5/' for fn in glob.iglob(os.path.join('include', '**'), recursive=False): shutil.copy( fn, arm.utils.build_dir() + dest + os.path.basename(fn))
def build_success(): log.clear() wrd = bpy.data.worlds['Arm'] if state.is_play and state.is_viewport: open(arm.utils.get_fp_build() + '/krom/krom.lock', 'w').close() elif state.is_play: if wrd.arm_play_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/debug/html5' webbrowser.open(html5_app_path) elif wrd.arm_play_runtime == 'Krom': bin_ext = '' if state.export_gapi == 'opengl' else '_' + state.export_gapi krom_location, krom_path = arm.utils.krom_paths(bin_ext=bin_ext) os.chdir(krom_location) cmd = [ krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources' ] if arm.utils.get_os() == 'win': cmd.append('--consolepid') cmd.append(str(os.getpid())) elif arm.utils.get_os( ) == 'mac': # TODO: Krom sound freezes on MacOS cmd.append('--nosound') # cmd.append('--stdout') # cmd.append(arm.utils.get_fp_build() + '/krom.txt') state.proc_play = run_proc(cmd, play_done) elif wrd.arm_play_runtime == 'Native': if arm.utils.get_os() == 'win': bin_location = arm.utils.get_fp_build() + '/windows' elif arm.utils.get_os() == 'linux': bin_location = arm.utils.get_fp_build() + '/linux' else: bin_location = arm.utils.get_fp_build() + '/osx' os.chdir(bin_location) if arm.utils.get_os() == 'win': p = bin_location + '/' + arm.utils.safestr( wrd.arm_project_name) + '.exe' elif arm.utils.get_os() == 'linux': p = bin_location + '/' + arm.utils.safestr( wrd.arm_project_name) else: p = bin_location + '/' + arm.utils.safestr( wrd.arm_project_name ) + '.app/Contents/MacOS/' + arm.utils.safestr( wrd.arm_project_name) state.proc_play = run_proc(p, play_done) elif state.is_publish: sdk_path = arm.utils.get_sdk_path() target_name = arm.utils.get_kha_target(state.target) files_path = arm.utils.get_fp_build() + '/' + target_name if (target_name == 'html5' or target_name == 'krom') and wrd.arm_minify_js: # Minify JS minifier_path = sdk_path + '/lib/armory_tools/uglifyjs/bin/uglifyjs' if target_name == 'html5': jsfile = files_path + '/kha.js' else: jsfile = files_path + '/krom.js' args = [ arm.utils.get_node_path(), minifier_path, jsfile, '-o', jsfile ] proc = subprocess.Popen(args) proc.wait() if target_name == 'krom': # Clean up mapfile = files_path + '/krom.js.temp.map' if os.path.exists(mapfile): os.remove(mapfile) # Copy Krom binaries if state.target == 'krom-windows': krom_location = sdk_path + '/Krom/win32/' elif state.target == 'krom-linux': krom_location = sdk_path + '/Krom/linux/' else: krom_location = sdk_path + '/Krom/macos/Krom.app' if state.target == 'krom-macos': shutil.copytree(krom_location, files_path + '/Krom.app') game_files = os.listdir(files_path) for f in game_files: f = files_path + '/' + f if os.path.isfile(f): shutil.move(f, files_path + '/Krom.app/Contents/MacOS') else: krom_files = os.listdir(krom_location) for f in krom_files: f = krom_location + '/' + f if os.path.isfile(f): shutil.copy(f, files_path) if state.target == 'krom-windows': gapi = state.export_gapi ext = '' if gapi == 'opengl' else '_' + gapi bin_path = files_path + '/Krom' + ext + '.exe' os.rename( bin_path, files_path + '/' + arm.utils.safestr(wrd.arm_project_name) + '.exe') if gapi != 'opengl' and os.path.exists(files_path + '/Krom.exe'): os.remove(files_path + '/Krom.exe') if gapi != 'direct3d11' and os.path.exists( files_path + '/Krom_direct3d11.exe'): os.remove(files_path + '/Krom_direct3d11.exe') elif state.target == 'krom-linux': os.rename( files_path + '/Krom', files_path + '/' + arm.utils.safestr(wrd.arm_project_name)) else: os.rename( files_path + '/Krom.app', files_path + '/' + arm.utils.safestr(wrd.arm_project_name) + '.app') # Rename ext = state.target.split('-')[-1] # krom-windows new_files_path = files_path + '-' + ext os.rename(files_path, new_files_path) files_path = new_files_path if target_name == 'html5': print('Exported HTML5 package to ' + files_path) elif target_name == 'ios' or target_name == 'osx': # TODO: to macos print('Exported XCode project to ' + files_path + '-build') elif target_name == 'windows' or target_name == 'windowsapp': print('Exported Visual Studio 2017 project to ' + files_path + '-build') elif target_name == 'android-native': print('Exported Android Studio project to ' + files_path + '-build/' + arm.utils.safestr(wrd.arm_project_name)) elif target_name == 'krom': print('Exported Krom package to ' + files_path) else: print('Exported makefiles to ' + files_path + '-build')
def build_success(): log.clear() wrd = bpy.data.worlds['Arm'] if state.is_play: if wrd.arm_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run_tcp) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/debug/html5' webbrowser.open(html5_app_path) elif wrd.arm_runtime == 'Krom': if wrd.arm_live_patch: open(arm.utils.get_fp_build() + '/debug/krom/krom.patch', 'w').close() krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) cmd = [ krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources' ] if arm.utils.get_os() == 'win': cmd.append('--consolepid') cmd.append(str(os.getpid())) if wrd.arm_audio == 'Enabled' and arm.utils.get_os() != 'mac': cmd.append('--sound') state.proc_play = run_proc(cmd, play_done) elif state.is_publish: sdk_path = arm.utils.get_sdk_path() target_name = arm.utils.get_kha_target(state.target) files_path = arm.utils.get_fp_build() + '/' + target_name if (target_name == 'html5' or target_name == 'krom') and wrd.arm_minify_js: # Minify JS minifier_path = sdk_path + '/lib/armory_tools/uglifyjs/bin/uglifyjs' if target_name == 'html5': jsfile = files_path + '/kha.js' else: jsfile = files_path + '/krom.js' args = [ arm.utils.get_node_path(), minifier_path, jsfile, '-o', jsfile ] proc = subprocess.Popen(args) proc.wait() if target_name == 'krom': # Copy Krom binaries if state.target == 'krom-windows': gapi = state.export_gapi ext = '' if gapi == 'direct3d11' else '_' + gapi krom_location = sdk_path + '/Krom/Krom' + ext + '.exe' shutil.copy(krom_location, files_path + '/Krom.exe') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.exe' os.rename(files_path + '/Krom.exe', files_path + '/' + krom_exe) elif state.target == 'krom-linux': krom_location = sdk_path + '/Krom/Krom' shutil.copy(krom_location, files_path) krom_exe = arm.utils.safestr(wrd.arm_project_name) os.rename(files_path + '/Krom', files_path + '/' + krom_exe) krom_exe = './' + krom_exe else: krom_location = sdk_path + '/Krom/Krom.app' shutil.copytree(krom_location, files_path + '/Krom.app') game_files = os.listdir(files_path) for f in game_files: f = files_path + '/' + f if os.path.isfile(f): shutil.move(f, files_path + '/Krom.app/Contents/MacOS') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.app' os.rename(files_path + '/Krom.app', files_path + '/' + krom_exe) # Serialize krom.js into krom.bin if wrd.arm_minify_js: cwd = os.getcwd() fp = files_path if state.target == 'krom-macos': fp += '/' + krom_exe + '/Contents/MacOS' krom_exe = './Krom' os.chdir(fp) args = [krom_exe, '.', '.', '--writebin'] proc = subprocess.Popen(args) proc.wait() os.chdir(cwd) os.remove(fp + '/krom.js') # Rename ext = state.target.split('-')[-1] # krom-windows new_files_path = files_path + '-' + ext os.rename(files_path, new_files_path) files_path = new_files_path if target_name == 'html5': print('Exported HTML5 package to ' + files_path) elif target_name.startswith('ios') or target_name.startswith( 'osx'): # TODO: to macos print('Exported XCode project to ' + files_path + '-build') elif target_name.startswith('windows'): print('Exported Visual Studio 2017 project to ' + files_path + '-build') elif target_name.startswith('android-native'): print('Exported Android Studio project to ' + files_path + '-build/' + arm.utils.safestr(wrd.arm_project_name)) elif target_name.startswith('krom'): print('Exported Krom package to ' + files_path) else: print('Exported makefiles to ' + files_path + '-build')
def build_project(is_play=False, is_publish=False, in_viewport=False, target=None): wrd = bpy.data.worlds['Arm'] # Set target if target == None: state.target = wrd.arm_project_target.lower() # Clear flag state.in_viewport = False # Save blend if arm.utils.get_save_on_build(): bpy.ops.wm.save_mainfile() log.clear() # Set camera in active scene active_scene = bpy.context.screen.scene if wrd.arm_play_active_scene else bpy.data.scenes[ wrd.arm_project_scene] if active_scene.camera == None: for o in active_scene.objects: if o.type == 'CAMERA': active_scene.camera = o break # Get paths sdk_path = arm.utils.get_sdk_path() raw_shaders_path = sdk_path + '/armory/Shaders/' # Set dir fp = arm.utils.get_fp() os.chdir(fp) # Create directories sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package) if not os.path.exists(sources_path): os.makedirs(sources_path) # Compile path tracer shaders # if len(bpy.data.cameras) > 0 and bpy.data.cameras[0].renderpath_path == 'pathtrace_path': # path_tracer.compile(raw_shaders_path + 'pt_trace_pass/pt_trace_pass.frag.glsl') # Save external scripts edited inside Blender write_texts = False for text in bpy.data.texts: if text.filepath != '' and text.is_dirty: write_texts = True break if write_texts: area = bpy.context.area old_type = area.type area.type = 'TEXT_EDITOR' for text in bpy.data.texts: if text.filepath != '' and text.is_dirty and os.path.isfile( text.filepath): area.spaces[0].text = text bpy.ops.text.save() area.type = old_type # Save internal Haxe scripts for text in bpy.data.texts: if text.filepath == '' and text.name[-3:] == '.hx': with open( 'Sources/' + arm.utils.safestr(wrd.arm_project_package) + '/' + text.name, 'w') as f: f.write(text.as_string()) # Export data export_data(fp, sdk_path, is_play=is_play, is_publish=is_publish, in_viewport=in_viewport) if state.target == 'html5': w, h = arm.utils.get_render_resolution(arm.utils.get_active_scene()) write_data.write_indexhtml(w, h) # Bundle files from include dir if os.path.isdir('include'): for fn in glob.iglob(os.path.join('include', '**'), recursive=False): shutil.copy( fn, arm.utils.build_dir() + '/html5/' + os.path.basename(fn)) if state.playproc == None: log.print_progress(50)
def play_project(in_viewport, is_render=False, is_render_anim=False): global scripts_mtime global code_parsed wrd = bpy.data.worlds['Arm'] log.clear() # Store area if arm.utils.with_krom( ) and in_viewport and bpy.context.area != None and bpy.context.area.type == 'VIEW_3D': state.play_area = bpy.context.area state.target = runtime_to_target(in_viewport) # Build data build_project(is_play=True, is_render=is_render, is_render_anim=is_render_anim, in_viewport=in_viewport) state.in_viewport = in_viewport khajs_path = get_khajs_path(in_viewport, state.target) if not wrd.arm_cache_compiler or \ not os.path.isfile(khajs_path) or \ assets.khafile_defs_last != assets.khafile_defs or \ state.last_target != state.target or \ state.last_in_viewport != state.in_viewport or \ state.target == 'native': wrd.arm_recompile = True state.last_target = state.target state.last_in_viewport = state.in_viewport # Trait sources modified state.mod_scripts = [] script_path = arm.utils.get_fp() + '/Sources/' + arm.utils.safestr( wrd.arm_project_package) if os.path.isdir(script_path): new_mtime = scripts_mtime for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True): mtime = os.path.getmtime(fn) if scripts_mtime < mtime: arm.utils.fetch_script_props(fn) # Trait props fn = fn.split('Sources/')[1] fn = fn[:-3] #.hx fn = fn.replace('/', '.') state.mod_scripts.append(fn) wrd.arm_recompile = True if new_mtime < mtime: new_mtime = mtime scripts_mtime = new_mtime if len(state.mod_scripts) > 0: # Trait props arm.utils.fetch_trait_props() # New compile requred - traits changed if wrd.arm_recompile: state.recompiled = True if state.krom_running: # TODO: Unable to live-patch, stop player bpy.ops.arm.space_stop('EXEC_DEFAULT') return if not code_parsed: code_parsed = True barmory.parse_code() else: code_parsed = False mode = 'play' if state.target == 'native': state.compileproc = compile_project(target_name='--run') elif state.target == 'krom': if in_viewport: mode = 'play_viewport' state.compileproc = compile_project(target_name='krom') else: # Browser state.compileproc = compile_project(target_name='html5') threading.Timer(0.1, watch_compile, [mode]).start() else: # kha.js up to date state.recompiled = False compile_project(patch=True)
def on_compiled(mode): # build, play, play_viewport, publish log.clear() wrd = bpy.data.worlds['Arm'] # Launch project in new window if mode == 'play': if wrd.arm_play_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir( ) + '/debug/html5' webbrowser.open(html5_app_path) elif wrd.arm_play_runtime == 'Krom': krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) args = [ krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources' ] # TODO: Krom sound freezes on MacOS if arm.utils.get_os() == 'mac': args.append('--nosound') if state.is_render: args.append('--nowindow') state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE) watch_play() elif mode == 'publish': sdk_path = arm.utils.get_sdk_path() target_name = arm.utils.get_kha_target(state.target) files_path = arm.utils.get_fp_build() + '/' + target_name if (target_name == 'html5' or target_name == 'krom') and wrd.arm_minify_js: # Minify JS minifier_path = sdk_path + '/lib/armory_tools/uglifyjs/bin/uglifyjs' if target_name == 'html5': jsfile = files_path + '/kha.js' else: jsfile = files_path + '/krom.js' args = [ arm.utils.get_node_path(), minifier_path, jsfile, '-o', jsfile ] proc = subprocess.Popen(args) proc.wait() if target_name == 'krom': # Clean up mapfile = files_path + '/krom.js.temp.map' if os.path.exists(mapfile): os.remove(mapfile) # Copy Krom binaries if state.target == 'krom-windows': krom_location = sdk_path + '/Krom/win32/' elif state.target == 'krom-linux': krom_location = sdk_path + '/Krom/linux/' else: krom_location = sdk_path + '/Krom/macos/Krom.app' if state.target == 'krom-macos': shutil.copytree(krom_location, files_path + '/Krom.app') game_files = os.listdir(files_path) for f in game_files: f = files_path + '/' + f if os.path.isfile(f): shutil.move(f, files_path + '/Krom.app/Contents/MacOS') else: krom_files = os.listdir(krom_location) for f in krom_files: f = krom_location + '/' + f if os.path.isfile(f): shutil.copy(f, files_path) if state.target == 'krom-windows': os.rename( files_path + '/Krom.exe', files_path + '/' + arm.utils.safestr(wrd.arm_project_name) + '.exe') elif state.target == 'krom-linux': os.rename( files_path + '/Krom', files_path + '/' + arm.utils.safestr(wrd.arm_project_name)) else: os.rename( files_path + '/Krom.app', files_path + '/' + arm.utils.safestr(wrd.arm_project_name) + '.app') # Rename ext = state.target.split('-')[-1] # krom-windows new_files_path = files_path + '-' + ext os.rename(files_path, new_files_path) files_path = new_files_path if target_name == 'html5': print('Exported HTML5 package to ' + files_path) elif target_name == 'ios' or target_name == 'osx': # TODO: to macos print('Exported XCode project to ' + files_path + '-build') elif target_name == 'windows' or target_name == 'windowsapp': print('Exported Visual Studio 2017 project to ' + files_path + '-build') elif target_name == 'android-native': print('Exported Android Studio project to ' + files_path + '-build/' + arm.utils.safestr(wrd.arm_project_name)) elif target_name == 'krom': print('Exported Krom package to ' + files_path) else: print('Exported makefiles to ' + files_path + '-build')
def play_done(): """Called if the player was stopped/terminated.""" state.proc_play = None state.redraw_ui = True log.clear() live_patch.stop()
def build_success(): log.clear() wrd = bpy.data.worlds['Arm'] if state.is_play: if wrd.arm_runtime == 'Browser': # Start server os.chdir(arm.utils.get_fp()) t = threading.Thread(name='localserver', target=arm.lib.server.run_tcp) t.daemon = True t.start() html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir() + '/debug/html5' webbrowser.open(html5_app_path) elif wrd.arm_runtime == 'Krom': if wrd.arm_live_patch: open(arm.utils.get_fp_build() + '/debug/krom/krom.patch', 'w').close() krom_location, krom_path = arm.utils.krom_paths() os.chdir(krom_location) cmd = [krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources'] if arm.utils.get_os() == 'win': cmd.append('--consolepid') cmd.append(str(os.getpid())) if wrd.arm_audio == 'Disabled': cmd.append('--nosound') state.proc_play = run_proc(cmd, play_done) elif state.is_publish: sdk_path = arm.utils.get_sdk_path() target_name = arm.utils.get_kha_target(state.target) files_path = os.path.join(arm.utils.get_fp_build(), target_name) if (target_name == 'html5' or target_name == 'krom') and wrd.arm_minify_js: # Minify JS minifier_path = sdk_path + '/lib/armory_tools/uglifyjs/bin/uglifyjs' if target_name == 'html5': jsfile = files_path + '/kha.js' else: jsfile = files_path + '/krom.js' args = [arm.utils.get_node_path(), minifier_path, jsfile, '-o', jsfile] proc = subprocess.Popen(args) proc.wait() if target_name == 'krom': # Copy Krom binaries if state.target == 'krom-windows': gapi = state.export_gapi ext = '' if gapi == 'direct3d11' else '_' + gapi krom_location = sdk_path + '/Krom/Krom' + ext + '.exe' shutil.copy(krom_location, files_path + '/Krom.exe') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.exe' os.rename(files_path + '/Krom.exe', files_path + '/' + krom_exe) elif state.target == 'krom-linux': krom_location = sdk_path + '/Krom/Krom' shutil.copy(krom_location, files_path) krom_exe = arm.utils.safestr(wrd.arm_project_name) os.rename(files_path + '/Krom', files_path + '/' + krom_exe) krom_exe = './' + krom_exe else: krom_location = sdk_path + '/Krom/Krom.app' shutil.copytree(krom_location, files_path + '/Krom.app') game_files = os.listdir(files_path) for f in game_files: f = files_path + '/' + f if os.path.isfile(f): shutil.move(f, files_path + '/Krom.app/Contents/MacOS') krom_exe = arm.utils.safestr(wrd.arm_project_name) + '.app' os.rename(files_path + '/Krom.app', files_path + '/' + krom_exe) # Rename ext = state.target.split('-')[-1] # krom-windows new_files_path = files_path + '-' + ext os.rename(files_path, new_files_path) files_path = new_files_path if target_name == 'html5': project_path = files_path print('Exported HTML5 package to ' + project_path) elif target_name.startswith('ios') or target_name.startswith('osx'): # TODO: to macos project_path = files_path + '-build' print('Exported XCode project to ' + project_path) elif target_name.startswith('windows'): project_path = files_path + '-build' print('Exported Visual Studio 2017 project to ' + project_path) elif target_name.startswith('android'): project_path = os.path.join(files_path + '-build', arm.utils.safestr(wrd.arm_project_name)) print('Exported Android Studio project to ' + project_path) elif target_name.startswith('krom'): project_path = files_path print('Exported Krom package to ' + project_path) else: project_path = files_path + '-build' print('Exported makefiles to ' + project_path) if arm.utils.get_arm_preferences().open_build_directory: arm.utils.open_folder(project_path) # Android build APK if (arm.utils.get_project_android_build_apk()) and (len(arm.utils.get_android_sdk_root_path()) > 0): print("\nBuilding APK") # Check settings path_sdk = arm.utils.get_android_sdk_root_path() if len(path_sdk) > 0: # Check Environment Variables - ANDROID_SDK_ROOT if os.getenv('ANDROID_SDK_ROOT') == None: # Set value from settings os.environ['ANDROID_SDK_ROOT'] = path_sdk else: project_path = '' # Build start if len(project_path) > 0: os.chdir(project_path) # set work folder if arm.utils.get_os_is_windows(): state.proc_publish_build = run_proc(os.path.join(project_path, "gradlew.bat assembleDebug"), done_gradlew_build) else: cmd = shlex.split(os.path.join(project_path, "gradlew assembleDebug")) state.proc_publish_build = run_proc(cmd, done_gradlew_build) else: print('\nBuilding APK Warning: ANDROID_SDK_ROOT is not specified in environment variables and "Android SDK Path" setting is not specified in preferences: \n- If you specify an environment variable ANDROID_SDK_ROOT, then you need to restart Blender;\n- If you specify the setting "Android SDK Path" in the preferences, then repeat operation "Publish"')