Exporter presets

This commit is contained in:
Lubos Lenco 2017-08-21 15:36:21 +02:00
parent 5dd42f6948
commit 3d1611d567
16 changed files with 273 additions and 179 deletions

View file

@ -2170,7 +2170,7 @@ class ArmoryExporter:
o['texture_resolution_y'] = int(objref.arm_texture_resolution_y)
o['frustum_culling'] = objref.arm_frustum_culling
o['render_path'] = wrd.renderpath_path + '/' + wrd.renderpath_path # Same file name and id
o['render_path'] = 'armory_default/armory_default'
if self.scene.world != None and 'Background' in self.scene.world.node_tree.nodes: # TODO: parse node tree
background_node = self.scene.world.node_tree.nodes['Background']
@ -2225,7 +2225,7 @@ class ArmoryExporter:
mat_users[mat] = mat_objs
mat_armusers = dict()
mat_armusers[mat] = [o]
make_material.parse(mat, o, mat_users, mat_armusers, ArmoryExporter.renderpath_id)
make_material.parse(mat, o, mat_users, mat_armusers)
self.output['material_datas'].append(o)
bpy.data.materials.remove(mat)
if bpy.data.worlds['Arm'].arm_culling == False:
@ -2238,8 +2238,7 @@ class ArmoryExporter:
if wrd.arm_batch_materials:
mat_users = self.materialToObjectDict
mat_armusers = self.materialToArmObjectDict
rid = ArmoryExporter.renderpath_id
mat_batch.build(self.materialArray, mat_users, mat_armusers, rid)
mat_batch.build(self.materialArray, mat_users, mat_armusers)
transluc_used = False
overlays_used = False
@ -2268,8 +2267,7 @@ class ArmoryExporter:
mat_users = self.materialToObjectDict
mat_armusers = self.materialToArmObjectDict
rid = ArmoryExporter.renderpath_id
sd, rpasses = make_material.parse(material, o, mat_users, mat_armusers, rid)
sd, rpasses = make_material.parse(material, o, mat_users, mat_armusers)
if 'translucent' in rpasses:
transluc_used = True
@ -2680,7 +2678,6 @@ class ArmoryExporter:
ArmoryExporter.sample_animation_flag = ArmoryExporter.option_sample_animation
# Used for material shader export and khafile
ArmoryExporter.renderpath_id = wrd.renderpath_id
ArmoryExporter.mesh_context = 'mesh'
ArmoryExporter.mesh_context_empty = ''
ArmoryExporter.shadows_context = 'shadowmap'
@ -2970,7 +2967,7 @@ class ArmoryExporter:
o['traits'].append(constr_trait)
def post_export_world(self, world, o):
defs = bpy.data.worlds['Arm'].world_defs + bpy.data.worlds['Arm'].rp_defs
defs = bpy.data.worlds['Arm'].world_defs
bgcol = world.arm_envtex_color
if '_LDR' in defs: # No compositor used
for i in range(0, 3):

View file

@ -130,7 +130,7 @@ def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False
# Data does not exist yet
if not os.path.isfile(fp + '/' + ref):
shader_name = ref.split('/')[3] # Extract from 'build/compiled/...'
defs = make_utils.def_strings_to_array(wrd.world_defs + wrd.rp_defs)
defs = make_utils.def_strings_to_array(wrd.world_defs)
if shader_name.startswith('compositor_pass'):
defs += make_utils.def_strings_to_array(wrd.compo_defs)
elif shader_name.startswith('grease_pencil'):
@ -161,7 +161,7 @@ def export_data(fp, sdk_path, is_play=False, is_publish=False, in_viewport=False
state.last_resx = resx
state.last_resy = resy
def compile_project(target_name=None, is_publish=False, watch=False, patch=False):
def compile_project(target_name=None, watch=False, patch=False):
wrd = bpy.data.worlds['Arm']
fp = arm.utils.get_fp()
@ -169,7 +169,7 @@ def compile_project(target_name=None, is_publish=False, watch=False, patch=False
# Set build command
if target_name == None:
target_name = wrd.arm_project_target
target_name = state.target
elif target_name == 'native':
target_name = ''
@ -231,15 +231,11 @@ def compile_project(target_name=None, is_publish=False, watch=False, patch=False
else:
return subprocess.Popen(cmd)
def build_project(is_play=False, is_publish=False, is_render=False, in_viewport=False, target=None):
def build_project(is_play=False, is_publish=False, is_render=False, in_viewport=False):
wrd = bpy.data.worlds['Arm']
state.is_render = is_render
# Set target
if target == None:
state.target = wrd.arm_project_target.lower()
# Clear flag
state.in_viewport = False
@ -383,7 +379,7 @@ def play_project(in_viewport, is_render=False):
state.target = runtime_to_target(in_viewport)
# Build data
build_project(is_play=True, is_render=is_render, in_viewport=in_viewport, target=state.target)
build_project(is_play=True, is_render=is_render, in_viewport=in_viewport)
state.in_viewport = in_viewport
khajs_path = get_khajs_path(in_viewport, state.target)
@ -443,7 +439,7 @@ def play_project(in_viewport, is_render=False):
threading.Timer(0.1, watch_compile, [mode]).start()
else: # kha.js up to date
state.recompiled = False
compile_project(target_name=state.target, patch=True)
compile_project(patch=True)
def on_compiled(mode): # build, play, play_viewport, publish
log.clear()
@ -452,7 +448,7 @@ def on_compiled(mode): # build, play, play_viewport, publish
# Print info
if mode == 'publish':
target_name = make_utils.get_kha_target(wrd.arm_project_target)
target_name = make_utils.get_kha_target(state.target)
print('Project published')
files_path = arm.utils.get_fp_build() + '/' + target_name
if target_name == 'html5':
@ -539,15 +535,13 @@ def clean_project():
print('Project cleaned')
def publish_project():
# Force minimize data
assets.invalidate_enabled = False
minimize = bpy.data.worlds['Arm'].arm_minimize
bpy.data.worlds['Arm'].arm_minimize = True
wrd = bpy.data.worlds['Arm']
state.target = wrd.arm_exporterlist[wrd.arm_exporterlist_index].arm_project_target
clean_project()
build_project(is_publish=True)
state.compileproc = compile_project(target_name=bpy.data.worlds['Arm'].arm_project_target, is_publish=True)
state.compileproc = compile_project()
threading.Timer(0.1, watch_compile, ['publish']).start()
bpy.data.worlds['Arm'].arm_minimize = minimize
assets.invalidate_enabled = True
def get_render_result():

View file

@ -281,7 +281,6 @@ def set_renderpath(self, context):
# assets.invalidate_compiled_data(self, context)
assets.invalidate_shader_cache(self, context)
make_renderer(bpy.data.worlds['Arm'])
bpy.data.worlds['Arm'].renderpath_path = 'armory_default'
def make_renderer(wrd):
global group

View file

@ -28,13 +28,9 @@ def build_node_trees(assets_path):
# Always include
assets.add(assets_path + 'brdf.png')
assets.add_embedded_data('brdf.png')
wrd.rp_defs = ''
parsed_paths = []
if wrd.renderpath_path not in parsed_paths:
node_group = bpy.data.node_groups[wrd.renderpath_path]
build_node_tree(wrd, node_group)
parsed_paths.append(wrd.renderpath_path)
node_group = bpy.data.node_groups['armory_default']
build_node_tree(wrd, node_group)
def build_node_tree(wrd, node_group):
build_node_tree.wrd = wrd
@ -208,7 +204,8 @@ def make_draw_material_quad(stage, node_group, node, context_index=1):
def make_draw_quad(stage, node_group, node, context_index=1, shader_context=None):
stage['command'] = 'draw_shader_quad'
# Append world defs to get proper context
world_defs = bpy.data.worlds['Arm'].world_defs + bpy.data.worlds['Arm'].rp_defs
wrd = bpy.data.worlds['Arm']
world_defs = wrd.world_defs
if shader_context == None:
shader_context = node.inputs[context_index].default_value
scon = shader_context.split('/')
@ -234,7 +231,7 @@ def make_draw_world(stage, node_group, node, dome=True):
def make_draw_compositor(stage, node_group, node, with_fxaa=False):
scon = 'compositor_pass'
wrd = bpy.data.worlds['Arm']
world_defs = wrd.world_defs + wrd.rp_defs
world_defs = wrd.world_defs
compositor_defs = make_compositor.parse_defs(bpy.data.scenes[0].node_tree) # Thrown in scene 0 for now
compositor_defs += '_CTone' + wrd.arm_tonemap
# Additional compositor flags
@ -750,10 +747,6 @@ def get_root_node(node_group):
rn = None
for n in node_group.nodes:
if n.bl_idname == 'BeginNodeType':
# Store contexts
build_node_tree.wrd.renderpath_id = n.inputs[0].default_value
if n.inputs[1].default_value == False:
bpy.data.worlds['Arm'].rp_defs += '_LDR'
rn = nodes.find_node_by_link_from(node_group, n, n.outputs[0])
break
return rn
@ -771,30 +764,31 @@ def preprocess_renderpath(root_node, node_group):
def traverse_renderpath(node, node_group, render_targets, depth_buffers):
# Gather defs from linked nodes
wrd = bpy.data.worlds['Arm']
if node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType':
if preprocess_renderpath.velocity_def_added == False:
assets.add_khafile_def('arm_veloc')
bpy.data.worlds['Arm'].rp_defs += '_Veloc'
wrd.world_defs += '_Veloc'
preprocess_renderpath.velocity_def_added = True
if node.bl_idname == 'TAAPassNodeType':
assets.add_khafile_def('arm_taa')
# bpy.data.worlds['Arm'].rp_defs += '_TAA'
# wrd.world_defs += '_TAA'
elif node.bl_idname == 'SMAAPassNodeType':
bpy.data.worlds['Arm'].rp_defs += '_SMAA'
wrd.world_defs += '_SMAA'
elif node.bl_idname == 'SSSPassNodeType':
bpy.data.worlds['Arm'].rp_defs += '_SSS'
wrd.world_defs += '_SSS'
elif node.bl_idname == 'HistogramPassNodeType':
bpy.data.worlds['Arm'].rp_defs += '_Hist'
wrd.world_defs += '_Hist'
elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType':
if bpy.data.worlds['Arm'].arm_ssao: # SSAO enabled
bpy.data.worlds['Arm'].rp_defs += '_SSAO'
wrd.world_defs += '_SSAO'
elif node.bl_idname == 'DrawStereoNodeType':
assets.add_khafile_def('arm_vr')
bpy.data.worlds['Arm'].rp_defs += '_VR'
wrd.world_defs += '_VR'
assets.add(build_node_trees.assets_path + 'vr.png')
assets.add_embedded_data('vr.png')
@ -802,7 +796,7 @@ def traverse_renderpath(node, node_group, render_targets, depth_buffers):
global dynRes_added
fstr = node.inputs[1].default_value
if not dynRes_added and fstr.startswith('armory.renderpath.DynamicResolutionScale'):
bpy.data.worlds['Arm'].rp_defs += '_DynRes'
wrd.world_defs += '_DynRes'
dynRes_added = True
# Collect render targets

View file

@ -2,6 +2,7 @@
target = 'krom'
last_target = 'krom'
in_viewport = False
is_export = False
last_in_viewport = False
last_resx = 0
last_resy = 0

View file

@ -27,27 +27,19 @@ def get_kha_target(target_name): # TODO: remove
return 'osx'
return target_name
def runtime_to_gapi():
wrd = bpy.data.worlds['Arm']
if wrd.arm_play_runtime == 'Krom' or wrd.arm_play_runtime == 'Native':
return 'arm_gapi_' + arm.utils.get_os()
else:
return 'arm_gapi_html5'
def target_to_gapi():
def target_to_gapi(arm_project_target):
# TODO: align target names
wrd = bpy.data.worlds['Arm']
if wrd.arm_project_target == 'krom':
if arm_project_target == 'krom':
return 'arm_gapi_' + arm.utils.get_os()
elif wrd.arm_project_target == 'macos':
elif arm_project_target == 'macos':
return 'arm_gapi_mac'
elif wrd.arm_project_target == 'windows':
elif arm_project_target == 'windows':
return 'arm_gapi_win'
elif wrd.arm_project_target == 'windowsapp':
elif arm_project_target == 'windowsapp':
return 'arm_gapi_winapp'
elif wrd.arm_project_target == 'android-native':
elif arm_project_target == 'android-native':
return 'arm_gapi_android'
elif wrd.arm_project_target == 'node':
elif arm_project_target == 'node':
return 'arm_gapi_html5'
else:
return 'arm_gapi_' + wrd.arm_project_target
return 'arm_gapi_' + arm_project_target

View file

@ -75,6 +75,10 @@ def build_node_tree(world):
if wrd.arm_two_sided_area_lamp:
wrd.world_defs += '_TwoSidedAreaLamp'
# Store contexts
if wrd.rp_hdr == False:
wrd.world_defs += '_LDR'
# Alternative models
if wrd.arm_material_model == 'Cycles':
wrd.world_defs += '_Cycles'
@ -142,7 +146,7 @@ def write_output(output):
dir_name = 'world'
# Append world defs
wrd = bpy.data.worlds['Arm']
data_name = 'world' + wrd.world_defs + wrd.rp_defs
data_name = 'world' + wrd.world_defs
# Reference correct shader context
dat = output['material_datas'][0]

View file

@ -21,12 +21,12 @@ def glslvalue(val):
else:
return val
def parse(material, mat_data, mat_users, mat_armusers, rid):
def parse(material, mat_data, mat_users, mat_armusers):
wrd = bpy.data.worlds['Arm']
# No batch - shader data per material
if not wrd.arm_batch_materials or material.name.startswith('armdefault'):
rpasses, shader_data, shader_data_name, bind_constants, bind_textures = make_shader.build(material, mat_users, mat_armusers, rid)
rpasses, shader_data, shader_data_name, bind_constants, bind_textures = make_shader.build(material, mat_users, mat_armusers)
else:
rpasses, shader_data, shader_data_name, bind_constants, bind_textures = mat_batch.get(material)

View file

@ -12,17 +12,18 @@ write_material_attribs = None
write_material_attribs_post = None
write_vertex_attribs = None
def make(context_id, rid):
def make(context_id):
con_mesh = mat_state.data.add_context({ 'name': context_id, 'depth_write': True, 'compare_mode': 'less', 'cull_mode': 'clockwise' })
if rid == 'forward':
rid = bpy.data.worlds['Arm'].rp_renderer
if rid == 'Forward':
if bpy.data.worlds['Arm'].arm_material_model != 'Restricted':
make_forward(con_mesh)
else:
make_forward_restricted(con_mesh)
elif rid == 'deferred':
elif rid == 'Deferred':
make_deferred(con_mesh)
elif rid == 'deferred_plus':
elif rid == 'Deferred Plus':
make_deferred_plus(con_mesh)
make_finalize(con_mesh)
@ -219,7 +220,7 @@ def make_deferred(con_mesh):
frag.write('if (opacity < {0}) discard;'.format(opac))
gapi = arm.utils.get_gapi()
if '_Veloc' in wrd.rp_defs:
if '_Veloc' in wrd.world_defs:
frag.add_out('vec4[3] fragColor')
if tese == None:
vert.add_uniform('mat4 prevWVP', link='_prevWorldViewProjectionMatrix')
@ -258,7 +259,7 @@ def make_deferred(con_mesh):
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0 - ((wvpposition.z / wvpposition.w) * 0.5 + 0.5));')
else:
frag.write('fragColor[0] = vec4(n.xy, packFloat(metallic, roughness), 1.0 - gl_FragCoord.z);')
if '_SSS' in wrd.rp_defs:
if '_SSS' in wrd.world_defs:
frag.add_uniform('int materialID')
frag.write('fragColor[1] = vec4(basecol.rgb, materialID + clamp(occlusion, 0.0, 1.0 - 0.001));')
elif wrd.arm_voxelgi_refraction:
@ -266,7 +267,7 @@ def make_deferred(con_mesh):
else:
frag.write('fragColor[1] = vec4(basecol.rgb, occlusion);')
if '_Veloc' in wrd.rp_defs:
if '_Veloc' in wrd.world_defs:
frag.write('vec2 posa = (wvpposition.xy / wvpposition.w) * 0.5 + 0.5;')
frag.write('vec2 posb = (prevwvpposition.xy / prevwvpposition.w) * 0.5 + 0.5;')
frag.write('fragColor[2].rg = vec2(posa - posb);')
@ -385,10 +386,11 @@ def make_forward_restricted(con_mesh):
frag.add_out('vec4 fragColor')
frag.write('fragColor = vec4(direct * lightColor * visibility, 1.0);')
if '_LDR' in bpy.data.worlds['Arm'].rp_defs:
if '_LDR' in wrd.world_defs:
frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')
def make_forward(con_mesh):
wrd = bpy.data.worlds['Arm']
make_forward_base(con_mesh)
frag = con_mesh.frag
@ -396,7 +398,7 @@ def make_forward(con_mesh):
frag.write('fragColor = vec4(direct * lightColor * visibility + indirect * occlusion * envmapStrength, 1.0);')
if '_LDR' in bpy.data.worlds['Arm'].rp_defs:
if '_LDR' in wrd.world_defs:
frag.add_include('../../Shaders/std/tonemap.glsl')
frag.write('fragColor.rgb = tonemapFilmic(fragColor.rgb);')
# frag.write('fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));')

View file

@ -18,7 +18,7 @@ import arm.material.make_voxelbounce as make_voxelbounce
rpass_hook = None
def build(material, mat_users, mat_armusers, rid):
def build(material, mat_users, mat_armusers):
mat_state.mat_users = mat_users
mat_state.mat_armusers = mat_armusers
mat_state.material = material
@ -62,7 +62,7 @@ def build(material, mat_users, mat_armusers, rid):
mat_state.bind_textures = tar
if rp == 'mesh':
con = make_mesh.make(rp, rid)
con = make_mesh.make(rp)
elif rp == 'rect':
con = make_rect.make(rp)

View file

@ -73,7 +73,7 @@ def mark_uniforms(mats):
ar[i].inputs[j].is_uniform = True
break
def build(materialArray, mat_users, mat_armusers, rid):
def build(materialArray, mat_users, mat_armusers):
global batchDict
batchDict = dict() # Stores shader data for given material
signatureDict = dict() # Stores materials for given signature
@ -106,7 +106,7 @@ def build(materialArray, mat_users, mat_armusers, rid):
# Signature not found - build it
if mat == mat2:
batchDict[mat] = make_shader.build(mat, mat_users, mat_armusers, rid)
batchDict[mat] = make_shader.build(mat, mat_users, mat_armusers)
break
# Already batched

View file

@ -81,62 +81,11 @@ def update_mat_cache(self, context):
else:
pass
def update_gapi_win(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/windows-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/windows-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_winapp(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/windowsapp-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/windowsapp-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_linux(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/linux-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/linux-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_mac(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/osx-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/osx-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_android(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/android-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/android-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_ios(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/ios-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/ios-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_html5(self, context):
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def init_properties():
global arm_version
bpy.types.World.arm_recompile = bpy.props.BoolProperty(name="Recompile", description="Recompile sources on next play", default=True)
bpy.types.World.arm_progress = bpy.props.FloatProperty(name="Progress", description="Current build progress", default=100.0, min=0.0, max=100.0, soft_min=0.0, soft_max=100.0, subtype='PERCENTAGE', get=log.get_progress)
bpy.types.World.arm_version = StringProperty(name="Version", description="Armory SDK version", default="")
bpy.types.World.arm_project_target = EnumProperty(
items = [('html5', 'HTML5', 'html5'),
('windows', 'Windows', 'windows'),
('windowsapp', 'WindowsApp', 'windowsapp'),
('macos', 'MacOS', 'macos'),
('linux', 'Linux', 'linux'),
('ios', 'iOS', 'ios'),
('android-native', 'Android', 'android-native'),
('krom', 'Krom', 'krom'),
('node', 'Node', 'node')],
name="Target", default='html5', description='Build paltform')
bpy.types.World.arm_project_name = StringProperty(name="Name", description="Exported project name", default="")
bpy.types.World.arm_project_package = StringProperty(name="Package", description="Package name for scripts", default="arm")
bpy.types.World.arm_play_active_scene = BoolProperty(name="Play Active Scene", description="Load currently edited scene when launching player", default=True)
@ -206,43 +155,6 @@ def init_properties():
bpy.types.World.arm_winresize = BoolProperty(name="Resizable", description="Allow window resize", default=False)
bpy.types.World.arm_winmaximize = BoolProperty(name="Maximizable", description="Allow window maximize", default=False)
bpy.types.World.arm_winminimize = BoolProperty(name="Minimizable", description="Allow window minimize", default=True)
bpy.types.World.arm_gapi_win = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan'),
('direct3d9', 'Direct3D9', 'direct3d9'),
('direct3d11', 'Direct3D11', 'direct3d11'),
('direct3d12', 'Direct3D12', 'direct3d12')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_win)
bpy.types.World.arm_gapi_winapp = EnumProperty(
items = [('direct3d11', 'Auto', 'direct3d11'),
('direct3d11', 'Direct3D11', 'direct3d11')],
name="Graphics API", default='direct3d11', description='Based on currently selected target', update=update_gapi_winapp)
bpy.types.World.arm_gapi_linux = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_linux)
bpy.types.World.arm_gapi_android = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_android)
bpy.types.World.arm_gapi_mac = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('metal', 'Metal', 'metal')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_mac)
bpy.types.World.arm_gapi_ios = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('metal', 'Metal', 'metal')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_ios)
bpy.types.World.arm_gapi_html5 = EnumProperty(
items = [('webgl', 'Auto', 'webgl'),
('webgl', 'WebGL', 'webgl')],
name="Graphics API", default='webgl', description='Based on currently selected target', update=update_gapi_html5)
# For object
bpy.types.Object.arm_instanced = bpy.props.BoolProperty(name="Instanced Children", description="Use instaced rendering", default=False, update=invalidate_instance_cache)
bpy.types.Object.arm_instanced_loc_x = bpy.props.BoolProperty(name="X", default=True)
@ -288,9 +200,6 @@ def init_properties():
bpy.types.Camera.arm_texture_resolution_x = bpy.props.FloatProperty(name="X", default=512.0)
bpy.types.Camera.arm_texture_resolution_y = bpy.props.FloatProperty(name="Y", default=256.0)
bpy.types.World.renderpath_path = bpy.props.StringProperty(name="Render Path", description="Render path nodes", default="armory_default", update=assets.invalidate_shader_cache)
bpy.types.World.renderpath_id = bpy.props.StringProperty(name="Render Path ID", description="Asset ID", default="deferred")
# Render path generator
bpy.types.World.rp_preset = EnumProperty(
items=[('Low', 'Low', 'Low'),
@ -552,7 +461,6 @@ def init_properties():
bpy.types.World.arm_bundled_scripts_list = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
bpy.types.World.arm_canvas_list = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
bpy.types.World.world_defs = bpy.props.StringProperty(name="World Shader Defs", default='')
bpy.types.World.rp_defs = bpy.props.StringProperty(name="Render Path Shader Defs", default='')
bpy.types.World.compo_defs = bpy.props.StringProperty(name="Compositor Shader Defs", default='')
bpy.types.Material.export_uvs = bpy.props.BoolProperty(name="Export UVs", default=False)
bpy.types.Material.export_vcols = bpy.props.BoolProperty(name="Export VCols", default=False)

View file

@ -0,0 +1,169 @@
import os
import shutil
import arm.assets as assets
import arm.make_utils as make_utils
import bpy
from bpy.types import Menu, Panel, UIList
from bpy.props import *
def update_gapi_win(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/windows-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/windows-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_winapp(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/windowsapp-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/windowsapp-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_linux(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/linux-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/linux-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_mac(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/osx-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/osx-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_android(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/android-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/android-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_ios(self, context):
if os.path.isdir(arm.utils.get_fp_build() + '/ios-build'):
shutil.rmtree(arm.utils.get_fp_build() + '/ios-build')
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
def update_gapi_html5(self, context):
bpy.data.worlds['Arm'].arm_recompile = True
assets.invalidate_compiled_data(self, context)
class ArmExporterListItem(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(
name="Name",
description="A name for this item",
default="Preset")
arm_project_target = EnumProperty(
items = [('html5', 'HTML5', 'html5'),
('windows', 'Windows', 'windows'),
('windowsapp', 'WindowsApp', 'windowsapp'),
('macos', 'MacOS', 'macos'),
('linux', 'Linux', 'linux'),
('ios', 'iOS', 'ios'),
('android-native', 'Android', 'android-native'),
('krom', 'Krom', 'krom'),
('node', 'Node', 'node')],
name="Target", default='html5', description='Build paltform')
arm_gapi_win = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan'),
('direct3d9', 'Direct3D9', 'direct3d9'),
('direct3d11', 'Direct3D11', 'direct3d11'),
('direct3d12', 'Direct3D12', 'direct3d12')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_win)
arm_gapi_winapp = EnumProperty(
items = [('direct3d11', 'Auto', 'direct3d11'),
('direct3d11', 'Direct3D11', 'direct3d11')],
name="Graphics API", default='direct3d11', description='Based on currently selected target', update=update_gapi_winapp)
arm_gapi_linux = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_linux)
arm_gapi_android = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('vulkan', 'Vulkan', 'vulkan')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_android)
arm_gapi_mac = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('metal', 'Metal', 'metal')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_mac)
arm_gapi_ios = EnumProperty(
items = [('opengl', 'Auto', 'opengl'),
('opengl', 'OpenGL', 'opengl'),
('metal', 'Metal', 'metal')],
name="Graphics API", default='opengl', description='Based on currently selected target', update=update_gapi_ios)
arm_gapi_html5 = EnumProperty(
items = [('webgl', 'Auto', 'webgl'),
('webgl', 'WebGL', 'webgl')],
name="Graphics API", default='webgl', description='Based on currently selected target', update=update_gapi_html5)
class ArmExporterList(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# We could write some code to decide which icon to use here...
custom_icon = 'OBJECT_DATAMODE'
# Make sure your code supports all 3 layout types
if self.layout_type in {'DEFAULT', 'COMPACT'}:
row = layout.row()
row.prop(item, "name", text="", emboss=False, icon=custom_icon)
row.alignment = 'RIGHT'
row.label(item.arm_project_target)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label("", icon = custom_icon)
class ArmExporterListNewItem(bpy.types.Operator):
# Add a new item to the list
bl_idname = "arm_exporterlist.new_item"
bl_label = "Add a new item"
def execute(self, context):
mdata = bpy.data.worlds['Arm']
mdata.arm_exporterlist.add()
mdata.arm_exporterlist_index = len(mdata.arm_exporterlist) - 1
return{'FINISHED'}
class ArmExporterListDeleteItem(bpy.types.Operator):
# Delete the selected item from the list
bl_idname = "arm_exporterlist.delete_item"
bl_label = "Deletes an item"
@classmethod
def poll(self, context):
""" Enable if there's something in the list """
mdata = bpy.data.worlds['Arm']
return len(mdata.arm_exporterlist) > 0
def execute(self, context):
mdata = bpy.data.worlds['Arm']
list = mdata.arm_exporterlist
index = mdata.arm_exporterlist_index
list.remove(index)
if index > 0:
index = index - 1
mdata.arm_exporterlist_index = index
return{'FINISHED'}
def register():
bpy.utils.register_class(ArmExporterListItem)
bpy.utils.register_class(ArmExporterList)
bpy.utils.register_class(ArmExporterListNewItem)
bpy.utils.register_class(ArmExporterListDeleteItem)
bpy.types.World.arm_exporterlist = bpy.props.CollectionProperty(type=ArmExporterListItem)
bpy.types.World.arm_exporterlist_index = bpy.props.IntProperty(name="Index for my_list", default=0)
def unregister():
bpy.utils.unregister_class(ArmExporterListItem)
bpy.utils.unregister_class(ArmExporterList)
bpy.utils.unregister_class(ArmExporterListNewItem)
bpy.utils.unregister_class(ArmExporterListDeleteItem)

View file

@ -110,7 +110,6 @@ class DataPropsPanel(bpy.types.Panel):
wrd = bpy.data.worlds['Arm']
if obj.type == 'CAMERA':
layout.prop_search(wrd, "renderpath_path", bpy.data, "node_groups")
layout.prop(obj.data, 'arm_frustum_culling')
layout.prop(obj.data, 'arm_render_to_texture')
col = layout.column()
@ -327,8 +326,21 @@ class ArmoryExporterPanel(bpy.types.Panel):
row.alignment = 'EXPAND'
row.operator("arm.build_project")
row.operator("arm.publish_project")
layout.prop(wrd, 'arm_project_target')
layout.prop(wrd, make_utils.target_to_gapi())
row.enabled = wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0
rows = 2
if len(wrd.arm_exporterlist) > 1:
rows = 4
row = layout.row()
row.template_list("ArmExporterList", "The_List", wrd, "arm_exporterlist", wrd, "arm_exporterlist_index", rows=rows)
col = row.column(align=True)
col.operator("arm_exporterlist.new_item", icon='ZOOMIN', text="")
col.operator("arm_exporterlist.delete_item", icon='ZOOMOUT', text="")
if wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0:
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
layout.prop(item, 'arm_project_target')
layout.prop(item, make_utils.target_to_gapi(item.arm_project_target))
class ArmoryProjectPanel(bpy.types.Panel):
bl_label = "Armory Project"
@ -516,6 +528,7 @@ class ArmoryPlayButton(bpy.types.Operator):
self.report({"ERROR"}, "Disable Camera - Armory Render Path - Render Capture first")
return {"CANCELLED"}
state.is_export = False
assets.invalidate_enabled = False
make.play_project(False)
assets.invalidate_enabled = True
@ -551,6 +564,7 @@ class ArmoryPlayInViewportButton(bpy.types.Operator):
self.report({"ERROR"}, "Disable Camera - Armory Render Path - Render Capture first")
return {"CANCELLED"}
state.is_export = False
assets.invalidate_enabled = False
if state.playproc == None and state.krom_running == False:
if context.area.type != 'VIEW_3D':
@ -595,9 +609,10 @@ class ArmoryBuildButton(bpy.types.Operator):
return {"CANCELLED"}
state.target = make.runtime_to_target(in_viewport=False)
state.is_export = False
assets.invalidate_enabled = False
make.build_project(target=state.target)
make.compile_project(target_name=state.target, watch=True)
make.build_project()
make.compile_project(watch=True)
assets.invalidate_enabled = True
return{'FINISHED'}
@ -619,11 +634,15 @@ class ArmoryBuildProjectButton(bpy.types.Operator):
if not arm.utils.check_engine(self):
return {"CANCELLED"}
state.target = bpy.data.worlds['Arm'].arm_project_target
wrd = bpy.data.worlds['Arm']
state.target = wrd.arm_exporterlist[wrd.arm_exporterlist_index].arm_project_target
state.is_export = True
assets.invalidate_shader_cache(None, None)
assets.invalidate_enabled = False
make.build_project(target=state.target)
make.compile_project(target_name=state.target, watch=True)
make.build_project()
make.compile_project(watch=True)
assets.invalidate_enabled = True
state.is_export = False
return{'FINISHED'}
class ArmoryPatchButton(bpy.types.Operator):
@ -722,7 +741,9 @@ class ArmoryPublishButton(bpy.types.Operator):
if not arm.utils.check_engine(self):
return {"CANCELLED"}
state.is_export = True
make.publish_project()
state.is_export = False
self.report({'INFO'}, 'Publishing project, check console for details.')
return{'FINISHED'}

View file

@ -6,6 +6,8 @@ import platform
import zipfile
import re
import arm.lib.armpack
import arm.make_state as state
import arm.make_utils as make_utils
def write_arm(filepath, output):
if filepath.endswith('.zip'):
@ -61,7 +63,15 @@ def get_os():
return 'linux'
def get_gapi():
return getattr(bpy.data.worlds['Arm'], 'arm_gapi_' + get_os())
wrd = bpy.data.worlds['Arm']
if state.is_export:
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
return getattr(item, make_utils.target_to_gapi(item.arm_project_target))
else:
if wrd.arm_play_runtime == 'Browser':
return 'webgl'
else:
return 'opengl'
def get_sdk_path():
user_preferences = bpy.context.user_preferences

View file

@ -6,6 +6,7 @@ import arm.props_traits_params
import arm.props_traits_props
import arm.props_traits
import arm.props_lod
import arm.props_exporter
import arm.props
import arm.props_ui
import arm.handlers
@ -23,6 +24,7 @@ def register():
arm.props_traits_props.register()
arm.props_traits.register()
arm.props_lod.register()
arm.props_exporter.register()
arm.props_library.register()
arm.props.register()
arm.props_ui.register()
@ -49,4 +51,5 @@ def unregister():
arm.props_traits_props.unregister()
arm.props_traits.unregister()
arm.props_lod.unregister()
arm.props_exporter.unregister()
arm.space_armory.unregister()