|
|
|
@ -14,23 +14,58 @@ from enum import Enum
|
|
|
|
|
|
|
|
|
|
from OpenGL.GL import (glBegin, glClearColor, glColor4f, glEnable, |
|
|
|
|
glEnd, GL_LIGHT0, GL_LIGHTING, GL_POINTS, |
|
|
|
|
glVertex3f) |
|
|
|
|
glPointSize, glVertex3f, glViewport) |
|
|
|
|
|
|
|
|
|
from clusterview.exceptions import InvalidStateError |
|
|
|
|
from clusterview.mode import InvalidMode, Mode |
|
|
|
|
from .exceptions import InvalidModeError, InvalidStateError |
|
|
|
|
from .mode import Mode |
|
|
|
|
|
|
|
|
|
class Color(Enum): |
|
|
|
|
BLUE = 0 |
|
|
|
|
|
|
|
|
|
# A simple map from Color -> RGBA 4-Tuple |
|
|
|
|
# Note: The color values in the tuple are not RGB, but |
|
|
|
|
# rather OpenGL percentage values for RGB. |
|
|
|
|
COLOR_TO_RGBA = { |
|
|
|
|
Color.BLUE: (0, 128, 255, 255) |
|
|
|
|
Color.BLUE: (0, 0.5, 1.0, 0.0) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
# Size of point for drawing |
|
|
|
|
__POINT_SIZE = 8 |
|
|
|
|
|
|
|
|
|
# Constants set based on the size of the window. |
|
|
|
|
__BOTTOM_LEFT = (0, 0) |
|
|
|
|
__WIDTH = None |
|
|
|
|
__HEIGHT = None |
|
|
|
|
|
|
|
|
|
# Module-global state variables for our drawing |
|
|
|
|
# state machine. |
|
|
|
|
# |
|
|
|
|
# Below functions have to mark these as `global` so |
|
|
|
|
# the interpreter knows that the variables are not |
|
|
|
|
# function local. |
|
|
|
|
__current_mode = None |
|
|
|
|
__current_event = None |
|
|
|
|
__current_context = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_drawing_context(ctx): |
|
|
|
|
""" |
|
|
|
|
Sets the drawing context so that drawing functions can properly |
|
|
|
|
interact with the widget. |
|
|
|
|
""" |
|
|
|
|
global __current_context |
|
|
|
|
|
|
|
|
|
def set_drawing_mode(mode, event=None): |
|
|
|
|
print("CALLING SET DRAWING CONTEXT: {}".format(ctx)) |
|
|
|
|
__current_context = ctx |
|
|
|
|
|
|
|
|
|
print("WIDTH OF OPENGL WINDOW: {}".format(__WIDTH)) |
|
|
|
|
print("HEIGHT OF OPENGL WINDOW: {}".format(__HEIGHT)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("SETTING: {}".format(__current_context)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_drawing_mode(mode): |
|
|
|
|
""" |
|
|
|
|
State management function. It is useful to look at the |
|
|
|
|
different drawing modes as modes in a state machine. |
|
|
|
@ -40,22 +75,44 @@ def set_drawing_mode(mode, event=None):
|
|
|
|
|
on the OpenGL Widget. |
|
|
|
|
|
|
|
|
|
@param mode The current mode. |
|
|
|
|
@param event The current event (Mostly used for passing coordinates). |
|
|
|
|
""" |
|
|
|
|
global __current_context |
|
|
|
|
global __current_mode |
|
|
|
|
|
|
|
|
|
print("SET DRAWING MODE CONTEXT: {}".format(__current_context)) |
|
|
|
|
if __current_context is None: |
|
|
|
|
raise InvalidStateError("Drawing context must be set before setting " + |
|
|
|
|
"drawing mode") |
|
|
|
|
|
|
|
|
|
if not isinstance(mode, Mode): |
|
|
|
|
raise ValueError("Mode in set_drawing_mode must be of type Mode") |
|
|
|
|
|
|
|
|
|
print("CALL FROM SET_DRAWING_MODE(MODE = {})".format(mode)) |
|
|
|
|
|
|
|
|
|
__current_mode = mode |
|
|
|
|
|
|
|
|
|
if event is not None: |
|
|
|
|
__current_event = event |
|
|
|
|
print("SET LOCALS (CURRENT MODE: {})".format(__current_mode)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_current_mode(): |
|
|
|
|
def set_drawing_event(event): |
|
|
|
|
""" |
|
|
|
|
Returns the current mode according to the OpenGL Widget. |
|
|
|
|
State machine event management function. |
|
|
|
|
|
|
|
|
|
@param event The event. |
|
|
|
|
""" |
|
|
|
|
return __current_mode |
|
|
|
|
global __current_context |
|
|
|
|
global __current_event |
|
|
|
|
|
|
|
|
|
if __current_context is None: |
|
|
|
|
raise InvalidStateError("Drawing context must be set before setting " + |
|
|
|
|
"drawing mode") |
|
|
|
|
|
|
|
|
|
print("CALL FROM SET_DRAWING_EVENT(event = {})".format(event)) |
|
|
|
|
|
|
|
|
|
if event is not None: |
|
|
|
|
__current_event = event |
|
|
|
|
|
|
|
|
|
print("SET LOCALS (CURRENT EVENT: {})".format(__current_event)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize_gl(): |
|
|
|
@ -71,20 +128,36 @@ def initialize_gl():
|
|
|
|
|
glClearColor(255, 255, 255, 0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def resize_gl(w, h): |
|
|
|
|
""" |
|
|
|
|
OpenGL resize handler used to get the current viewport size. |
|
|
|
|
|
|
|
|
|
@param w The new width. |
|
|
|
|
@param h The new height. |
|
|
|
|
""" |
|
|
|
|
global __WIDTH |
|
|
|
|
global __HEIGHT |
|
|
|
|
|
|
|
|
|
__WIDTH = __current_context.width() |
|
|
|
|
__HEIGHT = __current_context.height() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def paint_gl(): |
|
|
|
|
""" |
|
|
|
|
Stock PaintGL function from OpenGL that switches |
|
|
|
|
on the current mode to determine what action to |
|
|
|
|
perform on the current event. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
if (__current_mode in [Mode.ADD, Mode.EDIT, Mode.MOVE, Mode.DELETE] and |
|
|
|
|
__current_event is None): |
|
|
|
|
raise InvalidStateError("Event must exist for ADD, EDIT, MOVE, " + |
|
|
|
|
"and DELETE") |
|
|
|
|
|
|
|
|
|
if __current_mode is Mode.ADD: |
|
|
|
|
raise NotImplementedError("Drawing for ADD not implemented.") |
|
|
|
|
# TODO: This needs to be modified to instead take the point list |
|
|
|
|
# and redraw the entire list (which will have the new point |
|
|
|
|
# added) each click. |
|
|
|
|
draw_points(__current_event.x(), __current_event.y(), Color.BLUE) |
|
|
|
|
elif __current_mode is Mode.EDIT: |
|
|
|
|
raise NotImplementedError("Drawing for EDIT not implemented.") |
|
|
|
|
elif __current_mode is Mode.MOVE: |
|
|
|
@ -93,7 +166,33 @@ def paint_gl():
|
|
|
|
|
raise NotImplementedError("Drawing for DELETE not implemented.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def draw_point(x, y, color): |
|
|
|
|
def __clamp_x(x): |
|
|
|
|
""" |
|
|
|
|
X-coordinate clamping function that goes from mouse coordinates to |
|
|
|
|
OpenGL coordinates. |
|
|
|
|
|
|
|
|
|
@param x The x-coordinate to clamp. |
|
|
|
|
@returns The clamped x coordinate. |
|
|
|
|
""" |
|
|
|
|
x_w = (x / (__WIDTH / 2.0) - 1.0) |
|
|
|
|
print(x_w) |
|
|
|
|
return x_w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __clamp_y(y): |
|
|
|
|
""" |
|
|
|
|
Y-coordinate clamping function that goes from mouse coordinates to |
|
|
|
|
OpenGL coordinates. |
|
|
|
|
|
|
|
|
|
@param y The y-coordinate to clamp. |
|
|
|
|
@returns The clamped y coordinate. |
|
|
|
|
""" |
|
|
|
|
y_w = -1.0 * (y / (__HEIGHT / 2.0) - 1.0) |
|
|
|
|
print(y_w) |
|
|
|
|
return y_w |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def draw_points(x, y, color): |
|
|
|
|
""" |
|
|
|
|
Simple point drawing function. |
|
|
|
|
|
|
|
|
@ -105,15 +204,27 @@ def draw_point(x, y, color):
|
|
|
|
|
@param y The y-coordinate. |
|
|
|
|
@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") |
|
|
|
|
|
|
|
|
|
ct = COLOR_TO_RGBA[color] |
|
|
|
|
|
|
|
|
|
glBegin(GL_POINTS) |
|
|
|
|
print("DRAW POINT - DRAWING WITH COLOR {}".format(ct)) |
|
|
|
|
|
|
|
|
|
glViewport(0, 0, __WIDTH, __HEIGHT) |
|
|
|
|
glPointSize(__POINT_SIZE) |
|
|
|
|
glColor4f(ct[0], ct[1], ct[2], ct[3]) |
|
|
|
|
glVertex3f(x, y, 0.0) # Z is currently fixed to 0 |
|
|
|
|
|
|
|
|
|
glBegin(GL_POINTS) |
|
|
|
|
glVertex3f(__clamp_x(__current_event.x()), |
|
|
|
|
__clamp_y(__current_event.y()), |
|
|
|
|
0.0) # Z is currently fixed to 0 |
|
|
|
|
glEnd() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|