armory/blender/arm/make.py

561 lines
20 KiB
Python
Raw Normal View History

import os
2017-01-18 14:52:51 +01:00
import glob
import time
import shutil
import bpy
import json
2017-10-21 16:09:06 +02:00
import stat
from bpy.props import *
import subprocess
import threading
import webbrowser
2017-03-15 12:30:14 +01:00
import arm.utils
import arm.write_data as write_data
import arm.make_logic as make_logic
import arm.make_renderpath as make_renderpath
import arm.make_world as make_world
import arm.make_state as state
import arm.assets as assets
import arm.log as log
import arm.lib.make_datas
import arm.lib.make_variants
import arm.lib.server
from arm.exporter import ArmoryExporter
2017-12-19 11:02:55 +01:00
import time
2017-07-02 20:48:19 +02:00
try:
import barmory
except ImportError:
pass
2016-10-19 13:28:06 +02:00
exporter = ArmoryExporter()
2017-01-18 14:52:51 +01:00
scripts_mtime = 0 # Monitor source changes
2017-07-02 20:48:19 +02:00
code_parsed = False
2017-12-19 11:02:55 +01:00
profile_time = 0
2017-12-13 14:21:42 +01:00
def compile_shader_pass(res, raw_shaders_path, shader_name, defs):
2017-11-08 16:49:13 +01:00
os.chdir(raw_shaders_path + '/' + shader_name)
2016-10-17 00:02:51 +02:00
# Open json file
2016-12-13 01:09:17 +01:00
json_name = shader_name + '.json'
2016-10-25 16:15:07 +02:00
with open(json_name) as f:
json_file = f.read()
2016-10-17 00:02:51 +02:00
json_data = json.loads(json_file)
2017-05-23 01:03:44 +02:00
fp = arm.utils.get_fp_build()
2017-12-20 15:37:58 +01:00
arm.lib.make_datas.make(res, shader_name, json_data, fp, defs)
arm.lib.make_variants.make(shader_name, json_data, fp, defs)
2017-10-21 16:07:08 +02:00
def remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
2016-10-12 17:52:27 +02:00
def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False):
2016-10-19 13:28:06 +02:00
global exporter
2016-12-10 14:26:02 +01:00
wrd = bpy.data.worlds['Arm']
2017-11-29 00:58:11 +01:00
print('\nArmory v{0} ({1})'.format(wrd.arm_version, wrd.arm_commit))
2017-05-13 10:44:17 +02:00
print('OS: ' + arm.utils.get_os() + ', Target: ' + state.target + ', GAPI: ' + arm.utils.get_gapi())
2016-10-19 13:28:06 +02:00
2016-12-13 01:09:17 +01:00
# Clean compiled variants if cache is disabled
2017-12-13 14:21:42 +01:00
build_dir = arm.utils.get_fp_build()
2016-12-13 01:09:17 +01:00
if wrd.arm_cache_shaders == False:
if os.path.isdir(build_dir + '/debug/html5-resources'):
shutil.rmtree(build_dir + '/debug/html5-resources', onerror=remove_readonly)
2017-11-13 16:36:58 +01:00
if os.path.isdir(build_dir + '/krom-resources'):
shutil.rmtree(build_dir + '/krom-resources', onerror=remove_readonly)
if os.path.isdir(build_dir + '/debug/krom-resources'):
shutil.rmtree(build_dir + '/debug/krom-resources', onerror=remove_readonly)
2017-11-13 16:36:58 +01:00
if os.path.isdir(build_dir + '/windows-resources'):
shutil.rmtree(build_dir + '/windows-resources', onerror=remove_readonly)
if os.path.isdir(build_dir + '/linux-resources'):
shutil.rmtree(build_dir + '/linux-resources', onerror=remove_readonly)
if os.path.isdir(build_dir + '/osx-resources'):
shutil.rmtree(build_dir + '/osx-resources', onerror=remove_readonly)
2017-05-23 01:03:44 +02:00
if os.path.isdir(build_dir + '/compiled/Shaders'):
2017-10-21 16:07:08 +02:00
shutil.rmtree(build_dir + '/compiled/Shaders', onerror=remove_readonly)
2016-12-13 01:09:17 +01:00
2017-10-14 23:24:04 +02:00
# Detect camera plane changes
if len(bpy.data.cameras) > 0:
cam = bpy.data.cameras[0]
if state.last_clip_start == 0:
state.last_clip_start = cam.clip_start
state.last_clip_end = cam.clip_end
elif cam.clip_start != state.last_clip_start or cam.clip_end != state.last_clip_end:
if os.path.isdir(build_dir + '/compiled/Shaders'):
2017-10-21 16:07:08 +02:00
shutil.rmtree(build_dir + '/compiled/Shaders', onerror=remove_readonly)
2017-10-14 23:24:04 +02:00
state.last_clip_start = cam.clip_start
state.last_clip_end = cam.clip_end
2016-10-17 00:02:51 +02:00
raw_shaders_path = sdk_path + 'armory/Shaders/'
assets_path = sdk_path + 'armory/Assets/'
2016-10-17 00:02:51 +02:00
export_physics = bpy.data.worlds['Arm'].arm_physics != 'Disabled'
2016-12-07 10:37:08 +01:00
export_navigation = bpy.data.worlds['Arm'].arm_navigation != 'Disabled'
2017-06-20 11:35:24 +02:00
export_ui = bpy.data.worlds['Arm'].arm_ui != 'Disabled'
assets.reset()
# Build node trees
2017-11-09 19:47:10 +01:00
ArmoryExporter.import_traits = []
2017-11-22 21:17:36 +01:00
make_logic.build()
2017-12-13 00:10:30 +01:00
make_world.build()
2017-11-22 21:17:36 +01:00
make_renderpath.build()
# Export scene data
2016-09-14 11:49:32 +02:00
assets.embedded_data = sorted(list(set(assets.embedded_data)))
2016-09-12 02:24:20 +02:00
physics_found = False
2016-12-07 10:37:08 +01:00
navigation_found = False
2017-06-20 11:35:24 +02:00
ui_found = False
2017-08-10 14:10:37 +02:00
ArmoryExporter.compress_enabled = is_publish and wrd.arm_asset_compression
2016-11-05 14:12:36 +01:00
ArmoryExporter.in_viewport = in_viewport
for scene in bpy.data.scenes:
2017-08-21 12:17:55 +02:00
if scene.arm_export:
ext = '.zip' if (scene.arm_compress and is_publish) else '.arm'
2017-11-13 16:36:58 +01:00
asset_path = build_dir + '/compiled/Assets/' + arm.utils.safestr(scene.name) + ext
2017-10-04 11:31:24 +02:00
exporter.execute(bpy.context, asset_path, scene=scene, write_capture_info=state.is_render_anim, play_area=state.play_area)
2017-06-20 11:35:24 +02:00
if ArmoryExporter.export_physics:
2016-09-12 02:24:20 +02:00
physics_found = True
2017-06-20 11:35:24 +02:00
if ArmoryExporter.export_navigation:
2016-12-07 10:37:08 +01:00
navigation_found = True
2017-06-20 11:35:24 +02:00
if ArmoryExporter.export_ui:
ui_found = True
assets.add(asset_path)
2017-06-20 11:35:24 +02:00
if physics_found == False: # Disable physics if no rigid body is exported
2016-09-12 02:24:20 +02:00
export_physics = False
2016-12-07 10:37:08 +01:00
if navigation_found == False:
export_navigation = False
2016-10-17 02:29:37 +02:00
2017-06-20 11:35:24 +02:00
if ui_found == False:
export_ui = False
if wrd.arm_ui == 'Enabled':
export_ui = True
2017-08-19 03:08:42 +02:00
modules = []
if export_physics:
modules.append('physics')
if export_navigation:
modules.append('navigation')
if export_ui:
modules.append('ui')
print('Exported modules: ' + str(modules))
2017-11-20 14:32:36 +01:00
defs = arm.utils.def_strings_to_array(wrd.world_defs)
2017-11-04 19:34:09 +01:00
print('Shader flags: ' + str(defs))
2017-11-08 16:49:13 +01:00
# Write referenced shader passes
2017-12-20 15:37:58 +01:00
path = build_dir + '/compiled/Shaders'
2017-12-13 14:21:42 +01:00
if not os.path.isfile(build_dir + '/compiled/Shaders/shader_datas.arm') or state.last_world_defs != wrd.world_defs:
path = build_dir + '/compiled/Shaders'
if not os.path.exists(path):
os.makedirs(path)
res = {}
res['shader_datas'] = []
for ref in assets.shader_passes:
# Ensure shader pass source exists
if not os.path.exists(raw_shaders_path + '/' + ref):
2017-11-08 16:49:13 +01:00
continue
2017-12-20 15:37:58 +01:00
assets.shader_passes_assets[ref] = []
2017-12-13 14:21:42 +01:00
if ref.startswith('compositor_pass'):
2017-11-20 14:32:36 +01:00
cdefs = arm.utils.def_strings_to_array(wrd.compo_defs)
2017-12-13 14:21:42 +01:00
compile_shader_pass(res, raw_shaders_path, ref, defs + cdefs)
# elif ref.startswith('grease_pencil'):
# compile_shader_pass(res, raw_shaders_path, ref, [])
2017-11-04 19:34:09 +01:00
else:
2017-12-13 14:21:42 +01:00
compile_shader_pass(res, raw_shaders_path, ref, defs)
arm.utils.write_arm(path + '/shader_datas.arm', res)
2017-12-20 15:37:58 +01:00
for ref in assets.shader_passes:
for s in assets.shader_passes_assets[ref]:
assets.add_shader(path + '/' + s + '.glsl')
2017-11-08 16:49:13 +01:00
state.last_world_defs = wrd.world_defs
2016-10-17 02:29:37 +02:00
# Reset path
os.chdir(fp)
2016-10-17 02:29:37 +02:00
# Copy std shaders
2017-12-13 14:21:42 +01:00
if not os.path.isdir(build_dir + '/compiled/Shaders/std'):
shutil.copytree(raw_shaders_path + 'std', build_dir + '/compiled/Shaders/std')
2016-10-17 02:29:37 +02:00
# Write compiled.glsl
write_data.write_compiledglsl()
# Write khafile.js
2017-06-20 15:50:06 +02:00
enable_dce = is_publish and wrd.arm_dce
2017-08-10 14:10:37 +02:00
import_logic = not is_publish and arm.utils.logic_editor_space() != None
write_data.write_khafilejs(is_play, export_physics, export_navigation, export_ui, is_publish, enable_dce, in_viewport, ArmoryExporter.import_traits, import_logic)
2016-11-07 23:06:08 +01:00
# Write Main.hx - depends on write_khafilejs for writing number of assets
2017-11-08 10:34:27 +01:00
scene_name = arm.utils.get_project_scene_name()
2017-05-28 20:22:07 +02:00
resx, resy = arm.utils.get_render_resolution(arm.utils.get_active_scene())
2017-07-03 15:16:15 +02:00
# Import all logic nodes for patching if logic is being edited
2017-11-08 10:34:27 +01:00
write_data.write_main(scene_name, resx, resy, is_play, in_viewport, is_publish)
if scene_name != state.last_scene or resx != state.last_resx or resy != state.last_resy:
2017-05-28 20:22:07 +02:00
wrd.arm_recompile = True
2017-10-14 23:24:04 +02:00
state.last_resx = resx
state.last_resy = resy
2017-11-08 10:34:27 +01:00
state.last_scene = scene_name
def compile_project(target_name=None, watch=False, patch=False, no_project_file=False):
"""
:param no_project_file: Pass '--noproject' to kha make. In the future assets will be copied.
"""
2016-10-12 17:52:27 +02:00
wrd = bpy.data.worlds['Arm']
fp = arm.utils.get_fp()
os.chdir(fp)
# Set build command
if target_name == None:
2017-08-21 15:36:21 +02:00
target_name = state.target
2017-09-05 16:18:19 +02:00
if target_name == 'native':
2017-01-17 18:13:54 +01:00
target_name = ''
2017-03-15 12:30:14 +01:00
node_path = arm.utils.get_node_path()
khamake_path = arm.utils.get_khamake_path()
2017-11-20 14:32:36 +01:00
kha_target_name = arm.utils.get_kha_target(target_name)
cmd = [node_path, khamake_path, kha_target_name]
2016-09-03 13:30:52 +02:00
2017-03-15 12:30:14 +01:00
ffmpeg_path = arm.utils.get_ffmpeg_path() # Path to binary
2016-09-23 00:34:42 +02:00
if ffmpeg_path != '':
cmd.append('--ffmpeg')
2017-02-15 16:55:46 +01:00
cmd.append(ffmpeg_path) # '"' + ffmpeg_path + '"'
2016-09-23 00:34:42 +02:00
2016-11-24 17:35:12 +01:00
if kha_target_name == 'krom':
2017-05-13 10:44:17 +02:00
cmd.append('-g')
cmd.append('opengl')
2017-01-18 14:52:51 +01:00
if state.in_viewport:
2017-03-15 12:30:14 +01:00
if arm.utils.glsl_version() >= 330:
2016-11-24 17:35:12 +01:00
cmd.append('--shaderversion')
cmd.append('330')
else:
cmd.append('--shaderversion')
cmd.append('110')
2017-07-27 13:52:41 +02:00
else:
cmd.append('-g')
cmd.append(arm.utils.get_gapi())
2017-11-29 01:24:30 +01:00
# Kha defaults to 110
if arm.utils.get_os() == 'linux' and (kha_target_name == 'krom' or kha_target_name == '') and state.in_viewport == False:
cmd.append('--shaderversion')
cmd.append('330')
2017-05-23 01:03:44 +02:00
cmd.append('--to')
if (kha_target_name == 'krom' and not state.in_viewport) or (kha_target_name == 'html5' and not state.is_publish):
cmd.append(arm.utils.build_dir() + '/debug')
2017-05-23 01:03:44 +02:00
else:
cmd.append(arm.utils.build_dir())
2016-11-24 17:35:12 +01:00
2016-10-12 17:52:27 +02:00
# User defined commands
2017-04-19 11:48:30 +02:00
if wrd.arm_khamake != '':
for s in bpy.data.texts[wrd.arm_khamake].as_string().split(' '):
2016-10-12 17:52:27 +02:00
cmd.append(s)
2017-01-18 14:52:51 +01:00
if patch:
2017-01-23 20:41:45 +01:00
if state.compileproc == None:
cmd.append('--nohaxe')
2017-01-23 00:48:59 +01:00
cmd.append('--noproject')
2017-05-24 23:04:24 +02:00
# cmd.append('--noshaders')
2017-01-23 20:41:45 +01:00
state.compileproc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
2017-01-18 14:52:51 +01:00
if state.playproc == None:
if state.in_viewport:
mode = 'play_viewport'
else:
mode = 'play'
else:
mode = 'build'
threading.Timer(0.1, watch_patch, [mode]).start()
2016-10-19 13:28:06 +02:00
return state.compileproc
2017-01-18 14:52:51 +01:00
elif watch:
2016-10-19 13:28:06 +02:00
state.compileproc = subprocess.Popen(cmd)
2016-09-23 00:34:42 +02:00
threading.Timer(0.1, watch_compile, ['build']).start()
2016-10-19 13:28:06 +02:00
return state.compileproc
2016-09-12 20:12:13 +02:00
else:
if no_project_file:
cmd.append('--noproject')
2017-10-18 09:51:35 +02:00
print("Running: ", cmd)
2016-09-12 20:12:13 +02:00
return subprocess.Popen(cmd)
2017-10-03 20:27:21 +02:00
def build_project(is_play=False, is_publish=False, is_render=False, is_render_anim=False, in_viewport=False):
2017-12-19 11:02:55 +01:00
global profile_time
profile_time = time.time()
2016-11-30 11:40:28 +01:00
wrd = bpy.data.worlds['Arm']
2017-06-26 15:37:10 +02:00
state.is_render = is_render
2017-10-03 20:27:21 +02:00
state.is_render_anim = is_render_anim
state.is_publish = is_publish
2017-12-05 23:06:24 +01:00
state.in_viewport = in_viewport
# Save blend
2017-07-03 12:30:08 +02:00
if arm.utils.get_save_on_build() and not state.krom_running:
2017-02-22 16:14:55 +01:00
bpy.ops.wm.save_mainfile()
2016-10-19 13:28:06 +02:00
log.clear()
2016-09-23 00:34:42 +02:00
2016-09-08 14:08:31 +02:00
# Set camera in active scene
2017-09-09 20:53:46 +02:00
active_scene = arm.utils.get_active_scene()
2016-09-08 14:08:31 +02:00
if active_scene.camera == None:
for o in active_scene.objects:
if o.type == 'CAMERA':
active_scene.camera = o
break
# Get paths
2017-03-15 12:30:14 +01:00
sdk_path = arm.utils.get_sdk_path()
2016-10-17 00:02:51 +02:00
raw_shaders_path = sdk_path + '/armory/Shaders/'
# Set dir
2017-03-15 12:30:14 +01:00
fp = arm.utils.get_fp()
os.chdir(fp)
# Create directories
2017-05-13 17:17:43 +02:00
sources_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package)
2017-02-09 23:33:54 +01:00
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:
2017-01-10 22:57:22 +01:00
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':
2017-05-13 17:17:43 +02:00
with open('Sources/' + arm.utils.safestr(wrd.arm_project_package) + '/' + text.name, 'w') as f:
f.write(text.as_string())
# Export data
2016-10-12 17:52:27 +02:00
export_data(fp, sdk_path, is_play=is_play, is_publish=is_publish, in_viewport=in_viewport)
2017-05-24 13:06:48 +02:00
if state.target == 'html5':
w, h = arm.utils.get_render_resolution(arm.utils.get_active_scene())
write_data.write_indexhtml(w, h, is_publish)
2017-05-24 13:06:48 +02:00
# Bundle files from include dir
if os.path.isdir('include'):
dest = '/html5/' if is_publish else '/debug/html5/'
2017-05-24 13:06:48 +02:00
for fn in glob.iglob(os.path.join('include', '**'), recursive=False):
shutil.copy(fn, arm.utils.build_dir() + dest + os.path.basename(fn))
2017-05-24 13:06:48 +02:00
2016-10-19 13:28:06 +02:00
if state.playproc == None:
log.print_progress(50)
2016-09-23 00:34:42 +02:00
def stop_project():
2016-10-19 13:28:06 +02:00
if state.playproc != None:
state.playproc.terminate()
state.playproc = None
def watch_play():
2016-10-19 13:28:06 +02:00
if state.playproc == None:
return
line = b''
2016-10-19 13:28:06 +02:00
while state.playproc != None and state.playproc.poll() == None:
char = state.playproc.stderr.read(1) # Read immediately one by one
if char == b'\n':
2016-09-08 14:08:31 +02:00
msg = str(line).split('"', 1) # Extract message
if len(msg) > 1:
trace = msg[1].rsplit('"', 1)[0]
2017-10-18 09:51:35 +02:00
log.krom_trace(trace)
line = b''
else:
line += char
2016-10-19 13:28:06 +02:00
state.playproc = None
state.playproc_finished = True
log.clear()
2016-09-23 00:34:42 +02:00
def watch_compile(mode):
2016-10-19 13:28:06 +02:00
state.compileproc.wait()
log.print_progress(100)
2017-12-20 10:19:44 +01:00
print('Finished in ' + str(time.time() - profile_time))
2016-10-19 13:28:06 +02:00
if state.compileproc == None: ##
2016-10-15 12:17:33 +02:00
return
2016-10-19 13:28:06 +02:00
result = state.compileproc.poll()
state.compileproc = None
state.compileproc_finished = True
if result == 0:
2017-01-18 14:52:51 +01:00
bpy.data.worlds['Arm'].arm_recompile = False
2016-10-19 13:28:06 +02:00
state.compileproc_success = True
2016-09-23 00:34:42 +02:00
on_compiled(mode)
else:
2016-10-19 13:28:06 +02:00
state.compileproc_success = False
log.print_info('Build failed, check console')
2017-01-18 14:52:51 +01:00
def watch_patch(mode):
2016-10-19 13:28:06 +02:00
state.compileproc.wait()
2017-01-18 14:52:51 +01:00
log.print_progress(100)
2016-10-19 13:28:06 +02:00
state.compileproc = None
state.compileproc_finished = True
2017-01-18 14:52:51 +01:00
on_compiled(mode)
2016-09-12 20:12:13 +02:00
2017-01-17 18:13:54 +01:00
def runtime_to_target(in_viewport):
wrd = bpy.data.worlds['Arm']
if in_viewport or wrd.arm_play_runtime == 'Krom':
return 'krom'
elif wrd.arm_play_runtime == 'Native':
return 'native'
else:
return 'html5'
2017-01-18 14:52:51 +01:00
def get_khajs_path(in_viewport, target):
if in_viewport:
2017-05-24 23:04:24 +02:00
return arm.utils.build_dir() + '/krom/krom.js'
2017-01-18 14:52:51 +01:00
elif target == 'krom':
return arm.utils.build_dir() + '/debug/krom/krom.js'
2017-05-26 16:05:14 +02:00
else: # Browser
return arm.utils.build_dir() + '/debug/html5/kha.js'
2017-01-18 14:52:51 +01:00
2017-10-03 20:27:21 +02:00
def play_project(in_viewport, is_render=False, is_render_anim=False):
2017-01-18 14:52:51 +01:00
global scripts_mtime
2017-07-02 20:48:19 +02:00
global code_parsed
2016-11-30 11:40:28 +01:00
wrd = bpy.data.worlds['Arm']
2017-03-15 12:30:14 +01:00
log.clear()
2016-11-30 11:40:28 +01:00
# Store area
2017-03-15 12:30:14 +01:00
if arm.utils.with_krom() and in_viewport and bpy.context.area != None and bpy.context.area.type == 'VIEW_3D':
2016-10-19 13:28:06 +02:00
state.play_area = bpy.context.area
2016-09-12 02:24:20 +02:00
2017-01-17 18:13:54 +01:00
state.target = runtime_to_target(in_viewport)
2016-11-30 11:40:28 +01:00
# Build data
2017-10-03 20:27:21 +02:00
build_project(is_play=True, is_render=is_render, is_render_anim=is_render_anim, in_viewport=in_viewport)
2017-01-18 14:52:51 +01:00
khajs_path = get_khajs_path(in_viewport, state.target)
2017-05-24 23:04:24 +02:00
if not wrd.arm_cache_compiler or \
2017-01-18 14:52:51 +01:00
not os.path.isfile(khajs_path) or \
2017-05-25 16:48:41 +02:00
assets.khafile_defs_last != assets.khafile_defs or \
2017-01-29 16:15:04 +01:00
state.last_target != state.target or \
2017-05-24 23:04:24 +02:00
state.last_in_viewport != state.in_viewport or \
state.target == 'native':
2017-01-18 14:52:51 +01:00
wrd.arm_recompile = True
state.last_target = state.target
2017-01-29 16:15:04 +01:00
state.last_in_viewport = state.in_viewport
2017-01-18 14:52:51 +01:00
2017-11-09 15:19:23 +01:00
if state.in_viewport:
if arm.utils.get_rp().rp_gi != 'Off' and bpy.app.version < (2, 80, 1):
log.warn('Use Blender 2.8 to run Voxel GI in viewport')
2017-01-18 14:52:51 +01:00
# Trait sources modified
2017-07-02 20:48:19 +02:00
state.mod_scripts = []
2017-05-13 17:17:43 +02:00
script_path = arm.utils.get_fp() + '/Sources/' + arm.utils.safestr(wrd.arm_project_package)
2017-01-18 14:52:51 +01:00
if os.path.isdir(script_path):
2017-07-02 20:48:19 +02:00
new_mtime = scripts_mtime
2017-01-18 14:52:51 +01:00
for fn in glob.iglob(os.path.join(script_path, '**', '*.hx'), recursive=True):
mtime = os.path.getmtime(fn)
if scripts_mtime < mtime:
2017-07-24 02:27:22 +02:00
arm.utils.fetch_script_props(fn) # Trait props
2017-07-02 20:48:19 +02:00
fn = fn.split('Sources/')[1]
fn = fn[:-3] #.hx
fn = fn.replace('/', '.')
state.mod_scripts.append(fn)
2017-01-18 14:52:51 +01:00
wrd.arm_recompile = True
2017-07-02 20:48:19 +02:00
if new_mtime < mtime:
new_mtime = mtime
scripts_mtime = new_mtime
2017-07-24 02:27:22 +02:00
if len(state.mod_scripts) > 0: # Trait props
arm.utils.fetch_trait_props()
2017-01-18 14:52:51 +01:00
2017-05-24 23:04:24 +02:00
# New compile requred - traits changed
if wrd.arm_recompile:
2017-07-02 20:48:19 +02:00
state.recompiled = True
2017-01-18 14:52:51 +01:00
if state.krom_running:
2017-10-20 10:44:04 +02:00
# TODO: Unable to live-patch, stop player
bpy.ops.arm.space_stop('EXEC_DEFAULT')
return
2017-07-02 20:48:19 +02:00
if not code_parsed:
code_parsed = True
barmory.parse_code()
else:
code_parsed = False
2017-01-18 14:52:51 +01:00
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')
2017-05-26 11:51:08 +02:00
else: # Browser
2017-01-18 14:52:51 +01:00
state.compileproc = compile_project(target_name='html5')
threading.Timer(0.1, watch_compile, [mode]).start()
else: # kha.js up to date
2017-07-02 20:48:19 +02:00
state.recompiled = False
2017-08-21 15:36:21 +02:00
compile_project(patch=True)
def on_compiled(mode): # build, play, play_viewport, publish
2016-10-19 13:28:06 +02:00
log.clear()
2017-03-15 12:30:14 +01:00
sdk_path = arm.utils.get_sdk_path()
2017-01-30 12:02:40 +01:00
wrd = bpy.data.worlds['Arm']
2016-11-23 15:34:59 +01:00
# Launch project in new window
2017-09-04 12:14:14 +02:00
if mode =='play':
2017-05-26 11:51:08 +02:00
if wrd.arm_play_runtime == 'Browser':
2016-09-12 02:24:20 +02:00
# Start server
2017-03-15 12:30:14 +01:00
os.chdir(arm.utils.get_fp())
t = threading.Thread(name='localserver', target=arm.lib.server.run)
2016-09-12 02:24:20 +02:00
t.daemon = True
t.start()
html5_app_path = 'http://localhost:8040/' + arm.utils.build_dir() + '/debug/html5'
2016-09-12 02:24:20 +02:00
webbrowser.open(html5_app_path)
2016-11-24 17:35:12 +01:00
elif wrd.arm_play_runtime == 'Krom':
2017-06-05 02:32:51 +02:00
krom_location, krom_path = arm.utils.krom_paths()
2017-07-04 13:29:01 +02:00
os.chdir(krom_location)
args = [krom_path, arm.utils.get_fp_build() + '/debug/krom', arm.utils.get_fp_build() + '/debug/krom-resources']
2017-09-06 16:37:23 +02:00
# TODO: Krom sound freezes on MacOS
if arm.utils.get_os() == 'mac':
args.append('--nosound')
2017-06-26 17:18:34 +02:00
if state.is_render:
args.append('--nowindow')
2017-06-26 15:37:10 +02:00
state.playproc = subprocess.Popen(args, stderr=subprocess.PIPE)
2016-11-24 17:35:12 +01:00
watch_play()
def clean_project():
2017-03-15 12:30:14 +01:00
os.chdir(arm.utils.get_fp())
2016-09-23 00:34:42 +02:00
wrd = bpy.data.worlds['Arm']
# Remove build and compiled data
2017-05-23 01:03:44 +02:00
if os.path.isdir(arm.utils.build_dir()):
2017-10-21 16:07:08 +02:00
shutil.rmtree(arm.utils.build_dir(), onerror=remove_readonly)
2017-12-04 15:13:42 +01:00
if os.path.isdir(arm.utils.get_fp() + '/build'): # Kode Studio build dir
shutil.rmtree(arm.utils.get_fp() + '/build', onerror=remove_readonly)
# Remove compiled nodes
2017-05-13 17:17:43 +02:00
nodes_path = 'Sources/' + arm.utils.safestr(wrd.arm_project_package).replace('.', '/') + '/node/'
if os.path.isdir(nodes_path):
2017-10-21 16:07:08 +02:00
shutil.rmtree(nodes_path, onerror=remove_readonly)
# Remove khafile/korefile/Main.hx
if os.path.isfile('khafile.js'):
os.remove('khafile.js')
if os.path.isfile('korefile.js'):
os.remove('korefile.js')
if os.path.isfile('Sources/Main.hx'):
os.remove('Sources/Main.hx')
2017-11-20 13:38:19 +01:00
# To recache signatures for batched materials
2017-03-14 20:43:54 +01:00
for mat in bpy.data.materials:
mat.signature = ''
2017-09-04 12:14:14 +02:00
mat.is_cached = False
2017-03-14 20:43:54 +01:00
print('Project cleaned')
2016-11-12 18:30:39 +01:00
def get_render_result():
2017-06-26 15:37:10 +02:00
play_project(False, is_render=True)
2017-10-03 20:27:21 +02:00
def get_render_anim_result():
if bpy.context.scene != None:
print('Capturing animation frames into ' + bpy.context.scene.render.filepath)
play_project(False, is_render=True, is_render_anim=True)