Fix playblast with api changes

2.0.0

- fix: error using playblast (api changes of Blender 3.0+)
gpv2
Pullusb 2022-03-24 14:41:32 +01:00
parent f36b31e3aa
commit bf60370ab0
4 changed files with 101 additions and 36 deletions

View File

@ -1,5 +1,9 @@
# Changelog
2.0.0
- fix: error using playblast (api changes of Blender 3.0+)
1.9.9
- fix: Bug setting GP layers actions on/off

View File

@ -40,6 +40,8 @@ exclude = (
'audio_bitrate',
]
"""
'''
def render_with_restore():
class RenderFileRestorer:
rd = bpy.context.scene.render
@ -80,8 +82,47 @@ def render_with_restore():
return RenderFileRestorer()
'''
class render_with_restore:
def __init__(self):
rd = bpy.context.scene.render
im = rd.image_settings
ff = rd.ffmpeg
# ffmpeg (ff) need to be before image_settings(im) in list
# otherwise __exit__ may try to restore settings of image mode in video mode !
# ex : "RGBA" not found in ('BW', 'RGB') (will still not stop thx to try block)
self.zones = [rd, ff, im]
self.val_dic = {}
self.cam = bpy.context.scene.camera
def __enter__(self):
## store attribute of data_path in self.zones list.
for data_path in self.zones:
self.val_dic[data_path] = {}
for attr in dir(data_path):#iterate in attribute of given datapath
if attr not in exclude and not attr.startswith('__') and not callable(getattr(data_path, attr)) and not data_path.is_property_readonly(attr):
self.val_dic[data_path][attr] = getattr(data_path, attr)
if self.cam and self.cam.name == 'draw_cam':
if self.cam.parent:
bpy.context.scene.camera = self.cam.parent
def __exit__(self, type, value, traceback):
## restore attribute from self.zones list
for data_path, prop_dic in self.val_dic.items():
for attr, val in prop_dic.items():
try:
setattr(data_path, attr, val)
except Exception as e:
print(f"/!\ Impossible to re-assign: {attr} = {val}")
print(e)
if self.cam:
bpy.context.scene.camera = self.cam
def playblast(viewport = False, stamping = True):
scn = bpy.context.scene
res_factor = scn.gptoolprops.resolution_percentage
@ -91,15 +132,15 @@ def playblast(viewport = False, stamping = True):
### can add propeties for personalisation as toolsetting props
rd.resolution_percentage = res_factor
while ( rd.resolution_x * res_factor / 100 ) % 2 != 0:# rd.resolution_percentage
while ( rd.resolution_x * res_factor / 100 ) % 2 != 0: # rd.resolution_percentage
rd.resolution_x = rd.resolution_x + 1
while ( rd.resolution_y * res_factor / 100 ) % 2 != 0:# rd.resolution_percentage
rd.resolution_y = rd.resolution_y + 1
while ( rd.resolution_y * res_factor / 100 ) % 2 != 0: # rd.resolution_percentage
rd.resolution_y = rd.resolution_y + 1
rd.image_settings.file_format = 'FFMPEG'
ff.format = 'MPEG4'
ff.codec = 'H264'
ff.constant_rate_factor = 'HIGH'# MEDIUM
ff.constant_rate_factor = 'HIGH' # MEDIUM
ff.ffmpeg_preset = 'REALTIME'
ff.gopsize = 10
ff.audio_codec = 'AAC'
@ -116,13 +157,13 @@ def playblast(viewport = False, stamping = True):
# mode incermental or just use fulldate (cannot create conflict and filter OK but long name)
blend = Path(bpy.data.filepath)
date_format = "%Y-%m-%d_%H-%M-%S"
fp = join(blend.parent, "images", f'playblast_{blend.stem}_{strftime(date_format)}.mp4')
fp = join(blend.parent, "playblast", f'playblast_{blend.stem}_{strftime(date_format)}.mp4')
#may need a properties for choosing location : bpy.types.Scene.qrd_savepath = bpy.props.StringProperty(subtype='DIR_PATH', description="Export location, if not specify, create a 'quick_render' directory aside blend location")#(change defaut name in user_prefernece)
rd.filepath = fp
rd.use_stamp = stamping# toolsetting.use_stamp# True for playblast
#stamp options
rd.stamp_font_size = rd.stamp_font_size * res_factor / 100# rd.resolution_percentage
rd.stamp_font_size = int(rd.stamp_font_size * res_factor / 100) # rd.resolution_percentage
# bpy.ops.render.render_wrap(use_view=viewport)
### render

View File

@ -21,15 +21,20 @@ exclude = (
'bl_rna', 'identifier','name_property','rna_type','properties', 'compare', 'to_string',#basic
)
def delete_file(filepath) :
try:
if os.path.isfile(filepath) :
print('removing', filepath)
os.remove(filepath)
def delete_file(filepath):
fp = Path(filepath)
if fp.exists() and fp.is_file():
try:
print('removing', fp)
fp.unlink(missing_ok=False)
# os.remove(fp)
return True
except PermissionError:
print(f'impossible to remove {filepath}')
return False
except PermissionError:
print(f'impossible to remove (permission error): {fp}')
return False
except FileNotFoundError:
print(f'Impossible to remove (file not found error): {fp}')
return False
# render function
def render_function(cmd, total_frame, scene) :
@ -58,7 +63,7 @@ def render_function(cmd, total_frame, scene) :
frame_count += 1
try :
# print('frame_count: ', frame_count, 'total_frame: ', total_frame)
bpy.context.window_manager.pblast_completion = frame_count / total_frame * 100
bpy.context.window_manager.pblast_completion = int(frame_count / total_frame * 100)
except AttributeError :
#debug
if debug : print("AttributeError avoided")
@ -231,9 +236,7 @@ class BGBLAST_OT_playblast_modal_check(bpy.types.Operator):
self.report({'INFO'}, "Render Finished")
### classic sauce
"""
def render_with_restore():
class RenderFileRestorer:
rd = bpy.context.scene.render
@ -266,6 +269,38 @@ def render_with_restore():
print(e)
return RenderFileRestorer()
"""
class render_with_restore:
def __init__(self):
rd = bpy.context.scene.render
im = rd.image_settings
ff = rd.ffmpeg
# ffmpeg (ff) need to be before image_settings(im) in list
# otherwise __exit__ may try to restore settings of image mode in video mode !
# ex : "RGBA" not found in ('BW', 'RGB') (will still not stop thx to try block)
self.zones = [rd, ff, im]
self.val_dic = {}
def __enter__(self):
## store attribute of data_path in self.zones list.
for data_path in self.zones:
self.val_dic[data_path] = {}
for attr in dir(data_path):#iterate in attribute of given datapath
if attr not in exclude and not attr.startswith('__') and not callable(getattr(data_path, attr)) and not data_path.is_property_readonly(attr):
self.val_dic[data_path][attr] = getattr(data_path, attr)
def __exit__(self, type, value, traceback):
## restore attribute from self.zones list
for data_path, prop_dic in self.val_dic.items():
for attr, val in prop_dic.items():
try:
setattr(data_path, attr, val)
except Exception as e:
print(f"/!\ Impossible to re-assign: {attr} = {val}")
print(e)
def playblast(context, viewport = False, stamping = True):
@ -325,7 +360,7 @@ def playblast(context, viewport = False, stamping = True):
rd.filepath = fp
rd.use_stamp = stamping# toolsetting.use_stamp# True for playblast
#stamp options
rd.stamp_font_size = rd.stamp_font_size * res_factor / 100# rd.resolution_percentage
rd.stamp_font_size = int(rd.stamp_font_size * res_factor / 100) # rd.resolution_percentage
# get total number of frames

View File

@ -1,21 +1,10 @@
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# SPDX-License-Identifier: GPL-2.0-or-later
bl_info = {
"name": "GP toolbox",
"description": "Tool set for Grease Pencil in animation production",
"author": "Samuel Bernou, Christophe Seux",
"version": (1, 9, 9),
"version": (2, 0, 0),
"blender": (2, 91, 0),
"location": "Sidebar (N menu) > Gpencil > Toolbox / Gpencil properties",
"warning": "",
@ -24,14 +13,10 @@ bl_info = {
"category": "3D View",
}
# from . import addon_updater_ops
# from .utils import *
from pathlib import Path
from shutil import which
from sys import modules
from .utils import get_addon_prefs, draw_kmi
# from .functions import *
## GMIC
from .GP_guided_colorize import GP_colorize