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