diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-03-05 04:32:28 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-03-05 04:32:28 +0300 |
commit | aec5a36c12a3ec1d068adb8270017e509087dff6 (patch) | |
tree | dcc0408cf538f1fb39a41dd84c775342863b8a32 /object_carver/carver_draw.py | |
parent | 353492b181e08663b8cd3bc5733920b6fcdbcbe4 (diff) |
Cleanup: tabs -> spaces
Diffstat (limited to 'object_carver/carver_draw.py')
-rw-r--r-- | object_carver/carver_draw.py | 940 |
1 files changed, 470 insertions, 470 deletions
diff --git a/object_carver/carver_draw.py b/object_carver/carver_draw.py index 922807ee..f2a3aadc 100644 --- a/object_carver/carver_draw.py +++ b/object_carver/carver_draw.py @@ -6,494 +6,494 @@ import numpy as np import gpu from gpu_extras.batch import batch_for_shader from math import( - cos, - sin, - ceil, - floor, - ) + cos, + sin, + ceil, + floor, + ) from bpy_extras.view3d_utils import ( - region_2d_to_location_3d, - location_3d_to_region_2d, + region_2d_to_location_3d, + location_3d_to_region_2d, ) from .carver_utils import ( - draw_circle, - draw_shader, - objDiagonal, - mini_grid, - ) + draw_circle, + draw_shader, + objDiagonal, + mini_grid, + ) from mathutils import ( - Color, - Euler, - Vector, - Quaternion, + Color, + Euler, + Vector, + Quaternion, ) def get_text_info(self, context, help_txt): - """ Return the dimensions of each part of the text """ + """ Return the dimensions of each part of the text """ - #Extract the longest first option in sublist - max_option = max(list(blf.dimensions(0, row[0])[0] for row in help_txt)) + #Extract the longest first option in sublist + max_option = max(list(blf.dimensions(0, row[0])[0] for row in help_txt)) - #Extract the longest key in sublist - max_key = max(list(blf.dimensions(0, row[1])[0] for row in help_txt)) + #Extract the longest key in sublist + max_key = max(list(blf.dimensions(0, row[1])[0] for row in help_txt)) - #Space between option and key with a comma separator (" : ") - comma = blf.dimensions(0, "_:_")[0] + #Space between option and key with a comma separator (" : ") + comma = blf.dimensions(0, "_:_")[0] - #Get a default height for all the letters - line_height = (blf.dimensions(0, "gM")[1] * 1.45) + #Get a default height for all the letters + line_height = (blf.dimensions(0, "gM")[1] * 1.45) - #Get the total height of the text - bloc_height = 0 - for row in help_txt: - bloc_height += line_height + #Get the total height of the text + bloc_height = 0 + for row in help_txt: + bloc_height += line_height - return(help_txt, bloc_height, max_option, max_key, comma) + return(help_txt, bloc_height, max_option, max_key, comma) def draw_string(self, color1, color2, left, bottom, text, max_option, divide = 1): - """ Draw the text like 'option : key' or just 'option' """ - - font_id = 0 - ui_scale = bpy.context.preferences.system.ui_scale - - blf.enable(font_id,blf.SHADOW) - blf.shadow(font_id, 0, 0.0, 0.0, 0.0, 1.0) - blf.shadow_offset(font_id,2,-2) - line_height = (blf.dimensions(font_id, "gM")[1] * 1.45) - y_offset = 5 - - # Test if the text is a list formatted like : ('option', 'key') - if isinstance(text,list): - spacer_text = " : " - spacer_width = blf.dimensions(font_id, spacer_text)[0] - for string in text: - blf.position(font_id, (left), (bottom + y_offset), 0) - blf.color(font_id, *color1) - blf.draw(font_id, string[0]) - blf.position(font_id, (left + max_option), (bottom + y_offset), 0) - blf.draw(font_id, spacer_text) - blf.color(font_id, *color2) - blf.position(font_id, (left + max_option + spacer_width), (bottom + y_offset), 0) - blf.draw(font_id, string[1]) - y_offset += line_height - else: - # The text is formatted like : ('option') - blf.position(font_id, left, (bottom + y_offset), 0) - blf.color(font_id, *color1) - blf.draw(font_id, text) - y_offset += line_height - - blf.disable(font_id,blf.SHADOW) + """ Draw the text like 'option : key' or just 'option' """ + + font_id = 0 + ui_scale = bpy.context.preferences.system.ui_scale + + blf.enable(font_id,blf.SHADOW) + blf.shadow(font_id, 0, 0.0, 0.0, 0.0, 1.0) + blf.shadow_offset(font_id,2,-2) + line_height = (blf.dimensions(font_id, "gM")[1] * 1.45) + y_offset = 5 + + # Test if the text is a list formatted like : ('option', 'key') + if isinstance(text,list): + spacer_text = " : " + spacer_width = blf.dimensions(font_id, spacer_text)[0] + for string in text: + blf.position(font_id, (left), (bottom + y_offset), 0) + blf.color(font_id, *color1) + blf.draw(font_id, string[0]) + blf.position(font_id, (left + max_option), (bottom + y_offset), 0) + blf.draw(font_id, spacer_text) + blf.color(font_id, *color2) + blf.position(font_id, (left + max_option + spacer_width), (bottom + y_offset), 0) + blf.draw(font_id, string[1]) + y_offset += line_height + else: + # The text is formatted like : ('option') + blf.position(font_id, left, (bottom + y_offset), 0) + blf.color(font_id, *color1) + blf.draw(font_id, text) + y_offset += line_height + + blf.disable(font_id,blf.SHADOW) # Opengl draw on screen def draw_callback_px(self, context): - font_id = 0 - region = context.region - UIColor = (0.992, 0.5518, 0.0, 1.0) - - # Cut Type - RECTANGLE = 0 - LINE = 1 - CIRCLE = 2 - self.carver_prefs = context.preferences.addons[__package__].preferences - - # Color - color1 = (1.0, 1.0, 1.0, 1.0) - color2 = UIColor - - #The mouse is outside the active region - if not self.in_view_3d: - color1 = color2 = (1.0, 0.2, 0.1, 1.0) - - # Primitives type - PrimitiveType = "Rectangle" - if self.CutType == CIRCLE: - PrimitiveType = "Circle" - if self.CutType == LINE: - PrimitiveType = "Line" - - # Width screen - overlap = context.preferences.system.use_region_overlap - - t_panel_width = 0 - if overlap: - for region in context.area.regions: - if region.type == 'TOOLS': - t_panel_width = region.width - - # Initial position - region_width = int(region.width / 2.0) - y_txt = 10 - - - # Draw the center command from bottom to top - - # Get the size of the text - text_size = 18 if region.width >= 850 else 12 - ui_scale = bpy.context.preferences.system.ui_scale - blf.size(0, round(text_size * ui_scale), 72) - - # Help Display - if (self.ObjectMode is False) and (self.ProfileMode is False): - - # Depth Cursor - TypeStr = "Cursor Depth [" + self.carver_prefs.Key_Depth + "]" - BoolStr = "(ON)" if self.snapCursor else "(OFF)" - help_txt = [[TypeStr, BoolStr]] - - # Close poygonal shape - if self.CreateMode and self.CutType == LINE: - TypeStr = "Close [" + self.carver_prefs.Key_Close + "]" - BoolStr = "(ON)" if self.Closed else "(OFF)" - help_txt += [[TypeStr, BoolStr]] - - if self.CreateMode is False: - # Apply Booleans - TypeStr = "Apply Operations [" + self.carver_prefs.Key_Apply + "]" - BoolStr = "(OFF)" if self.dont_apply_boolean else "(ON)" - help_txt += [[TypeStr, BoolStr]] - - #Auto update for bevel - TypeStr = "Bevel Update [" + self.carver_prefs.Key_Update + "]" - BoolStr = "(ON)" if self.Auto_BevelUpdate else "(OFF)" - help_txt += [[TypeStr, BoolStr]] - - # Circle subdivisions - if self.CutType == CIRCLE: - TypeStr = "Subdivisions [" + self.carver_prefs.Key_Subrem + "][" + self.carver_prefs.Key_Subadd + "]" - BoolStr = str((int(360 / self.stepAngle[self.step]))) - help_txt += [[TypeStr, BoolStr]] - - if self.CreateMode: - help_txt += [["Type [Space]", PrimitiveType]] - else: - help_txt += [["Cut Type [Space]", PrimitiveType]] - - else: - # Instantiate - TypeStr = "Instantiate [" + self.carver_prefs.Key_Instant + "]" - BoolStr = "(ON)" if self.Instantiate else "(OFF)" - help_txt = [[TypeStr, BoolStr]] - - # Random rotation - if self.alt: - TypeStr = "Random Rotation [" + self.carver_prefs.Key_Randrot + "]" - BoolStr = "(ON)" if self.RandomRotation else "(OFF)" - help_txt += [[TypeStr, BoolStr]] - - # Thickness - if self.BrushSolidify: - TypeStr = "Thickness [" + self.carver_prefs.Key_Depth + "]" - if self.ProfileMode: - BoolStr = str(round(self.ProfileBrush.modifiers["CT_SOLIDIFY"].thickness, 2)) - if self.ObjectMode: - BoolStr = str(round(self.ObjectBrush.modifiers["CT_SOLIDIFY"].thickness, 2)) - help_txt += [[TypeStr, BoolStr]] - - # Brush depth - if (self.ObjectMode): - TypeStr = "Carve Depth [" + self.carver_prefs.Key_Depth + "]" - BoolStr = str(round(self.ObjectBrush.data.vertices[0].co.z, 2)) - help_txt += [[TypeStr, BoolStr]] - - TypeStr = "Brush Depth [" + self.carver_prefs.Key_BrushDepth + "]" - BoolStr = str(round(self.BrushDepthOffset, 2)) - help_txt += [[TypeStr, BoolStr]] - - help_txt, bloc_height, max_option, max_key, comma = get_text_info(self, context, help_txt) - xCmd = region_width - (max_option + max_key + comma) / 2 - draw_string(self, color1, color2, xCmd, y_txt, help_txt, max_option, divide = 2) - - - # Separator (Line) - LineWidth = (max_option + max_key + comma) / 2 - if region.width >= 850: - LineWidth = 140 - - LineWidth = (max_option + max_key + comma) - coords = [(int(region_width - LineWidth/2), y_txt + bloc_height + 8), \ - (int(region_width + LineWidth/2), y_txt + bloc_height + 8)] - draw_shader(self, UIColor, 1, 'LINES', coords, self.carver_prefs.LineWidth) - - # Command Display - if self.CreateMode and ((self.ObjectMode is False) and (self.ProfileMode is False)): - BooleanMode = "Create" - else: - if self.ObjectMode or self.ProfileMode: - BooleanType = "Difference) [T]" if self.BoolOps == self.difference else "Union) [T]" - BooleanMode = \ - "Object Brush (" + BooleanType if self.ObjectMode else "Profil Brush (" + BooleanType - else: - BooleanMode = \ - "Difference" if (self.shift is False) and (self.ForceRebool is False) else "Rebool" - - # Display boolean mode - text_size = 40 if region.width >= 850 else 20 - blf.size(0, round(text_size * ui_scale), 72) - - draw_string(self, color2, color2, region_width - (blf.dimensions(0, BooleanMode)[0]) / 2, \ - y_txt + bloc_height + 16, BooleanMode, 0, divide = 2) - - if region.width >= 850: - - if self.AskHelp is False: - # "H for Help" text - blf.size(0, round(13 * ui_scale), 72) - help_txt = "[" + self.carver_prefs.Key_Help + "] for help" - txt_width = blf.dimensions(0, help_txt)[0] - txt_height = (blf.dimensions(0, "gM")[1] * 1.45) - - # Draw a rectangle and put the text "H for Help" - xrect = 40 - yrect = 40 - rect_vertices = [(xrect - 5, yrect - 5), (xrect + txt_width + 5, yrect - 5), \ - (xrect + txt_width + 5, yrect + txt_height + 5), (xrect - 5, yrect + txt_height + 5)] - draw_shader(self, (0.0, 0.0, 0.0), 0.3, 'TRI_FAN', rect_vertices, self.carver_prefs.LineWidth) - draw_string(self, color1, color2, xrect, yrect, help_txt, 0) - - else: - #Draw the help text - xHelp = 30 + t_panel_width - yHelp = 10 - - if self.ObjectMode or self.ProfileMode: - if self.ProfileMode: - help_txt = [["Object Mode", self.carver_prefs.Key_Brush]] - else: - help_txt = [["Cut Mode", self.carver_prefs.Key_Brush]] - - else: - help_txt =[ - ["Profil Brush", self.carver_prefs.Key_Brush],\ - ["Move Cursor", "Ctrl + LMB"] - ] - - if (self.ObjectMode is False) and (self.ProfileMode is False): - if self.CreateMode is False: - help_txt +=[ - ["Create geometry", self.carver_prefs.Key_Create],\ - ] - else: - help_txt +=[ - ["Cut", self.carver_prefs.Key_Create],\ - ] - if self.CutMode == RECTANGLE: - help_txt +=[ - ["Dimension", "MouseMove"],\ - ["Move all", "Alt"],\ - ["Validate", "LMB"],\ - ["Rebool", "Shift"] - ] - - elif self.CutMode == CIRCLE: - help_txt +=[ - ["Rotation and Radius", "MouseMove"],\ - ["Move all", "Alt"],\ - ["Subdivision", self.carver_prefs.Key_Subrem + " " + self.carver_prefs.Key_Subadd],\ - ["Incremental rotation", "Ctrl"],\ - ["Rebool", "Shift"] - ] - - elif self.CutMode == LINE: - help_txt +=[ - ["Dimension", "MouseMove"],\ - ["Move all", "Alt"],\ - ["Validate", "Space"],\ - ["Rebool", "Shift"],\ - ["Snap", "Ctrl"],\ - ["Scale Snap", "WheelMouse"],\ - ] - else: - # ObjectMode - help_txt +=[ - ["Difference", "Space"],\ - ["Rebool", "Shift + Space"],\ - ["Duplicate", "Alt + Space"],\ - ["Scale", self.carver_prefs.Key_Scale],\ - ["Rotation", "LMB + Move"],\ - ["Step Angle", "CTRL + LMB + Move"],\ - ] - - if self.ProfileMode: - help_txt +=[["Previous or Next Profile", self.carver_prefs.Key_Subadd + " " + self.carver_prefs.Key_Subrem]] - - help_txt +=[ - ["Create / Delete rows", chr(8597)],\ - ["Create / Delete cols", chr(8596)],\ - ["Gap for rows or columns", self.carver_prefs.Key_Gapy + " " + self.carver_prefs.Key_Gapx] - ] - - blf.size(0, round(15 * ui_scale), 72) - help_txt, bloc_height, max_option, max_key, comma = get_text_info(self, context, help_txt) - draw_string(self, color1, color2, xHelp, yHelp, help_txt, max_option) - - if self.ProfileMode: - xrect = region.width - t_panel_width - 80 - yrect = 80 - coords = [(xrect, yrect), (xrect+60, yrect), (xrect+60, yrect-60), (xrect, yrect-60)] - - # Draw rectangle background in the lower right - draw_shader(self, (0.0, 0.0, 0.0), 0.3, 'TRI_FAN', coords, size=self.carver_prefs.LineWidth) - - # Use numpy to get the vertices and indices of the profile object to draw - WidthProfil = 50 - location = Vector((region.width - t_panel_width - WidthProfil, 50, 0)) - ProfilScale = 20.0 - coords = [] - mesh = bpy.data.meshes[self.Profils[self.nProfil][0]] - mesh.calc_loop_triangles() - vertices = np.empty((len(mesh.vertices), 3), 'f') - indices = np.empty((len(mesh.loop_triangles), 3), 'i') - mesh.vertices.foreach_get("co", np.reshape(vertices, len(mesh.vertices) * 3)) - mesh.loop_triangles.foreach_get("vertices", np.reshape(indices, len(mesh.loop_triangles) * 3)) - - for idx, vals in enumerate(vertices): - coords.append([ - vals[0] * ProfilScale + location.x, - vals[1] * ProfilScale + location.y, - vals[2] * ProfilScale + location.z - ]) - - #Draw the silhouette of the mesh - draw_shader(self, UIColor, 0.5, 'TRIS', coords, size=self.carver_prefs.LineWidth, indices=indices) - - - if self.CutMode: - - if len(self.mouse_path) > 1: - x0 = self.mouse_path[0][0] - y0 = self.mouse_path[0][1] - x1 = self.mouse_path[1][0] - y1 = self.mouse_path[1][1] - - # Cut rectangle - if self.CutType == RECTANGLE: - coords = [ - (x0 + self.xpos, y0 + self.ypos), (x1 + self.xpos, y0 + self.ypos), \ - (x1 + self.xpos, y1 + self.ypos), (x0 + self.xpos, y1 + self.ypos) - ] - indices = ((0, 1, 2), (2, 0, 3)) - - self.rectangle_coord = coords - - draw_shader(self, UIColor, 1, 'LINE_LOOP', coords, size=self.carver_prefs.LineWidth) - - #Draw points - draw_shader(self, UIColor, 1, 'POINTS', coords, size=3) - - if self.shift or self.CreateMode: - draw_shader(self, UIColor, 0.5, 'TRIS', coords, size=self.carver_prefs.LineWidth, indices=indices) - - # Draw grid (based on the overlay options) to show the incremental snapping - if self.ctrl: - mini_grid(self, context, UIColor) - - # Cut Line - elif self.CutType == LINE: - coords = [] - indices = [] - top_grid = False - - for idx, vals in enumerate(self.mouse_path): - coords.append([vals[0] + self.xpos, vals[1] + self.ypos]) - indices.append([idx]) - - # Draw lines - if self.Closed: - draw_shader(self, UIColor, 1.0, 'LINE_LOOP', coords, size=self.carver_prefs.LineWidth) - else: - draw_shader(self, UIColor, 1.0, 'LINE_STRIP', coords, size=self.carver_prefs.LineWidth) - - # Draw points - draw_shader(self, UIColor, 1.0, 'POINTS', coords, size=3) - - # Draw polygon - if (self.shift) or (self.CreateMode and self.Closed): - draw_shader(self, UIColor, 0.5, 'TRI_FAN', coords, size=self.carver_prefs.LineWidth) - - # Draw grid (based on the overlay options) to show the incremental snapping - if self.ctrl: - mini_grid(self, context, UIColor) - - # Circle Cut - elif self.CutType == CIRCLE: - # Create a circle using a tri fan - tris_coords, indices = draw_circle(self, x0, y0) - - # Remove the vertex in the center to get the outer line of the circle - line_coords = tris_coords[1:] - draw_shader(self, UIColor, 1.0, 'LINE_LOOP', line_coords, size=self.carver_prefs.LineWidth) - - if self.shift or self.CreateMode: - draw_shader(self, UIColor, 0.5, 'TRIS', tris_coords, size=self.carver_prefs.LineWidth, indices=indices) - - if (self.ObjectMode or self.ProfileMode) and len(self.CurrentSelection) > 0: - if self.ShowCursor: - region = context.region - rv3d = context.space_data.region_3d - - if self.ObjectMode: - ob = self.ObjectBrush - if self.ProfileMode: - ob = self.ProfileBrush - mat = ob.matrix_world - - # 50% alpha, 2 pixel width line - bgl.glEnable(bgl.GL_BLEND) - - bbox = [mat @ Vector(b) for b in ob.bound_box] - objBBDiagonal = objDiagonal(self.CurrentSelection[0]) - - if self.shift: - gl_size = 4 - UIColor = (0.5, 1.0, 0.0, 1.0) - else: - gl_size = 2 - UIColor = (1.0, 0.8, 0.0, 1.0) - - line_coords = [] - idx = 0 - CRadius = ((bbox[7] - bbox[0]).length) / 2 - for i in range(int(len(self.CLR_C) / 3)): - vector3d = (self.CLR_C[idx * 3] * CRadius + self.CurLoc.x, \ - self.CLR_C[idx * 3 + 1] * CRadius + self.CurLoc.y, \ - self.CLR_C[idx * 3 + 2] * CRadius + self.CurLoc.z) - vector2d = bpy_extras.view3d_utils.location_3d_to_region_2d(region, rv3d, vector3d) - if vector2d is not None: - line_coords.append((vector2d[0], vector2d[1])) - idx += 1 - if len(line_coords) > 0 : - draw_shader(self, UIColor, 1.0, 'LINE_LOOP', line_coords, size=gl_size) - - # Object display - if self.quat_rot is not None: - ob.location = self.CurLoc - v = Vector() - v.x = v.y = 0.0 - v.z = self.BrushDepthOffset - ob.location += self.quat_rot @ v - - e = Euler() - e.x = 0.0 - e.y = 0.0 - e.z = self.aRotZ / 25.0 - - qe = e.to_quaternion() - qRot = self.quat_rot @ qe - ob.rotation_mode = 'QUATERNION' - ob.rotation_quaternion = qRot - ob.rotation_mode = 'XYZ' - - if self.ProfileMode: - if self.ProfileBrush is not None: - self.ProfileBrush.location = self.CurLoc - self.ProfileBrush.rotation_mode = 'QUATERNION' - self.ProfileBrush.rotation_quaternion = qRot - self.ProfileBrush.rotation_mode = 'XYZ' - - # Opengl defaults - bgl.glLineWidth(1) - bgl.glDisable(bgl.GL_BLEND) + font_id = 0 + region = context.region + UIColor = (0.992, 0.5518, 0.0, 1.0) + + # Cut Type + RECTANGLE = 0 + LINE = 1 + CIRCLE = 2 + self.carver_prefs = context.preferences.addons[__package__].preferences + + # Color + color1 = (1.0, 1.0, 1.0, 1.0) + color2 = UIColor + + #The mouse is outside the active region + if not self.in_view_3d: + color1 = color2 = (1.0, 0.2, 0.1, 1.0) + + # Primitives type + PrimitiveType = "Rectangle" + if self.CutType == CIRCLE: + PrimitiveType = "Circle" + if self.CutType == LINE: + PrimitiveType = "Line" + + # Width screen + overlap = context.preferences.system.use_region_overlap + + t_panel_width = 0 + if overlap: + for region in context.area.regions: + if region.type == 'TOOLS': + t_panel_width = region.width + + # Initial position + region_width = int(region.width / 2.0) + y_txt = 10 + + + # Draw the center command from bottom to top + + # Get the size of the text + text_size = 18 if region.width >= 850 else 12 + ui_scale = bpy.context.preferences.system.ui_scale + blf.size(0, round(text_size * ui_scale), 72) + + # Help Display + if (self.ObjectMode is False) and (self.ProfileMode is False): + + # Depth Cursor + TypeStr = "Cursor Depth [" + self.carver_prefs.Key_Depth + "]" + BoolStr = "(ON)" if self.snapCursor else "(OFF)" + help_txt = [[TypeStr, BoolStr]] + + # Close poygonal shape + if self.CreateMode and self.CutType == LINE: + TypeStr = "Close [" + self.carver_prefs.Key_Close + "]" + BoolStr = "(ON)" if self.Closed else "(OFF)" + help_txt += [[TypeStr, BoolStr]] + + if self.CreateMode is False: + # Apply Booleans + TypeStr = "Apply Operations [" + self.carver_prefs.Key_Apply + "]" + BoolStr = "(OFF)" if self.dont_apply_boolean else "(ON)" + help_txt += [[TypeStr, BoolStr]] + + #Auto update for bevel + TypeStr = "Bevel Update [" + self.carver_prefs.Key_Update + "]" + BoolStr = "(ON)" if self.Auto_BevelUpdate else "(OFF)" + help_txt += [[TypeStr, BoolStr]] + + # Circle subdivisions + if self.CutType == CIRCLE: + TypeStr = "Subdivisions [" + self.carver_prefs.Key_Subrem + "][" + self.carver_prefs.Key_Subadd + "]" + BoolStr = str((int(360 / self.stepAngle[self.step]))) + help_txt += [[TypeStr, BoolStr]] + + if self.CreateMode: + help_txt += [["Type [Space]", PrimitiveType]] + else: + help_txt += [["Cut Type [Space]", PrimitiveType]] + + else: + # Instantiate + TypeStr = "Instantiate [" + self.carver_prefs.Key_Instant + "]" + BoolStr = "(ON)" if self.Instantiate else "(OFF)" + help_txt = [[TypeStr, BoolStr]] + + # Random rotation + if self.alt: + TypeStr = "Random Rotation [" + self.carver_prefs.Key_Randrot + "]" + BoolStr = "(ON)" if self.RandomRotation else "(OFF)" + help_txt += [[TypeStr, BoolStr]] + + # Thickness + if self.BrushSolidify: + TypeStr = "Thickness [" + self.carver_prefs.Key_Depth + "]" + if self.ProfileMode: + BoolStr = str(round(self.ProfileBrush.modifiers["CT_SOLIDIFY"].thickness, 2)) + if self.ObjectMode: + BoolStr = str(round(self.ObjectBrush.modifiers["CT_SOLIDIFY"].thickness, 2)) + help_txt += [[TypeStr, BoolStr]] + + # Brush depth + if (self.ObjectMode): + TypeStr = "Carve Depth [" + self.carver_prefs.Key_Depth + "]" + BoolStr = str(round(self.ObjectBrush.data.vertices[0].co.z, 2)) + help_txt += [[TypeStr, BoolStr]] + + TypeStr = "Brush Depth [" + self.carver_prefs.Key_BrushDepth + "]" + BoolStr = str(round(self.BrushDepthOffset, 2)) + help_txt += [[TypeStr, BoolStr]] + + help_txt, bloc_height, max_option, max_key, comma = get_text_info(self, context, help_txt) + xCmd = region_width - (max_option + max_key + comma) / 2 + draw_string(self, color1, color2, xCmd, y_txt, help_txt, max_option, divide = 2) + + + # Separator (Line) + LineWidth = (max_option + max_key + comma) / 2 + if region.width >= 850: + LineWidth = 140 + + LineWidth = (max_option + max_key + comma) + coords = [(int(region_width - LineWidth/2), y_txt + bloc_height + 8), \ + (int(region_width + LineWidth/2), y_txt + bloc_height + 8)] + draw_shader(self, UIColor, 1, 'LINES', coords, self.carver_prefs.LineWidth) + + # Command Display + if self.CreateMode and ((self.ObjectMode is False) and (self.ProfileMode is False)): + BooleanMode = "Create" + else: + if self.ObjectMode or self.ProfileMode: + BooleanType = "Difference) [T]" if self.BoolOps == self.difference else "Union) [T]" + BooleanMode = \ + "Object Brush (" + BooleanType if self.ObjectMode else "Profil Brush (" + BooleanType + else: + BooleanMode = \ + "Difference" if (self.shift is False) and (self.ForceRebool is False) else "Rebool" + + # Display boolean mode + text_size = 40 if region.width >= 850 else 20 + blf.size(0, round(text_size * ui_scale), 72) + + draw_string(self, color2, color2, region_width - (blf.dimensions(0, BooleanMode)[0]) / 2, \ + y_txt + bloc_height + 16, BooleanMode, 0, divide = 2) + + if region.width >= 850: + + if self.AskHelp is False: + # "H for Help" text + blf.size(0, round(13 * ui_scale), 72) + help_txt = "[" + self.carver_prefs.Key_Help + "] for help" + txt_width = blf.dimensions(0, help_txt)[0] + txt_height = (blf.dimensions(0, "gM")[1] * 1.45) + + # Draw a rectangle and put the text "H for Help" + xrect = 40 + yrect = 40 + rect_vertices = [(xrect - 5, yrect - 5), (xrect + txt_width + 5, yrect - 5), \ + (xrect + txt_width + 5, yrect + txt_height + 5), (xrect - 5, yrect + txt_height + 5)] + draw_shader(self, (0.0, 0.0, 0.0), 0.3, 'TRI_FAN', rect_vertices, self.carver_prefs.LineWidth) + draw_string(self, color1, color2, xrect, yrect, help_txt, 0) + + else: + #Draw the help text + xHelp = 30 + t_panel_width + yHelp = 10 + + if self.ObjectMode or self.ProfileMode: + if self.ProfileMode: + help_txt = [["Object Mode", self.carver_prefs.Key_Brush]] + else: + help_txt = [["Cut Mode", self.carver_prefs.Key_Brush]] + + else: + help_txt =[ + ["Profil Brush", self.carver_prefs.Key_Brush],\ + ["Move Cursor", "Ctrl + LMB"] + ] + + if (self.ObjectMode is False) and (self.ProfileMode is False): + if self.CreateMode is False: + help_txt +=[ + ["Create geometry", self.carver_prefs.Key_Create],\ + ] + else: + help_txt +=[ + ["Cut", self.carver_prefs.Key_Create],\ + ] + if self.CutMode == RECTANGLE: + help_txt +=[ + ["Dimension", "MouseMove"],\ + ["Move all", "Alt"],\ + ["Validate", "LMB"],\ + ["Rebool", "Shift"] + ] + + elif self.CutMode == CIRCLE: + help_txt +=[ + ["Rotation and Radius", "MouseMove"],\ + ["Move all", "Alt"],\ + ["Subdivision", self.carver_prefs.Key_Subrem + " " + self.carver_prefs.Key_Subadd],\ + ["Incremental rotation", "Ctrl"],\ + ["Rebool", "Shift"] + ] + + elif self.CutMode == LINE: + help_txt +=[ + ["Dimension", "MouseMove"],\ + ["Move all", "Alt"],\ + ["Validate", "Space"],\ + ["Rebool", "Shift"],\ + ["Snap", "Ctrl"],\ + ["Scale Snap", "WheelMouse"],\ + ] + else: + # ObjectMode + help_txt +=[ + ["Difference", "Space"],\ + ["Rebool", "Shift + Space"],\ + ["Duplicate", "Alt + Space"],\ + ["Scale", self.carver_prefs.Key_Scale],\ + ["Rotation", "LMB + Move"],\ + ["Step Angle", "CTRL + LMB + Move"],\ + ] + + if self.ProfileMode: + help_txt +=[["Previous or Next Profile", self.carver_prefs.Key_Subadd + " " + self.carver_prefs.Key_Subrem]] + + help_txt +=[ + ["Create / Delete rows", chr(8597)],\ + ["Create / Delete cols", chr(8596)],\ + ["Gap for rows or columns", self.carver_prefs.Key_Gapy + " " + self.carver_prefs.Key_Gapx] + ] + + blf.size(0, round(15 * ui_scale), 72) + help_txt, bloc_height, max_option, max_key, comma = get_text_info(self, context, help_txt) + draw_string(self, color1, color2, xHelp, yHelp, help_txt, max_option) + + if self.ProfileMode: + xrect = region.width - t_panel_width - 80 + yrect = 80 + coords = [(xrect, yrect), (xrect+60, yrect), (xrect+60, yrect-60), (xrect, yrect-60)] + + # Draw rectangle background in the lower right + draw_shader(self, (0.0, 0.0, 0.0), 0.3, 'TRI_FAN', coords, size=self.carver_prefs.LineWidth) + + # Use numpy to get the vertices and indices of the profile object to draw + WidthProfil = 50 + location = Vector((region.width - t_panel_width - WidthProfil, 50, 0)) + ProfilScale = 20.0 + coords = [] + mesh = bpy.data.meshes[self.Profils[self.nProfil][0]] + mesh.calc_loop_triangles() + vertices = np.empty((len(mesh.vertices), 3), 'f') + indices = np.empty((len(mesh.loop_triangles), 3), 'i') + mesh.vertices.foreach_get("co", np.reshape(vertices, len(mesh.vertices) * 3)) + mesh.loop_triangles.foreach_get("vertices", np.reshape(indices, len(mesh.loop_triangles) * 3)) + + for idx, vals in enumerate(vertices): + coords.append([ + vals[0] * ProfilScale + location.x, + vals[1] * ProfilScale + location.y, + vals[2] * ProfilScale + location.z + ]) + + #Draw the silhouette of the mesh + draw_shader(self, UIColor, 0.5, 'TRIS', coords, size=self.carver_prefs.LineWidth, indices=indices) + + + if self.CutMode: + + if len(self.mouse_path) > 1: + x0 = self.mouse_path[0][0] + y0 = self.mouse_path[0][1] + x1 = self.mouse_path[1][0] + y1 = self.mouse_path[1][1] + + # Cut rectangle + if self.CutType == RECTANGLE: + coords = [ + (x0 + self.xpos, y0 + self.ypos), (x1 + self.xpos, y0 + self.ypos), \ + (x1 + self.xpos, y1 + self.ypos), (x0 + self.xpos, y1 + self.ypos) + ] + indices = ((0, 1, 2), (2, 0, 3)) + + self.rectangle_coord = coords + + draw_shader(self, UIColor, 1, 'LINE_LOOP', coords, size=self.carver_prefs.LineWidth) + + #Draw points + draw_shader(self, UIColor, 1, 'POINTS', coords, size=3) + + if self.shift or self.CreateMode: + draw_shader(self, UIColor, 0.5, 'TRIS', coords, size=self.carver_prefs.LineWidth, indices=indices) + + # Draw grid (based on the overlay options) to show the incremental snapping + if self.ctrl: + mini_grid(self, context, UIColor) + + # Cut Line + elif self.CutType == LINE: + coords = [] + indices = [] + top_grid = False + + for idx, vals in enumerate(self.mouse_path): + coords.append([vals[0] + self.xpos, vals[1] + self.ypos]) + indices.append([idx]) + + # Draw lines + if self.Closed: + draw_shader(self, UIColor, 1.0, 'LINE_LOOP', coords, size=self.carver_prefs.LineWidth) + else: + draw_shader(self, UIColor, 1.0, 'LINE_STRIP', coords, size=self.carver_prefs.LineWidth) + + # Draw points + draw_shader(self, UIColor, 1.0, 'POINTS', coords, size=3) + + # Draw polygon + if (self.shift) or (self.CreateMode and self.Closed): + draw_shader(self, UIColor, 0.5, 'TRI_FAN', coords, size=self.carver_prefs.LineWidth) + + # Draw grid (based on the overlay options) to show the incremental snapping + if self.ctrl: + mini_grid(self, context, UIColor) + + # Circle Cut + elif self.CutType == CIRCLE: + # Create a circle using a tri fan + tris_coords, indices = draw_circle(self, x0, y0) + + # Remove the vertex in the center to get the outer line of the circle + line_coords = tris_coords[1:] + draw_shader(self, UIColor, 1.0, 'LINE_LOOP', line_coords, size=self.carver_prefs.LineWidth) + + if self.shift or self.CreateMode: + draw_shader(self, UIColor, 0.5, 'TRIS', tris_coords, size=self.carver_prefs.LineWidth, indices=indices) + + if (self.ObjectMode or self.ProfileMode) and len(self.CurrentSelection) > 0: + if self.ShowCursor: + region = context.region + rv3d = context.space_data.region_3d + + if self.ObjectMode: + ob = self.ObjectBrush + if self.ProfileMode: + ob = self.ProfileBrush + mat = ob.matrix_world + + # 50% alpha, 2 pixel width line + bgl.glEnable(bgl.GL_BLEND) + + bbox = [mat @ Vector(b) for b in ob.bound_box] + objBBDiagonal = objDiagonal(self.CurrentSelection[0]) + + if self.shift: + gl_size = 4 + UIColor = (0.5, 1.0, 0.0, 1.0) + else: + gl_size = 2 + UIColor = (1.0, 0.8, 0.0, 1.0) + + line_coords = [] + idx = 0 + CRadius = ((bbox[7] - bbox[0]).length) / 2 + for i in range(int(len(self.CLR_C) / 3)): + vector3d = (self.CLR_C[idx * 3] * CRadius + self.CurLoc.x, \ + self.CLR_C[idx * 3 + 1] * CRadius + self.CurLoc.y, \ + self.CLR_C[idx * 3 + 2] * CRadius + self.CurLoc.z) + vector2d = bpy_extras.view3d_utils.location_3d_to_region_2d(region, rv3d, vector3d) + if vector2d is not None: + line_coords.append((vector2d[0], vector2d[1])) + idx += 1 + if len(line_coords) > 0 : + draw_shader(self, UIColor, 1.0, 'LINE_LOOP', line_coords, size=gl_size) + + # Object display + if self.quat_rot is not None: + ob.location = self.CurLoc + v = Vector() + v.x = v.y = 0.0 + v.z = self.BrushDepthOffset + ob.location += self.quat_rot @ v + + e = Euler() + e.x = 0.0 + e.y = 0.0 + e.z = self.aRotZ / 25.0 + + qe = e.to_quaternion() + qRot = self.quat_rot @ qe + ob.rotation_mode = 'QUATERNION' + ob.rotation_quaternion = qRot + ob.rotation_mode = 'XYZ' + + if self.ProfileMode: + if self.ProfileBrush is not None: + self.ProfileBrush.location = self.CurLoc + self.ProfileBrush.rotation_mode = 'QUATERNION' + self.ProfileBrush.rotation_quaternion = qRot + self.ProfileBrush.rotation_mode = 'XYZ' + + # Opengl defaults + bgl.glLineWidth(1) + bgl.glDisable(bgl.GL_BLEND) |