Skip to content
Snippets Groups Projects
Commit 4f28fe78 authored by Bastien Montagne's avatar Bastien Montagne
Browse files

Fix typo (dimention > dimension), and cleanup the ugly windows EOL (grrrrr).

parent 8c41091b
No related branches found
No related tags found
No related merge requests found
# BEGIN GPL LICENSE BLOCK ##### # BEGIN GPL LICENSE BLOCK #####
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 # as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. # of the License, or (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation, # along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
# END GPL LICENSE BLOCK ##### # END GPL LICENSE BLOCK #####
bl_info = { bl_info = {
"name": "Auto Tile Size", "name": "Auto Tile Size",
"description": "Estimate and set the tile size that will render the fastest", "description": "Estimate and set the tile size that will render the fastest",
"author": "Greg Zaal", "author": "Greg Zaal",
"version": (3, 1), "version": (3, 1, 1),
"blender": (2, 74, 0), "blender": (2, 74, 0),
"location": "Render Settings > Performance", "location": "Render Settings > Performance",
"warning": "", "warning": "",
"wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Render/Auto_Tile_Size", "wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Render/Auto_Tile_Size",
"category": "Render", "category": "Render",
} }
import bpy import bpy
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
from math import ceil, floor, sqrt from math import ceil, floor, sqrt
SUPPORTED_RENDER_ENGINES = {'CYCLES', 'BLENDER_RENDER'} SUPPORTED_RENDER_ENGINES = {'CYCLES', 'BLENDER_RENDER'}
TILE_SIZES = ( TILE_SIZES = (
('16', "16", "16 x 16"), ('16', "16", "16 x 16"),
('32', "32", "32 x 32"), ('32', "32", "32 x 32"),
('64', "64", "64 x 64"), ('64', "64", "64 x 64"),
('128', "128", "128 x 128"), ('128', "128", "128 x 128"),
('256', "256", "256 x 256"), ('256', "256", "256 x 256"),
('512', "512", "512 x 512"), ('512', "512", "512 x 512"),
('1024', "1024", "1024 x 1024"), ('1024', "1024", "1024 x 1024"),
) )
def _update_tile_size(self, context): def _update_tile_size(self, context):
do_set_tile_size(context) do_set_tile_size(context)
class AutoTileSizeSettings(bpy.types.PropertyGroup): class AutoTileSizeSettings(bpy.types.PropertyGroup):
gpu_choice = bpy.props.EnumProperty( gpu_choice = bpy.props.EnumProperty(
name="Target GPU Tile Size", name="Target GPU Tile Size",
items=TILE_SIZES, items=TILE_SIZES,
default='256', default='256',
description="Square dimentions of tiles for GPU rendering", description="Square dimensions of tiles for GPU rendering",
update=_update_tile_size) update=_update_tile_size)
cpu_choice = bpy.props.EnumProperty( cpu_choice = bpy.props.EnumProperty(
name="Target CPU Tile Size", name="Target CPU Tile Size",
items=TILE_SIZES, items=TILE_SIZES,
default='32', default='32',
description="Square dimentions of tiles for CPU rendering", description="Square dimensions of tiles for CPU rendering",
update=_update_tile_size) update=_update_tile_size)
bi_choice = bpy.props.EnumProperty( bi_choice = bpy.props.EnumProperty(
name="Target CPU Tile Size", name="Target CPU Tile Size",
items=TILE_SIZES, items=TILE_SIZES,
default='64', default='64',
description="Square dimentions of tiles", description="Square dimensions of tiles",
update=_update_tile_size) update=_update_tile_size)
gpu_custom = bpy.props.IntProperty( gpu_custom = bpy.props.IntProperty(
name="Target Size", name="Target Size",
default=256, default=256,
min=8, # same as blender's own limits min=8, # same as blender's own limits
max=65536, max=65536,
description="Custom target tile size for GPU rendering", description="Custom target tile size for GPU rendering",
update=_update_tile_size) update=_update_tile_size)
cpu_custom = bpy.props.IntProperty( cpu_custom = bpy.props.IntProperty(
name="Target Size", name="Target Size",
default=32, default=32,
min=8, # same as blender's own limits min=8, # same as blender's own limits
max=65536, max=65536,
description="Custom target tile size for CPU rendering", description="Custom target tile size for CPU rendering",
update=_update_tile_size) update=_update_tile_size)
bi_custom = bpy.props.IntProperty( bi_custom = bpy.props.IntProperty(
name="Target Size", name="Target Size",
default=64, default=64,
min=8, # same as blender's own limits min=8, # same as blender's own limits
max=65536, max=65536,
description="Custom target tile size", description="Custom target tile size",
update=_update_tile_size) update=_update_tile_size)
target_type = bpy.props.EnumProperty( target_type = bpy.props.EnumProperty(
name="Target tile size", name="Target tile size",
items=( items=(
('po2', "Po2", "A choice between powers of 2 (16, 32, 64...)"), ('po2', "Po2", "A choice between powers of 2 (16, 32, 64...)"),
('custom', "Custom", "Choose any number as the tile size target")), ('custom', "Custom", "Choose any number as the tile size target")),
default='po2', default='po2',
description="Method of choosing the target tile size", description="Method of choosing the target tile size",
update=_update_tile_size) update=_update_tile_size)
use_optimal = bpy.props.BoolProperty( use_optimal = bpy.props.BoolProperty(
name="Optimal Tiles", name="Optimal Tiles",
default=True, default=True,
description="Try to find a similar tile size for best performance, instead of using exact selected one", description="Try to find a similar tile size for best performance, instead of using exact selected one",
update=_update_tile_size) update=_update_tile_size)
is_enabled = bpy.props.BoolProperty( is_enabled = bpy.props.BoolProperty(
name="Auto Tile Size", name="Auto Tile Size",
default=True, default=True,
description="Calculate the best tile size based on factors of the render size and the chosen target", description="Calculate the best tile size based on factors of the render size and the chosen target",
update=_update_tile_size) update=_update_tile_size)
use_advanced_ui = bpy.props.BoolProperty( use_advanced_ui = bpy.props.BoolProperty(
name="Advanced Settings", name="Advanced Settings",
default=False, default=False,
description="Show extra options for more control over the calculated tile size") description="Show extra options for more control over the calculated tile size")
thread_error_correct = bpy.props.BoolProperty( thread_error_correct = bpy.props.BoolProperty(
name="Fix", name="Fix",
default=True, default=True,
description="Reduce the tile size so that all your available threads are used", description="Reduce the tile size so that all your available threads are used",
update=_update_tile_size) update=_update_tile_size)
# Internally used props (not for GUI) # Internally used props (not for GUI)
first_run = bpy.props.BoolProperty(default=True, options={'HIDDEN'}) first_run = bpy.props.BoolProperty(default=True, options={'HIDDEN'})
threads_error = bpy.props.BoolProperty(options={'HIDDEN'}) threads_error = bpy.props.BoolProperty(options={'HIDDEN'})
num_tiles = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'}) num_tiles = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'})
prev_choice = bpy.props.StringProperty(default='', options={'HIDDEN'}) prev_choice = bpy.props.StringProperty(default='', options={'HIDDEN'})
prev_engine = bpy.props.StringProperty(default='', options={'HIDDEN'}) prev_engine = bpy.props.StringProperty(default='', options={'HIDDEN'})
prev_device = bpy.props.StringProperty(default='', options={'HIDDEN'}) prev_device = bpy.props.StringProperty(default='', options={'HIDDEN'})
prev_res = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'}) prev_res = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'})
prev_border = bpy.props.BoolProperty(default=False, options={'HIDDEN'}) prev_border = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
prev_border_res = bpy.props.FloatVectorProperty(default=(0, 0, 0, 0), size=4, options={'HIDDEN'}) prev_border_res = bpy.props.FloatVectorProperty(default=(0, 0, 0, 0), size=4, options={'HIDDEN'})
prev_actual_tile_size = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'}) prev_actual_tile_size = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'})
prev_threads = bpy.props.IntProperty(default=0, options={'HIDDEN'}) prev_threads = bpy.props.IntProperty(default=0, options={'HIDDEN'})
def ats_poll(context): def ats_poll(context):
scene = context.scene scene = context.scene
if scene.render.engine not in SUPPORTED_RENDER_ENGINES or not scene.ats_settings.is_enabled: if scene.render.engine not in SUPPORTED_RENDER_ENGINES or not scene.ats_settings.is_enabled:
return False return False
return True return True
def engine_is_gpu(engine, device, userpref): def engine_is_gpu(engine, device, userpref):
return engine == 'CYCLES' and device == 'GPU' and userpref.system.compute_device_type != 'NONE' return engine == 'CYCLES' and device == 'GPU' and userpref.system.compute_device_type != 'NONE'
def get_tilesize_prop(engine, device, userpref): def get_tilesize_prop(engine, device, userpref):
target_type = "_choice" if bpy.context.scene.ats_settings.target_type == 'po2' else "_custom" target_type = "_choice" if bpy.context.scene.ats_settings.target_type == 'po2' else "_custom"
if engine_is_gpu(engine, device, userpref): if engine_is_gpu(engine, device, userpref):
return ("gpu" + target_type) return ("gpu" + target_type)
elif engine == 'CYCLES': elif engine == 'CYCLES':
return ("cpu" + target_type) return ("cpu" + target_type)
return ("bi" + target_type) return ("bi" + target_type)
@persistent @persistent
def on_scene_update(scene): def on_scene_update(scene):
context = bpy.context context = bpy.context
if not ats_poll(context): if not ats_poll(context):
return return
userpref = context.user_preferences userpref = context.user_preferences
settings = scene.ats_settings settings = scene.ats_settings
render = scene.render render = scene.render
engine = render.engine engine = render.engine
# scene.cycles might not always exist (Cycles is an addon)... # scene.cycles might not always exist (Cycles is an addon)...
device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
border = render.use_border border = render.use_border
threads = get_threads(context, device) threads = get_threads(context, device)
choice = getattr(settings, get_tilesize_prop(engine, device, userpref)) choice = getattr(settings, get_tilesize_prop(engine, device, userpref))
res = get_actual_res(render) res = get_actual_res(render)
actual_ts = (render.tile_x, render.tile_y) actual_ts = (render.tile_x, render.tile_y)
border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y) border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y)
# detect relevant changes in scene # detect relevant changes in scene
do_change = (engine != settings.prev_engine or do_change = (engine != settings.prev_engine or
device != settings.prev_device or device != settings.prev_device or
border != settings.prev_border or border != settings.prev_border or
threads != settings.prev_threads or threads != settings.prev_threads or
str(choice) != settings.prev_choice or str(choice) != settings.prev_choice or
res != settings.prev_res[:] or res != settings.prev_res[:] or
border_res != settings.prev_border_res[:] or border_res != settings.prev_border_res[:] or
actual_ts != settings.prev_actual_tile_size[:]) actual_ts != settings.prev_actual_tile_size[:])
if do_change: if do_change:
do_set_tile_size(context) do_set_tile_size(context)
def get_actual_res(render): def get_actual_res(render):
rend_percent = render.resolution_percentage * 0.01 rend_percent = render.resolution_percentage * 0.01
# floor is implicitly done by int conversion... # floor is implicitly done by int conversion...
return (int(render.resolution_x * rend_percent), int(render.resolution_y * rend_percent)) return (int(render.resolution_x * rend_percent), int(render.resolution_y * rend_percent))
def get_threads(context, device): def get_threads(context, device):
render = context.scene.render render = context.scene.render
engine = render.engine engine = render.engine
userpref = context.user_preferences userpref = context.user_preferences
if engine_is_gpu(engine, device, userpref): if engine_is_gpu(engine, device, userpref):
gpu_device_str = userpref.system.compute_device gpu_device_str = userpref.system.compute_device
if 'MULTI' in gpu_device_str: if 'MULTI' in gpu_device_str:
threads = int(gpu_device_str.split('_')[-1]) threads = int(gpu_device_str.split('_')[-1])
else: else:
threads = 1 threads = 1
else: else:
threads = render.threads threads = render.threads
return threads return threads
def max_tile_size(threads, xres, yres): def max_tile_size(threads, xres, yres):
''' Give the largest tile size that will still use all threads ''' ''' Give the largest tile size that will still use all threads '''
render_area = xres * yres render_area = xres * yres
tile_area = render_area / threads tile_area = render_area / threads
tile_length = sqrt(tile_area) tile_length = sqrt(tile_area)
# lists: num x tiles, num y tiles, squareness, total tiles # lists: num x tiles, num y tiles, squareness, total tiles
perfect_attempts = [] # attempts with correct number of tiles perfect_attempts = [] # attempts with correct number of tiles
attempts = [] # all attempts, even if incorrect number of tiles attempts = [] # all attempts, even if incorrect number of tiles
axes = [xres, yres] axes = [xres, yres]
funcs = [floor, ceil] funcs = [floor, ceil]
for axis in axes: for axis in axes:
sec_axis = yres if axis == xres else xres sec_axis = yres if axis == xres else xres
for func in funcs: for func in funcs:
primary = func(axis / tile_length) primary = func(axis / tile_length)
if primary > 0: if primary > 0:
secondary = threads / primary secondary = threads / primary
ts_p = axis/primary ts_p = axis/primary
ts_s = sec_axis/secondary ts_s = sec_axis/secondary
squareness = max(ts_p, ts_s) - min(ts_p, ts_s) squareness = max(ts_p, ts_s) - min(ts_p, ts_s)
attempt = [primary if axis == xres else secondary, primary if axis != xres else secondary, squareness, primary * secondary] attempt = [primary if axis == xres else secondary, primary if axis != xres else secondary, squareness, primary * secondary]
if attempt not in attempts: if attempt not in attempts:
attempts.append(attempt) attempts.append(attempt)
if secondary.is_integer(): # will only be an integer if there are the right number of tiles if secondary.is_integer(): # will only be an integer if there are the right number of tiles
perfect_attempts.append(attempt) perfect_attempts.append(attempt)
if perfect_attempts: # prefer to use attempt that has exactly the right number of tiles if perfect_attempts: # prefer to use attempt that has exactly the right number of tiles
attempts = perfect_attempts attempts = perfect_attempts
attempt = sorted(attempts, key=lambda k: k[2])[0] # pick set with most square tiles attempt = sorted(attempts, key=lambda k: k[2])[0] # pick set with most square tiles
numtiles_x = round(attempt[0]) numtiles_x = round(attempt[0])
numtiles_y = round(attempt[1]) numtiles_y = round(attempt[1])
tile_x = ceil(xres / numtiles_x) tile_x = ceil(xres / numtiles_x)
tile_y = ceil(yres / numtiles_y) tile_y = ceil(yres / numtiles_y)
return (tile_x, tile_y) return (tile_x, tile_y)
def do_set_tile_size(context): def do_set_tile_size(context):
if not ats_poll(context): if not ats_poll(context):
return False return False
scene = context.scene scene = context.scene
userpref = context.user_preferences userpref = context.user_preferences
settings = scene.ats_settings settings = scene.ats_settings
render = scene.render render = scene.render
engine = render.engine engine = render.engine
device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
border = render.use_border border = render.use_border
realxres, realyres = xres, yres = res = get_actual_res(scene.render) realxres, realyres = xres, yres = res = get_actual_res(scene.render)
if border: if border:
xres = round(xres * (render.border_max_x - render.border_min_x)) xres = round(xres * (render.border_max_x - render.border_min_x))
yres = round(yres * (render.border_max_y - render.border_min_y)) yres = round(yres * (render.border_max_y - render.border_min_y))
choice = getattr(settings, get_tilesize_prop(engine, device, userpref)) choice = getattr(settings, get_tilesize_prop(engine, device, userpref))
target = int(choice) target = int(choice)
numtiles_x = ceil(xres / target) numtiles_x = ceil(xres / target)
numtiles_y = ceil(yres / target) numtiles_y = ceil(yres / target)
settings.num_tiles = (numtiles_x, numtiles_y) settings.num_tiles = (numtiles_x, numtiles_y)
if settings.use_optimal: if settings.use_optimal:
tile_x = ceil(xres / numtiles_x) tile_x = ceil(xres / numtiles_x)
tile_y = ceil(yres / numtiles_y) tile_y = ceil(yres / numtiles_y)
else: else:
tile_x = target tile_x = target
tile_y = target tile_y = target
# Print tile size (for debug purposes) # Print tile size (for debug purposes)
# print("Tile size: %dx%d (%dx%d tiles)" % (tile_x, tile_y, ceil(xres / tile_x), ceil(yres / tile_y))) # print("Tile size: %dx%d (%dx%d tiles)" % (tile_x, tile_y, ceil(xres / tile_x), ceil(yres / tile_y)))
# Detect if there are fewer tiles than available threads # Detect if there are fewer tiles than available threads
threads = get_threads(context, device) threads = get_threads(context, device)
if ((numtiles_x * numtiles_y) < threads): if ((numtiles_x * numtiles_y) < threads):
settings.threads_error = True settings.threads_error = True
if settings.thread_error_correct: if settings.thread_error_correct:
tile_x, tile_y = max_tile_size(threads, xres, yres) tile_x, tile_y = max_tile_size(threads, xres, yres)
settings.num_tiles = (ceil(xres/tile_x), ceil(yres/tile_y)) settings.num_tiles = (ceil(xres/tile_x), ceil(yres/tile_y))
else: else:
settings.threads_error = False settings.threads_error = False
# Make sure tile sizes are within the internal limit # Make sure tile sizes are within the internal limit
tile_x = max(8, tile_x) tile_x = max(8, tile_x)
tile_y = max(8, tile_y) tile_y = max(8, tile_y)
tile_x = min(65536, tile_x) tile_x = min(65536, tile_x)
tile_y = min(65536, tile_y) tile_y = min(65536, tile_y)
render.tile_x = tile_x render.tile_x = tile_x
render.tile_y = tile_y render.tile_y = tile_y
settings.prev_engine = engine
settings.prev_engine = engine settings.prev_device = device
settings.prev_device = device settings.prev_border = border
settings.prev_border = border settings.prev_threads = threads
settings.prev_threads = threads settings.prev_choice = str(choice)
settings.prev_choice = str(choice) settings.prev_res = res
settings.prev_res = res settings.prev_border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y)
settings.prev_border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y) settings.prev_actual_tile_size = (tile_x, tile_y)
settings.prev_actual_tile_size = (tile_x, tile_y) settings.first_run = False
settings.first_run = False
return True
return True
class SetTileSize(bpy.types.Operator):
class SetTileSize(bpy.types.Operator): """The first render may not obey the tile-size set here"""
"""The first render may not obey the tile-size set here""" bl_idname = "render.autotilesize_set"
bl_idname = "render.autotilesize_set" bl_label = "Set"
bl_label = "Set"
@classmethod
@classmethod def poll(clss, context):
def poll(clss, context): return ats_poll(context)
return ats_poll(context)
def execute(self, context):
def execute(self, context): if do_set_tile_size(context):
if do_set_tile_size(context): return {'FINISHED'}
return {'FINISHED'} return {'CANCELLED'}
return {'CANCELLED'}
# ##### INTERFACE #####
# ##### INTERFACE #####
def ui_layout(engine, layout, context):
def ui_layout(engine, layout, context): scene = context.scene
scene = context.scene userpref = context.user_preferences
userpref = context.user_preferences
settings = scene.ats_settings
settings = scene.ats_settings render = scene.render
render = scene.render engine = render.engine
engine = render.engine device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
col = layout.column(align=True)
col = layout.column(align=True) sub = col.column(align=True)
sub = col.column(align=True) row = sub.row(align=True)
row = sub.row(align=True) row.prop(settings, "is_enabled", toggle=True)
row.prop(settings, "is_enabled", toggle=True) row.prop(settings, "use_advanced_ui", toggle=True, text="", icon='PREFERENCES')
row.prop(settings, "use_advanced_ui", toggle=True, text="", icon='PREFERENCES')
sub = col.column(align=False)
sub = col.column(align=False) sub.enabled = settings.is_enabled
sub.enabled = settings.is_enabled
if settings.use_advanced_ui:
if settings.use_advanced_ui: row = sub.row(align=True)
row = sub.row(align=True) row.label("Target tile size:")
row.label("Target tile size:") row.separator()
row.separator() row.prop(settings, "target_type", expand=True)
row.prop(settings, "target_type", expand=True)
row = sub.row(align=True)
row = sub.row(align=True) row.prop(settings, get_tilesize_prop(engine, device, userpref), expand=True)
row.prop(settings, get_tilesize_prop(engine, device, userpref), expand=True) sub.prop(settings, "use_optimal", text="Calculate Optimal Size")
sub.prop(settings, "use_optimal", text="Calculate Optimal Size")
sub.label("Number of tiles: %s x %s (Total: %s)" % (settings.num_tiles[0], settings.num_tiles[1], settings.num_tiles[0] * settings.num_tiles[1]))
sub.label("Number of tiles: %s x %s (Total: %s)" % (settings.num_tiles[0], settings.num_tiles[1], settings.num_tiles[0] * settings.num_tiles[1]))
if settings.first_run:
if settings.first_run: sub = layout.column(align=True)
sub = layout.column(align=True) sub.operator("render.autotilesize_set", text="First-render fix", icon='ERROR')
sub.operator("render.autotilesize_set", text="First-render fix", icon='ERROR') elif settings.prev_device != device:
elif settings.prev_device != device: sub = layout.column(align=True)
sub = layout.column(align=True) sub.operator("render.autotilesize_set", text="Device changed - fix", icon='ERROR')
sub.operator("render.autotilesize_set", text="Device changed - fix", icon='ERROR')
if (render.tile_x / render.tile_y > 2) or (render.tile_x / render.tile_y < 0.5): # if not very square tile
if (render.tile_x / render.tile_y > 2) or (render.tile_x / render.tile_y < 0.5): # if not very square tile sub.label(text="Warning: Tile size is not very square", icon='ERROR')
sub.label(text="Warning: Tile size is not very square", icon='ERROR') sub.label(text=" Try a slightly different resolution")
sub.label(text=" Try a slightly different resolution") if settings.threads_error:
if settings.threads_error: row = sub.row(align=True)
row = sub.row(align=True) row.alignment = 'CENTER'
row.alignment = 'CENTER' row.label(text="Warning: Fewer tiles than threads", icon='ERROR')
row.label(text="Warning: Fewer tiles than threads", icon='ERROR') row.prop(settings, 'thread_error_correct')
row.prop(settings, 'thread_error_correct')
def menu_func_cycles(self, context):
def menu_func_cycles(self, context): ui_layout('CYCLES', self.layout, context)
ui_layout('CYCLES', self.layout, context)
def menu_func_bi(self, context):
def menu_func_bi(self, context): ui_layout('BLENDER_RENDER', self.layout, context)
ui_layout('BLENDER_RENDER', self.layout, context)
# ##### REGISTRATION #####
# ##### REGISTRATION #####
def register():
def register(): bpy.utils.register_module(__name__)
bpy.utils.register_module(__name__)
bpy.types.Scene.ats_settings = bpy.props.PointerProperty(type=AutoTileSizeSettings)
bpy.types.Scene.ats_settings = bpy.props.PointerProperty(type=AutoTileSizeSettings)
# Note, the Cycles addon must be registered first, otherwise this panel doesn't exist - better be safe here!
# Note, the Cycles addon must be registered first, otherwise this panel doesn't exist - better be safe here! cycles_panel = getattr(bpy.types, "CyclesRender_PT_performance", None)
cycles_panel = getattr(bpy.types, "CyclesRender_PT_performance", None) if cycles_panel is not None:
if cycles_panel is not None: cycles_panel.append(menu_func_cycles)
cycles_panel.append(menu_func_cycles)
bpy.types.RENDER_PT_performance.append(menu_func_bi)
bpy.types.RENDER_PT_performance.append(menu_func_bi) bpy.app.handlers.scene_update_post.append(on_scene_update)
bpy.app.handlers.scene_update_post.append(on_scene_update)
def unregister():
def unregister(): bpy.app.handlers.scene_update_post.remove(on_scene_update)
bpy.app.handlers.scene_update_post.remove(on_scene_update) bpy.types.RENDER_PT_performance.remove(menu_func_bi)
bpy.types.RENDER_PT_performance.remove(menu_func_bi)
cycles_panel = getattr(bpy.types, "CyclesRender_PT_performance", None)
cycles_panel = getattr(bpy.types, "CyclesRender_PT_performance", None) if cycles_panel is not None:
if cycles_panel is not None: cycles_panel.remove(menu_func_cycles)
cycles_panel.remove(menu_func_cycles)
del bpy.types.Scene.ats_settings
del bpy.types.Scene.ats_settings
bpy.utils.unregister_module(__name__)
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
if __name__ == "__main__": register()
register()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment