|
|
@ -8,26 +8,31 @@ To be clear, the actual widget is defined in the UI |
|
|
|
generated code - `clusterview_ui.py`. The functions |
|
|
|
generated code - `clusterview_ui.py`. The functions |
|
|
|
here are imported as overrides to the OpenGL functions of |
|
|
|
here are imported as overrides to the OpenGL functions of |
|
|
|
that widget. |
|
|
|
that widget. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
It should be split up into a few more separate files eventually... |
|
|
|
|
|
|
|
Probably even into it's own module folder. |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
from enum import Enum |
|
|
|
from enum import Enum |
|
|
|
|
|
|
|
|
|
|
|
from OpenGL.GL import (glBegin, glClearColor, glColor4f, glEnable, |
|
|
|
from OpenGL.GL import (glBegin, glClearColor, glColor4f, glEnable, |
|
|
|
glEnd, GL_LIGHT0, GL_LIGHTING, GL_POINTS, |
|
|
|
glEnd, GL_LIGHT0, GL_LIGHTING, GL_LINE_LOOP, GL_POINTS, |
|
|
|
glPointSize, glVertex3f, glViewport) |
|
|
|
glPointSize, glVertex3f, glViewport) |
|
|
|
|
|
|
|
|
|
|
|
from .exceptions import InvalidModeError, InvalidStateError |
|
|
|
from .exceptions import handle_exceptions, InvalidModeError, InvalidStateError |
|
|
|
from .mode import Mode |
|
|
|
from .mode import Mode |
|
|
|
from .points import PointSet |
|
|
|
from .points import PointSet |
|
|
|
|
|
|
|
|
|
|
|
class Color(Enum): |
|
|
|
class Color(Enum): |
|
|
|
BLUE = 0 |
|
|
|
BLUE = 0 |
|
|
|
|
|
|
|
BLACK = 1 |
|
|
|
|
|
|
|
|
|
|
|
# A simple map from Color -> RGBA 4-Tuple |
|
|
|
# A simple map from Color -> RGBA 4-Tuple |
|
|
|
# Note: The color values in the tuple are not RGB, but |
|
|
|
# Note: The color values in the tuple are not RGB, but |
|
|
|
# rather OpenGL percentage values for RGB. |
|
|
|
# rather OpenGL percentage values for RGB. |
|
|
|
COLOR_TO_RGBA = { |
|
|
|
COLOR_TO_RGBA = { |
|
|
|
Color.BLUE: (0, 0.5, 1.0, 0.0) |
|
|
|
Color.BLUE: (0, 0.5, 1.0, 0.0), |
|
|
|
|
|
|
|
Color.BLACK: (0.0, 0.0, 0.0, 0.0) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# Constants set based on the size of the window. |
|
|
|
# Constants set based on the size of the window. |
|
|
@ -35,6 +40,11 @@ __BOTTOM_LEFT = (0, 0) |
|
|
|
__WIDTH = None |
|
|
|
__WIDTH = None |
|
|
|
__HEIGHT = None |
|
|
|
__HEIGHT = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# State variables for a move selection bounding box. |
|
|
|
|
|
|
|
# There are always reset to None after a selection has been made. |
|
|
|
|
|
|
|
__move_bb_top_left = None |
|
|
|
|
|
|
|
__move_bb_bottom_right = None |
|
|
|
|
|
|
|
|
|
|
|
# Module-global state variables for our drawing |
|
|
|
# Module-global state variables for our drawing |
|
|
|
# state machine. |
|
|
|
# state machine. |
|
|
|
# |
|
|
|
# |
|
|
@ -117,6 +127,38 @@ def set_drawing_event(event): |
|
|
|
__current_event = event |
|
|
|
__current_event = event |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_move_bb_top_left(x, y): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Called to set the move bounding box's top left corner. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@param x The x-coordinate. |
|
|
|
|
|
|
|
@param y The y-coordinate. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
global __move_bb_top_left |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__move_bb_top_left = (x, y) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_move_bb_bottom_right(x, y): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Called to set the move bounding box's bottom right corner. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@param x The x-coordinate. |
|
|
|
|
|
|
|
@param y The y-coordinate. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
global __move_bb_bottom_right |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__move_bb_bottom_right = (x, y) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def reset_move_bbs(): |
|
|
|
|
|
|
|
global __move_bb_top_left |
|
|
|
|
|
|
|
global __move_bb_bottom_right |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__move_bb_top_left = None |
|
|
|
|
|
|
|
__move_bb_bottom_right = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize_gl(): |
|
|
|
def initialize_gl(): |
|
|
|
""" |
|
|
|
""" |
|
|
|
Initializes the OpenGL context on the Window. |
|
|
|
Initializes the OpenGL context on the Window. |
|
|
@ -144,6 +186,7 @@ def resize_gl(w, h): |
|
|
|
__HEIGHT = __current_context.height() |
|
|
|
__HEIGHT = __current_context.height() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@handle_exceptions |
|
|
|
def paint_gl(): |
|
|
|
def paint_gl(): |
|
|
|
""" |
|
|
|
""" |
|
|
|
Stock PaintGL function from OpenGL that switches |
|
|
|
Stock PaintGL function from OpenGL that switches |
|
|
@ -155,10 +198,9 @@ def paint_gl(): |
|
|
|
raise InvalidStateError("Event must exist for ADD, EDIT, MOVE, " + |
|
|
|
raise InvalidStateError("Event must exist for ADD, EDIT, MOVE, " + |
|
|
|
"and DELETE") |
|
|
|
"and DELETE") |
|
|
|
|
|
|
|
|
|
|
|
if (__current_mode in [Mode.ADD, Mode.EDIT, Mode.MOVE, Mode.DELETE] and |
|
|
|
if (__current_mode in [Mode.ADD, Mode.EDIT, Mode.DELETE] and |
|
|
|
__current_points is None): |
|
|
|
__current_points is None): |
|
|
|
raise InvalidStateError("Points must exist for ADD, EDIT, MOVE, " + |
|
|
|
return |
|
|
|
"and DELETE") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __current_mode is Mode.ADD or __current_mode is Mode.DELETE: |
|
|
|
if __current_mode is Mode.ADD or __current_mode is Mode.DELETE: |
|
|
|
# Note that drawing the points doesn't require a bounding box or |
|
|
|
# Note that drawing the points doesn't require a bounding box or |
|
|
@ -167,10 +209,29 @@ def paint_gl(): |
|
|
|
# is the same as adding a point since we just draw what is in |
|
|
|
# is the same as adding a point since we just draw what is in |
|
|
|
# the point set. |
|
|
|
# the point set. |
|
|
|
draw_points(__current_points, Color.BLUE) |
|
|
|
draw_points(__current_points, Color.BLUE) |
|
|
|
|
|
|
|
|
|
|
|
elif __current_mode is Mode.EDIT: |
|
|
|
elif __current_mode is Mode.EDIT: |
|
|
|
raise NotImplementedError("Drawing for EDIT not implemented.") |
|
|
|
raise NotImplementedError("Drawing for EDIT not implemented.") |
|
|
|
|
|
|
|
|
|
|
|
elif __current_mode is Mode.MOVE: |
|
|
|
elif __current_mode is Mode.MOVE: |
|
|
|
raise NotImplementedError("Drawing for MOVE not implemented.") |
|
|
|
# We have to repeatedly draw the points while we are showing the |
|
|
|
|
|
|
|
# move box. |
|
|
|
|
|
|
|
if __current_points is not None: |
|
|
|
|
|
|
|
draw_points(__current_points, Color.BLUE) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
draw_selection_box(Color.BLACK) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __move_bb_top_left is None and __move_bb_bottom_right is None: |
|
|
|
|
|
|
|
# Currently this fires all the time - not great. Needs to only fire |
|
|
|
|
|
|
|
# when, additionally, we have a selection chosen based on the box |
|
|
|
|
|
|
|
# calculated in the mode handlers. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("FIRE THE MOVE STUFF") |
|
|
|
|
|
|
|
# Once the selection boxes go to None begin the highlight selected |
|
|
|
|
|
|
|
# points procedure. This will store a point list of selected points |
|
|
|
|
|
|
|
# highlight them, etc. |
|
|
|
|
|
|
|
# Once thats done moving points will be difficult but do-able. |
|
|
|
|
|
|
|
|
|
|
|
elif __current_mode is Mode.DELETE: |
|
|
|
elif __current_mode is Mode.DELETE: |
|
|
|
raise NotImplementedError("Drawing for DELETE not implemented.") |
|
|
|
raise NotImplementedError("Drawing for DELETE not implemented.") |
|
|
|
|
|
|
|
|
|
|
@ -199,6 +260,60 @@ def __clamp_y(y): |
|
|
|
return y_w |
|
|
|
return y_w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def draw_selection_box(color): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
When the move bounding box state is populated and the mode is set |
|
|
|
|
|
|
|
to MODE.Move this function will draw the selection bounding box. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@param color The color Enum. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
global __current_context |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __current_context is None: |
|
|
|
|
|
|
|
raise InvalidStateError("Drawing context must be set before setting " + |
|
|
|
|
|
|
|
"drawing mode") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not isinstance(color, Color): |
|
|
|
|
|
|
|
raise ValueError("Color must exist in the Color enumeration") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __move_bb_top_left is None or __move_bb_bottom_right is None: |
|
|
|
|
|
|
|
# Nothing to draw. |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ct = COLOR_TO_RGBA[color] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glViewport(0, 0, __WIDTH, __HEIGHT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Top right corner has the same x as the bottom right |
|
|
|
|
|
|
|
# and same y as the top left. |
|
|
|
|
|
|
|
top_right_corner = (__move_bb_bottom_right[0], __move_bb_top_left[1]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Bottom left corner has the same x as the top left and |
|
|
|
|
|
|
|
# same y as the bottom right. |
|
|
|
|
|
|
|
bottom_left_corner = (__move_bb_top_left[0], __move_bb_bottom_right[1]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glBegin(GL_LINE_LOOP) |
|
|
|
|
|
|
|
glColor4f(ct[0], ct[1], ct[2], ct[3]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glVertex3f(__clamp_x(__move_bb_top_left[0]), |
|
|
|
|
|
|
|
__clamp_y(__move_bb_top_left[1]), |
|
|
|
|
|
|
|
0.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glVertex3f(__clamp_x(top_right_corner[0]), |
|
|
|
|
|
|
|
__clamp_y(top_right_corner[1]), |
|
|
|
|
|
|
|
0.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glVertex3f(__clamp_x(__move_bb_bottom_right[0]), |
|
|
|
|
|
|
|
__clamp_y(__move_bb_bottom_right[1]), |
|
|
|
|
|
|
|
0.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glVertex3f(__clamp_x(bottom_left_corner[0]), |
|
|
|
|
|
|
|
__clamp_y(bottom_left_corner[1]), |
|
|
|
|
|
|
|
0.0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glEnd() |
|
|
|
|
|
|
|
|
|
|
|
def draw_points(point_set, color): |
|
|
|
def draw_points(point_set, color): |
|
|
|
""" |
|
|
|
""" |
|
|
|
Simple point drawing function. |
|
|
|
Simple point drawing function. |
|
|
|