def execute(self, context): # do not proceed if list is already empty if len(SCSPathsInitialization.__static_paths_list) <= 0: return {'FINISHED'} self.__path_in_progress = True # update message with current path and apply it SCSPathsInitialization.__static_message += "Initializing " + SCSPathsInitialization.__static_paths_list[0].name + "..." setattr(_get_scs_globals(), SCSPathsInitialization.__static_paths_list[0].attr, SCSPathsInitialization.__static_paths_list[0].path) SCSPathsInitialization.__static_paths_list.remove(0) # remove just processed item SCSPathsInitialization.__static_message += " Done in %.2f s!\n" % (time() - self.__last_time) SCSPathsInitialization.__static_paths_done += 1 # when executing last one, also print out hiding message if len(SCSPathsInitialization.__static_paths_list) == 0: SCSPathsInitialization.__static_message += "SCS Blender Tools are ready!" _view3d_utils.tag_redraw_all_view3d() self.__last_time = time() # reset last time for next path self.__path_in_progress = False # if debug then report whole progress message otherwise print out condensed message if int(_get_scs_globals().dump_level) >= self.DUMP_LEVEL: message = SCSPathsInitialization.__static_message hide_controls = False else: message = "Paths and libraries initialization %s/%s ..." % (SCSPathsInitialization.__static_paths_done, SCSPathsInitialization.__static_paths_count) hide_controls = True bpy.ops.wm.show_3dview_report('INVOKE_DEFAULT', message=message, hide_controls=hide_controls, is_progress_message=True) return {'FINISHED'}
def modal(self, context, event): if event.type == "LEFTMOUSE" and event.value in {'PRESS'}: for area in context.screen.areas: if area.type != 'VIEW_3D': continue for region in area.regions: if region.type != 'WINDOW': continue curr_x = event.mouse_x - region.x curr_y = region.height - (event.mouse_y - region.y) if 20 < curr_x < 95 and 38 < curr_y < 62: # close self.cancel(context) return {'FINISHED'} if 100 < curr_x < 250 and 38 < curr_y < 62: # show/hide Show3DViewReport.__static_is_shown = not Show3DViewReport.__static_is_shown _view3d_utils.tag_redraw_all_view3d() return {'RUNNING_MODAL'} return {'PASS_THROUGH'}
def execute(self, context): mesh = context.active_object.data start_time = time() # prepare buffers vcolors_buffer_arrays = [ numpy.array([0.0] * (len(mesh.loops) * 3)), numpy.array([0.0] * (len(mesh.loops) * 3)), numpy.array([0.0] * (len(mesh.loops) * 3)), numpy.array([0.0] * (len(mesh.loops) * 3)) ] # rebake result = _mesh_utils.vcoloring_rebake(mesh, vcolors_buffer_arrays, None) if result: message = "I Successful! Vertex colors rebake took: %.4fs" % (time() - start_time) lprint(message) self.report({'INFO'}, message[2:]) _view3d_utils.tag_redraw_all_view3d() # trigger view update to see rebaked colors else: message = "E Failed! This shouldn't happen, please contact the developer..." lprint(message) self.report({'ERROR'}, message[2:]) return {'FINISHED'}
def modal(self, context, event): active_obj = self.__get_active_object__() active_object_changed = active_obj != context.active_object # abort immeadiatelly if active object was changed if active_object_changed: self.cancel(context) return {'CANCELLED'} is_object_mode_changed = self.__active_object_mode != context.active_object.mode # allow changing into the edit mode as user might go there just to reselect # masked faces on which he wants to paint if is_object_mode_changed and context.active_object.mode == "EDIT": return {'PASS_THROUGH'} # abort if active object mode has changed if is_object_mode_changed: self.cancel(context) return {'CANCELLED'} if event.type == "ESC" and event.value == "PRESS": self.cancel(context) return {'FINISHED'} # always ensure to be in proper vertex color layer self.switch_to_layer(self.__static_active_layer) # do rebake only on timer event if event.type == "TIMER": start_time = time() new_hash = _mesh_utils.vcoloring_rebake( active_obj.data, self.__vcolors_buffer_arrays, self.__old_vcolors_array_hash) if new_hash is None: # sth went really wrong, no sufficient data lprint( "E VColoring rebake failed! Contact the developer...") elif new_hash != self.__old_vcolors_array_hash: # rebake happened self.__old_vcolors_array_hash = new_hash _view3d_utils.tag_redraw_all_view3d( ) # trigger view update to see rebaked colors lprint("D VColoring real-time rebake took: %.4fs" % (time() - start_time)) else: # checked active vertex color layer, but nothing had to be recalculated lprint("D VColoring checkup took: %.4fs" % (time() - start_time)) return {'PASS_THROUGH'}
def cancel(self, context): # free BT logo image resources if _OP_consts.View3DReport.BT_LOGO_IMG_NAME in bpy.data.images: img = bpy.data.images[_OP_consts.View3DReport.BT_LOGO_IMG_NAME] img.gl_free() bpy.data.images.remove(img, do_unlink=True) Show3DViewReport.__static_message_l.clear() Show3DViewReport.__static_progress_message_l.clear() _view3d_utils.tag_redraw_all_view3d()
def __object_rename__(old_name, new_name): """Hookup function for object rename operation :param old_name: old name of an object :type old_name: str :param new_name: new name of an object :type new_name: str """ # send rename notify into connections storage if _connections_group_wrapper.rename_locator(old_name, new_name): _view3d_utils.tag_redraw_all_view3d() # send rename notify to preview models _preview_models.rename(old_name, new_name)
def __objects_delete__(unparented_objects): """Hookup function for objects delete operation :param unparented_objects: objects which were unparented during delete :type unparented_objects: list of bpy.types.Objects """ # fix connections recalculations for unparented _connections_group_wrapper.force_recalculate(unparented_objects) _view3d_utils.tag_redraw_all_view3d() # delete unused previe models for obj in bpy.data.objects: if obj.type == 'MESH': if "scs_props" in obj.data and obj.data.scs_props.locator_preview_model_path != "" and not obj.parent: _preview_models.unlink(obj)
def __objects_copy__(old_objects, new_objects): """Hookup function for objects copy operation. :param old_objects: old objects from which new ones were created :type old_objects: list of bpy.types.Object :param new_objects: copies of old objects :type new_objects: list of bpy.types.Object """ # try to copy connections for new objects _connections_group_wrapper.copy_check(old_objects, new_objects) _view3d_utils.tag_redraw_all_view3d() # also check for any preview models which should be also copied to new ones for i, old_obj in enumerate(old_objects): if old_obj.scs_props.locator_preview_model_present: _preview_models.load(new_objects[i])
def discard_drawing_data(): """Discards drawing by cleaning static messages and removing banner image. """ # free BT logo image resources if _OP_consts.View3DReport.BT_BANNER_IMG_NAME in bpy.data.images: img = bpy.data.images[_OP_consts.View3DReport.BT_BANNER_IMG_NAME] img.gl_free() bpy.data.images.remove(img, do_unlink=True) SCS_TOOLS_OT_Show3DViewReport.__static_title = "" SCS_TOOLS_OT_Show3DViewReport.__static_message_l.clear() SCS_TOOLS_OT_Show3DViewReport.__static_progress_message_l.clear() # trigger redraw so 3d view reports will be removed _view3d_utils.tag_redraw_all_view3d()
def cancel(self, context): # find oldest main window for possible re-call of the operator oldest_main_window = None if bpy.context.window_manager: for window in bpy.context.window_manager.windows: if not window.parent: oldest_main_window = window break # when operator get's cancelled, either user closed blender or window itself, in which our operator was handled. # Thus make sure to re-call on exisiting oldest main window, so that 3d view opearator "reopens" if oldest_main_window and SCS_TOOLS_OT_Show3DViewReport.__static_window_instance != oldest_main_window: override = bpy.context.copy() override["window"] = oldest_main_window bpy.ops.wm.scs_tools_show_3dview_report( override, 'INVOKE_DEFAULT', modal_handler_reassign=True) _view3d_utils.tag_redraw_all_view3d() else: SCS_TOOLS_OT_Show3DViewReport.discard_drawing_data()
def lprint(string, values=(), report_errors=0, report_warnings=0): """Handy printout function with alert levels and more fancy stuff. :param string: Message string which will be printed. :type string: str :param values: Tuple of values, which complements the message string :type values: tuple :param report_errors: 0 - don't print anything, but store the errors; 1 - print error summary; -1 - clear stored errors :type report_errors: int :param report_warnings: 0 - don't print anything, but store the warnings; 1 - print warning summary; -1 - clear stored warnings :type report_warnings: int """ from io_scs_tools.utils import get_scs_globals as _get_scs_globals dump_level = int(_get_scs_globals().dump_level) prech = '' if string is not "": while string[0] in '\n\t': prech += string[0] string = string[1:] message = None if string[0] == 'E': message = str(prech + 'ERROR\t- ' + string[2:] % values) error_messages.append(message.strip('\n')) # raise Exception('ERROR - ' + string[2:]) if string[0] == 'W': message = str(prech + 'WARNING\t- ' + string[2:] % values) warning_messages.append(message.strip('\n')) if not dump_level >= 1: message = None if dump_level >= 2: if string[0] == 'I': message = str(prech + 'INFO\t- ' + string[2:] % values) if dump_level >= 3: if string[0] == 'D': message = prech + 'DEBUG\t- ' + string[2:] % values if dump_level >= 4: if string[0] == 'S': message = prech + string[2:] % values if message is not None: print(message) file_logger.write(message + "\n") if string[0] not in 'EWIDS': print(prech + '!!! UNKNOWN MESSAGE SIGN !!! - "' + string + '"' % values) # CLEAR ERROR AND WARNING STACK IF REQUESTED if report_errors == -1: error_messages.clear() if report_warnings == -1: warning_messages.clear() # ERROR AND WARNING REPORTS text = "" if report_errors == 1 and error_messages: # print error summary text += '\n\t ERROR SUMMARY:\n\t ================\n\t ' printed_messages = [] for message_i, message in enumerate(error_messages): message = message.replace("ERROR\t- ", "> ") message = message.replace("\n\t ", "\n\t ") # print out only unique error messages if message not in printed_messages: printed_messages.append(message) text += message + "\n\t " text += "================\n" if dump_level == 5: dev_error_messages.extend(error_messages) error_messages.clear() if report_warnings == 1 and warning_messages: if dump_level > 0: # print warning summary text += '\n\t WARNING SUMMARY:\n\t ================\n\t ' printed_messages = [] for message_i, message in enumerate(warning_messages): message = message.replace("WARNING\t- ", "> ") message = message.replace("\n\t ", "\n\t ") # print only unique messages if message not in printed_messages: printed_messages.append(message) text += message + "\n\t " text += "================\n" if dump_level == 5: dev_warning_messages.extend(warning_messages) warning_messages.clear() file_logger.flush() if text != "": print(text) file_logger.write(text + "\n") file_logger.flush() bpy.ops.wm.scs_tools_show_3dview_report('INVOKE_DEFAULT', message=text) # make sure to tag any 3D view for redraw so errors OpenGL drawing is triggered from io_scs_tools.utils.view3d import tag_redraw_all_view3d tag_redraw_all_view3d() return True else: return False
def cancel(self, context): Show3DViewReport.__static_message_l.clear() _view3d_utils.tag_redraw_all_view3d()
def modal(self, context, event): # if not main instance finish if SCS_TOOLS_OT_Show3DViewReport.__static_main_instance != self: return {'FINISHED'} # if global abort was requested finish this modal operator instance if SCS_TOOLS_OT_Show3DViewReport.__static_abort: return {'FINISHED'} # if operator doesn't have controls, then it can not be cancelled by user, # so we should simply pass trough if not SCS_TOOLS_OT_Show3DViewReport.has_controls( SCS_TOOLS_OT_Show3DViewReport.__static_window_instance): return {'PASS_THROUGH'} # handle ESC press # NOTE: do it in stages to prevent canceling operator while user tries to abort # current action in blender (for example user entered scaling and then aborted with ESC) if event.type == "ESC" and event.value == "PRESS" and self.esc_abort == 0: self.esc_abort = 1 elif event.type == "ESC" and event.value == "RELEASE" and self.esc_abort == 1: self.esc_abort = 2 elif event.type != "MOUSEMOVE": self.esc_abort = 0 if (event.type == "LEFTMOUSE" and event.value in {'PRESS'}) or self.esc_abort == 2: # make sure to reset ESC abort state to 0 so next press will be properly handled if self.esc_abort == 2: self.esc_abort = 0 for area in context.screen.areas: if area.type != 'VIEW_3D': continue for region in area.regions: if region.type != 'WINDOW': continue curr_x = event.mouse_x - region.x curr_y = region.height - (event.mouse_y - region.y) # if mouse cursor is over 3D view and ESC was pressed then switch to hide mode or exit operator if event.type == "ESC" and area.x < event.mouse_x < area.x + area.width and area.y < event.mouse_y < area.y + area.height: # if shown first hide extended view and then if hidden it can be closed # NOTE: there is two stage exit on ESC because user might hit ESC unintentionally. # Plus in case some transformation was in progress (like translation) ESC will cancel it and # in worst case only hide 3d view logging operator, if stage ESC handling fails to capture that if SCS_TOOLS_OT_Show3DViewReport.__static_is_shown: SCS_TOOLS_OT_Show3DViewReport.__static_is_shown = False _view3d_utils.tag_redraw_all_view3d() return {'RUNNING_MODAL'} else: SCS_TOOLS_OT_Show3DViewReport.discard_drawing_data( ) return {'FINISHED'} # also exit/cancel operator if Close button area was clicked if SCS_TOOLS_OT_Show3DViewReport.is_in_btn_area( curr_x, curr_y, _OP_consts.View3DReport.CLOSE_BTN_AREA): # close SCS_TOOLS_OT_Show3DViewReport.discard_drawing_data() return {'FINISHED'} if SCS_TOOLS_OT_Show3DViewReport.is_in_btn_area( curr_x, curr_y, _OP_consts.View3DReport. HIDE_BTN_AREA): # show/hide SCS_TOOLS_OT_Show3DViewReport.__static_is_shown = not SCS_TOOLS_OT_Show3DViewReport.__static_is_shown _view3d_utils.tag_redraw_all_view3d() return {'RUNNING_MODAL'} # scroll up/down if SCS_TOOLS_OT_Show3DViewReport.is_shown( ) and SCS_TOOLS_OT_Show3DViewReport.is_scrolled(): if SCS_TOOLS_OT_Show3DViewReport.is_in_btn_area( curr_x, curr_y, _OP_consts.View3DReport.SCROLLUP_BTN_AREA): new_position = SCS_TOOLS_OT_Show3DViewReport.__static_scroll_pos - 5 min_position = 0 SCS_TOOLS_OT_Show3DViewReport.__static_scroll_pos = max( new_position, min_position) _view3d_utils.tag_redraw_all_view3d() return {'RUNNING_MODAL'} if SCS_TOOLS_OT_Show3DViewReport.is_in_btn_area( curr_x, curr_y, _OP_consts.View3DReport.SCROLLDOWN_BTN_AREA): new_position = SCS_TOOLS_OT_Show3DViewReport.__static_scroll_pos + 5 max_position = (len(SCS_TOOLS_OT_Show3DViewReport. __static_message_l) + len(SCS_TOOLS_OT_Show3DViewReport. __static_progress_message_l) - 1) SCS_TOOLS_OT_Show3DViewReport.__static_scroll_pos = min( new_position, max_position) _view3d_utils.tag_redraw_all_view3d() return {'RUNNING_MODAL'} return {'PASS_THROUGH'}