Sun Position: fix error in HDRI mode when no env tex is selected
[blender-addons.git] / measureit / measureit_render.py
blob093149d5cfc7774bebf14e5ad5a20e281f2dbdf7
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 # ----------------------------------------------------------
4 # support routines for render measures in final image
5 # Author: Antonio Vazquez (antonioya)
7 # ----------------------------------------------------------
8 # noinspection PyUnresolvedReferences
9 import bpy
10 import gpu
11 # noinspection PyUnresolvedReferences
12 import blf
13 from os import path, remove
14 from sys import exc_info
15 # noinspection PyUnresolvedReferences
16 import bpy_extras.image_utils as img_utils
17 # noinspection PyUnresolvedReferences
18 import bpy_extras.object_utils as object_utils
19 # noinspection PyUnresolvedReferences
20 from bpy_extras import view3d_utils
21 from math import ceil
22 from .measureit_geometry import *
25 # -------------------------------------------------------------
26 # Render image main entry point
28 # -------------------------------------------------------------
29 def render_main(self, context, animation=False):
30 # Save old info
31 settings = bpy.context.scene.render.image_settings
32 depth = settings.color_depth
33 settings.color_depth = '8'
35 # Get object list
36 scene = context.scene
37 objlist = context.scene.objects
38 # --------------------
39 # Get resolution
40 # --------------------
41 render_scale = scene.render.resolution_percentage / 100
42 width = int(scene.render.resolution_x * render_scale)
43 height = int(scene.render.resolution_y * render_scale)
45 # --------------------------------------
46 # Loop to draw all lines in Offsecreen
47 # --------------------------------------
48 offscreen = gpu.types.GPUOffScreen(width, height)
49 view_matrix = Matrix([
50 [2 / width, 0, 0, -1],
51 [0, 2 / height, 0, -1],
52 [0, 0, 1, 0],
53 [0, 0, 0, 1]])
55 with offscreen.bind():
56 fb = gpu.state.active_framebuffer_get()
57 fb.clear(color=(0.0, 0.0, 0.0, 0.0))
58 gpu.matrix.reset()
59 gpu.matrix.load_matrix(view_matrix)
60 gpu.matrix.load_projection_matrix(Matrix.Identity(4))
62 # -----------------------------
63 # Loop to draw all objects
64 # -----------------------------
65 for myobj in objlist:
66 if myobj.visible_get() is True:
67 if 'MeasureGenerator' in myobj:
68 op = myobj.MeasureGenerator[0]
69 draw_segments(context, myobj, op, None, None)
70 # -----------------------------
71 # Loop to draw all debug
72 # -----------------------------
73 if scene.measureit_debug is True:
74 selobj = bpy.context.selected_objects
75 for myobj in selobj:
76 if scene.measureit_debug_objects is True:
77 draw_object(context, myobj, None, None)
78 elif scene.measureit_debug_object_loc is True:
79 draw_object(context, myobj, None, None)
80 if scene.measureit_debug_vertices is True:
81 draw_vertices(context, myobj, None, None)
82 elif scene.measureit_debug_vert_loc is True:
83 draw_vertices(context, myobj, None, None)
84 if scene.measureit_debug_edges is True:
85 draw_edges(context, myobj, None, None)
86 if scene.measureit_debug_faces is True or scene.measureit_debug_normals is True:
87 draw_faces(context, myobj, None, None)
88 # -----------------------------
89 # Draw a rectangle frame
90 # -----------------------------
91 if scene.measureit_rf is True:
92 rfcolor = scene.measureit_rf_color
93 rfborder = scene.measureit_rf_border
94 rfline = scene.measureit_rf_line
96 imm_set_line_width(rfline)
97 x1 = rfborder
98 x2 = width - rfborder
99 y1 = int(ceil(rfborder / (width / height)))
100 y2 = height - y1
101 draw_rectangle((x1, y1), (x2, y2), rfcolor)
103 buffer = fb.read_color(0, 0, width, height, 4, 0, 'UBYTE')
104 buffer.dimensions = width * height * 4
106 offscreen.free()
108 # -----------------------------
109 # Create image
110 # -----------------------------
111 image_name = "measureit_output"
112 if not image_name in bpy.data.images:
113 bpy.data.images.new(image_name, width, height)
115 image = bpy.data.images[image_name]
116 image.scale(width, height)
117 image.pixels = [v / 255 for v in buffer]
119 # Saves image
120 if image is not None and (scene.measureit_render is True or animation is True):
121 ren_path = bpy.context.scene.render.filepath
122 filename = "mit_frame"
123 if len(ren_path) > 0:
124 if ren_path.endswith(path.sep):
125 initpath = path.realpath(ren_path) + path.sep
126 else:
127 (initpath, filename) = path.split(ren_path)
129 ftxt = "%04d" % scene.frame_current
130 outpath = path.realpath(path.join(initpath, filename + ftxt + ".png"))
131 save_image(self, outpath, image)
133 # restore default value
134 settings.color_depth = depth
137 # -------------------------------------
138 # Save image to file
139 # -------------------------------------
140 def save_image(self, filepath, myimage):
141 # noinspection PyBroadException
142 try:
144 # Save old info
145 settings = bpy.context.scene.render.image_settings
146 myformat = settings.file_format
147 mode = settings.color_mode
148 depth = settings.color_depth
150 # Apply new info and save
151 settings.file_format = 'PNG'
152 settings.color_mode = "RGBA"
153 settings.color_depth = '8'
154 myimage.save_render(filepath)
155 print("MeasureIt: Image " + filepath + " saved")
157 # Restore old info
158 settings.file_format = myformat
159 settings.color_mode = mode
160 settings.color_depth = depth
161 except:
162 print("Unexpected error:" + str(exc_info()))
163 self.report({'ERROR'}, "MeasureIt: Unable to save render image")
164 return