armory/blender/arm/props_ui.py

2689 lines
105 KiB
Python
Raw Normal View History

import json
2018-08-07 08:56:48 +02:00
import os
import shutil
import bpy
from bpy.props import *
2021-08-04 22:49:38 +02:00
from arm.lightmapper.panels import scene
import arm.api
2017-03-15 12:30:14 +01:00
import arm.assets as assets
from arm.exporter import ArmoryExporter
2017-03-15 12:30:14 +01:00
import arm.log as log
import arm.logicnode.replacement
import arm.make as make
import arm.make_state as state
import arm.props as props
import arm.props_properties
import arm.props_traits
import arm.nodes_logic
import arm.proxy
import arm.ui_icons as ui_icons
import arm.utils
2016-10-19 13:28:06 +02:00
if arm.is_reload(__name__):
2021-08-04 22:49:38 +02:00
arm.api = arm.reload_module(arm.api)
assets = arm.reload_module(assets)
arm.exporter = arm.reload_module(arm.exporter)
from arm.exporter import ArmoryExporter
log = arm.reload_module(log)
arm.logicnode.replacement = arm.reload_module(arm.logicnode.replacement)
make = arm.reload_module(make)
state = arm.reload_module(state)
props = arm.reload_module(props)
arm.props_properties = arm.reload_module(arm.props_properties)
arm.props_traits = arm.reload_module(arm.props_traits)
arm.nodes_logic = arm.reload_module(arm.nodes_logic)
arm.proxy = arm.reload_module(arm.proxy)
ui_icons = arm.reload_module(ui_icons)
arm.utils = arm.reload_module(arm.utils)
else:
arm.enable_reload(__name__)
2020-08-23 23:11:49 +02:00
class ARM_PT_ObjectPropsPanel(bpy.types.Panel):
"""Menu in object region."""
2016-10-19 13:28:06 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
obj = bpy.context.object
if obj == None:
return
2017-10-12 20:21:10 +02:00
col = layout.column()
col.prop(obj, 'arm_export')
2017-08-21 12:17:55 +02:00
if not obj.arm_export:
2016-10-19 13:28:06 +02:00
return
col.prop(obj, 'arm_spawn')
col.prop(obj, 'arm_mobile')
col.prop(obj, 'arm_animation_enabled')
2017-08-19 03:08:42 +02:00
if obj.type == 'MESH':
2017-08-19 12:10:06 +02:00
layout.prop(obj, 'arm_instanced')
2017-09-21 18:30:02 +02:00
wrd = bpy.data.worlds['Arm']
2018-09-05 10:20:02 +02:00
layout.prop_search(obj, "arm_tilesheet", wrd, "arm_tilesheetlist", text="Tilesheet")
2017-09-21 18:30:02 +02:00
if obj.arm_tilesheet != '':
selected_ts = None
for ts in wrd.arm_tilesheetlist:
if ts.name == obj.arm_tilesheet:
selected_ts = ts
break
2018-09-05 10:20:02 +02:00
layout.prop_search(obj, "arm_tilesheet_action", selected_ts, "arm_tilesheetactionlist", text="Action")
2017-09-21 18:30:02 +02:00
# Properties list
arm.props_properties.draw_properties(layout, obj)
# Lightmapping props
if obj.type == "MESH":
row = layout.row(align=True)
2020-11-28 23:23:52 +01:00
scene = bpy.context.scene
if scene == None:
return
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_lightmap_use")
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_use_default_channel")
if not obj.TLM_ObjectProperties.tlm_use_default_channel:
row = layout.row()
row.prop_search(obj.TLM_ObjectProperties, "tlm_uv_channel", obj.data, "uv_layers", text='UV Channel')
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_lightmap_resolution")
if obj.TLM_ObjectProperties.tlm_use_default_channel:
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_lightmap_unwrap_mode")
row = layout.row()
2020-11-28 23:23:52 +01:00
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode == "AtlasGroupA":
if scene.TLM_AtlasListItem >= 0 and len(scene.TLM_AtlasList) > 0:
row = layout.row()
item = scene.TLM_AtlasList[scene.TLM_AtlasListItem]
row.prop_search(obj.TLM_ObjectProperties, "tlm_atlas_pointer", scene, "TLM_AtlasList", text='Atlas Group')
row = layout.row()
else:
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
row = layout.row()
else:
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_postpack_object")
row = layout.row()
if obj.TLM_ObjectProperties.tlm_postpack_object and obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode != "AtlasGroupA":
if scene.TLM_PostAtlasListItem >= 0 and len(scene.TLM_PostAtlasList) > 0:
row = layout.row()
item = scene.TLM_PostAtlasList[scene.TLM_PostAtlasListItem]
row.prop_search(obj.TLM_ObjectProperties, "tlm_postatlas_pointer", scene, "TLM_PostAtlasList", text='Atlas Group')
row = layout.row()
else:
row = layout.label(text="Add Atlas Groups from the scene lightmapping settings.")
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_unwrap_margin")
row = layout.row()
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filter_override")
row = layout.row()
if obj.TLM_ObjectProperties.tlm_mesh_filter_override:
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_mode")
row = layout.row(align=True)
if obj.TLM_ObjectProperties.tlm_mesh_filtering_mode == "Gaussian":
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_gaussian_strength")
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
elif obj.TLM_ObjectProperties.tlm_mesh_filtering_mode == "Box":
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_box_strength")
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
elif obj.TLM_ObjectProperties.tlm_mesh_filtering_mode == "Bilateral":
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_bilateral_diameter")
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_bilateral_color_deviation")
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_bilateral_coordinate_deviation")
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
else:
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_median_kernel", expand=True)
row = layout.row(align=True)
row.prop(obj.TLM_ObjectProperties, "tlm_mesh_filtering_iterations")
class ARM_PT_ModifiersPropsPanel(bpy.types.Panel):
2016-10-19 13:28:06 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "modifier"
2018-12-19 13:33:17 +01:00
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
obj = bpy.context.object
if obj == None:
return
2016-11-07 00:31:48 +01:00
layout.operator("arm.invalidate_cache")
class ARM_PT_ParticlesPropsPanel(bpy.types.Panel):
2017-09-29 01:18:57 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "particle"
2018-12-19 13:33:17 +01:00
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-09-29 01:18:57 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-09-29 01:18:57 +02:00
obj = bpy.context.particle_system
if obj == None:
return
2017-10-15 18:16:55 +02:00
layout.prop(obj.settings, 'arm_loop')
2017-09-29 17:00:21 +02:00
layout.prop(obj.settings, 'arm_count_mult')
2017-09-29 01:18:57 +02:00
class ARM_PT_PhysicsPropsPanel(bpy.types.Panel):
2017-01-10 10:41:06 +01:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "physics"
2017-10-12 20:21:10 +02:00
2017-01-10 10:41:06 +01:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-01-10 10:41:06 +01:00
obj = bpy.context.object
if obj == None:
return
rb = obj.rigid_body
if rb is not None:
col = layout.column()
row = col.row()
row.alignment = 'RIGHT'
rb_type = 'Dynamic'
if ArmoryExporter.rigid_body_static(rb):
rb_type = 'Static'
if rb.kinematic:
rb_type = 'Kinematic'
row.label(text=(f'Rigid Body Export Type: {rb_type}'), icon='AUTO')
2017-11-06 13:01:08 +01:00
layout.prop(obj, 'arm_rb_linear_factor')
layout.prop(obj, 'arm_rb_angular_factor')
layout.prop(obj, 'arm_rb_trigger')
2018-10-30 12:56:49 +01:00
layout.prop(obj, 'arm_rb_ccd')
2017-11-06 13:01:08 +01:00
if obj.soft_body is not None:
2017-11-06 13:01:08 +01:00
layout.prop(obj, 'arm_soft_body_margin')
2021-08-04 22:49:38 +02:00
if obj.rigid_body_constraint is not None:
layout.prop(obj, 'arm_relative_physics_constraint')
2017-01-10 10:41:06 +01:00
2016-10-19 13:28:06 +02:00
# Menu in data region
class ARM_PT_DataPropsPanel(bpy.types.Panel):
2016-10-19 13:28:06 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "data"
2018-12-19 13:33:17 +01:00
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
obj = bpy.context.object
if obj == None:
return
2017-08-19 03:08:42 +02:00
wrd = bpy.data.worlds['Arm']
2016-10-19 13:28:06 +02:00
if obj.type == 'CAMERA':
2017-08-21 12:17:55 +02:00
layout.prop(obj.data, 'arm_frustum_culling')
2016-11-28 14:40:07 +01:00
elif obj.type == 'MESH' or obj.type == 'FONT' or obj.type == 'META':
2018-12-19 13:33:17 +01:00
layout.prop(obj.data, 'arm_dynamic_usage')
2016-10-19 13:28:06 +02:00
layout.operator("arm.invalidate_cache")
2018-12-19 13:33:17 +01:00
elif obj.type == 'LIGHT':
layout.prop(obj.data, 'arm_clip_start')
layout.prop(obj.data, 'arm_clip_end')
layout.prop(obj.data, 'arm_fov')
layout.prop(obj.data, 'arm_shadows_bias')
layout.prop(wrd, 'arm_light_ies_texture')
layout.prop(wrd, 'arm_light_clouds_texture')
2016-10-19 13:28:06 +02:00
elif obj.type == 'SPEAKER':
layout.prop(obj.data, 'arm_play_on_start')
2017-10-13 15:21:36 +02:00
layout.prop(obj.data, 'arm_loop')
layout.prop(obj.data, 'arm_stream')
2016-10-19 13:28:06 +02:00
elif obj.type == 'ARMATURE':
2020-03-02 15:03:42 +01:00
layout.prop(obj.data, 'arm_autobake')
2018-12-18 16:46:36 +01:00
pass
2016-10-19 13:28:06 +02:00
class ARM_PT_WorldPropsPanel(bpy.types.Panel):
bl_label = "Armory World Properties"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "world"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
world = context.world
if world is None:
return
layout.prop(world, 'arm_use_clouds')
col = layout.column(align=True)
col.enabled = world.arm_use_clouds
col.prop(world, 'arm_darken_clouds')
col.prop(world, 'arm_clouds_lower')
col.prop(world, 'arm_clouds_upper')
col.prop(world, 'arm_clouds_precipitation')
col.prop(world, 'arm_clouds_secondary')
col.prop(world, 'arm_clouds_wind')
col.prop(world, 'arm_clouds_steps')
class ARM_PT_ScenePropsPanel(bpy.types.Panel):
2016-10-19 13:28:06 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
2018-12-19 13:33:17 +01:00
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
scene = bpy.context.scene
if scene == None:
return
2017-08-19 03:08:42 +02:00
row = layout.row()
column = row.column()
2017-11-20 15:59:22 +01:00
row.prop(scene, 'arm_export')
2016-10-19 13:28:06 +02:00
class InvalidateCacheButton(bpy.types.Operator):
2021-01-06 17:23:21 +01:00
"""Delete cached mesh data"""
2016-10-19 13:28:06 +02:00
bl_idname = "arm.invalidate_cache"
bl_label = "Invalidate Cache"
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def execute(self, context):
2017-08-21 12:17:55 +02:00
context.object.data.arm_cached = False
2016-10-19 13:28:06 +02:00
return{'FINISHED'}
2016-12-21 00:51:04 +01:00
class InvalidateMaterialCacheButton(bpy.types.Operator):
2021-01-06 17:23:21 +01:00
"""Delete cached material data"""
2016-12-21 00:51:04 +01:00
bl_idname = "arm.invalidate_material_cache"
bl_label = "Invalidate Cache"
2017-10-12 20:21:10 +02:00
2016-12-21 00:51:04 +01:00
def execute(self, context):
2018-12-19 20:10:34 +01:00
context.material.arm_cached = False
2018-05-24 22:16:28 +02:00
context.material.signature = ''
2016-12-21 00:51:04 +01:00
return{'FINISHED'}
class ARM_OT_NewCustomMaterial(bpy.types.Operator):
bl_idname = "arm.new_custom_material"
bl_label = "New Custom Material"
bl_description = "Add a new custom material. This will create all the necessary files and folders"
def poll_mat_name(self, context):
project_dir = arm.utils.get_fp()
shader_dir_dst = os.path.join(project_dir, 'Shaders')
mat_name = arm.utils.safestr(self.mat_name)
self.mat_exists = os.path.isdir(os.path.join(project_dir, 'Bundled', mat_name))
vert_exists = os.path.isfile(os.path.join(shader_dir_dst, f'{mat_name}.vert.glsl'))
frag_exists = os.path.isfile(os.path.join(shader_dir_dst, f'{mat_name}.frag.glsl'))
self.shader_exists = vert_exists or frag_exists
mat_name: StringProperty(
name='Material Name', description='The name of the new material',
default='MyCustomMaterial',
update=poll_mat_name)
mode: EnumProperty(
name='Target RP', description='Choose for which render path mode the new material is created',
default='deferred',
items=[('deferred', 'Deferred', 'Create the material for a deferred render path'),
('forward', 'Forward', 'Create the material for a forward render path')])
mat_exists: BoolProperty(
name='Material Already Exists',
default=False,
options={'HIDDEN', 'SKIP_SAVE'})
shader_exists: BoolProperty(
name='Shaders Already Exist',
default=False,
options={'HIDDEN', 'SKIP_SAVE'})
def invoke(self, context, event):
if not bpy.data.is_saved:
self.report({'INFO'}, "Please save your file first")
return {"CANCELLED"}
# Try to set deferred/forward based on the selected render path
try:
self.mode = 'forward' if arm.utils.get_rp().rp_renderer == 'Forward' else 'deferred'
except IndexError:
# No render path, use default (deferred)
pass
self.poll_mat_name(context)
wm = context.window_manager
return wm.invoke_props_dialog(self, width=300)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(self, 'mat_name')
layout.prop(self, 'mode', expand=True)
if self.mat_exists:
box = layout.box()
box.alert = True
col = box.column(align=True)
col.label(text='A custom material with that name already exists,', icon='ERROR')
col.label(text='clicking on \'OK\' will override the material!', icon='BLANK1')
if self.shader_exists:
box = layout.box()
box.alert = True
col = box.column(align=True)
col.label(text='Shader file(s) with that name already exists,', icon='ERROR')
col.label(text='clicking on \'OK\' will override the shader(s)!', icon='BLANK1')
def execute(self, context):
if self.mat_name == '':
return {'CANCELLED'}
project_dir = arm.utils.get_fp()
shader_dir_src = os.path.join(arm.utils.get_sdk_path(), 'armory', 'Shaders', 'custom_mat_presets')
shader_dir_dst = os.path.join(project_dir, 'Shaders')
mat_name = arm.utils.safestr(self.mat_name)
mat_dir = os.path.join(project_dir, 'Bundled', mat_name)
os.makedirs(mat_dir, exist_ok=True)
os.makedirs(shader_dir_dst, exist_ok=True)
# Shader data
if self.mode == 'forward':
col_attachments = ['RGBA64']
constants = [{'link': '_worldViewProjectionMatrix', 'name': 'WVP', 'type': 'mat4'}]
vertex_elems = [{'name': 'pos', 'data': 'short4norm'}]
else:
col_attachments = ['RGBA64', 'RGBA64']
constants = [
{'link': '_worldViewProjectionMatrix', 'name': 'WVP', 'type': 'mat4'},
{'link': '_normalMatrix', 'name': 'N', 'type': 'mat3'}
]
vertex_elems = [
{'name': 'pos', 'data': 'short4norm'},
{'name': 'nor', 'data': 'short2norm'}
]
con = {
'color_attachments': col_attachments,
'compare_mode': 'less',
'constants': constants,
'cull_mode': 'clockwise',
'depth_write': True,
'fragment_shader': f'{mat_name}.frag',
'name': 'mesh',
'texture_units': [],
'vertex_shader': f'{mat_name}.vert',
'vertex_elements': vertex_elems
}
data = {
'shader_datas': [{
'contexts': [con],
'name': f'{mat_name}'
}]
}
# Save shader data file
with open(os.path.join(mat_dir, f'{mat_name}.json'), 'w') as datafile:
json.dump(data, datafile, indent=4, sort_keys=True)
# Copy preset shaders to project
if self.mode == 'forward':
shutil.copy(os.path.join(shader_dir_src, 'custom_mat_forward.frag.glsl'), os.path.join(shader_dir_dst, f'{mat_name}.frag.glsl'))
shutil.copy(os.path.join(shader_dir_src, 'custom_mat_forward.vert.glsl'), os.path.join(shader_dir_dst, f'{mat_name}.vert.glsl'))
else:
shutil.copy(os.path.join(shader_dir_src, 'custom_mat_deferred.frag.glsl'), os.path.join(shader_dir_dst, f'{mat_name}.frag.glsl'))
shutil.copy(os.path.join(shader_dir_src, 'custom_mat_deferred.vert.glsl'), os.path.join(shader_dir_dst, f'{mat_name}.vert.glsl'))
# True if called from the material properties tab, else it was called from the search menu
if hasattr(context, 'material') and context.material is not None:
context.material.arm_custom_material = mat_name
return{'FINISHED'}
class ARM_PT_MaterialPropsPanel(bpy.types.Panel):
2016-10-19 13:28:06 +02:00
bl_label = "Armory Props"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
mat = bpy.context.material
2020-11-17 18:54:53 +01:00
if mat is None:
2016-10-19 13:28:06 +02:00
return
2018-12-19 13:33:17 +01:00
layout.prop(mat, 'arm_cast_shadow')
columnb = layout.column()
2018-08-08 22:43:14 +02:00
wrd = bpy.data.worlds['Arm']
columnb.enabled = len(wrd.arm_rplist) > 0 and arm.utils.get_rp().rp_renderer == 'Forward'
columnb.prop(mat, 'arm_receive_shadow')
layout.prop(mat, 'arm_ignore_irradiance')
2018-12-19 13:33:17 +01:00
layout.prop(mat, 'arm_two_sided')
columnb = layout.column()
2017-08-21 12:17:55 +02:00
columnb.enabled = not mat.arm_two_sided
columnb.prop(mat, 'arm_cull_mode')
2018-12-19 13:33:17 +01:00
layout.prop(mat, 'arm_material_id')
layout.prop(mat, 'arm_overlay')
layout.prop(mat, 'arm_decal')
layout.prop(mat, 'arm_discard')
columnb = layout.column()
2017-08-21 12:17:55 +02:00
columnb.enabled = mat.arm_discard
columnb.prop(mat, 'arm_discard_opacity')
columnb.prop(mat, 'arm_discard_opacity_shadows')
row = layout.row(align=True)
row.prop(mat, 'arm_custom_material')
row.operator('arm.new_custom_material', text='', icon='ADD')
2018-12-19 13:33:17 +01:00
layout.prop(mat, 'arm_skip_context')
layout.prop(mat, 'arm_particle_fade')
layout.prop(mat, 'arm_billboard')
layout.operator("arm.invalidate_material_cache")
2020-11-17 18:54:53 +01:00
class ARM_PT_MaterialDriverPropsPanel(bpy.types.Panel):
"""Per-material properties for custom render path drivers"""
bl_label = "Armory Driver Properties"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
@classmethod
def poll(cls, context):
mat = context.material
if mat is None:
return False
wrd = bpy.data.worlds['Arm']
if wrd.arm_rplist_index < 0 or len(wrd.arm_rplist) == 0:
return False
if len(arm.api.drivers) == 0:
return False
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
return rpdat.rp_driver != 'Armory' and arm.api.drivers[rpdat.rp_driver]['draw_mat_props'] is not None
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
arm.api.drivers[rpdat.rp_driver]['draw_mat_props'](layout, context.material)
class ARM_PT_MaterialBlendingPropsPanel(bpy.types.Panel):
bl_label = "Blending"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_MaterialPropsPanel"
def draw_header(self, context):
if context.material is None:
2019-04-02 18:53:53 +02:00
return
self.layout.prop(context.material, 'arm_blending', text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
mat = bpy.context.material
if mat is None:
return
flow = layout.grid_flow()
flow.enabled = mat.arm_blending
col = flow.column(align=True)
2018-08-08 22:43:14 +02:00
col.prop(mat, 'arm_blending_source')
col.prop(mat, 'arm_blending_destination')
col.prop(mat, 'arm_blending_operation')
flow.separator()
col = flow.column(align=True)
2018-08-08 22:43:14 +02:00
col.prop(mat, 'arm_blending_source_alpha')
col.prop(mat, 'arm_blending_destination_alpha')
col.prop(mat, 'arm_blending_operation_alpha')
2017-09-17 16:59:00 +02:00
class ARM_PT_ArmoryPlayerPanel(bpy.types.Panel):
2017-01-17 18:13:54 +01:00
bl_label = "Armory Player"
2016-10-19 13:28:06 +02:00
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2016-10-19 13:28:06 +02:00
wrd = bpy.data.worlds['Arm']
2017-01-17 18:13:54 +01:00
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.scale_y = 1.3
if state.proc_play is None and state.proc_build is None:
2017-02-23 13:30:11 +01:00
row.operator("arm.play", icon="PLAY")
else:
row.operator("arm.stop", icon="MESH_PLANE")
row.operator("arm.clean_menu", icon="BRUSH_DATA")
col = layout.box().column()
col.prop(wrd, 'arm_runtime')
col.prop(wrd, 'arm_play_camera')
col.prop(wrd, 'arm_play_scene')
col.prop_search(wrd, 'arm_play_renderpath', wrd, 'arm_rplist', text='Render Path')
2016-10-19 13:28:06 +02:00
if log.num_warnings > 0:
box = layout.box()
box.alert = True
col = box.column(align=True)
warnings = 'warnings' if log.num_warnings > 1 else 'warning'
col.label(text=f'{log.num_warnings} {warnings} occurred during compilation!', icon='ERROR')
# Blank icon to achieve the same indentation as the line before
# prevent showing "open console" twice:
if log.num_errors == 0:
col.label(text='Please open the console to get more information.', icon='BLANK1')
if log.num_errors > 0:
box = layout.box()
box.alert = True
# Less spacing between lines
col = box.column(align=True)
errors = 'errors' if log.num_errors > 1 else 'error'
col.label(text=f'{log.num_errors} {errors} occurred during compilation!', icon='CANCEL')
# Blank icon to achieve the same indentation as the line before
col.label(text='Please open the console to get more information.', icon='BLANK1')
class ARM_PT_ArmoryExporterPanel(bpy.types.Panel):
2017-08-19 03:08:42 +02:00
bl_label = "Armory Exporter"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-08-19 03:08:42 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-08-19 03:08:42 +02:00
wrd = bpy.data.worlds['Arm']
2021-01-25 13:53:28 +01:00
2017-01-23 20:41:45 +01:00
row = layout.row(align=True)
row.alignment = 'EXPAND'
2021-01-25 13:53:28 +01:00
row.scale_y = 1.3
row.operator("arm.build_project", icon="MOD_BUILD")
2018-05-24 22:16:28 +02:00
# row.operator("arm.patch_project")
2018-03-15 23:24:48 +01:00
row.operator("arm.publish_project", icon="EXPORT")
2017-08-21 15:36:21 +02:00
rows = 2
if len(wrd.arm_exporterlist) > 1:
rows = 4
row = layout.row()
2019-03-30 07:48:55 +01:00
row.template_list("ARM_UL_ExporterList", "The_List", wrd, "arm_exporterlist", wrd, "arm_exporterlist_index", rows=rows)
2017-08-21 15:36:21 +02:00
col = row.column(align=True)
2018-12-18 23:48:38 +01:00
col.operator("arm_exporterlist.new_item", icon='ADD', text="")
col.operator("arm_exporterlist.delete_item", icon='REMOVE', text="")
2019-03-30 07:48:55 +01:00
col.menu("ARM_MT_ExporterListSpecials", icon='DOWNARROW_HLT', text="")
2017-08-21 15:36:21 +02:00
2018-11-22 13:31:15 +01:00
if len(wrd.arm_exporterlist) > 1:
col.separator()
op = col.operator("arm_exporterlist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_exporterlist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
2017-08-21 15:36:21 +02:00
if wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0:
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
2018-03-15 23:24:48 +01:00
box = layout.box().column()
box.prop(item, 'arm_project_target')
2018-12-05 10:36:36 +01:00
if item.arm_project_target == 'custom':
box.prop(item, 'arm_project_khamake')
2018-03-15 23:24:48 +01:00
box.prop(item, arm.utils.target_to_gapi(item.arm_project_target))
2017-08-21 20:16:06 +02:00
wrd.arm_rpcache_list.clear() # Make UIList work with prop_search()
for i in wrd.arm_rplist:
wrd.arm_rpcache_list.add().name = i.name
2018-09-05 10:20:02 +02:00
box.prop_search(item, "arm_project_rp", wrd, "arm_rpcache_list", text="Render Path")
box.prop_search(item, 'arm_project_scene', bpy.data, 'scenes', text='Scene')
2018-01-23 19:42:06 +01:00
layout.separator()
2018-03-15 23:24:48 +01:00
2021-01-25 13:53:28 +01:00
col = layout.column(align=True)
2018-03-15 23:24:48 +01:00
col.prop(wrd, 'arm_project_name')
col.prop(wrd, 'arm_project_package')
2018-06-13 14:00:01 +02:00
col.prop(wrd, 'arm_project_bundle')
2021-01-25 13:53:28 +01:00
col = layout.column(align=True)
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
col.prop(wrd, 'arm_project_version')
col.prop(wrd, 'arm_project_version_autoinc')
2021-01-25 13:53:28 +01:00
col = layout.column()
2018-06-13 14:00:01 +02:00
col.prop(wrd, 'arm_project_icon')
2021-01-25 13:53:28 +01:00
col = layout.column(heading='Code Output')
2018-12-15 19:03:11 +01:00
col.prop(wrd, 'arm_dce')
col.prop(wrd, 'arm_compiler_inline')
col.prop(wrd, 'arm_minify_js')
2021-01-25 13:53:28 +01:00
col = layout.column(heading='Data')
col.prop(wrd, 'arm_minimize')
2018-12-15 19:03:11 +01:00
col.prop(wrd, 'arm_optimize_data')
2018-12-18 16:46:36 +01:00
col.prop(wrd, 'arm_asset_compression')
2019-05-14 11:43:41 +02:00
col.prop(wrd, 'arm_single_data_file')
2017-08-19 03:08:42 +02:00
class ExporterTargetSettingsMixin:
"""Mixin for common exporter setting subpanel functionality.
Panels that inherit from this mixin need to have a arm_target
variable for polling."""
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'render'
bl_parent_id = 'ARM_PT_ArmoryExporterPanel'
# Override this in sub classes
arm_panel = ''
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
@classmethod
def poll(cls, context):
wrd = bpy.data.worlds['Arm']
if (len(wrd.arm_exporterlist) > 0) and (wrd.arm_exporterlist_index >= 0):
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
return item.arm_project_target == cls.arm_target
return False
def draw_header(self, context):
self.layout.label(text='', icon='SETTINGS')
class ARM_PT_ArmoryExporterAndroidSettingsPanel(ExporterTargetSettingsMixin, bpy.types.Panel):
bl_label = "Android Settings"
arm_target = 'android-hl' # See ExporterTargetSettingsMixin
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
col = layout.column()
col.prop(wrd, 'arm_winorient')
col.prop(wrd, 'arm_project_android_sdk_min')
col.prop(wrd, 'arm_project_android_sdk_target')
col.prop(wrd, 'arm_project_android_sdk_compile')
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
class ARM_PT_ArmoryExporterAndroidPermissionsPanel(bpy.types.Panel):
bl_label = "Permissions"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
bl_parent_id = "ARM_PT_ArmoryExporterAndroidSettingsPanel"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
# Permission
row = layout.row()
rows = 2
if len(wrd.arm_exporter_android_permission_list) > 1:
rows = 4
row.template_list("ARM_UL_Exporter_AndroidPermissionList", "The_List", wrd, "arm_exporter_android_permission_list", wrd, "arm_exporter_android_permission_list_index", rows=rows)
col = row.column(align=True)
col.operator("arm_exporter_android_permission_list.new_item", icon='ADD', text="")
col.operator("arm_exporter_android_permission_list.delete_item", icon='REMOVE', text="")
row = layout.row()
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
if wrd.arm_exporter_android_permission_list_index >= 0 and len(wrd.arm_exporter_android_permission_list) > 0:
item = wrd.arm_exporter_android_permission_list[wrd.arm_exporter_android_permission_list_index]
row = layout.row()
row.prop(item, 'arm_android_permissions')
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
class ARM_PT_ArmoryExporterAndroidAbiPanel(bpy.types.Panel):
bl_label = "Android ABI Filters"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = { 'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_ArmoryExporterAndroidSettingsPanel"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
# ABIs
row = layout.row()
rows = 2
if len(wrd.arm_exporter_android_abi_list) > 1:
rows = 4
row.template_list("ARM_UL_Exporter_AndroidAbiList", "The_List", wrd, "arm_exporter_android_abi_list", wrd, "arm_exporter_android_abi_list_index", rows=rows)
col = row.column(align=True)
col.operator("arm_exporter_android_abi_list.new_item", icon='ADD', text="")
col.operator("arm_exporter_android_abi_list.delete_item", icon='REMOVE', text="")
row = layout.row()
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
if wrd.arm_exporter_android_abi_list_index >= 0 and len(wrd.arm_exporter_android_abi_list) > 0:
item = wrd.arm_exporter_android_abi_list[wrd.arm_exporter_android_abi_list_index]
row = layout.row()
row.prop(item, 'arm_android_abi')
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
class ARM_PT_ArmoryExporterAndroidBuildAPKPanel(bpy.types.Panel):
bl_label = "Building APK"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_ArmoryExporterAndroidSettingsPanel"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
path = arm.utils.get_android_sdk_root_path()
col = layout.column()
row = col.row()
row.enabled = len(path) > 0
row.prop(wrd, 'arm_project_android_build_apk')
row = col.row()
row.enabled = wrd.arm_project_android_build_apk
row.prop(wrd, 'arm_project_android_rename_apk')
row = col.row()
row.enabled = wrd.arm_project_android_build_apk and len(arm.utils.get_android_apk_copy_path()) > 0
row.prop(wrd, 'arm_project_android_copy_apk')
row = col.row(align=True)
row.prop(wrd, 'arm_project_android_list_avd')
sub = row.column(align=True)
sub.enabled = len(path) > 0
sub.operator('arm.update_list_android_emulator', text='', icon='FILE_REFRESH')
sub = row.column(align=True)
sub.enabled = len(path) > 0 and len(arm.utils.get_android_emulator_name()) > 0
sub.operator('arm.run_android_emulator', text='', icon='PLAY')
row = col.row()
row.enabled = arm.utils.get_project_android_build_apk() and len(arm.utils.get_android_emulator_name()) > 0
row.prop(wrd, 'arm_project_android_run_avd')
class ARM_PT_ArmoryExporterHTML5SettingsPanel(ExporterTargetSettingsMixin, bpy.types.Panel):
bl_label = "HTML5 Settings"
arm_target = 'html5' # See ExporterTargetSettingsMixin
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
col = layout.column()
col.prop(wrd, 'arm_project_html5_popupmenu_in_browser')
row = col.row()
row.enabled = len(arm.utils.get_html5_copy_path()) > 0
row.prop(wrd, 'arm_project_html5_copy')
row = col.row()
row.enabled = len(arm.utils.get_html5_copy_path()) > 0 and wrd.arm_project_html5_copy and len(arm.utils.get_link_web_server()) > 0
row.prop(wrd, 'arm_project_html5_start_browser')
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
class ARM_PT_ArmoryExporterWindowsSettingsPanel(ExporterTargetSettingsMixin, bpy.types.Panel):
bl_label = "Windows Settings"
arm_target = 'windows-hl' # See ExporterTargetSettingsMixin
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
col = layout.column()
row = col.row(align=True)
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
row.prop(wrd, 'arm_project_win_list_vs')
sub = row.column(align=True)
sub.enabled = arm.utils.get_os_is_windows()
sub.operator('arm.update_list_installed_vs', text='', icon='FILE_REFRESH')
row = col.row()
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
row.enabled = arm.utils.get_os_is_windows()
row.prop(wrd, 'arm_project_win_build', text='After Publish')
layout.separator()
col = layout.column()
col.enabled = arm.utils.get_os_is_windows() and wrd.arm_project_win_build != '0' and wrd.arm_project_win_build != '1'
col.prop(wrd, 'arm_project_win_build_mode')
col.prop(wrd, 'arm_project_win_build_arch')
col.prop(wrd, 'arm_project_win_build_log')
col.prop(wrd, 'arm_project_win_build_cpu')
col.prop(wrd, 'arm_project_win_build_open')
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
class ARM_PT_ArmoryProjectPanel(bpy.types.Panel):
2017-08-19 03:08:42 +02:00
bl_label = "Armory Project"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-08-19 03:08:42 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-08-10 14:10:37 +02:00
row = layout.row(align=True)
2020-04-12 20:04:28 +02:00
row.operator("arm.open_editor", icon="DESKTOP")
2018-03-15 23:24:48 +01:00
row.operator("arm.open_project_folder", icon="FILE_FOLDER")
2017-08-19 03:08:42 +02:00
class ARM_PT_ProjectFlagsPanel(bpy.types.Panel):
2018-12-24 16:26:43 +01:00
bl_label = "Flags"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_parent_id = "ARM_PT_ArmoryProjectPanel"
2018-12-24 16:26:43 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
2021-08-27 01:26:00 +02:00
col = layout.column(heading='Debug', align=True)
col.prop(wrd, 'arm_verbose_output')
col.prop(wrd, 'arm_cache_build')
2021-08-27 01:26:00 +02:00
col.prop(wrd, 'arm_assert_level')
col.prop(wrd, 'arm_assert_quit')
2021-08-27 01:26:00 +02:00
col = layout.column(heading='Runtime', align=True)
col.prop(wrd, 'arm_live_patch')
col.prop(wrd, 'arm_stream_scene')
col.prop(wrd, 'arm_loadscreen')
col.prop(wrd, 'arm_write_config')
2021-08-27 01:26:00 +02:00
col = layout.column(heading='Renderer', align=True)
col.prop(wrd, 'arm_batch_meshes')
col.prop(wrd, 'arm_batch_materials')
col.prop(wrd, 'arm_deinterleaved_buffers')
col.prop(wrd, 'arm_export_tangents')
col = layout.column(heading='Quality')
col.prop(wrd, 'arm_texture_quality')
col.prop(wrd, 'arm_sound_quality')
2017-08-19 03:08:42 +02:00
class ARM_PT_ProjectFlagsDebugConsolePanel(bpy.types.Panel):
bl_label = "Debug Console"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_ProjectFlagsPanel"
def draw_header(self, context):
wrd = bpy.data.worlds['Arm']
self.layout.prop(wrd, 'arm_debug_console', text='')
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
col = layout.column()
col.enabled = wrd.arm_debug_console
col.prop(wrd, 'arm_debug_console_position')
col.prop(wrd, 'arm_debug_console_scale')
col.prop(wrd, 'arm_debug_console_visible')
col.prop(wrd, 'arm_debug_console_trace_pos')
class ARM_PT_ProjectWindowPanel(bpy.types.Panel):
2018-12-24 16:26:43 +01:00
bl_label = "Window"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_ArmoryProjectPanel"
2018-12-24 16:26:43 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_winmode')
col = layout.column(align=True)
col.prop(wrd, 'arm_winresize')
sub = col.column()
sub.enabled = wrd.arm_winresize
sub.prop(wrd, 'arm_winmaximize')
col.enabled = True
col.prop(wrd, 'arm_winminimize')
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_vsync')
2017-08-19 03:08:42 +02:00
class ARM_PT_ProjectModulesPanel(bpy.types.Panel):
2018-12-24 16:26:43 +01:00
bl_label = "Modules"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_ArmoryProjectPanel"
2018-12-24 16:26:43 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
wrd = bpy.data.worlds['Arm']
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_audio')
layout.prop(wrd, 'arm_physics')
if wrd.arm_physics != 'Disabled':
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_physics_engine')
layout.prop(wrd, 'arm_navigation')
if wrd.arm_navigation != 'Disabled':
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_navigation_engine')
layout.prop(wrd, 'arm_ui')
layout.prop_search(wrd, 'arm_khafile', bpy.data, 'texts', text='Khafile')
layout.prop(wrd, 'arm_project_root')
2016-10-19 13:28:06 +02:00
2017-08-19 03:08:42 +02:00
class ArmVirtualInputPanel(bpy.types.Panel):
bl_label = "Armory Virtual Input"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-08-19 03:08:42 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-08-19 03:08:42 +02:00
2016-10-19 13:28:06 +02:00
class ArmoryPlayButton(bpy.types.Operator):
'''Launch player in new window'''
bl_idname = 'arm.play'
bl_label = 'Play'
2017-10-12 20:21:10 +02:00
2021-08-17 17:47:04 +02:00
def invoke(self, context, event):
if event.shift:
state.is_play = True
make.build_success()
return{'FINISHED'}
return self.execute(context)
2016-10-19 13:28:06 +02:00
def execute(self, context):
2018-06-19 23:21:53 +02:00
if state.proc_build != None:
2017-01-10 15:06:46 +01:00
return {"CANCELLED"}
2017-10-12 20:21:10 +02:00
# Compare version Blender and Armory (major, minor)
if not arm.utils.compare_version_blender_arm():
self.report({'INFO'}, 'For Armory to work correctly, you need Blender 2.93 LTS.')
2017-03-15 12:30:14 +01:00
if not arm.utils.check_saved(self):
return {"CANCELLED"}
2017-03-15 12:30:14 +01:00
if not arm.utils.check_sdkpath(self):
2017-01-08 00:56:49 +01:00
return {"CANCELLED"}
2017-07-27 10:23:59 +02:00
2019-01-21 16:57:38 +01:00
arm.utils.check_projectpath(None)
2018-08-15 15:42:25 +02:00
arm.utils.check_default_props()
2016-12-09 02:08:01 +01:00
2016-10-19 13:28:06 +02:00
assets.invalidate_enabled = False
2019-02-10 11:47:42 +01:00
make.play()
2016-10-19 13:28:06 +02:00
assets.invalidate_enabled = True
return{'FINISHED'}
class ArmoryStopButton(bpy.types.Operator):
'''Stop currently running player'''
bl_idname = 'arm.stop'
bl_label = 'Stop'
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def execute(self, context):
2018-06-19 23:21:53 +02:00
if state.proc_play != None:
state.proc_play.terminate()
state.proc_play = None
elif state.proc_build != None:
state.proc_build.terminate()
state.proc_build = None
2016-10-19 13:28:06 +02:00
return{'FINISHED'}
2017-01-23 20:41:45 +01:00
class ArmoryBuildProjectButton(bpy.types.Operator):
"""Build and compile project"""
2017-01-23 20:41:45 +01:00
bl_idname = 'arm.build_project'
bl_label = 'Build'
2017-10-12 20:21:10 +02:00
@classmethod
def poll(cls, context):
wrd = bpy.data.worlds['Arm']
return wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0
2017-01-23 20:41:45 +01:00
def execute(self, context):
# Compare version Blender and Armory (major, minor)
if not arm.utils.compare_version_blender_arm():
self.report({'INFO'}, 'For Armory to work correctly, you need Blender 2.93 LTS.')
2017-03-15 12:30:14 +01:00
if not arm.utils.check_saved(self):
2017-01-23 20:41:45 +01:00
return {"CANCELLED"}
2017-03-15 12:30:14 +01:00
if not arm.utils.check_sdkpath(self):
2017-01-23 20:41:45 +01:00
return {"CANCELLED"}
2017-09-08 14:07:41 +02:00
arm.utils.check_projectpath(self)
2018-08-15 15:42:25 +02:00
arm.utils.check_default_props()
2017-08-21 20:16:06 +02:00
2017-08-21 15:36:21 +02:00
wrd = bpy.data.worlds['Arm']
2017-08-21 20:16:06 +02:00
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
if item.arm_project_rp == '':
item.arm_project_rp = wrd.arm_rplist[wrd.arm_rplist_index].name
2019-01-24 15:09:49 +01:00
if item.arm_project_scene == None:
item.arm_project_scene = context.scene
2017-08-21 20:16:06 +02:00
# Assume unique rp names
rplist_index = wrd.arm_rplist_index
for i in range(0, len(wrd.arm_rplist)):
if wrd.arm_rplist[i].name == item.arm_project_rp:
wrd.arm_rplist_index = i
break
2017-08-21 15:36:21 +02:00
assets.invalidate_shader_cache(None, None)
2017-01-23 20:41:45 +01:00
assets.invalidate_enabled = False
2018-06-19 23:21:53 +02:00
make.build(item.arm_project_target, is_export=True)
make.compile()
2017-10-12 20:21:10 +02:00
wrd.arm_rplist_index = rplist_index
assets.invalidate_enabled = True
return{'FINISHED'}
2017-09-04 12:14:14 +02:00
class ArmoryPublishProjectButton(bpy.types.Operator):
"""Build project ready for publishing."""
2017-09-04 12:14:14 +02:00
bl_idname = 'arm.publish_project'
bl_label = 'Publish'
2017-10-12 20:21:10 +02:00
@classmethod
def poll(cls, context):
wrd = bpy.data.worlds['Arm']
return wrd.arm_exporterlist_index >= 0 and len(wrd.arm_exporterlist) > 0
2017-09-04 12:14:14 +02:00
def execute(self, context):
# Compare version Blender and Armory (major, minor)
if not arm.utils.compare_version_blender_arm():
self.report({'INFO'}, 'For Armory to work correctly, you need Blender 2.93 LTS.')
2017-09-04 12:14:14 +02:00
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
2017-09-08 14:07:41 +02:00
self.report({'INFO'}, 'Publishing project, check console for details.')
arm.utils.check_projectpath(self)
2018-08-15 15:42:25 +02:00
arm.utils.check_default_props()
2017-09-04 12:14:14 +02:00
wrd = bpy.data.worlds['Arm']
item = wrd.arm_exporterlist[wrd.arm_exporterlist_index]
if item.arm_project_rp == '':
item.arm_project_rp = wrd.arm_rplist[wrd.arm_rplist_index].name
2019-01-25 08:07:35 +01:00
if item.arm_project_scene == None:
item.arm_project_scene = context.scene
2017-09-04 12:14:14 +02:00
# Assume unique rp names
rplist_index = wrd.arm_rplist_index
for i in range(0, len(wrd.arm_rplist)):
if wrd.arm_rplist[i].name == item.arm_project_rp:
wrd.arm_rplist_index = i
break
2018-05-24 22:16:28 +02:00
make.clean()
2017-09-04 12:14:14 +02:00
assets.invalidate_enabled = False
2018-06-19 23:21:53 +02:00
make.build(item.arm_project_target, is_publish=True, is_export=True)
make.compile()
2017-08-21 20:16:06 +02:00
wrd.arm_rplist_index = rplist_index
2017-09-04 12:14:14 +02:00
assets.invalidate_enabled = True
2017-01-23 20:41:45 +01:00
return{'FINISHED'}
2017-02-28 13:48:19 +01:00
class ArmoryOpenProjectFolderButton(bpy.types.Operator):
2016-10-19 13:28:06 +02:00
'''Open project folder'''
2017-02-28 13:48:19 +01:00
bl_idname = 'arm.open_project_folder'
2016-10-19 13:28:06 +02:00
bl_label = 'Project Folder'
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def execute(self, context):
2017-03-15 12:30:14 +01:00
if not arm.utils.check_saved(self):
2016-10-31 19:29:03 +01:00
return {"CANCELLED"}
arm.utils.open_folder(arm.utils.get_fp())
2016-10-19 13:28:06 +02:00
return{'FINISHED'}
class ArmoryOpenEditorButton(bpy.types.Operator):
'''Launch this project in the IDE'''
bl_idname = 'arm.open_editor'
2019-05-07 09:54:10 +02:00
bl_label = 'Code Editor'
bl_description = 'Open Project in IDE'
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def execute(self, context):
2017-03-15 12:30:14 +01:00
if not arm.utils.check_saved(self):
2016-10-31 19:29:03 +01:00
return {"CANCELLED"}
2018-09-27 12:38:54 +02:00
arm.utils.check_default_props()
2018-09-21 21:32:45 +02:00
if not os.path.exists(arm.utils.get_fp() + "/khafile.js"):
print('Generating Krom project for IDE build configuration')
2018-09-21 21:32:45 +02:00
make.build('krom')
2018-08-07 08:56:48 +02:00
arm.utils.open_editor()
2016-10-19 13:28:06 +02:00
return{'FINISHED'}
2016-12-01 18:46:48 +01:00
class CleanMenu(bpy.types.Menu):
bl_label = "Ok?"
bl_idname = "OBJECT_MT_clean_menu"
def draw(self, context):
layout = self.layout
layout.operator("arm.clean_project")
class CleanButtonMenu(bpy.types.Operator):
'''Clean cached data'''
bl_label = "Clean"
bl_idname = "arm.clean_menu"
2017-10-12 20:21:10 +02:00
2016-12-01 18:46:48 +01:00
def execute(self, context):
bpy.ops.wm.call_menu(name=CleanMenu.bl_idname)
return {"FINISHED"}
2016-11-05 14:12:36 +01:00
class ArmoryCleanProjectButton(bpy.types.Operator):
'''Delete all cached project data'''
bl_idname = 'arm.clean_project'
bl_label = 'Clean Project'
2017-10-12 20:21:10 +02:00
2016-10-19 13:28:06 +02:00
def execute(self, context):
2017-03-15 12:30:14 +01:00
if not arm.utils.check_saved(self):
2016-10-31 19:29:03 +01:00
return {"CANCELLED"}
2018-05-24 22:16:28 +02:00
make.clean()
2016-10-19 13:28:06 +02:00
return{'FINISHED'}
def draw_view3d_header(self, context):
if state.proc_build is not None:
2018-09-05 10:20:02 +02:00
self.layout.label(text='Compiling..')
2018-05-24 22:16:28 +02:00
elif log.info_text != '':
2018-09-05 10:20:02 +02:00
self.layout.label(text=log.info_text)
2016-10-19 13:28:06 +02:00
2020-08-10 14:42:42 +02:00
def draw_view3d_object_menu(self, context):
self.layout.separator()
self.layout.operator_context = 'INVOKE_DEFAULT'
self.layout.operator('arm.copy_traits_to_active')
class ARM_PT_RenderPathPanel(bpy.types.Panel):
2017-08-19 12:10:06 +02:00
bl_label = "Armory Render Path"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
2017-08-21 20:16:06 +02:00
2017-08-19 12:10:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-08-19 12:10:06 +02:00
wrd = bpy.data.worlds['Arm']
2017-08-21 20:16:06 +02:00
rows = 2
if len(wrd.arm_rplist) > 1:
rows = 4
2017-08-21 12:17:55 +02:00
row = layout.row()
2019-03-30 07:48:55 +01:00
row.template_list("ARM_UL_RPList", "The_List", wrd, "arm_rplist", wrd, "arm_rplist_index", rows=rows)
2017-08-21 20:16:06 +02:00
col = row.column(align=True)
2018-12-18 23:48:38 +01:00
col.operator("arm_rplist.new_item", icon='ADD', text="")
col.operator("arm_rplist.delete_item", icon='REMOVE', text="")
2017-08-21 20:16:06 +02:00
2018-11-22 13:31:15 +01:00
if len(wrd.arm_rplist) > 1:
col.separator()
op = col.operator("arm_rplist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_rplist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
2018-03-15 16:02:56 +01:00
if wrd.arm_rplist_index < 0 or len(wrd.arm_rplist) == 0:
return
2017-08-21 20:16:06 +02:00
2018-03-15 16:02:56 +01:00
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
if len(arm.api.drivers) > 0:
rpdat.rp_driver_list.clear()
rpdat.rp_driver_list.add().name = 'Armory'
for d in arm.api.drivers:
rpdat.rp_driver_list.add().name = arm.api.drivers[d]['driver_name']
2018-09-05 10:20:02 +02:00
layout.prop_search(rpdat, "rp_driver", rpdat, "rp_driver_list", text="Driver")
2017-08-23 23:37:55 +02:00
layout.separator()
2018-03-15 16:02:56 +01:00
if rpdat.rp_driver != 'Armory' and arm.api.drivers[rpdat.rp_driver]['draw_props'] != None:
arm.api.drivers[rpdat.rp_driver]['draw_props'](layout)
return
2018-11-15 14:07:03 +01:00
class ARM_PT_RenderPathRendererPanel(bpy.types.Panel):
2018-12-19 13:33:17 +01:00
bl_label = "Renderer"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2018-12-19 13:33:17 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
2019-01-09 21:25:09 +01:00
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
2018-12-19 13:33:17 +01:00
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.prop(rpdat, 'rp_renderer')
2018-12-10 09:46:46 +01:00
if rpdat.rp_renderer == 'Forward':
2018-12-19 13:33:17 +01:00
layout.prop(rpdat, 'rp_depthprepass')
layout.prop(rpdat, 'arm_material_model')
layout.prop(rpdat, 'rp_translucency_state')
layout.prop(rpdat, 'rp_overlays_state')
layout.prop(rpdat, 'rp_decals_state')
layout.prop(rpdat, 'rp_blending_state')
layout.prop(rpdat, 'rp_draw_order')
layout.prop(rpdat, 'arm_samples_per_pixel')
layout.prop(rpdat, 'arm_texture_filter')
layout.prop(rpdat, 'rp_sss_state')
col = layout.column()
col.enabled = rpdat.rp_sss_state != 'Off'
col.prop(rpdat, 'arm_sss_width')
layout.prop(rpdat, 'arm_rp_displacement')
2018-05-07 23:09:38 +02:00
if rpdat.arm_rp_displacement == 'Tessellation':
2018-12-19 13:33:17 +01:00
layout.label(text='Mesh')
layout.prop(rpdat, 'arm_tess_mesh_inner')
layout.prop(rpdat, 'arm_tess_mesh_outer')
layout.label(text='Shadow')
layout.prop(rpdat, 'arm_tess_shadows_inner')
layout.prop(rpdat, 'arm_tess_shadows_outer')
2018-12-19 13:33:17 +01:00
layout.prop(rpdat, 'arm_particles')
layout.separator(factor=0.1)
col = layout.column()
col.prop(rpdat, 'arm_skin')
col = col.column()
col.enabled = rpdat.arm_skin == 'On'
col.prop(rpdat, 'arm_skin_max_bones_auto')
row = col.row()
2018-12-19 13:33:17 +01:00
row.enabled = not rpdat.arm_skin_max_bones_auto
row.prop(rpdat, 'arm_skin_max_bones')
layout.separator(factor=0.1)
2021-11-02 15:58:38 +01:00
col = layout.column()
col.prop(rpdat, 'arm_morph_target')
col = col.column()
col.enabled = rpdat.arm_morph_target == 'On'
layout.separator(factor=0.1)
col = layout.column()
col.prop(rpdat, "rp_hdr")
col.prop(rpdat, "rp_stereo")
col.prop(rpdat, 'arm_culling')
col.prop(rpdat, 'rp_pp')
2018-12-19 13:33:17 +01:00
class ARM_PT_RenderPathShadowsPanel(bpy.types.Panel):
2018-12-19 13:33:17 +01:00
bl_label = "Shadows"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2017-08-21 20:16:06 +02:00
2018-12-19 13:33:17 +01:00
def draw_header(self, context):
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
self.layout.prop(rpdat, "rp_shadows", text="")
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
def compute_subdivs(self, max, subdivs):
l = [max]
for i in range(subdivs - 1):
l.append(int(max / 2))
max = max / 2
return l
def tiles_per_light_type(self, rpdat: arm.props_renderpath.ArmRPListItem, light_type: str) -> int:
if light_type == 'point':
return 6
elif light_type == 'spot':
return 1
else:
return int(rpdat.rp_shadowmap_cascades)
def lights_number_atlas(self, rpdat: arm.props_renderpath.ArmRPListItem, atlas_size: int, shadowmap_size: int, light_type: str) -> int:
'''Compute number lights that could fit in an atlas'''
lights = atlas_size / shadowmap_size
lights *= lights / self.tiles_per_light_type(rpdat, light_type)
return int(lights)
2018-12-19 13:33:17 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.enabled = rpdat.rp_shadows
col = layout.column()
col.enabled = not rpdat.rp_shadowmap_atlas_single_map or not rpdat.rp_shadowmap_atlas
col.prop(rpdat, 'rp_shadowmap_cube')
2018-12-19 13:33:17 +01:00
layout.prop(rpdat, 'rp_shadowmap_cascade')
layout.prop(rpdat, 'rp_shadowmap_cascades')
col = layout.column()
col2 = col.column()
col2.enabled = rpdat.rp_shadowmap_cascades != '1'
col2.prop(rpdat, 'arm_shadowmap_split')
col.prop(rpdat, 'arm_shadowmap_bounds')
col.prop(rpdat, 'arm_pcfsize')
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
layout.separator()
layout.prop(rpdat, 'rp_shadowmap_atlas')
colatlas = layout.column()
colatlas.enabled = rpdat.rp_shadowmap_atlas
colatlas.prop(rpdat, 'rp_max_lights')
colatlas.prop(rpdat, 'rp_max_lights_cluster')
colatlas.prop(rpdat, 'rp_shadowmap_atlas_lod')
colatlas_lod = colatlas.column()
colatlas_lod.enabled = rpdat.rp_shadowmap_atlas_lod
colatlas_lod.prop(rpdat, 'rp_shadowmap_atlas_lod_subdivisions')
colatlas_lod_info = colatlas_lod.row()
colatlas_lod_info.alignment = 'RIGHT'
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cascade), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
subdiv_text = "Subdivisions for spot lights: " + ', '.join(map(str, subdivs_list))
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
if not rpdat.rp_shadowmap_atlas_single_map:
colatlas_lod_info = colatlas_lod.row()
colatlas_lod_info.alignment = 'RIGHT'
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cube), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
subdiv_text = "Subdivisions for point lights: " + ', '.join(map(str, subdivs_list))
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
size_warning = int(rpdat.rp_shadowmap_cascade) > 2048 or int(rpdat.rp_shadowmap_cube) > 2048
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
colatlas.prop(rpdat, 'rp_shadowmap_atlas_single_map')
# show size for single texture
if rpdat.rp_shadowmap_atlas_single_map:
colatlas_single = colatlas.column()
colatlas_single.prop(rpdat, 'rp_shadowmap_atlas_max_size')
if rpdat.rp_shadowmap_atlas_max_size != '':
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size)
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
if shadowmap_size > 2048:
size_warning = True
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
col = colatlas_single.row()
col.alignment = 'RIGHT'
col.label(text=f'Enough space for { point_lights } point lights or { spot_lights } spot lights or { dir_lights } directional lights.')
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
else:
# show size for all types
colatlas_mixed = colatlas.column()
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_spot')
if rpdat.rp_shadowmap_atlas_max_size_spot != '':
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_spot)
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
if shadowmap_size > 2048:
size_warning = True
col = colatlas_mixed.row()
col.alignment = 'RIGHT'
col.label(text=f'Enough space for {spot_lights} spot lights.')
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_point')
if rpdat.rp_shadowmap_atlas_max_size_point != '':
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_point)
shadowmap_size = int(rpdat.rp_shadowmap_cube)
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
if shadowmap_size > 2048:
size_warning = True
col = colatlas_mixed.row()
col.alignment = 'RIGHT'
col.label(text=f'Enough space for {point_lights} point lights.')
Add support for shadow map atlasing With this it is now possible to enable atlasing of shadow maps, which solves the existing limitation of 4 lights in a scene. This is done by grouping the rendering of shadow maps, that currently are drawn into their own images for each light, into one or several big textures. This was done because the openGL and webGL version Armory targets do not support dynamic indexing of shadowMapSamplers, meaning that the index that access an array of shadow maps has to be know by the compiler before hand so it can be unrolled into if/else branching. By instead simply using a big shadow map texture and moving the dynamic part to other types of array that are allowed dynamic indexing like vec4 and mat4, this limitation was solved. The premise was simple enough for the shader part, but for the Haxe part, managing and solving where lights shadow maps should go in a shadow map can be tricky. So to keep track and solve this, ShadowMapAtlas and ShadowMapTile were created. These classes have the minimally required logic to solve the basic features needed for this problem: defining some kind of abstraction to prevent overlapping of shadowmaps, finding available space, assigning such space efficiently, locking and freeing this space, etc. This functionality it is used by drawShadowMapAtlas(), which is a modified version of drawShadowMap(). Shadow map atlases are represented with perfectly balanced 4-ary trees, where each tree of the previous definition represents a "tile" or slice that results from dividing a square that represents the image into 4 slices or sub-images. The root of this "tile" it's a reference to the tile-slice, and this tile is divided in 4 slices, and the process is repeated depth-times. If depth is 1, slices are kept at just the initial 4 tiles of max size, which is the default size of the shadow map. #arm_shadowmap_atlas_lod allows controlling if code to support more depth levels is added or not when compiling. the tiles that populate atlases tile trees are simply a data structure that contains a reference to the light they are linked to, inner subtiles in case LOD is enabled, coordinates to where this tile starts in the atlas that go from 0 to Shadow Map Size, and a reference to a linked tile for LOD. This simple definition allows tiles having a theoretically small memory footprint, but in turn this simplicity might make some functionality that might be responsibility of tiles (for example knowing if they are overlapping) a responsibility of the ones that utilizes tiles instead. This decision may complicate maintenance so it is to be revised in future iterations of this feature.
2021-01-27 02:01:06 +01:00
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_sun')
if rpdat.rp_shadowmap_atlas_max_size_sun != '':
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_sun)
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
if shadowmap_size > 2048:
size_warning = True
col = colatlas_mixed.row()
col.alignment = 'RIGHT'
col.label(text=f'Enough space for {dir_lights} directional lights.')
# show warning when user picks a size higher than 2048 (arbitrary number).
if size_warning:
col = layout.column()
row = col.row()
row.alignment = 'RIGHT'
row.label(text='Warning: Game will crash if texture size is higher than max texture size allowed by target.', icon='ERROR')
2018-12-19 13:33:17 +01:00
class ARM_PT_RenderPathVoxelsPanel(bpy.types.Panel):
bl_label = "Voxel AO"
2018-12-19 13:33:17 +01:00
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2018-12-19 13:33:17 +01:00
def draw_header(self, context):
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
self.layout.prop(rpdat, "rp_voxelao", text="")
2018-12-19 13:33:17 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.enabled = rpdat.rp_voxelao
layout.prop(rpdat, 'arm_voxelgi_shadows')
layout.prop(rpdat, 'arm_voxelgi_cones')
layout.prop(rpdat, 'rp_voxelgi_resolution')
layout.prop(rpdat, 'rp_voxelgi_resolution_z')
layout.prop(rpdat, 'arm_voxelgi_dimensions')
layout.prop(rpdat, 'arm_voxelgi_revoxelize')
col2 = layout.column()
2018-12-19 13:33:17 +01:00
col2.enabled = rpdat.arm_voxelgi_revoxelize
col2.prop(rpdat, 'arm_voxelgi_camera')
col2.prop(rpdat, 'arm_voxelgi_temporal')
layout.prop(rpdat, 'arm_voxelgi_occ')
layout.prop(rpdat, 'arm_voxelgi_step')
layout.prop(rpdat, 'arm_voxelgi_range')
layout.prop(rpdat, 'arm_voxelgi_offset')
layout.prop(rpdat, 'arm_voxelgi_aperture')
2018-12-19 13:33:17 +01:00
class ARM_PT_RenderPathWorldPanel(bpy.types.Panel):
2018-12-19 13:33:17 +01:00
bl_label = "World"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2018-12-19 13:33:17 +01:00
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.prop(rpdat, "rp_background")
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, 'arm_irradiance')
2018-12-19 13:33:17 +01:00
colb = col.column()
colb.enabled = rpdat.arm_irradiance
colb.prop(rpdat, 'arm_radiance')
sub = colb.row()
sub.enabled = rpdat.arm_radiance
sub.prop(rpdat, 'arm_radiance_size')
layout.separator()
2018-12-19 13:33:17 +01:00
layout.prop(rpdat, 'arm_clouds')
col = layout.column(align=True)
col.prop(rpdat, "rp_water")
col = col.column(align=True)
col.enabled = rpdat.rp_water
col.prop(rpdat, 'arm_water_level')
col.prop(rpdat, 'arm_water_density')
col.prop(rpdat, 'arm_water_displace')
col.prop(rpdat, 'arm_water_speed')
col.prop(rpdat, 'arm_water_freq')
col.prop(rpdat, 'arm_water_refract')
col.prop(rpdat, 'arm_water_reflect')
col.prop(rpdat, 'arm_water_color')
2018-12-19 13:33:17 +01:00
class ARM_PT_RenderPathPostProcessPanel(bpy.types.Panel):
2018-12-19 13:33:17 +01:00
bl_label = "Post Process"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2018-12-19 13:33:17 +01:00
def draw_header(self, context):
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
self.layout.prop(rpdat, "rp_render_to_texture", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.enabled = rpdat.rp_render_to_texture
col = layout.column()
col.prop(rpdat, "rp_antialiasing")
col.prop(rpdat, "rp_supersampling")
col = layout.column()
col.prop(rpdat, 'arm_rp_resolution')
2018-04-20 00:56:54 +02:00
if rpdat.arm_rp_resolution == 'Custom':
col.prop(rpdat, 'arm_rp_resolution_size')
col.prop(rpdat, 'arm_rp_resolution_filter')
col.prop(rpdat, 'rp_dynres')
2018-12-19 13:33:17 +01:00
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_ssgi")
sub = col.column()
sub.enabled = rpdat.rp_ssgi != 'Off'
sub.prop(rpdat, 'arm_ssgi_half_res')
sub.prop(rpdat, 'arm_ssgi_rays')
sub.prop(rpdat, 'arm_ssgi_radius')
sub.prop(rpdat, 'arm_ssgi_strength')
sub.prop(rpdat, 'arm_ssgi_max_steps')
layout.separator(factor=0.5)
layout.prop(rpdat, 'arm_micro_shadowing')
2018-12-19 13:33:17 +01:00
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_ssr")
col = col.column()
2018-12-19 13:33:17 +01:00
col.enabled = rpdat.rp_ssr
col.prop(rpdat, 'arm_ssr_half_res')
col.prop(rpdat, 'arm_ssr_ray_step')
col.prop(rpdat, 'arm_ssr_min_ray_step')
col.prop(rpdat, 'arm_ssr_search_dist')
col.prop(rpdat, 'arm_ssr_falloff_exp')
col.prop(rpdat, 'arm_ssr_jitter')
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, 'arm_ssrs')
col = col.column()
2018-12-19 13:33:17 +01:00
col.enabled = rpdat.arm_ssrs
col.prop(rpdat, 'arm_ssrs_ray_step')
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_bloom")
col = col.column()
2018-12-19 13:33:17 +01:00
col.enabled = rpdat.rp_bloom
col.prop(rpdat, 'arm_bloom_threshold')
col.prop(rpdat, 'arm_bloom_strength')
col.prop(rpdat, 'arm_bloom_radius')
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_motionblur")
col = col.column()
2018-12-19 13:33:17 +01:00
col.enabled = rpdat.rp_motionblur != 'Off'
col.prop(rpdat, 'arm_motion_blur_intensity')
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_volumetriclight")
col = col.column()
2018-12-19 13:33:17 +01:00
col.enabled = rpdat.rp_volumetriclight
col.prop(rpdat, 'arm_volumetric_light_air_color')
col.prop(rpdat, 'arm_volumetric_light_air_turbidity')
col.prop(rpdat, 'arm_volumetric_light_steps')
2019-08-08 20:02:42 +02:00
layout.separator()
2019-08-08 20:02:42 +02:00
col = layout.column()
col.prop(rpdat, "rp_chromatic_aberration")
col = col.column()
2019-08-08 20:02:42 +02:00
col.enabled = rpdat.rp_chromatic_aberration
col.prop(rpdat, 'arm_chromatic_aberration_type')
col.prop(rpdat, 'arm_chromatic_aberration_strength')
if rpdat.arm_chromatic_aberration_type == "Spectral":
col.prop(rpdat, 'arm_chromatic_aberration_samples')
2018-12-19 13:33:17 +01:00
class ARM_PT_RenderPathCompositorPanel(bpy.types.Panel):
2018-12-19 13:33:17 +01:00
bl_label = "Compositor"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
bl_parent_id = "ARM_PT_RenderPathPanel"
2018-12-19 13:33:17 +01:00
def draw_header(self, context):
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
self.layout.prop(rpdat, "rp_compositornodes", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-12-19 13:33:17 +01:00
wrd = bpy.data.worlds['Arm']
if len(wrd.arm_rplist) <= wrd.arm_rplist_index:
return
rpdat = wrd.arm_rplist[wrd.arm_rplist_index]
layout.enabled = rpdat.rp_compositornodes
layout.prop(rpdat, 'arm_tonemap')
layout.separator()
2019-02-21 14:20:18 +01:00
col = layout.column()
draw_conditional_prop(col, 'Letterbox', rpdat, 'arm_letterbox', 'arm_letterbox_size')
draw_conditional_prop(col, 'Sharpen', rpdat, 'arm_sharpen', 'arm_sharpen_strength')
draw_conditional_prop(col, 'Vignette', rpdat, 'arm_vignette', 'arm_vignette_strength')
draw_conditional_prop(col, 'Film Grain', rpdat, 'arm_grain', 'arm_grain_strength')
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, 'arm_fog')
col = col.column(align=True)
col.enabled = rpdat.arm_fog
col.prop(rpdat, 'arm_fog_color')
col.prop(rpdat, 'arm_fog_amounta')
col.prop(rpdat, 'arm_fog_amountb')
2018-12-19 13:33:17 +01:00
layout.separator()
2018-12-19 13:33:17 +01:00
col = layout.column()
col.prop(rpdat, "rp_autoexposure")
sub = col.column(align=True)
sub.enabled = rpdat.rp_autoexposure
sub.prop(rpdat, 'arm_autoexposure_strength', text='Strength')
sub.prop(rpdat, 'arm_autoexposure_speed', text='Speed')
layout.separator()
col = layout.column()
col.prop(rpdat, 'arm_lensflare')
col.prop(rpdat, 'arm_fisheye')
layout.separator()
col = layout.column()
col.prop(rpdat, 'arm_lens_texture')
2019-08-08 18:56:56 +02:00
if rpdat.arm_lens_texture != "":
col.prop(rpdat, 'arm_lens_texture_masking')
2019-08-08 18:56:56 +02:00
if rpdat.arm_lens_texture_masking:
sub = col.column(align=True)
sub.prop(rpdat, 'arm_lens_texture_masking_centerMinClip')
sub.prop(rpdat, 'arm_lens_texture_masking_centerMaxClip')
sub = col.column(align=True)
sub.prop(rpdat, 'arm_lens_texture_masking_luminanceMin')
sub.prop(rpdat, 'arm_lens_texture_masking_luminanceMax')
col.prop(rpdat, 'arm_lens_texture_masking_brightnessExp')
layout.separator()
2018-12-19 13:33:17 +01:00
layout.prop(rpdat, 'arm_lut_texture')
2017-08-19 12:10:06 +02:00
class ARM_PT_BakePanel(bpy.types.Panel):
2018-03-05 00:24:04 +01:00
bl_label = "Armory Bake"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
scn = bpy.data.scenes[context.scene.name]
2018-03-13 18:23:00 +01:00
row = layout.row(align=True)
2020-08-23 23:11:49 +02:00
row.prop(scn, "arm_bakemode", expand=True)
2018-03-14 13:24:43 +01:00
2020-08-23 23:11:49 +02:00
if scn.arm_bakemode == "Static Map":
2018-03-13 18:23:00 +01:00
2020-08-23 23:11:49 +02:00
row = layout.row(align=True)
row.alignment = 'EXPAND'
row.operator("arm.bake_textures", icon="RENDER_STILL")
row.operator("arm.bake_apply")
2018-06-11 21:06:30 +02:00
2020-08-23 23:11:49 +02:00
col = layout.column()
col.prop(scn, 'arm_bakelist_scale')
col.prop(scn.cycles, "samples")
2018-03-05 00:24:04 +01:00
2020-08-23 23:11:49 +02:00
layout.prop(scn, 'arm_bakelist_unwrap')
rows = 2
if len(scn.arm_bakelist) > 1:
rows = 4
row = layout.row()
row.template_list("ARM_UL_BakeList", "The_List", scn, "arm_bakelist", scn, "arm_bakelist_index", rows=rows)
col = row.column(align=True)
col.operator("arm_bakelist.new_item", icon='ADD', text="")
col.operator("arm_bakelist.delete_item", icon='REMOVE', text="")
col.menu("ARM_MT_BakeListSpecials", icon='DOWNARROW_HLT', text="")
if len(scn.arm_bakelist) > 1:
col.separator()
op = col.operator("arm_bakelist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_bakelist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
if scn.arm_bakelist_index >= 0 and len(scn.arm_bakelist) > 0:
item = scn.arm_bakelist[scn.arm_bakelist_index]
layout.prop_search(item, "obj", bpy.data, "objects", text="Object")
layout.prop(item, "res_x")
layout.prop(item, "res_y")
2018-03-13 18:23:00 +01:00
2017-08-19 12:10:06 +02:00
class ArmGenLodButton(bpy.types.Operator):
"""Automatically generate LoD levels."""
2017-08-19 12:10:06 +02:00
bl_idname = 'arm.generate_lod'
bl_label = 'Auto Generate'
2017-10-12 20:21:10 +02:00
2017-08-19 12:10:06 +02:00
def lod_name(self, name, level):
return name + '_LOD' + str(level + 1)
def execute(self, context):
obj = context.object
if obj == None:
return{'CANCELLED'}
# Clear
mdata = context.object.data
2017-08-21 12:17:55 +02:00
mdata.arm_lodlist_index = 0
mdata.arm_lodlist.clear()
2017-08-19 12:10:06 +02:00
# Lod levels
wrd = bpy.data.worlds['Arm']
ratio = wrd.arm_lod_gen_ratio
num_levels = wrd.arm_lod_gen_levels
for level in range(0, num_levels):
new_obj = obj.copy()
for i in range(0, 3):
new_obj.location[i] = 0
new_obj.rotation_euler[i] = 0
new_obj.scale[i] = 1
new_obj.data = obj.data.copy()
new_obj.name = self.lod_name(obj.name, level)
new_obj.parent = obj
2019-01-08 22:49:21 +01:00
new_obj.hide_viewport = True
2017-08-19 12:10:06 +02:00
new_obj.hide_render = True
mod = new_obj.modifiers.new('Decimate', 'DECIMATE')
mod.ratio = ratio
ratio *= wrd.arm_lod_gen_ratio
2019-01-08 22:49:21 +01:00
context.scene.collection.objects.link(new_obj)
2017-10-12 20:21:10 +02:00
2017-08-19 12:10:06 +02:00
# Screen sizes
for level in range(0, num_levels):
2017-08-21 12:17:55 +02:00
mdata.arm_lodlist.add()
mdata.arm_lodlist[-1].name = self.lod_name(obj.name, level)
mdata.arm_lodlist[-1].screen_size_prop = (1 - (1 / (num_levels + 1)) * level) - (1 / (num_levels + 1))
2017-08-19 12:10:06 +02:00
return{'FINISHED'}
class ARM_PT_LodPanel(bpy.types.Panel):
2017-08-19 12:10:06 +02:00
bl_label = "Armory Lod"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-08-19 12:10:06 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-08-19 12:10:06 +02:00
obj = bpy.context.object
# Mesh only for now
if obj.type != 'MESH':
return
mdata = obj.data
rows = 2
2017-08-21 12:17:55 +02:00
if len(mdata.arm_lodlist) > 1:
2017-08-19 12:10:06 +02:00
rows = 4
2017-10-12 20:21:10 +02:00
2017-08-19 12:10:06 +02:00
row = layout.row()
2019-03-30 07:48:55 +01:00
row.template_list("ARM_UL_LodList", "The_List", mdata, "arm_lodlist", mdata, "arm_lodlist_index", rows=rows)
2017-08-19 12:10:06 +02:00
col = row.column(align=True)
2018-12-18 23:48:38 +01:00
col.operator("arm_lodlist.new_item", icon='ADD', text="")
col.operator("arm_lodlist.delete_item", icon='REMOVE', text="")
2017-08-19 12:10:06 +02:00
2018-11-22 13:31:15 +01:00
if len(mdata.arm_lodlist) > 1:
col.separator()
op = col.operator("arm_lodlist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_lodlist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
2017-08-21 12:17:55 +02:00
if mdata.arm_lodlist_index >= 0 and len(mdata.arm_lodlist) > 0:
item = mdata.arm_lodlist[mdata.arm_lodlist_index]
2018-12-19 13:33:17 +01:00
layout.prop_search(item, "name", bpy.data, "objects", text="Object")
layout.prop(item, "screen_size_prop")
2018-08-01 10:20:42 +02:00
layout.prop(mdata, "arm_lod_material")
2017-08-19 12:10:06 +02:00
# Auto lod for meshes
if obj.type == 'MESH':
layout.separator()
layout.operator("arm.generate_lod")
wrd = bpy.data.worlds['Arm']
2018-12-19 13:33:17 +01:00
layout.prop(wrd, 'arm_lod_gen_levels')
layout.prop(wrd, 'arm_lod_gen_ratio')
2017-08-19 12:10:06 +02:00
2019-01-17 21:34:38 +01:00
class ArmGenTerrainButton(bpy.types.Operator):
'''Generate terrain sectors'''
bl_idname = 'arm.generate_terrain'
bl_label = 'Generate'
def execute(self, context):
scn = context.scene
if scn == None:
return{'CANCELLED'}
sectors = scn.arm_terrain_sectors
2019-01-20 18:32:52 +01:00
size = scn.arm_terrain_sector_size
height_scale = scn.arm_terrain_height_scale
2019-01-20 18:32:52 +01:00
# Create material
2019-01-17 21:34:38 +01:00
mat = bpy.data.materials.new(name="Terrain")
2019-01-20 18:32:52 +01:00
mat.use_nodes = True
nodes = mat.node_tree.nodes
links = mat.node_tree.links
node = nodes.new('ShaderNodeDisplacement')
node.location = (-200, 100)
2019-02-04 21:47:46 +01:00
node.inputs[2].default_value = height_scale
node.space = 'WORLD'
2019-01-20 18:32:52 +01:00
links.new(nodes['Material Output'].inputs[2], node.outputs[0])
node = nodes.new('ShaderNodeTexImage')
node.location = (-600, 100)
node.interpolation = 'Closest'
2019-02-04 21:47:46 +01:00
node.extension = 'EXTEND'
2019-01-20 18:32:52 +01:00
node.arm_material_param = True
node.name = '_TerrainHeight'
node.label = '_TerrainHeight' # Height-map texture link for this sector
links.new(nodes['Displacement'].inputs[0], nodes['_TerrainHeight'].outputs[0])
2019-02-04 21:47:46 +01:00
node = nodes.new('ShaderNodeBump')
node.location = (-200, -200)
node.inputs[0].default_value = 5.0
links.new(nodes['Bump'].inputs[2], nodes['_TerrainHeight'].outputs[0])
links.new(nodes['Principled BSDF'].inputs[20], nodes['Bump'].outputs[0])
2019-01-20 18:32:52 +01:00
# Create sectors
2019-01-17 21:34:38 +01:00
root_obj = bpy.data.objects.new("Terrain", None)
root_obj.location[0] = 0
root_obj.location[1] = 0
root_obj.location[2] = 0
root_obj.arm_export = False
scn.collection.objects.link(root_obj)
scn.arm_terrain_object = root_obj
for i in range(sectors[0] * sectors[1]):
j = str(i + 1).zfill(2)
x = i % sectors[0]
y = int(i / sectors[0])
bpy.ops.mesh.primitive_plane_add(location=(x * size, -y * size, 0))
slice_obj = bpy.context.active_object
slice_obj.scale[0] = size / 2
2019-02-04 21:47:46 +01:00
slice_obj.scale[1] = -(size / 2)
2019-01-17 21:34:38 +01:00
slice_obj.scale[2] = height_scale
slice_obj.data.materials.append(mat)
for p in slice_obj.data.polygons:
p.use_smooth = True
slice_obj.name = 'Terrain.' + j
slice_obj.parent = root_obj
sub_mod = slice_obj.modifiers.new('Subdivision', 'SUBSURF')
sub_mod.subdivision_type = 'SIMPLE'
disp_mod = slice_obj.modifiers.new('Displace', 'DISPLACE')
disp_mod.texture_coords = 'UV'
disp_mod.texture = bpy.data.textures.new(name='Terrain.' + j, type='IMAGE')
disp_mod.texture.extension = 'EXTEND'
disp_mod.texture.use_interpolation = False
disp_mod.texture.use_mipmap = False
disp_mod.texture.image = bpy.data.images.load(filepath=scn.arm_terrain_textures+'/heightmap_' + j + '.png')
f = 1
levels = 0
while f < disp_mod.texture.image.size[0]:
f *= 2
levels += 1
sub_mod.levels = sub_mod.render_levels = levels
return{'FINISHED'}
class ARM_PT_TerrainPanel(bpy.types.Panel):
2019-01-17 21:34:38 +01:00
bl_label = "Armory Terrain"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scn = bpy.context.scene
if scn == None:
return
layout.prop(scn, 'arm_terrain_textures')
layout.prop(scn, 'arm_terrain_sectors')
layout.prop(scn, 'arm_terrain_sector_size')
layout.prop(scn, 'arm_terrain_height_scale')
layout.operator('arm.generate_terrain')
layout.prop(scn, 'arm_terrain_object')
class ARM_PT_TilesheetPanel(bpy.types.Panel):
2017-09-21 18:30:02 +02:00
bl_label = "Armory Tilesheet"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
2017-09-21 18:30:02 +02:00
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-09-21 18:30:02 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-09-21 18:30:02 +02:00
wrd = bpy.data.worlds['Arm']
rows = 2
if len(wrd.arm_tilesheetlist) > 1:
rows = 4
row = layout.row()
2019-03-30 07:48:55 +01:00
row.template_list("ARM_UL_TilesheetList", "The_List", wrd, "arm_tilesheetlist", wrd, "arm_tilesheetlist_index", rows=rows)
2017-09-21 18:30:02 +02:00
col = row.column(align=True)
2018-12-18 23:48:38 +01:00
col.operator("arm_tilesheetlist.new_item", icon='ADD', text="")
col.operator("arm_tilesheetlist.delete_item", icon='REMOVE', text="")
2017-09-21 18:30:02 +02:00
2018-11-22 13:31:15 +01:00
if len(wrd.arm_tilesheetlist) > 1:
col.separator()
op = col.operator("arm_tilesheetlist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_tilesheetlist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
2017-09-21 18:30:02 +02:00
if wrd.arm_tilesheetlist_index >= 0 and len(wrd.arm_tilesheetlist) > 0:
dat = wrd.arm_tilesheetlist[wrd.arm_tilesheetlist_index]
2018-12-19 13:33:17 +01:00
layout.prop(dat, "tilesx_prop")
layout.prop(dat, "tilesy_prop")
2017-09-21 18:30:02 +02:00
layout.prop(dat, "framerate_prop")
2018-09-05 10:20:02 +02:00
layout.label(text='Actions')
2017-09-21 18:30:02 +02:00
rows = 2
if len(dat.arm_tilesheetactionlist) > 1:
rows = 4
row = layout.row()
2019-03-30 07:48:55 +01:00
row.template_list("ARM_UL_TilesheetList", "The_List", dat, "arm_tilesheetactionlist", dat, "arm_tilesheetactionlist_index", rows=rows)
2017-09-21 18:30:02 +02:00
col = row.column(align=True)
2018-12-18 23:48:38 +01:00
col.operator("arm_tilesheetactionlist.new_item", icon='ADD', text="")
col.operator("arm_tilesheetactionlist.delete_item", icon='REMOVE', text="")
2017-09-21 18:30:02 +02:00
2018-11-22 13:31:15 +01:00
if len(dat.arm_tilesheetactionlist) > 1:
col.separator()
op = col.operator("arm_tilesheetactionlist.move_item", icon='TRIA_UP', text="")
op.direction = 'UP'
op = col.operator("arm_tilesheetactionlist.move_item", icon='TRIA_DOWN', text="")
op.direction = 'DOWN'
2017-09-21 18:30:02 +02:00
if dat.arm_tilesheetactionlist_index >= 0 and len(dat.arm_tilesheetactionlist) > 0:
adat = dat.arm_tilesheetactionlist[dat.arm_tilesheetactionlist_index]
2018-12-19 13:33:17 +01:00
layout.prop(adat, "start_prop")
layout.prop(adat, "end_prop")
2017-09-21 18:30:02 +02:00
layout.prop(adat, "loop_prop")
class ARM_PT_ProxyPanel(bpy.types.Panel):
2017-10-10 09:58:03 +02:00
bl_label = "Armory Proxy"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
2017-10-12 20:21:10 +02:00
2017-10-10 09:58:03 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2017-10-10 09:58:03 +02:00
layout.operator("arm.make_proxy")
2017-10-10 12:13:06 +02:00
obj = bpy.context.object
if obj is not None and obj.proxy is not None:
col = layout.column(heading="Sync")
col.prop(obj, "arm_proxy_sync_loc")
col.prop(obj, "arm_proxy_sync_rot")
col.prop(obj, "arm_proxy_sync_scale")
col.separator()
col.prop(obj, "arm_proxy_sync_materials")
col.prop(obj, "arm_proxy_sync_modifiers")
col.separator()
col.prop(obj, "arm_proxy_sync_traits")
row = col.row()
row.enabled = obj.arm_proxy_sync_traits
row.prop(obj, "arm_proxy_sync_trait_props")
row = layout.row(align=True)
row.operator("arm.proxy_toggle_all")
row.operator("arm.proxy_apply_all")
2017-10-10 09:58:03 +02:00
class ArmMakeProxyButton(bpy.types.Operator):
'''Create proxy from linked object'''
bl_idname = 'arm.make_proxy'
bl_label = 'Make Proxy'
def execute(self, context):
obj = context.object
if obj == None:
return{'CANCELLED'}
2017-10-10 12:13:06 +02:00
if obj.library == None:
2018-03-22 21:43:22 +01:00
self.report({'ERROR'}, 'Select linked object')
2017-10-10 09:58:03 +02:00
arm.proxy.make(obj)
return{'FINISHED'}
2017-10-17 14:24:29 +02:00
class ArmProxyToggleAllButton(bpy.types.Operator):
bl_idname = 'arm.proxy_toggle_all'
bl_label = 'Toggle All'
2017-10-16 21:10:33 +02:00
def execute(self, context):
2017-10-17 13:39:50 +02:00
obj = context.object
b = not obj.arm_proxy_sync_loc
obj.arm_proxy_sync_loc = b
obj.arm_proxy_sync_rot = b
obj.arm_proxy_sync_scale = b
obj.arm_proxy_sync_materials = b
obj.arm_proxy_sync_modifiers = b
obj.arm_proxy_sync_traits = b
obj.arm_proxy_sync_trait_props = b
2017-10-16 21:10:33 +02:00
return{'FINISHED'}
2017-10-17 13:39:50 +02:00
class ArmProxyApplyAllButton(bpy.types.Operator):
bl_idname = 'arm.proxy_apply_all'
bl_label = 'Apply to All'
2020-04-12 20:04:28 +02:00
2017-10-16 21:10:33 +02:00
def execute(self, context):
2017-10-17 13:39:50 +02:00
for obj in bpy.data.objects:
if obj.proxy == None:
continue
if obj.proxy == context.object.proxy:
obj.arm_proxy_sync_loc = context.object.arm_proxy_sync_loc
obj.arm_proxy_sync_rot = context.object.arm_proxy_sync_rot
obj.arm_proxy_sync_scale = context.object.arm_proxy_sync_scale
obj.arm_proxy_sync_materials = context.object.arm_proxy_sync_materials
obj.arm_proxy_sync_modifiers = context.object.arm_proxy_sync_modifiers
obj.arm_proxy_sync_traits = context.object.arm_proxy_sync_traits
obj.arm_proxy_sync_trait_props = context.object.arm_proxy_sync_trait_props
2017-10-16 21:10:33 +02:00
return{'FINISHED'}
2017-10-17 13:39:50 +02:00
class ArmSyncProxyButton(bpy.types.Operator):
bl_idname = 'arm.sync_proxy'
bl_label = 'Sync'
2017-10-16 21:10:33 +02:00
def execute(self, context):
2017-10-17 13:39:50 +02:00
if len(bpy.data.libraries) > 0:
2017-10-16 21:10:33 +02:00
for obj in bpy.data.objects:
2017-10-18 10:20:37 +02:00
if obj == None or obj.proxy == None:
continue
2017-10-17 13:39:50 +02:00
if obj.arm_proxy_sync_loc:
arm.proxy.sync_location(obj)
if obj.arm_proxy_sync_rot:
arm.proxy.sync_rotation(obj)
if obj.arm_proxy_sync_scale:
arm.proxy.sync_scale(obj)
if obj.arm_proxy_sync_materials:
arm.proxy.sync_materials(obj)
if obj.arm_proxy_sync_modifiers:
arm.proxy.sync_modifiers(obj)
if obj.arm_proxy_sync_traits:
arm.proxy.sync_traits(obj)
2021-09-09 14:22:14 +02:00
print('Proxy objects synchronized')
2017-10-16 21:10:33 +02:00
return{'FINISHED'}
2017-12-03 12:30:14 +01:00
class ArmPrintTraitsButton(bpy.types.Operator):
bl_idname = 'arm.print_traits'
bl_label = 'Print Traits'
def execute(self, context):
2017-12-03 13:04:24 +01:00
for s in bpy.data.scenes:
2017-12-03 13:28:30 +01:00
print(s.name + ' traits:')
2017-12-03 13:04:24 +01:00
for o in s.objects:
for t in o.arm_traitlist:
2017-12-04 09:40:58 +01:00
if not t.enabled_prop:
continue
tname = t.node_tree_prop.name if t.type_prop == 'Logic Nodes' else t.class_name_prop
2017-12-03 13:04:24 +01:00
print('Object {0} - {1}'.format(o.name, tname))
2017-12-03 12:30:14 +01:00
return{'FINISHED'}
class ARM_PT_MaterialNodePanel(bpy.types.Panel):
2018-06-12 00:26:52 +02:00
bl_label = 'Armory Material Node'
bl_idname = 'ARM_PT_MaterialNodePanel'
2018-06-12 00:26:52 +02:00
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_category = 'Armory'
2018-06-12 00:26:52 +02:00
2020-10-11 00:24:11 +02:00
@classmethod
def poll(cls, context):
return (context.space_data.tree_type == 'ShaderNodeTree'
and context.space_data.edit_tree
and context.space_data.shader_type == 'OBJECT')
2018-06-12 00:26:52 +02:00
def draw(self, context):
layout = self.layout
2018-12-19 13:33:17 +01:00
layout.use_property_split = True
2018-12-19 20:10:34 +01:00
layout.use_property_decorate = False
2018-06-12 00:26:52 +02:00
n = context.active_node
if n != None and (n.bl_idname == 'ShaderNodeRGB' or n.bl_idname == 'ShaderNodeValue' or n.bl_idname == 'ShaderNodeTexImage'):
layout.prop(context.active_node, 'arm_material_param')
class ARM_OT_ShowFileVersionInfo(bpy.types.Operator):
bl_label = 'Show old file version info'
bl_idname = 'arm.show_old_file_version_info'
bl_description = ('Displays an info panel that warns about opening a file'
'which was created in a previous version of Armory')
2021-01-06 17:23:21 +01:00
bl_options = {'INTERNAL'}
wrd = None
def draw_message_box(self, context):
file_version = ARM_OT_ShowFileVersionInfo.wrd.arm_version
current_version = props.arm_version
layout = self.layout
layout = layout.column(align=True)
layout.alignment = 'EXPAND'
if current_version == file_version:
layout.label('This file was saved in', icon='INFO')
layout.label('the current Armory version', icon='BLANK1')
layout.separator()
layout.label(f'(version: {current_version}')
row = layout.row(align=True)
row.active_default = True
row.operator('arm.discard_popup', text='Ok')
# this will help order versions better, somewhat.
# note: this is NOT complete
current_version = tuple( current_version.split('.') )
file_version = tuple( file_version.split('.') )
if current_version > file_version:
layout.label(text='Warning: This file was saved in a', icon='ERROR')
layout.label(text='previous version of Armory!', icon='BLANK1')
layout.separator()
layout.label(text='Please inform yourself about breaking changes!', icon='BLANK1')
layout.label(text=f'File saved in: {file_version}', icon='BLANK1')
layout.label(text=f'Current version: {current_version}', icon='BLANK1')
layout.separator()
layout.separator()
layout.label(text='Should Armory try to automatically update', icon='BLANK1')
layout.label(text='the file to the current SDK version?', icon='BLANK1')
layout.separator()
row = layout.row(align=True)
row.active_default = True
row.operator('arm.update_file_sdk', text='Yes')
row.active_default = False
row.operator('arm.discard_popup', text='No')
else:
layout.label(text='Warning: This file was saved in a', icon='ERROR')
layout.label(text='future version of Armory!', icon='BLANK1')
layout.separator()
layout.label(text='It is impossible to downgrade a file,', icon='BLANK1')
layout.label(text='Something will probably be broken here.', icon='BLANK1')
layout.label(text=f'File saved in: {file_version}', icon='BLANK1')
layout.label(text=f'Current version: {current_version}', icon='BLANK1')
layout.separator()
layout.separator()
layout.label(text='Please check how this file was created', icon='BLANK1')
layout.separator()
row = layout.row(align=True)
row.active_default = True
row.operator('arm.discard_popup', text='Ok')
def execute(self, context):
ARM_OT_ShowFileVersionInfo.wrd = bpy.data.worlds['Arm']
context.window_manager.popover(ARM_OT_ShowFileVersionInfo.draw_message_box, ui_units_x=16)
return {"FINISHED"}
class ARM_OT_ShowNodeUpdateErrors(bpy.types.Operator):
bl_label = 'Show upgrade failure details'
bl_idname = 'arm.show_node_update_errors'
bl_description = ('Displays an info panel that shows the different errors that occurred when upgrading nodes')
wrd = None # a helper internal variable
def draw_message_box(self, context):
list_of_errors = arm.logicnode.replacement.replacement_errors.copy()
# note: list_of_errors is a set of tuples: `(error_type, node_class, tree_name)`
# where `error_type` can be "unregistered", "update failed", "future version", "bad version", or "misc."
file_version = ARM_OT_ShowNodeUpdateErrors.wrd.arm_version
current_version = props.arm_version
# this will help order versions better, somewhat.
# note: this is NOT complete
current_version_2 = tuple(current_version.split('.'))
file_version_2 = tuple(file_version.split('.'))
is_armory_upgrade = (current_version_2 > file_version_2)
error_types = set()
errored_trees = set()
errored_nodes = set()
for error_entry in list_of_errors:
error_types.add(error_entry[0])
errored_nodes.add(error_entry[1])
errored_trees.add(error_entry[2])
layout = self.layout
layout = layout.column(align=True)
layout.alignment = 'EXPAND'
layout.label(text="Some nodes failed to be updated to the current Armory version", icon="ERROR")
if current_version == file_version:
layout.label(text="(This might be because you are using a development snapshot, or a homemade version ;) )", icon='BLANK1')
elif not is_armory_upgrade:
layout.label(text="(Please note that it is not possible do downgrade nodes to a previous version either.", icon='BLANK1')
layout.label(text="This might be the cause of your problem.)", icon='BLANK1')
layout.label(text=f'File saved in: {file_version}', icon='BLANK1')
layout.label(text=f'Current version: {current_version}', icon='BLANK1')
layout.separator()
if 'update failed' in error_types:
layout.label(text="Some nodes do not have an update procedure to deal with the version saved in this file.", icon='BLANK1')
if current_version == file_version:
layout.label(text="(if you are a developer, this might be because you didn't implement it yet.)", icon='BLANK1')
if 'bad version' in error_types:
layout.label(text="Some nodes do not have version information attached to them.", icon='BLANK1')
if 'unregistered' in error_types:
if is_armory_upgrade:
layout.label(text='Some nodes seem to be too old to be understood by armory anymore', icon='BLANK1')
else:
layout.label(text="Some nodes are unknown to armory, either because they are too new or too old.", icon='BLANK1')
if 'future version' in error_types:
if is_armory_upgrade:
layout.label(text='Somehow, some nodes seem to have been created with a future version of armory.', icon='BLANK1')
else:
layout.label(text='Some nodes seem to have been created with a future version of armory.', icon='BLANK1')
if 'misc.' in error_types:
layout.label(text="Some nodes' update procedure failed to complete")
layout.separator()
layout.label(text='the nodes impacted are the following:', icon='BLANK1')
for node in errored_nodes:
layout.label(text=f' {node}', icon='BLANK1')
layout.separator()
layout.label(text='the node trees impacted are the following:', icon='BLANK1')
for tree in errored_trees:
layout.label(text=f' "{tree}"', icon='BLANK1')
layout.separator()
layout.label(text="A detailed error report has been saved next to the blender file.", icon='BLANK1')
layout.label(text="the file name is \"node_update_failure\", followed by the current time.", icon='BLANK1')
layout.separator()
row = layout.row(align=True)
row.active_default = False
row.operator('arm.discard_popup', text='Ok')
row.operator('arm.open_project_folder', text='Open Project Folder', icon="FILE_FOLDER")
def execute(self, context):
ARM_OT_ShowNodeUpdateErrors.wrd = bpy.data.worlds['Arm']
context.window_manager.popover(ARM_OT_ShowNodeUpdateErrors.draw_message_box, ui_units_x=32)
return {"FINISHED"}
class ARM_OT_UpdateFileSDK(bpy.types.Operator):
bl_idname = 'arm.update_file_sdk'
bl_label = 'Update file to current SDK version'
bl_description = bl_label
bl_options = {'INTERNAL'}
def execute(self, context):
wrd = bpy.data.worlds['Arm']
# This allows for seamless migration from ealier versions of Armory
for rp in wrd.arm_rplist: # TODO: deprecated
if rp.rp_gi != 'Off':
rp.rp_gi = 'Off'
rp.rp_voxelao = True
# Replace deprecated nodes
arm.logicnode.replacement.replace_all()
wrd.arm_version = props.arm_version
wrd.arm_commit = props.arm_commit
arm.make.clean()
print(f'Project updated to SDK {props.arm_version}. Please save the .blend file.')
return {'FINISHED'}
2020-08-10 00:23:26 +02:00
class ARM_OT_DiscardPopup(bpy.types.Operator):
"""Empty operator for discarding dialogs."""
bl_idname = 'arm.discard_popup'
bl_label = 'OK'
bl_description = 'Discard'
bl_options = {'INTERNAL'}
def execute(self, context):
return {'FINISHED'}
class ArmoryUpdateListAndroidEmulatorButton(bpy.types.Operator):
'''Updating the list of emulators for the Android platform'''
bl_idname = 'arm.update_list_android_emulator'
bl_label = 'Update List Emulators'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if len(arm.utils.get_android_sdk_root_path()) == 0:
return {"CANCELLED"}
2020-11-16 19:55:15 +01:00
os.environ['ANDROID_SDK_ROOT'] = arm.utils.get_android_sdk_root_path()
items, err = arm.utils.get_android_emulators_list()
if len(err) > 0:
print('Update List Emulators Warning: File "'+ arm.utils.get_android_emulator_file() +'" not found. Check that the variable ANDROID_SDK_ROOT is correct in environment variables or in "Android SDK Path" setting: \n- If you specify an environment variable ANDROID_SDK_ROOT, then you need to restart Blender;\n- If you specify the setting "Android SDK Path", then repeat operation "Publish"')
return{'FINISHED'}
if len(items) > 0:
items_enum = []
for i in items:
items_enum.append((i, i, i))
bpy.types.World.arm_project_android_list_avd = EnumProperty(items=items_enum, name="Emulator", update=assets.invalidate_compiler_cache)
return{'FINISHED'}
class ArmoryUpdateListAndroidEmulatorRunButton(bpy.types.Operator):
'''Launch Android emulator selected from the list'''
bl_idname = 'arm.run_android_emulator'
bl_label = 'Launch Emulator'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if len(arm.utils.get_android_sdk_root_path()) == 0:
return {"CANCELLED"}
2020-11-16 19:55:15 +01:00
make.run_android_emulators(arm.utils.get_android_emulator_name())
return{'FINISHED'}
2020-08-10 00:23:26 +02:00
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
class ArmoryUpdateListInstalledVSButton(bpy.types.Operator):
'''Updating the list installed Visual Studio for the Windows platform'''
bl_idname = 'arm.update_list_installed_vs'
bl_label = 'Update List Installed Visual Studio'
def execute(self, context):
if not arm.utils.check_saved(self):
return {"CANCELLED"}
if not arm.utils.check_sdkpath(self):
return {"CANCELLED"}
if not arm.utils.get_os_is_windows():
return {"CANCELLED"}
2020-12-04 21:17:50 +01:00
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
wrd = bpy.data.worlds['Arm']
items, err = arm.utils.get_list_installed_vs_version()
if len(err) > 0:
print('Warning for operation Update List Installed Visual Studio: '+ err +'. Check if ArmorySDK is installed correctly.')
return{'FINISHED'}
if len(items) > 0:
items_enum = [('10', '2010', 'Visual Studio 2010 (version 10)'),
('11', '2012', 'Visual Studio 2012 (version 11)'),
('12', '2013', 'Visual Studio 2013 (version 12)'),
('14', '2015', 'Visual Studio 2015 (version 14)'),
('15', '2017', 'Visual Studio 2017 (version 15)'),
('16', '2019', 'Visual Studio 2019 (version 16)')]
prev_select = wrd.arm_project_win_list_vs
res_items_enum = []
for vs in items_enum:
2020-12-04 21:17:50 +01:00
l_vs = list(vs)
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
for ver in items:
if l_vs[0] == ver[0]:
l_vs[1] = l_vs[1] + ' (installed)'
l_vs[2] = l_vs[2] + ' (installed)'
break
res_items_enum.append((l_vs[0], l_vs[1], l_vs[2]))
bpy.types.World.arm_project_win_list_vs = EnumProperty(items=res_items_enum, name="Visual Studio Version", default=prev_select, update=assets.invalidate_compiler_cache)
return{'FINISHED'}
def draw_custom_node_menu(self, context):
"""Extension of the node context menu.
https://blender.stackexchange.com/questions/150101/python-how-to-add-items-in-context-menu-in-2-8
"""
if context.selected_nodes is None or len(context.selected_nodes) != 1:
return
if context.space_data.tree_type == 'ArmLogicTreeType':
if context.selected_nodes[0].bl_idname.startswith('LN'):
layout = self.layout
layout.separator()
layout.operator("arm.open_node_documentation", text="Show documentation for this node", icon='HELP')
layout.operator("arm.open_node_haxe_source", text="Open .hx source in the browser", icon_value=ui_icons.get_id("haxe"))
layout.operator("arm.open_node_python_source", text="Open .py source in the browser", icon='FILE_SCRIPT')
elif context.space_data.tree_type == 'ShaderNodeTree':
if context.active_node.bl_idname in ('ShaderNodeRGB', 'ShaderNodeValue', 'ShaderNodeTexImage'):
layout = self.layout
layout.separator()
layout.prop(context.active_node, 'arm_material_param', text='Armory: Material Parameter')
def draw_conditional_prop(layout: bpy.types.UILayout, heading: str, data: bpy.types.AnyType, prop_condition: str, prop_value: str) -> None:
"""Draws a property row with a checkbox that enables a value field.
The function fails when prop_condition is not a boolean property.
"""
col = layout.column(heading=heading)
row = col.row()
row.prop(data, prop_condition, text='')
sub = row.row()
sub.enabled = getattr(data, prop_condition)
sub.prop(data, prop_value, expand=True)
2016-10-19 13:28:06 +02:00
def register():
bpy.utils.register_class(ARM_PT_ObjectPropsPanel)
bpy.utils.register_class(ARM_PT_ModifiersPropsPanel)
bpy.utils.register_class(ARM_PT_ParticlesPropsPanel)
bpy.utils.register_class(ARM_PT_PhysicsPropsPanel)
bpy.utils.register_class(ARM_PT_DataPropsPanel)
bpy.utils.register_class(ARM_PT_ScenePropsPanel)
bpy.utils.register_class(ARM_PT_WorldPropsPanel)
2017-03-15 12:30:14 +01:00
bpy.utils.register_class(InvalidateCacheButton)
bpy.utils.register_class(InvalidateMaterialCacheButton)
bpy.utils.register_class(ARM_OT_NewCustomMaterial)
bpy.utils.register_class(ARM_PT_MaterialPropsPanel)
bpy.utils.register_class(ARM_PT_MaterialBlendingPropsPanel)
2020-11-17 18:54:53 +01:00
bpy.utils.register_class(ARM_PT_MaterialDriverPropsPanel)
bpy.utils.register_class(ARM_PT_ArmoryPlayerPanel)
bpy.utils.register_class(ARM_PT_ArmoryExporterPanel)
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
bpy.utils.register_class(ARM_PT_ArmoryExporterAndroidSettingsPanel)
bpy.utils.register_class(ARM_PT_ArmoryExporterAndroidPermissionsPanel)
bpy.utils.register_class(ARM_PT_ArmoryExporterAndroidAbiPanel)
bpy.utils.register_class(ARM_PT_ArmoryExporterAndroidBuildAPKPanel)
bpy.utils.register_class(ARM_PT_ArmoryExporterHTML5SettingsPanel)
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
bpy.utils.register_class(ARM_PT_ArmoryExporterWindowsSettingsPanel)
bpy.utils.register_class(ARM_PT_ArmoryProjectPanel)
bpy.utils.register_class(ARM_PT_ProjectFlagsPanel)
bpy.utils.register_class(ARM_PT_ProjectFlagsDebugConsolePanel)
bpy.utils.register_class(ARM_PT_ProjectWindowPanel)
bpy.utils.register_class(ARM_PT_ProjectModulesPanel)
bpy.utils.register_class(ARM_PT_RenderPathPanel)
bpy.utils.register_class(ARM_PT_RenderPathRendererPanel)
bpy.utils.register_class(ARM_PT_RenderPathShadowsPanel)
bpy.utils.register_class(ARM_PT_RenderPathVoxelsPanel)
bpy.utils.register_class(ARM_PT_RenderPathWorldPanel)
bpy.utils.register_class(ARM_PT_RenderPathPostProcessPanel)
bpy.utils.register_class(ARM_PT_RenderPathCompositorPanel)
bpy.utils.register_class(ARM_PT_BakePanel)
2017-08-19 03:08:42 +02:00
# bpy.utils.register_class(ArmVirtualInputPanel)
2017-03-15 12:30:14 +01:00
bpy.utils.register_class(ArmoryPlayButton)
bpy.utils.register_class(ArmoryStopButton)
bpy.utils.register_class(ArmoryBuildProjectButton)
bpy.utils.register_class(ArmoryOpenProjectFolderButton)
bpy.utils.register_class(ArmoryOpenEditorButton)
2017-03-15 12:30:14 +01:00
bpy.utils.register_class(CleanMenu)
bpy.utils.register_class(CleanButtonMenu)
bpy.utils.register_class(ArmoryCleanProjectButton)
2017-09-04 12:14:14 +02:00
bpy.utils.register_class(ArmoryPublishProjectButton)
2017-08-19 12:10:06 +02:00
bpy.utils.register_class(ArmGenLodButton)
bpy.utils.register_class(ARM_PT_LodPanel)
2019-01-17 21:34:38 +01:00
bpy.utils.register_class(ArmGenTerrainButton)
bpy.utils.register_class(ARM_PT_TerrainPanel)
bpy.utils.register_class(ARM_PT_TilesheetPanel)
bpy.utils.register_class(ARM_PT_ProxyPanel)
2017-10-10 09:58:03 +02:00
bpy.utils.register_class(ArmMakeProxyButton)
2017-10-17 14:24:29 +02:00
bpy.utils.register_class(ArmProxyToggleAllButton)
2017-10-17 13:39:50 +02:00
bpy.utils.register_class(ArmProxyApplyAllButton)
bpy.utils.register_class(ArmSyncProxyButton)
2017-12-03 12:30:14 +01:00
bpy.utils.register_class(ArmPrintTraitsButton)
bpy.utils.register_class(ARM_PT_MaterialNodePanel)
bpy.utils.register_class(ARM_OT_UpdateFileSDK)
bpy.utils.register_class(ARM_OT_ShowFileVersionInfo)
bpy.utils.register_class(ARM_OT_ShowNodeUpdateErrors)
2020-08-10 00:23:26 +02:00
bpy.utils.register_class(ARM_OT_DiscardPopup)
bpy.utils.register_class(ArmoryUpdateListAndroidEmulatorButton)
bpy.utils.register_class(ArmoryUpdateListAndroidEmulatorRunButton)
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
bpy.utils.register_class(ArmoryUpdateListInstalledVSButton)
2020-08-10 00:23:26 +02:00
bpy.utils.register_class(scene.TLM_PT_Settings)
bpy.utils.register_class(scene.TLM_PT_Denoise)
bpy.utils.register_class(scene.TLM_PT_Filtering)
bpy.utils.register_class(scene.TLM_PT_Encoding)
bpy.utils.register_class(scene.TLM_PT_Utility)
bpy.utils.register_class(scene.TLM_PT_Additional)
2016-10-19 13:28:06 +02:00
bpy.types.VIEW3D_HT_header.append(draw_view3d_header)
2020-08-10 00:23:26 +02:00
bpy.types.VIEW3D_MT_object.append(draw_view3d_object_menu)
bpy.types.NODE_MT_context_menu.append(draw_custom_node_menu)
2020-08-10 00:23:26 +02:00
2016-10-19 13:28:06 +02:00
def unregister():
bpy.types.NODE_MT_context_menu.remove(draw_custom_node_menu)
2020-08-10 00:23:26 +02:00
bpy.types.VIEW3D_MT_object.remove(draw_view3d_object_menu)
2016-10-19 13:28:06 +02:00
bpy.types.VIEW3D_HT_header.remove(draw_view3d_header)
2020-11-16 19:55:15 +01:00
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
bpy.utils.unregister_class(ArmoryUpdateListInstalledVSButton)
bpy.utils.unregister_class(ArmoryUpdateListAndroidEmulatorRunButton)
bpy.utils.unregister_class(ArmoryUpdateListAndroidEmulatorButton)
2020-08-10 00:23:26 +02:00
bpy.utils.unregister_class(ARM_OT_DiscardPopup)
bpy.utils.unregister_class(ARM_OT_ShowNodeUpdateErrors)
bpy.utils.unregister_class(ARM_OT_ShowFileVersionInfo)
bpy.utils.unregister_class(ARM_OT_UpdateFileSDK)
bpy.utils.unregister_class(ARM_PT_ObjectPropsPanel)
bpy.utils.unregister_class(ARM_PT_ModifiersPropsPanel)
bpy.utils.unregister_class(ARM_PT_ParticlesPropsPanel)
bpy.utils.unregister_class(ARM_PT_PhysicsPropsPanel)
bpy.utils.unregister_class(ARM_PT_DataPropsPanel)
bpy.utils.unregister_class(ARM_PT_WorldPropsPanel)
bpy.utils.unregister_class(ARM_PT_ScenePropsPanel)
2017-03-15 12:30:14 +01:00
bpy.utils.unregister_class(InvalidateCacheButton)
bpy.utils.unregister_class(InvalidateMaterialCacheButton)
bpy.utils.unregister_class(ARM_OT_NewCustomMaterial)
2020-11-17 18:54:53 +01:00
bpy.utils.unregister_class(ARM_PT_MaterialDriverPropsPanel)
bpy.utils.unregister_class(ARM_PT_MaterialBlendingPropsPanel)
2020-11-17 18:54:53 +01:00
bpy.utils.unregister_class(ARM_PT_MaterialPropsPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryPlayerPanel)
Windows Settings – Publish and action after Windows Settings: Visual Studio Version - select the studio version for which the project will be exported. Options: 2010, 2012, 2013, 2015, 2017, 2019. Default: 2019. Update - checks the installed versions of Visual Studio on the PC and adds (installed) to the version in the list if available (for information). Example: sample_vs_2 Action After Publishing - select an action after a successful publication. Options: Nothing - do nothing. Default value; Open In Visual Studio - open the project in the corresponding studio version; Compile - compilation of the project; Compile and Run - compile and run the project. Then the executable file will be copied to the windows-hl folder (where the resources are located). Mode - compilation mode. Options: Debug, Release. Default: Debug. Architecture - the architecture for which the application will be built. Options: x86, x64. Default: version of the user’s PC architecture. Compile Log Parameter - setting the output of messages during compilation: Summary - show the error and warning summary at the end. Default value; No Summary - don \ 't show the error and warning summary at the end; Warnings and Errors Only - show only warnings and errors; Warnings Only - show only warnings; Errors Only - show only errors. More details can be found here - MSBuild command-line reference (I took only part of the settings). Count CPU - specifies the maximum number of concurrent processes to use when building. More details can be found here - MSBuild command-line reference. The default is 1. Maximum value: the number of CPUs in the system (function multiprocessing.cpu_count()). Open Build Directory - open the folder with the application after a successful build. If the Compile and Run option is selected, then the executable file will be copied to the windows-hl folder (where the resources are located) and this folder will open. Otherwise, the folder where the given Visual Studio file is going will open. The user will also receive a message if the studio version selected for export and for opening in the studio or compilation is not on the PC. And a list of installed ones will be issued. Example: Visual Studio 2017 (version 15) not found. The following are installed on the PC: - Visual Studio Community 2019 (version 16.8.30711.63) To obtain information about the installed versions of Visual Studio, use the vswhere.exe utility (open source) included in Kha (located in the …\ArmorySDK\Kha\Kinc\Tools\kincmake\Data\windows).
2020-11-24 18:41:50 +01:00
bpy.utils.unregister_class(ARM_PT_ArmoryExporterWindowsSettingsPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryExporterHTML5SettingsPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryExporterAndroidBuildAPKPanel)
Add Android Settings + LN Set Vibrate 1. For the new settings to fully function, you need to update the submodules so that this Pull Request (https://github.com/Kode/kincmake/pull/100) gets into armsdk. Extended settings via khafile.js. 2. Added Android Settings panel: - invisible until the target platform android-hl is added to the list; - inactive until the target platform android-hl is selected in the list. Options: - Orientation; - Compile Version SDK - from 26 to 30, default 29; - Minimal Version SDK - from 14 to 30, default 14; - Target Version SDK - from 26 to 30, default 29; - Permissions - a list of permissions. If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty; - Android ABI Filters - a list of platforms to build for (arm64-v8a, armeabi-v7a, x86, x86_64). If I will duplicate entries in the list, then only unique entries will be included during export. By default, the list is empty. If the list is empty, then all platforms will be used (as before). 3. The enum (names of permissions) and the function have been added to the utils.py modules, which adds the specified value to the list of permissions. Feature added for ease of use from different locations (different logical nodes). 4. List of permissions: - ACCESS_COARSE_LOCATION - Allows an app to access approximate location; - ACCESS_NETWORK_STATE - Allows applications to access information about networks; - ACCESS_FINE_LOCATION - Allows an app to access precise location; - ACCESS_WIFI_STATE - Allows applications to access information about Wi-Fi network; - BLUETOOTH - Allows applications to connect to paired bluetooth devices; - BLUETOOTH_ADMIN - Allows applications to discover and pair bluetooth devices; - CAMERA - Required to be able to access the camera device; - EXPAND_STATUS_BAR - Allows an application to expand or collapse the status bar; - FOREGROUND_SERVICE - Allows a regular application to use Service.startForeground; - GET_ACCOUNTS - Allows access to the list of accounts in the Accounts Service; - INTERNET - Allows applications to open network sockets'; - READ_EXTERNAL_STORAGE - Allows an application to read from external storage; - VIBRATE - Allows access to the vibrator; - WRITE_EXTERNAL_STORAGE - Allows an application to write to external storage. 5. Added logical node Set Vibrate: Category: Native Pulses the vibration hardware on the device for time in milliseconds, if such hardware exists. Input parameters: - Milliseconds - time in milliseconds (data type Int, default value 100). When adding the logical node Set Vibrate, the permission is automatically added to the list, even if the target android-hl has not been added to the export list (using a function from utils.py).
2020-10-17 15:47:54 +02:00
bpy.utils.unregister_class(ARM_PT_ArmoryExporterAndroidAbiPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryExporterAndroidPermissionsPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryExporterAndroidSettingsPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryExporterPanel)
bpy.utils.unregister_class(ARM_PT_ArmoryProjectPanel)
bpy.utils.unregister_class(ARM_PT_ProjectFlagsDebugConsolePanel)
bpy.utils.unregister_class(ARM_PT_ProjectFlagsPanel)
bpy.utils.unregister_class(ARM_PT_ProjectWindowPanel)
bpy.utils.unregister_class(ARM_PT_ProjectModulesPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathRendererPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathShadowsPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathVoxelsPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathWorldPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathPostProcessPanel)
bpy.utils.unregister_class(ARM_PT_RenderPathCompositorPanel)
bpy.utils.unregister_class(ARM_PT_BakePanel)
2017-08-19 03:08:42 +02:00
# bpy.utils.unregister_class(ArmVirtualInputPanel)
2017-03-15 12:30:14 +01:00
bpy.utils.unregister_class(ArmoryPlayButton)
bpy.utils.unregister_class(ArmoryStopButton)
bpy.utils.unregister_class(ArmoryBuildProjectButton)
bpy.utils.unregister_class(ArmoryOpenProjectFolderButton)
bpy.utils.unregister_class(ArmoryOpenEditorButton)
2017-03-15 12:30:14 +01:00
bpy.utils.unregister_class(CleanMenu)
bpy.utils.unregister_class(CleanButtonMenu)
bpy.utils.unregister_class(ArmoryCleanProjectButton)
2017-09-04 12:14:14 +02:00
bpy.utils.unregister_class(ArmoryPublishProjectButton)
2017-08-19 12:10:06 +02:00
bpy.utils.unregister_class(ArmGenLodButton)
bpy.utils.unregister_class(ARM_PT_LodPanel)
2019-01-17 21:34:38 +01:00
bpy.utils.unregister_class(ArmGenTerrainButton)
bpy.utils.unregister_class(ARM_PT_TerrainPanel)
bpy.utils.unregister_class(ARM_PT_TilesheetPanel)
bpy.utils.unregister_class(ARM_PT_ProxyPanel)
2017-10-10 09:58:03 +02:00
bpy.utils.unregister_class(ArmMakeProxyButton)
2017-10-17 14:24:29 +02:00
bpy.utils.unregister_class(ArmProxyToggleAllButton)
2017-10-17 13:39:50 +02:00
bpy.utils.unregister_class(ArmProxyApplyAllButton)
bpy.utils.unregister_class(ArmSyncProxyButton)
2017-12-03 12:30:14 +01:00
bpy.utils.unregister_class(ArmPrintTraitsButton)
bpy.utils.unregister_class(ARM_PT_MaterialNodePanel)
bpy.utils.unregister_class(scene.TLM_PT_Settings)
bpy.utils.unregister_class(scene.TLM_PT_Denoise)
bpy.utils.unregister_class(scene.TLM_PT_Filtering)
bpy.utils.unregister_class(scene.TLM_PT_Encoding)
bpy.utils.unregister_class(scene.TLM_PT_Utility)
bpy.utils.unregister_class(scene.TLM_PT_Additional)