diff --git a/CHANGELOG.md b/CHANGELOG.md index 74e3c2b..71ca392 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ Activate / deactivate layer opacity according to prefix Activate / deactivate all masks using MA layers --> +1.5.0 + +- added: swf export (include binary for linux and windows) +- added: pdf single multipage file exports + + 1.4.1 - added: expose button for output file de-numbering diff --git a/OP_render_pdf.py b/OP_render_pdf.py index 01704e2..53d39d3 100644 --- a/OP_render_pdf.py +++ b/OP_render_pdf.py @@ -1,4 +1,6 @@ import bpy +import sys +import subprocess from . import fn from pathlib import Path from itertools import groupby @@ -71,9 +73,36 @@ def export_all_selected_frame_as_svg(): print('Done') -def pdf_render(fp): +def pdf_render(fp, multi_page=False): + '''Render a sequence of pdf and return path to folder + or render a multipage pdf (in place of parent folder) and return path to file + ''' scn = bpy.context.scene + + if multi_page: + ## Set folder name (when using sequence) as output with pdf extension + fp = fp.parent + fp.parent.mkdir(parents=True, exist_ok=True) # mode=0o777 + + if multi_page: + ## In case of sequence path: + ## Remove padding separator (or add scene range: "0100-0230" ?) + # fp = fp.with_stem(fp.stem.rstrip('-_. ')) # strip typical padding separator + + fp = fp.with_suffix('.pdf') + + # print('Exporting multi-page pdf at: ', fp) + bpy.ops.wm.gpencil_export_pdf(filepath=str(fp), + check_existing=False, # True by default + use_fill=True, + selected_object_type='ACTIVE', # VISIBLE, SELECTED + stroke_sample=0, + use_normalized_thickness=False, + frame_mode='SCENE') + return fp + + ## Sequence for fnum in range(scn.frame_start, scn.frame_end + 1): # print('fnum: ', fnum) scn.frame_current = fnum @@ -92,6 +121,107 @@ def pdf_render(fp): stroke_sample=0, use_normalized_thickness=False, frame_mode='ACTIVE') + return fp.parent + +def swf_render(fp): + ''' + Render as pdf then convert to swf using pdf2swf + + -h , --help Print short help message and exit + -V , --version Print version info and exit + -o , --output file.swf Direct output to file.swf. If file.swf contains '%' (file%.swf), then each page goes to a separate file. + -p , --pages range Convert only pages in range with range e.g. 1-20 or 1,4,6,9-11 or + -P , --password password Use password for deciphering the pdf. + -v , --verbose Be verbose. Use more than one -v for greater effect. + -z , --zlib Use Flash 6 (MX) zlib compression. + -i , --ignore Allows pdf2swf to change the draw order of the pdf. This may make the generated + -j , --jpegquality quality Set quality of embedded jpeg pictures to quality. 0 is worst (small), 100 is best (big). (default:85) + -s , --set param=value Set a SWF encoder specific parameter. See pdf2swf -s help for more information. + -w , --samewindow When converting pdf hyperlinks, don't make the links open a new window. + -t , --stop Insert a stop() command in each page. + -T , --flashversion num Set Flash Version in the SWF header to num. + -F , --fontdir directory Add directory to the font search path. + -b , --defaultviewer Link a standard viewer to the swf file. + -l , --defaultloader Link a standard preloader to the swf file which will be displayed while the main swf is loading. + -B , --viewer filename Link viewer filename to the swf file. + -L , --preloader filename Link preloader filename to the swf file. + -q , --quiet Suppress normal messages. Use -qq to suppress warnings, also. + -S , --shapes Don't use SWF Fonts, but store everything as shape. + -f , --fonts Store full fonts in SWF. (Don't reduce to used characters). + -G , --flatten Remove as many clip layers from file as possible. + -I , --info Don't do actual conversion, just display a list of all pages in the PDF. + -Q , --maxtime n Abort conversion after n seconds. Only available on Unix. + + ##with -s arg: + PDF Parameters: + + PDF device global parameters: + fontdir= a directory with additional fonts + font= an additional font filename + pages= the range of pages to convert (example: pages=1-100,210-) + zoom= the resultion (default: 72) + languagedir= Add an xpdf language directory + multiply= Render everything at the resolution + poly2bitmap Convert graphics to bitmaps + bitmap Convert everything to bitmaps + SWF Parameters: + + SWF layer options: + jpegsubpixels= resolution adjustment for jpeg images (same as jpegdpi, but in pixels) + ppmsubpixels= shortcut for setting both jpegsubpixels and ppmsubpixels + drawonlyshapes convert everything to shapes (currently broken) + ignoredraworder allow to perform a few optimizations for creating smaller SWFs + linksopennewwindow make links open a new browser window + linktarget target window name of new links + linkcolor==6) + bboxvars store the bounding box of the SWF file in actionscript variables + dots Take care to handle dots correctly + reordertags=0/1 (default: 1) perform some tag optimizations + internallinkfunction= when the user clicks a internal link (to a different page) in the converted file, this actionscript function is called + externallinkfunction= when the user clicks an external link (e.g. http://www.foo.bar/) on the converted file, this actionscript function is called + disable_polygon_conversion never convert strokes to polygons (will remove capstyles and joint styles) + caplinewidth= the minimum thichness a line needs to have so that capstyles become visible (and are converted) + insertstop put an ActionScript "STOP" tag in every frame + protect add a "protect" tag to the file, to prevent loading in the Flash editor + flashversion= the SWF fileversion (6) + framerate= SWF framerate + minlinewidth= convert horizontal/vertical boxes smaller than this width to lines (0.05) + simpleviewer Add next/previous buttons to the SWF + animate insert a showframe tag after each placeobject (animate draw order of PDF files) + jpegquality= set compression quality of jpeg images + splinequality= Set the quality of spline convertion to value (0-100, default: 100). + disablelinks Disable links. + ''' + + # Convert pdf to swf + if sys.platform == 'linux': + binary = Path(__file__).parent / 'bin' / 'linux' / 'pdf2swf' + elif sys.platform.startswith('win'): + binary = Path(__file__).parent / 'bin' / 'windows' / 'pdf2swf.exe' + else: + print('Render to SWF is only supported on mat and linux') + return + + pdf_fp = pdf_render(fp, multi_page=True) + + swf_fp = pdf_fp.with_suffix('.swf') + cmd = [ + str(binary), + '-s', f'framerate={bpy.context.scene.render.fps}', + # -z, # use zlib + str(pdf_fp), + # '-o', # no need to put output flag + str(swf_fp) + ] + subprocess.call(cmd) + + # Remove single pdf file + pdf_fp.unlink() + return swf_fp class GPEXP_OT_export_as_pdf(bpy.types.Operator): bl_idname = "gp.export_as_pdf" @@ -103,6 +233,17 @@ class GPEXP_OT_export_as_pdf(bpy.types.Operator): def poll(cls, context): return True + # multi_page : bpy.props.BoolProperty(name='multi page pdf', default=False) + export_type : bpy.props.StringProperty(name='Export Type', default='pdf_sequence') + + @classmethod + def description(cls, context, properties) -> str: + if properties.export_type == 'pdf': + return 'Export layers as individual pdf file (multi-page) using scene range' + elif properties.export_type == 'pdf_sequence': + return 'Export layers as sequence of single-paged pdf file, using scene range' + return 'Export layers as individual SWF files, using scene range' + def execute(self, context): # rd_scn = bpy.data.scenes.get('Render') # if not rd_scn: @@ -228,6 +369,7 @@ class GPEXP_OT_export_as_pdf(bpy.types.Operator): # fo_socket.name isn't right idx = [i for i in fo_node.inputs].index(fo_socket) + subpath = fo_node.file_slots[idx].path fp = Path(fo_node.base_path.rstrip('/')) / subpath fp = Path(bpy.path.abspath(str(fp)).rstrip("/")) @@ -242,7 +384,14 @@ class GPEXP_OT_export_as_pdf(bpy.types.Operator): if not l.hide: print(f'-> {l.info}') #Dbg - pdf_render(fp) + if self.export_type == 'pdf_sequence': + pdf_render(fp, multi_page=False) + elif self.export_type == 'pdf': + ## TODO: change fp to parent and adapt in pdf render ? + pdf_render(fp, multi_page=self.multi_page) + elif self.export_type == 'swf': + swf_render(fp) + print() ### restore diff --git a/__init__.py b/__init__.py index 2387d40..61d2fb0 100644 --- a/__init__.py +++ b/__init__.py @@ -2,7 +2,7 @@ bl_info = { "name": "GP Render", "description": "Organise export of gp layers through compositor output", "author": "Samuel Bernou", - "version": (1, 4, 1), + "version": (1, 5, 0), "blender": (3, 0, 0), "location": "View3D", "warning": "", diff --git a/bin/linux/pdf2swf b/bin/linux/pdf2swf new file mode 100644 index 0000000..1b7fa9a Binary files /dev/null and b/bin/linux/pdf2swf differ diff --git a/bin/windows/pdf2swf.exe b/bin/windows/pdf2swf.exe new file mode 100644 index 0000000..f0a1f7c Binary files /dev/null and b/bin/windows/pdf2swf.exe differ diff --git a/ui.py b/ui.py index 20b5664..3d73acf 100644 --- a/ui.py +++ b/ui.py @@ -249,11 +249,17 @@ class GPEXP_PT_gp_dopesheet_ui(Panel): layout.prop(bpy.context.preferences.edit, 'use_anim_channel_group_colors') layout.separator() + + # row.operator('gp.export_as_pdf', icon='RENDER_STILL', text='Render All to PDF Sequences') + layout.label(text='Render All To Vector:') + col= layout.column() + row = col.row(align=True) + row.operator('gp.export_as_pdf', icon='RENDER_STILL', text='PDF Sequences').export_type = 'pdf_sequence' + row.operator('gp.export_as_pdf', icon='RENDER_STILL', text='PDF File').export_type = 'pdf' + col.operator('gp.export_as_pdf', icon='RENDER_STILL', text='SWF File').export_type = 'swf' - row = layout.row() - row.operator('gp.export_as_pdf', icon='RENDER_STILL', text='Render All to PDF Sequences') if bpy.app.version < (3,0,0): - row.label(text='Not Blender 3.0.0+') + col.label(text='Not Blender 3.0.0+ !') ## Append GP Render workspace (usefull for user with disabled 'load_UI') if not bpy.data.workspaces.get('GP Render'):