Spaces:
Sleeping
Sleeping
from __future__ import annotations | |
import abc | |
import vtk | |
from custom_types import * | |
from ui import ui_utils, ui_controllers | |
import colorsys | |
import options | |
class CustomTextWidget(vtk.vtkTextWidget): | |
def set_to_start(self): | |
# self.EnabledOff() | |
h, s, v = colorsys.rgb_to_hsv(*ui_utils.button_color) | |
self.GetTextActor().GetTextProperty().SetColor(*ui_utils.rgb_to_float(colorsys.hsv_to_rgb(h, .3, 255))) | |
# self.EnabledOn() | |
self.GetInteractor().Render() | |
self.on = False | |
def set_to_stop(self): | |
# self.EnabledOff() | |
h, s, v = colorsys.rgb_to_hsv(*ui_utils.button_color) | |
self.GetTextActor().GetTextProperty().SetColor(*ui_utils.rgb_to_float(colorsys.hsv_to_rgb(h, .9, 255))) | |
# self.EnabledOn() | |
self.GetInteractor().Render() | |
self.on = True | |
def left_button_press_event(self, obj, event): | |
self.on_click(self) | |
def hover(self, obj, event): | |
print(self.b_type.value) | |
def toggle_selection(self): | |
if self.on: | |
self.set_to_start() | |
else: | |
self.set_to_stop() | |
def __init__(self, b_type: ui_utils.Buttons, position, size, interactor: vtk.vtkRenderWindowInteractor, ren: vtk.vtkRenderer, on_click): | |
super(CustomTextWidget, self).__init__() | |
self.ren = ren | |
self.on_click = on_click | |
self.SetInteractor(interactor) | |
text_actor = vtk.vtkTextActor() | |
text_representation = vtk.vtkTextRepresentation() | |
self.SetRepresentation(text_representation) | |
self.SetTextActor(text_actor) | |
self.GetRepresentation().SetRenderer(self.ren) | |
self.SetCurrentRenderer(self.ren) | |
self.GetTextActor().SetInput(b_type.value) | |
self.GetRepresentation().GetPositionCoordinate().SetValue(*position) | |
self.set_to_start() | |
# self.Set | |
self.SelectableOn() | |
self.SetResizable(0) | |
self.EnabledOn() | |
self.On() | |
self.AddObserver(vtk.vtkCommand.EndInteractionEvent, self.left_button_press_event) | |
self.AddObserver(vtk.vtkCommand.HoverEvent, self.hover) | |
self.on = False | |
self.b_type = b_type | |
self.GetRepresentation().GetPosition2Coordinate().SetValue(*size) | |
def get_selection(self) -> ui_utils.Buttons: | |
return self.select | |
class InteractorStyle(vtk.vtkInteractorStyleTrackballCamera, abc.ABC): | |
def init_renders(self) -> List[vtk.vtkRenderer]: | |
raise NotImplementedError | |
def button_release_event(self, to_do): | |
raise NotImplementedError | |
def draw_end(self): | |
raise NotImplementedError | |
def stage(self) -> ui_controllers.GmmMeshStage: | |
return self.status.main_stage | |
def canvas(self): | |
if self.draw_view == -1: | |
return None | |
return self.renders[self.draw_view] | |
def interactor(self): | |
return self.GetInteractor() | |
class MouseStatus: | |
def update(self, pos: Tuple[int, int], selected_view: int) -> bool: | |
is_changed = selected_view != self.selected_view or (pos[0] - self.last_pos[0]) ** 2 > 4 and ( | |
pos[1] - self.last_pos[1]) ** 2 > 4 | |
self.selected_view = selected_view | |
self.last_pos = pos | |
return is_changed | |
def __init__(self): | |
self.last_pos = (0, 0) | |
self.selected_view = 0 | |
def change_opacity(self, sphere_ids: List[int], is_left: bool, on: bool): | |
actors = self.renders[self.selected_view].GetActors() | |
for sphere_ids in sphere_ids: | |
properties = actors.GetItemAsObject(sphere_ids).GetProperty() | |
properties.SetOpacity(float(on)) | |
def slider_event(self, slider, event): | |
value = slider.GetRepresentation().GetValue() | |
value = value / 100. | |
self.stage.set_opacity(value) | |
return | |
def get_cur_view(self): | |
cur_render = self.GetCurrentRenderer() | |
if cur_render is None: | |
return -1, cur_render | |
return self.rend_to_view[cur_render.GetAddressAsString("")], cur_render | |
def update_default(self): | |
click_pos = self.interactor.GetEventPosition() | |
picker = vtk.vtkPropPicker() | |
cur_view, cur_render = self.get_cur_view() | |
if cur_view != self.selected_view: | |
# self.SetDefaultRenderer(self.renders[cur_view]) | |
self.selected_view = cur_view | |
elif cur_render is None: | |
return None, False, click_pos | |
picker.Pick(click_pos[0], click_pos[1], 0, cur_render) | |
return picker, self.mouse_status.update((click_pos[0], click_pos[1]), cur_view), click_pos | |
def get_trace(self): | |
picker, is_changed, pos_2d = self.update_default() | |
if picker is not None: | |
points = self.canvas.draw(pos_2d) | |
actors = [] | |
for point in points: | |
picker.Pick(point[0], point[1], 0, self.canvas) | |
actors.append(picker.GetActor()) | |
self.status.vote(*actors) | |
self.interactor.Render() | |
return 0 | |
def on_key_press(self, obj, event): | |
key = self.interactor.GetKeySym() | |
if type(key) is not str: | |
return | |
key: str = key.lower() | |
if self.pondering: | |
if key in ('g', 'r'): | |
self.edit_status = {'g': ui_utils.EditType.Translating, | |
'r': ui_utils.EditType.Rotating, | |
's': ui_utils.EditType.Scaling}[key] | |
click_pos = self.interactor.GetEventPosition() | |
self.status.init_transition(click_pos, self.edit_status) | |
elif key == 'escape': | |
if self.status.clear_selection(): | |
self.interactor.Render() | |
elif self.in_transition: | |
if key == 'escape': | |
self.status.temporary_transition() | |
self.interactor.Render() | |
self.edit_status = ui_utils.EditType.Pondering | |
elif key in ('x', 'y', 'z'): | |
self.status.toggle_edit_direction({'x': ui_utils.EditDirection.X_Axis, | |
'y': ui_utils.EditDirection.Y_Axis, | |
'z': ui_utils.EditDirection.Z_Axis}[key]) | |
if key == 'return' or key == 'kp_enter': | |
self.status.save() | |
# elif key in ("left", "right", "up", "down", "a", "z"): | |
# if self.status.update_gmm(ui_utils.Buttons.translate, key): | |
# self.status.update_mesh() | |
# self.interactor.Render() | |
# axis = {"left": 0, "right", "up", "down", "a", "z") | |
elif key == 'control_l': | |
self.status.replace_mesh() | |
self.interactor.Render() | |
return | |
def draw_init(self): | |
self.status.init_draw(self.draw_view) | |
def left_button_release_event(self, obj, event): | |
if self.pondering: | |
# self.button_release_event(self.status.event_manger) | |
self.OnLeftButtonUp() | |
def left_button_press_event(self, obj, event): | |
if self.pondering: | |
_ = self.update_default() | |
self.OnLeftButtonDown() | |
elif self.in_transition: | |
click_pos = self.interactor.GetEventPosition() | |
if self.status.end_transition(click_pos): | |
self.status.update_mesh() | |
self.edit_status = ui_utils.EditType.Pondering | |
def right_button_release_event(self, obj, event): | |
if self.marking: | |
self.draw_end() | |
self.edit_status = ui_utils.EditType.Pondering | |
def right_button_press_event(self, obj, event): | |
self.OnRightButtonDown() | |
self.OnRightButtonUp() | |
_ = self.update_default() | |
if -1 < self.selected_view and self.pondering: | |
self.draw_view = self.selected_view | |
self.draw_init() | |
self.edit_status = ui_utils.EditType.Marking | |
def on_mouse_move(self, obj, event): | |
if self.marking: | |
self.get_trace() | |
elif self.in_transition: | |
click_pos = self.interactor.GetEventPosition() | |
if self.status.temporary_transition(click_pos): | |
self.interactor.Render() | |
else: | |
super(InteractorStyle, self).OnMouseMove() | |
def toggle_symmetric(self, _, __): | |
self.status.toggle_symmetric() | |
self.interactor.Render() | |
def toggle_arrows(self, button, __): | |
self.status.switch_arrows({0: ui_utils.Buttons.translate, 1: ui_utils.Buttons.rotate}[button.GetRepresentation().GetState()]) | |
self.interactor.Render() | |
def reset(self, obj, event): | |
self.status.reset() | |
self.interactor.Render() | |
def toggle_select_mode(self, button, __): | |
self.select_mode = button.GetRepresentation().GetState() == 0 | |
self.status.set_brush(self.select_mode) | |
self.interactor.Render() | |
def add_buttons(self, interactor): | |
button_pencil = ui_utils.ImageButton(["../assets/ui_resources/icons-03.png", "../assets/ui_resources/icons-04.png"], | |
ui_utils.bg_menu_color, interactor, (.1, .1), (0.24, 0.15), | |
interactor.GetRenderWindow(), self.toggle_select_mode) | |
button_symmetric = ui_utils.ImageButton(["../assets/ui_resources/icons-08.png", "../assets/ui_resources/icons-09.png"], | |
ui_utils.bg_menu_color, interactor, (.1, .1), (0.3, 0.15), | |
interactor.GetRenderWindow(), self.toggle_symmetric) | |
button_reset = ui_utils.ImageButton(["../assets/ui_resources/icons-05.png"], ui_utils.bg_menu_color, interactor, | |
(.1, .1), (0.35, .15), interactor.GetRenderWindow(), self.reset) | |
slider_widget, _ = ui_utils.make_slider(interactor, self.slider_event) | |
return button_pencil, button_symmetric, button_reset, slider_widget | |
def marking(self) -> bool: | |
return self.edit_status == ui_utils.EditType.Marking | |
def pondering(self) -> bool: | |
return self.edit_status == ui_utils.EditType.Pondering | |
def translating(self) -> bool: | |
return self.edit_status == ui_utils.EditType.Translating | |
def rotating(self) -> bool: | |
return self.edit_status == ui_utils.EditType.Rotating | |
def scaling(self) -> bool: | |
return self.edit_status == ui_utils.EditType.Scaling | |
def in_transition(self): | |
return self.translating or self.rotating or self.scaling | |
def __init__(self, opt: options.Options, status: ui_controllers.MeshGmmStatuses, interactor: vtk.vtkRenderWindowInteractor): | |
super(InteractorStyle, self).__init__() | |
self.mouse_status = self.MouseStatus() | |
self.opt = opt | |
self.edit_status = ui_utils.EditType.Pondering | |
self.edit_direction = ui_utils.EditDirection.X_Axis | |
self.select_mode = True | |
self.AddObserver(vtk.vtkCommand.KeyPressEvent, self.on_key_press) | |
self.AddObserver(vtk.vtkCommand.MouseMoveEvent, self.on_mouse_move) | |
self.AddObserver(vtk.vtkCommand.LeftButtonReleaseEvent, self.left_button_release_event) | |
self.AddObserver(vtk.vtkCommand.LeftButtonPressEvent, self.left_button_press_event) | |
self.AddObserver(vtk.vtkCommand.RightButtonReleaseEvent, self.right_button_release_event) | |
self.AddObserver(vtk.vtkCommand.RightButtonPressEvent, self.right_button_press_event) | |
self.AddObserver(vtk.vtkCommand.CharEvent, lambda _, __: None) | |
self.status = status | |
self.renders = self.init_renders() | |
self.rend_to_view = {render.GetAddressAsString(""): i for i, render in enumerate(self.renders)} | |
self.selected_view = -1 | |
self.draw_view = -1 | |
self.buttons = self.add_buttons(interactor) | |
class MixInteractorStyle(InteractorStyle): | |
def draw_end(self): | |
self.canvas.clear() | |
if self.status.aggregate_votes(self.select_mode): | |
self.status.update_mesh() | |
self.interactor.Render() | |
def init_renders(self) -> List[vtk.vtkRenderer]: | |
return [stage.render for stage in self.status.stages] + [self.status.main_stage.render] | |
# def on_key_press(self, obj, event): | |
# key = self.interactor.GetKeySym() | |
# if type(key) is not str: | |
# return | |
# key: str = key.lower() | |
# if key == 'return' or key == 'kp_enter': | |
# self.status.save() | |
# if key == 'space': | |
# self.mark_ready = True | |
# # if self.status.update_mesh(): | |
# # self.interactor.Render() | |
# # # if key == 'f' or key == 'F': | |
# # self.status.flip(1 - int(self.is_left_viewport)) | |
# # if key == 'f': | |
# # self.status.flip(1 - int(self.is_left_viewport)) | |
# elif key in ("left", "right", "up", "down", "a", "z"): | |
# if self.status.update_gmm(ui_utils.Buttons.translate, key): | |
# self.status.update_mesh() | |
# self.interactor.Render() | |
# # axis = {"left": 0, "right", "up", "down", "a", "z") | |
# elif key == 'control_l': | |
# self.status.replace_mesh() | |
# self.interactor.Render() | |
# # if key == 'b' or key == 'B': | |
# # self.mesh_stage_left.replace_mesh(files_utils.load_mesh( | |
# # r"C:\Users\t-amhert\PycharmProjects\sdf_gmm\assets\checkpoints\sdformer_sn_chairs_deep\sdfs/samples_953")) | |
def button_release_event(self, to_do): | |
picker, is_changed, _ = self.update_default() | |
if picker is not None and not is_changed: | |
picked_actor = picker.GetActor() | |
if picked_actor: | |
object_id = picked_actor.GetAddressAsString('') | |
if to_do(object_id): | |
self.status.update_mesh(128) | |
class SingleInteractorStyle(InteractorStyle): | |
def draw_end(self): | |
self.canvas.clear() | |
if self.status.aggregate_votes(self.select_mode): | |
self.interactor.Render() | |
def init_renders(self) -> List[vtk.vtkRenderer]: | |
return [stage.render for stage in self.status.stages] | |
def button_release_event(self, to_do): | |
picker, is_changed, _ = self.update_default() | |
if picker is not None and not is_changed: | |
picked_actor = picker.GetActor() | |
if picked_actor: | |
mapper = picked_actor.GetMapper() | |
object_id = mapper.GetAddressAsString('') | |
if to_do(object_id): | |
self.status.update_mesh(128) | |