1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
20 "name": "Render to Print",
21 "author": "Marco Crippa <thekrypt77@tiscali.it>, Dealga McArdle, zebus3d",
23 "blender": (2, 80, 0),
24 "location": "Output > Render to Print",
25 "description": "Set the size of the render for a print",
26 "doc_url": "http://wiki.blender.org/index.php/Extensions:2.6/"
27 "Py/Scripts/Render/Render to Print",
28 "tracker_url": "https://developer.blender.org/maniphest/task/edit/form/2/",
35 from bpy
.types
import Panel
, Operator
, Scene
, PropertyGroup
36 from bpy
.props
import (
46 ("custom_1_1", "custom", ""),
47 ("A0_84.1_118.9", "A0 (84.1x118.9 cm)", ""),
48 ("A1_59.4_84.1", "A1 (59.4x84.1 cm)", ""),
49 ("A2_42.0_59.4", "A2 (42.0x59.4 cm)", ""),
50 ("A3_29.7_42.0", "A3 (29.7 42.0 cm)", ""),
51 ("A4_21.0_29.7", "A4 (21.0x29.7 cm)", ""),
52 ("A5_14.8_21.0", "A5 (14.8x21.0 cm)", ""),
53 ("A6_10.5_14.8", "A6 (10.5x14.8 cm)", ""),
54 ("A7_7.4_10.5", "A7 (7.4x10.5 cm)", ""),
55 ("A8_5.2_7.4", "A8 (5.2x7.4 cm)", ""),
56 ("A9_3.7_5.2", "A9 (3.7x5.2 cm)", ""),
57 ("A10_2.6_3.7", "A10 (2.6x3.7 cm)", ""),
59 ("B0_100.0_141.4", "B0 (100.0x141.4 cm)", ""),
60 ("B1_70.7_100.0", "B1 (70.7x100.0 cm)", ""),
61 ("B2_50.0_70.7", "B2 (50.0x70.7 cm)", ""),
62 ("B3_35.3_50.0", "B3 (35.3x50.0 cm)", ""),
63 ("B4_25.0_35.3", "B4 (25.0x35.3 cm)", ""),
64 ("B5_17.6_25.0", "B5 (17.6x25.0 cm)", ""),
65 ("B6_12.5_17.6", "B6 (12.5x17.6 cm)", ""),
66 ("B7_8.8_12.5", "B7 (8.8x12.5 cm)", ""),
67 ("B8_6.2_8.8", "B8 (6.2x8.8 cm)", ""),
68 ("B9_4.4_6.2", "B9 (4.4x6.2 cm)", ""),
69 ("B10_3.1_4.4", "B10 (3.1x4.4 cm)", ""),
71 ("C0_91.7_129.7", "C0 (91.7x129.7 cm)", ""),
72 ("C1_64.8_91.7", "C1 (64.8x91.7 cm)", ""),
73 ("C2_45.8_64.8", "C2 (45.8x64.8 cm)", ""),
74 ("C3_32.4_45.8", "C3 (32.4x45.8 cm)", ""),
75 ("C4_22.9_32.4", "C4 (22.9x32.4 cm)", ""),
76 ("C5_16.2_22.9", "C5 (16.2x22.9 cm)", ""),
77 ("C6_11.4_16.2", "C6 (11.4x16.2 cm)", ""),
78 ("C7_8.1_11.4", "C7 (8.1x11.4 cm)", ""),
79 ("C8_5.7_8.1", "C8 (5.7x8.1 cm)", ""),
80 ("C9_4.0_5.7", "C9 (4.0x5.7 cm)", ""),
81 ("C10_2.8_4.0", "C10 (2.8x4.0 cm)", ""),
83 ("Letter_21.6_27.9", "Letter (21.6x27.9 cm)", ""),
84 ("Legal_21.6_35.6", "Legal (21.6x35.6 cm)", ""),
85 ("Legal junior_20.3_12.7", "Legal junior (20.3x12.7 cm)", ""),
86 ("Ledger_43.2_27.9", "Ledger (43.2x27.9 cm)", ""),
87 ("Tabloid_27.9_43.2", "Tabloid (27.9x43.2 cm)", ""),
89 ("ANSI C_43.2_55.9", "ANSI C (43.2x55.9 cm)", ""),
90 ("ANSI D_55.9_86.4", "ANSI D (55.9x86.4 cm)", ""),
91 ("ANSI E_86.4_111.8", "ANSI E (86.4x111.8 cm)", ""),
93 ("Arch A_22.9_30.5", "Arch A (22.9x30.5 cm)", ""),
94 ("Arch B_30.5_45.7", "Arch B (30.5x45.7 cm)", ""),
95 ("Arch C_45.7_61.0", "Arch C (45.7x61.0 cm)", ""),
96 ("Arch D_61.0_91.4", "Arch D (61.0x91.4 cm)", ""),
97 ("Arch E_91.4_121.9", "Arch E (91.4x121.9 cm)", ""),
98 ("Arch E1_76.2_106.7", "Arch E1 (76.2x106.7 cm)", ""),
99 ("Arch E2_66.0_96.5", "Arch E2 (66.0x96.5 cm)", ""),
100 ("Arch E3_68.6_99.1", "Arch E3 (68.6x99.1 cm)", ""),
104 def paper_enum_parse(idname
):
105 tipo
, dim_w
, dim_h
= idname
.split("_")
106 return tipo
, float(dim_w
), float(dim_h
)
109 paper_presets_data
= {
110 idname
: paper_enum_parse(idname
)
111 for idname
, name
, descr
in paper_presets
115 def update_settings_cb(self
, context
):
116 # annoying workaround for recursive call
117 if update_settings_cb
.level
is False:
118 update_settings_cb
.level
= True
119 pixels_from_print(self
)
120 update_settings_cb
.level
= False
122 update_settings_cb
.level
= False
125 class RenderPrintSertings(PropertyGroup
):
126 unit_from
: EnumProperty(
128 description
="Set from",
130 ("CM_TO_PIXELS", "CM -> Pixel", "Centermeters to Pixels"),
131 ("PIXELS_TO_CM", "Pixel -> CM", "Pixels to Centermeters")
133 default
="CM_TO_PIXELS",
135 orientation
: EnumProperty(
136 name
="Page Orientation",
137 description
="Set orientation",
139 ("Portrait", "Portrait", "Portrait"),
140 ("Landscape", "Landscape", "Landscape")
143 update
=update_settings_cb
,
145 preset
: EnumProperty(
146 name
="Select Preset",
147 description
="Select from preset",
149 default
="custom_1_1",
150 update
=update_settings_cb
,
154 description
="Dots per Inch",
157 update
=update_settings_cb
,
159 width_cm
: FloatProperty(
161 description
="Width in CM",
163 min=1.0, max=100000.0,
164 update
=update_settings_cb
,
166 height_cm
: FloatProperty(
168 description
="Height in CM",
170 min=1.0, max=100000.0,
171 update
=update_settings_cb
,
173 width_px
: IntProperty(
175 description
="Pixel Width",
178 update
=update_settings_cb
,
180 height_px
: IntProperty(
182 description
="Pixel Height",
185 update
=update_settings_cb
,
189 def pixels_from_print(ps
):
190 tipo
, dim_w
, dim_h
= paper_presets_data
[ps
.preset
]
192 if ps
.unit_from
== "CM_TO_PIXELS":
198 elif tipo
!= "custom" and ps
.orientation
== "Landscape":
201 elif tipo
!= "custom" and ps
.orientation
== "Portrait":
205 ps
.width_px
= math
.ceil((ps
.width_cm
* ps
.dpi
) / 2.54)
206 ps
.height_px
= math
.ceil((ps
.height_cm
* ps
.dpi
) / 2.54)
208 if tipo
!= "custom" and ps
.orientation
== "Landscape":
211 ps
.width_px
= math
.ceil((ps
.width_cm
* ps
.dpi
) / 2.54)
212 ps
.height_px
= math
.ceil((ps
.height_cm
* ps
.dpi
) / 2.54)
213 elif tipo
!= "custom" and ps
.orientation
== "Portrait":
216 ps
.width_px
= math
.ceil((ps
.width_cm
* ps
.dpi
) / 2.54)
217 ps
.height_px
= math
.ceil((ps
.height_cm
* ps
.dpi
) / 2.54)
219 ps
.width_cm
= (ps
.width_px
/ ps
.dpi
) * 2.54
220 ps
.height_cm
= (ps
.height_px
/ ps
.dpi
) * 2.54
223 class RENDER_PT_print(Panel
):
224 bl_label
= "Render to Print"
225 bl_space_type
= 'PROPERTIES'
226 bl_region_type
= 'WINDOW'
227 bl_context
= "output"
228 bl_options
= {'DEFAULT_CLOSED'}
230 def draw(self
, context
):
233 scene
= context
.scene
234 ps
= scene
.print_settings
236 row
= layout
.row(align
=True)
237 row1
= layout
.row(align
=True)
238 row2
= layout
.row(align
=True)
239 row3
= layout
.row(align
=True)
240 row4
= layout
.row(align
=True)
241 row5
= layout
.row(align
=True)
242 row6
= layout
.row(align
=True)
243 row7
= layout
.row(align
=True)
244 col
= layout
.column(align
=True)
246 row
.prop(ps
, "unit_from")
247 row1
.prop(ps
, "orientation")
248 row2
.prop(ps
, "preset")
251 row3
.prop(ps
, "width_cm")
253 row3
.prop(ps
, "height_cm")
257 row5
.prop(ps
, "width_px")
259 row5
.prop(ps
, "height_px")
262 row6
.label(text
="Inch Width: %.2f" % (ps
.width_cm
/ 2.54))
263 row6
.label(text
="Inch Height: %.2f" % (ps
.height_cm
/ 2.54))
266 row7
.operator("render.apply_size", icon
="RENDER_STILL")
268 # this if else deals with hiding UI elements when logic demands it.
269 tipo
= paper_presets_data
[ps
.preset
][0]
275 if ps
.unit_from
== "CM_TO_PIXELS":
284 elif tipo
!= "custom" and ps
.orientation
== "Landscape":
289 elif tipo
!= "custom" and ps
.orientation
== "Portrait":
301 elif tipo
!= "custom" and ps
.orientation
== "Landscape":
306 elif tipo
!= "custom" and ps
.orientation
== "Portrait":
313 class RENDER_OT_apply_size(Operator
):
314 bl_idname
= "render.apply_size"
315 bl_label
= "Apply Print to Render"
316 bl_description
= "Set the render dimension"
318 def execute(self
, context
):
320 scene
= context
.scene
321 ps
= scene
.print_settings
323 pixels_from_print(ps
)
325 render
= scene
.render
326 render
.resolution_x
= ps
.width_px
327 render
.resolution_y
= ps
.height_px
333 RENDER_OT_apply_size
,
339 from bpy
.utils
import register_class
344 Scene
.print_settings
= PointerProperty(type=RenderPrintSertings
)
348 from bpy
.utils
import unregister_class
351 unregister_class(cls
)
353 del Scene
.print_settings
356 if __name__
== "__main__":