1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
# Copyright 2007-2008 Nanorex, Inc. See LICENSE file for details.
"""
DirectionArrow.py
@author: Ninad
@version: $Id$
@copyright: 2007-2008 Nanorex, Inc. See LICENSE file for details.
History:
ninad 2007-06-12: Created this class (initially) to support the implementation
of 'offset plane' (was created in Plane.py)
ninad 2007-08-20: Split it out of Plane.py into this new file.
TODO:
- Need to implement some grid plane features.
- Plane should be selectable when clicked anywhere inside.
"""
from OpenGL.GL import glPushName
from OpenGL.GL import glPopName
from OpenGL.GL import glPushMatrix
from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
from OpenGL.GL import glPopMatrix
from graphics.drawing.CS_draw_primitives import drawDirectionArrow
from geometry.VQT import V, norm, vlen
from math import pi
from utilities.constants import gray, orange
from utilities.debug import print_compact_traceback
from graphics.drawables.DragHandler import DragHandler_API
from graphics.drawables.Selobj import Selobj_API
import foundation.env as env
ONE_RADIAN = 180.0 / pi
# One radian = 57.29577951 degrees
# This is for optimization since this computation occurs repeatedly
# in very tight drawning loops. --Mark 2007-08-14
class DirectionArrow(DragHandler_API, Selobj_API):
"""
The DirectionArrow class provides a 3D direction arrow that can be
interacted with in the 3D graphics area. The direction arrow object
is created in its parent class. (class corresponding to self.parent)
Example: Used to generate a plane offset to the selected plane,
in the direction indicated by the direction arrow.
Clicking on the arrow reverses its direction and
thus the direction of the plane placement.
"""
def __init__(self, parent, glpane, tailPoint, defaultDirection):
"""
Creates a direction arrow.
@param parent: The parent object.
@type parent:
@param glpane: The 3D graphics area object.
@type glpane: L{GLPane}
@param tailPoint: The origin of the arrow.
@type tailPoint: V
@param defaultDirection: The direction of the arrow.
@type defaultDirection:
"""
self.parent = parent
self.glpane = glpane
self.tailPoint = tailPoint
self.direction = defaultDirection
self.glname = glpane.alloc_my_glselect_name(self) #bruce 080917 revised
self.flipDirection = False
self.drawRequested = False
def setDrawRequested(self, bool_request = False):
"""
Sets the draw request for drawing the direction arrow.
This class's draw method is called in the parent class's draw method
This functions sets the flag that decides whether to draw direction
arrow (the flag value is returned using isDrawRequested method.
@param bool_request: Default is False. (request to draw direction arrow)
@type bool_request: bool
"""
self.drawRequested = bool_request
def isDrawRequested(self):
"""
Returns the flag that decides whether to draw the direction arrow.
@return B{self.drawRequested} (boolean value)
@rtype instance variable B{self.drawRequested}
"""
return self.drawRequested
def draw(self):
"""
Draw the direction arrow. (This method is called inside of the
parent object's drawing code.
"""
try:
glPushName(self.glname)
if self.flipDirection:
self._draw(flipDirection = self.flipDirection)
else:
self._draw()
except:
glPopName()
print_compact_traceback("ignoring exception when drawing handle %r: " % self)
else:
glPopName()
pass
def _draw(self, flipDirection = False, highlighted = False):
""" Main drawing code.
@param flipDirection: This flag decides the direction in which the
arrow is drawn. This value is set in the leftClick method.
The default value is 'False'
@type flipDirection: bool
@param highlighted: Decids the color of the arrow based on whether
it is highlighted. The default value is 'False'
@type highlighted: bool
"""
if highlighted:
color = orange
else:
color = gray
if flipDirection:
#@NOTE: Remember we are drawing the arrow inside of the _draw_geometry
#so its drawing it in the translated coordinate system (translated
#at the center of the Plane. So we should do the following.
#(i.e. use V(0,0,1)). This will change if we decide to draw the
#direction arrow outside of the parent object
#requesting this drawing.--ninad 20070612
#Using headPoint = self.tailPoint + V(0,0,1) * 2.0 etc along with
#the transformation matrix in self.draw_in_abs_coordinate()
#fixes bug 2702 and 2703 -- Ninad 2008-06-11
headPoint = self.tailPoint + V(0,0,1) * 2.0
##headPoint = self.tailPoint + 2.0 * norm(self.parent.getaxis())
else:
headPoint = self.tailPoint - V(0,0,1) * 2.0
##headPoint = self.tailPoint - 2.0 * self.parent.getaxis()
vec = vlen(headPoint - self.tailPoint)
vec = self.glpane.scale*0.07*vec
tailRadius = vlen(vec)*0.16
drawDirectionArrow(color,
self.tailPoint,
headPoint,
tailRadius,
self.glpane.scale,
flipDirection = flipDirection)
def draw_in_abs_coords(self, glpane, color):
"""
Draw the handle as a highlighted object.
@param glpane: B{GLPane} object
@type glpane: L{GLPane}
@param color: Highlight color
"""
q = self.parent.quat
glPushMatrix()
glTranslatef( self.parent.center[0],
self.parent.center[1],
self.parent.center[2])
glRotatef( q.angle * ONE_RADIAN,
q.x,
q.y,
q.z)
if self.flipDirection:
self._draw(flipDirection = self.flipDirection,
highlighted = True)
else:
self._draw(highlighted = True)
glPopMatrix()
###=========== Drag Handler interface Starts =============###
#@TODO Need some documentation. Basically it implements the drag handler
#interface described in DragHandler.py See also exprs.Highlightable.py
# -- ninad 20070612
def handles_updates(self):
return True
def DraggedOn(self, event, mode):
return
def ReleasedOn(self, selobj, event, mode):
pass
# =========== Drag Handler interface Ends =============
# ============== selobj interface Starts ==============
#@TODO Need some documentation. Basically it implements the selobj
# interface mentioned in exprs.Highlightable.py -- ninad 2007-06-12
def leftClick(self, point, event, mode):
"""
Left clicking on the DirectionArrow flips its direction.
@param point: not used for now.
@type point: V
@param event: Left down event.
@type event: QEvent
@param mode: Current mode program is in.
@type mode: L{anyMode}
"""
self.flipDirection = not self.flipDirection
mode.update_selobj(event)
mode.o.gl_update()
return self
def mouseover_statusbar_message(self):
"""
Returns the statusbar message to display when the cursor is over the
direction arrow in the 3D graphics area.
@return: The statusbar message
@rtype: str
"""
msg1 = "Click on arrow to flip its direction"
return msg1
def highlight_color_for_modkeys(self, modkeys):
return orange
# Copied Bruce's code from class Highlightable with some mods.
# Need to see if selobj_still_ok() is needed. OK for now.
# --Ninad 2007-05-31
def selobj_still_ok(self, glpane):
res = self.__class__ is DirectionArrow
if res:
our_selobj = self
glname = self.glname
owner = glpane.assy.object_for_glselect_name(glname)
if owner is not our_selobj:
res = False
# Do debug prints.
print "%r no longer owns glname %r, instead %r does" \
% (self, glname, owner) # [perhaps never seen as of 061121]
pass
pass
if not res and env.debug():
print "debug: selobj_still_ok is false for %r" % self
return res
###============== selobj interface Ends===============###
pass
|