Exporter presets
This commit is contained in:
parent
5dd42f6948
commit
3d1611d567
|
@ -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):
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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));')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
169
blender/arm/props_exporter.py
Normal file
169
blender/arm/props_exporter.py
Normal 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)
|
|
@ -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'}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in a new issue