added a 40s timeout on frame analisys

0.5.7

- added: timeout on scene plit and autocrop border to avoid freezing blender
- ui: minor correction
main
Pullusb 2021-10-13 19:00:15 +02:00
parent 64695a042f
commit 20ab99889d
6 changed files with 38 additions and 8 deletions

View File

@ -14,6 +14,11 @@ Activate / deactivate layer opaticty according to prefix
Activate / deactivate all masks using MA layers Activate / deactivate all masks using MA layers
--> -->
0.5.7
- added: timeout on scene plit and autocrop border to avoid freezing blender
- ui: minor correction
0.5.6 0.5.6
- feat: `check layers` new `clear frame out of range` option (Disabled by default) - feat: `check layers` new `clear frame out of range` option (Disabled by default)

View File

@ -93,7 +93,7 @@ class GPEXP_OT_add_objects_to_render(bpy.types.Operator):
class GPEXP_OT_split_to_scene(bpy.types.Operator): class GPEXP_OT_split_to_scene(bpy.types.Operator):
bl_idname = "gp.split_to_scene" bl_idname = "gp.split_to_scene"
bl_label = "Split Objects To Scene" bl_label = "Split Objects To Scene"
bl_description = "Take selected objects and send them to separate scene" bl_description = "Take selected objects and send them to separate scene\n(new scene is named after active object)"
bl_options = {"REGISTER"} bl_options = {"REGISTER"}
@classmethod @classmethod
@ -103,7 +103,10 @@ class GPEXP_OT_split_to_scene(bpy.types.Operator):
mode : bpy.props.StringProperty(default='ALL', options={'SKIP_SAVE'}) mode : bpy.props.StringProperty(default='ALL', options={'SKIP_SAVE'})
def execute(self, context): def execute(self, context):
fn.split_object_to_scene() err = fn.split_object_to_scene()
if err:
self.report({'ERROR'}, err)
return {"CANCELLED"}
return {"FINISHED"} return {"FINISHED"}

View File

@ -13,7 +13,11 @@ class GPEXP_OT_set_crop_from_selection(bpy.types.Operator):
def execute(self, context): def execute(self, context):
scn = context.scene scn = context.scene
fn.set_box_from_selected_objects(scn=scn, cam=scn.camera) err = fn.set_box_from_selected_objects(scn=scn, cam=scn.camera)
if err:
self.report({'ERROR'}, err)
return {"CANCELLED"}
scn.render.use_border = True scn.render.use_border = True
scn.render.use_crop_to_border = True scn.render.use_crop_to_border = True
return {"FINISHED"} return {"FINISHED"}

View File

@ -2,7 +2,7 @@ bl_info = {
"name": "GP Render", "name": "GP Render",
"description": "Organise export of gp layers through compositor output", "description": "Organise export of gp layers through compositor output",
"author": "Samuel Bernou", "author": "Samuel Bernou",
"version": (0, 5, 6), "version": (0, 5, 7),
"blender": (2, 93, 0), "blender": (2, 93, 0),
"location": "View3D", "location": "View3D",
"warning": "", "warning": "",

22
fn.py
View File

@ -803,7 +803,10 @@ def export_crop_to_json():
return coord_dic return coord_dic
def set_border_region_from_coord(coords, scn=None, margin=30, export_json=True): def set_border_region_from_coord(coords, scn=None, margin=30, export_json=True):
'''Get a list of point coord in worldcamera view space (0 to 1) on each axis''' '''Get a list of point coord in worldcamera view space (0 to 1) on each axis
set border (of passed scene :scn: ) with given coordinate
return the coords list as pixel coordinate
'''
scn = scn or bpy.context.scene scn = scn or bpy.context.scene
@ -883,14 +886,16 @@ def has_anim(ob):
# TODO make a better check (check if there is only one key in each channel, count as not animated) # TODO make a better check (check if there is only one key in each channel, count as not animated)
return ob.animation_data and ob.animation_data.action return ob.animation_data and ob.animation_data.action
def get_gp_box_all_frame_selection(oblist=None, scn=None, cam=None): def get_gp_box_all_frame_selection(oblist=None, scn=None, cam=None, timeout=40):
''' '''
get points of all selection get points of all selection
return 2d bbox in pixels return 2d bbox in pixels
return None if timeout (too long to process, better to do it visually)
''' '''
from bpy_extras.object_utils import world_to_camera_view from bpy_extras.object_utils import world_to_camera_view
t0 = time()
coords_cam_list = [] coords_cam_list = []
scn = scn or bpy.context.scene scn = scn or bpy.context.scene
oblist = oblist or [o for o in scn.objects if o.select_get()] oblist = oblist or [o for o in scn.objects if o.select_get()]
@ -912,6 +917,10 @@ def get_gp_box_all_frame_selection(oblist=None, scn=None, cam=None):
if len(s.points) == 1: # skip isolated points if len(s.points) == 1: # skip isolated points
continue continue
coords_cam_list += [world_to_camera_view(scn, cam, ob.matrix_world @ p.co) for p in s.points] coords_cam_list += [world_to_camera_view(scn, cam, ob.matrix_world @ p.co) for p in s.points]
if time() - t0 > timeout:
print(f'timeout (more than {timeout}s to calculate) evaluating frame position of objects {oblist}')
return
else: else:
print(f'No anim') print(f'No anim')
for ob in oblist: for ob in oblist:
@ -920,12 +929,16 @@ def get_gp_box_all_frame_selection(oblist=None, scn=None, cam=None):
if l.hide or l.opacity == 0.0: if l.hide or l.opacity == 0.0:
continue continue
for f in l.frames: for f in l.frames:
if time() - t0 > timeout:
print(f'timeout (more than {timeout}s to calculate) evaluating frame position of objects {oblist}')
return
if not (scn.frame_start <= f.frame_number <= scn.frame_end): if not (scn.frame_start <= f.frame_number <= scn.frame_end):
continue continue
for s in f.strokes: for s in f.strokes:
if len(s.points) == 1: # skip isolated points if len(s.points) == 1: # skip isolated points
continue continue
coords_cam_list += [world_to_camera_view(scn, cam, ob.matrix_world @ p.co) for p in s.points] coords_cam_list += [world_to_camera_view(scn, cam, ob.matrix_world @ p.co) for p in s.points]
print(f'{len(coords_cam_list)} gp points listed {time() - start:.1f}s') print(f'{len(coords_cam_list)} gp points listed {time() - start:.1f}s')
return coords_cam_list return coords_cam_list
@ -954,6 +967,9 @@ def set_box_from_selected_objects(scn=None, cam=None, export_json=False):
selection = [o for o in scn.objects if o.select_get()] # selected_objects selection = [o for o in scn.objects if o.select_get()] # selected_objects
coords = get_gp_box_all_frame_selection(oblist=selection, scn=scn, cam=cam) coords = get_gp_box_all_frame_selection(oblist=selection, scn=scn, cam=cam)
if not coords:
return f'Border not set: Timeout during analysis of {len(selection)} objects'
_bbox_px = set_border_region_from_coord(coords, margin=30, scn=scn, export_json=export_json) _bbox_px = set_border_region_from_coord(coords, margin=30, scn=scn, export_json=export_json)
@ -1032,6 +1048,8 @@ def split_object_to_scene():
# border to GP objects of the scene # border to GP objects of the scene
gp_objs = [o for o in new.objects if o.type == 'GPENCIL'] gp_objs = [o for o in new.objects if o.type == 'GPENCIL']
coords = get_gp_box_all_frame_selection(oblist=gp_objs, scn=new, cam=new.camera) coords = get_gp_box_all_frame_selection(oblist=gp_objs, scn=new, cam=new.camera)
if not coords:
return f'Scene "{scene_name}" created. But Border was not set (Timeout during GP analysis), should be done by hand if needed then use export crop to json'
set_border_region_from_coord(coords, margin=30, scn=new, export_json=True) set_border_region_from_coord(coords, margin=30, scn=new, export_json=True)
export_crop_to_json() export_crop_to_json()

4
ui.py
View File

@ -130,10 +130,10 @@ class GPEXP_PT_gp_node_ui(Panel):
layout.separator() layout.separator()
layout.label(text='Sub Scenes:') layout.label(text='Sub Scenes:')
layout.operator('gp.split_to_scene', icon='DUPLICATE', text='Split To Scene') layout.operator('gp.split_to_scene', icon='DUPLICATE', text='Split Selected Obj To Scene')
row = layout.row(align=True) row = layout.row(align=True)
row.operator('gp.set_crop_from_selection', icon='CON_OBJECTSOLVER', text='Set Crop') row.operator('gp.set_crop_from_selection', icon='CON_OBJECTSOLVER', text='Autoset Crop')
row.operator('gp.export_crop_coord_to_json', icon='FILE', text='Export json') row.operator('gp.export_crop_coord_to_json', icon='FILE', text='Export json')
layout.operator('gp.render_all_scenes', icon='RENDER_ANIMATION', text='Render All Sub-Scene') layout.operator('gp.render_all_scenes', icon='RENDER_ANIMATION', text='Render All Sub-Scene')