primera subida
This commit is contained in:
533
Utils/graphics - copia.py
Normal file
533
Utils/graphics - copia.py
Normal file
@@ -0,0 +1,533 @@
|
||||
from pivy import coin
|
||||
#from pivy.utils import getPointOnScreen
|
||||
|
||||
def getPointOnScreen(render_manager, screen_pos, normal="camera", point=None):
|
||||
"""get coordinates from pixel position"""
|
||||
|
||||
pCam = render_manager.getCamera()
|
||||
vol = pCam.getViewVolume()
|
||||
|
||||
point = point or coin.SbVec3f(0, 0, 0)
|
||||
|
||||
if normal == "camera":
|
||||
plane = vol.getPlane(10)
|
||||
normal = plane.getNormal()
|
||||
elif normal == "x":
|
||||
normal = SbVec3f(1, 0, 0)
|
||||
elif normal == "y":
|
||||
normal = SbVec3f(0, 1, 0)
|
||||
elif normal == "z":
|
||||
normal = SbVec3f(0, 0, 1)
|
||||
normal.normalize()
|
||||
x, y = screen_pos
|
||||
vp = render_manager.getViewportRegion()
|
||||
size = vp.getViewportSize()
|
||||
dX, dY = size
|
||||
|
||||
fRatio = vp.getViewportAspectRatio()
|
||||
pX = float(x) / float(vp.getViewportSizePixels()[0])
|
||||
pY = float(y) / float(vp.getViewportSizePixels()[1])
|
||||
|
||||
if (fRatio > 1.0):
|
||||
pX = (pX - 0.5 * dX) * fRatio + 0.5 * dX
|
||||
elif (fRatio < 1.0):
|
||||
pY = (pY - 0.5 * dY) / fRatio + 0.5 * dY
|
||||
|
||||
plane = coin.SbPlane(normal, point)
|
||||
line = coin.SbLine(*vol.projectPointToLine(coin.SbVec2f(pX,pY)))
|
||||
pt = plane.intersect(line)
|
||||
return(pt)
|
||||
|
||||
COLORS = {
|
||||
"black": (0., 0., 0.),
|
||||
"white": (1., 1., 1.),
|
||||
"grey": (.5, .5, .5),
|
||||
"red": (1., 0., 0.),
|
||||
"green": (0., 1., 0.),
|
||||
"blue": (0., 0., 1.),
|
||||
"yellow": (1., 1., 0.),
|
||||
"cyan": (0., 1., 1.),
|
||||
"magenta":(1., 0., 1.)
|
||||
}
|
||||
|
||||
class Object3D(coin.SoSeparator):
|
||||
std_col = "black"
|
||||
ovr_col = "red"
|
||||
sel_col = "yellow"
|
||||
non_col = "grey"
|
||||
|
||||
def __init__(self, points, dynamic=False):
|
||||
super(Object3D, self).__init__()
|
||||
self.data = coin.SoCoordinate3()
|
||||
self.color = coin.SoMaterial()
|
||||
self.set_color()
|
||||
self += [self.color, self.data]
|
||||
self.start_pos = None
|
||||
self.dynamic = dynamic
|
||||
|
||||
# callback function lists
|
||||
self.on_drag = []
|
||||
self.on_drag_release = []
|
||||
self.on_drag_start = []
|
||||
|
||||
self._delete = False
|
||||
self._tmp_points = None
|
||||
self.enabled = True
|
||||
self.points = points
|
||||
|
||||
def set_disabled(self):
|
||||
self.color.diffuseColor = COLORS[self.non_col]
|
||||
self.enabled = False
|
||||
|
||||
def set_enabled(self):
|
||||
self.color.diffuseColor = COLORS[self.std_col]
|
||||
self.enabled = True
|
||||
|
||||
def set_color(self, col=None):
|
||||
self.std_col = col or self.std_col
|
||||
self.color.diffuseColor = COLORS[self.std_col]
|
||||
|
||||
@property
|
||||
def points(self):
|
||||
return self.data.point.getValues()
|
||||
|
||||
@points.setter
|
||||
def points(self, points):
|
||||
self.data.point.setValue(0, 0, 0)
|
||||
self.data.point.setValues(0, len(points), points)
|
||||
|
||||
def set_mouse_over(self):
|
||||
if self.enabled:
|
||||
self.color.diffuseColor = COLORS[self.ovr_col]
|
||||
|
||||
def unset_mouse_over(self):
|
||||
if self.enabled:
|
||||
self.color.diffuseColor = COLORS[self.std_col]
|
||||
|
||||
def select(self):
|
||||
if self.enabled:
|
||||
self.color.diffuseColor = COLORS[self.sel_col]
|
||||
|
||||
def unselect(self):
|
||||
if self.enabled:
|
||||
self.color.diffuseColor = COLORS[self.std_col]
|
||||
|
||||
def drag(self, mouse_coords, fact=1.):
|
||||
if self.enabled:
|
||||
pts = self.points
|
||||
for i, pt in enumerate(pts):
|
||||
pt[0] = mouse_coords[0] * fact + self._tmp_points[i][0]
|
||||
pt[1] = mouse_coords[1] * fact + self._tmp_points[i][1]
|
||||
pt[2] = mouse_coords[2] * fact + self._tmp_points[i][2]
|
||||
self.points = pts
|
||||
for foo in self.on_drag:
|
||||
foo()
|
||||
|
||||
def drag_release(self):
|
||||
if self.enabled:
|
||||
for foo in self.on_drag_release:
|
||||
foo()
|
||||
|
||||
def drag_start(self):
|
||||
self._tmp_points = self.points
|
||||
if self.enabled:
|
||||
for foo in self.on_drag_start:
|
||||
foo()
|
||||
|
||||
@property
|
||||
def drag_objects(self):
|
||||
if self.enabled:
|
||||
return [self]
|
||||
|
||||
def delete(self):
|
||||
if self.enabled and not self._delete:
|
||||
self._delete = True
|
||||
|
||||
def check_dependency(self):
|
||||
pass
|
||||
|
||||
|
||||
class Marker(Object3D):
|
||||
def __init__(self, points, dynamic=False):
|
||||
super(Marker, self).__init__(points, dynamic)
|
||||
self.marker = coin.SoMarkerSet()
|
||||
self.marker.markerIndex = coin.SoMarkerSet.CIRCLE_FILLED_9_9
|
||||
self.addChild(self.marker)
|
||||
|
||||
|
||||
class Line(Object3D):
|
||||
def __init__(self, points, dynamic=False):
|
||||
super(Line, self).__init__(points, dynamic)
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.line = coin.SoLineSet()
|
||||
self.addChild(self.drawstyle)
|
||||
self.addChild(self.line)
|
||||
|
||||
class Point(Object3D):
|
||||
def __init__(self, points, dynamic=False):
|
||||
super(Point, self).__init__(points, dynamic)
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.point = coin.SoPointSet()
|
||||
self.addChild(self.drawstyle)
|
||||
self.addChild(self.point)
|
||||
|
||||
class Polygon(Object3D):
|
||||
def __init__(self, points, dynamic=False):
|
||||
super(Polygon, self).__init__(points, dynamic)
|
||||
self.polygon = coin.SoFaceSet()
|
||||
self.addChild(self.polygon)
|
||||
|
||||
class Arrow(Line):
|
||||
def __init__(self, points, dynamic=False, arrow_size=0.04, length=2):
|
||||
super(Arrow, self).__init__(points, dynamic)
|
||||
self.arrow_sep = coin.SoSeparator()
|
||||
self.arrow_rot = coin.SoRotation()
|
||||
self.arrow_scale = coin.SoScale()
|
||||
self.arrow_translate = coin.SoTranslation()
|
||||
self.arrow_scale.scaleFactor.setValue(arrow_size, arrow_size, arrow_size)
|
||||
self.cone = coin.SoCone()
|
||||
arrow_length = coin.SoScale()
|
||||
arrow_length.scaleFactor = (1, length, 1)
|
||||
arrow_origin = coin.SoTranslation()
|
||||
arrow_origin.translation = (0, -1, 0)
|
||||
self.arrow_sep += [self.arrow_translate, self.arrow_rot, self.arrow_scale]
|
||||
self.arrow_sep += [arrow_length, arrow_origin, self.cone]
|
||||
self += [self.arrow_sep]
|
||||
self.set_arrow_direction()
|
||||
|
||||
def set_arrow_direction(self):
|
||||
pts = np.array(self.points)
|
||||
self.arrow_translate.translation = tuple(pts[-1])
|
||||
direction = pts[-1] - pts[-2]
|
||||
direction /= np.linalg.norm(direction)
|
||||
_rot = coin.SbRotation()
|
||||
_rot.setValue(coin.SbVec3f(0, 1, 0), coin.SbVec3f(*direction))
|
||||
self.arrow_rot.rotation.setValue(_rot)
|
||||
|
||||
class InteractionSeparator(coin.SoSeparator):
|
||||
pick_radius = 20
|
||||
ctrl_keys = {"grab": "g",
|
||||
"abort_grab": u"\uff1b",
|
||||
"select_all": "a",
|
||||
"delete": u"\uffff",
|
||||
"axis_x": "x",
|
||||
"axis_y": "y",
|
||||
"axis_z": "z"}
|
||||
|
||||
def __init__(self, render_manager):
|
||||
super(InteractionSeparator, self).__init__()
|
||||
self.render_manager = render_manager
|
||||
self.objects = coin.SoSeparator()
|
||||
self.dynamic_objects = []
|
||||
self.static_objects = []
|
||||
self.over_object = None
|
||||
self.selected_objects = []
|
||||
self.drag_objects = []
|
||||
|
||||
self.on_drag = []
|
||||
self.on_drag_release = []
|
||||
self.on_drag_start = []
|
||||
|
||||
self._direction = None
|
||||
|
||||
self.events = coin.SoEventCallback()
|
||||
self += self.events, self.objects
|
||||
|
||||
def register(self):
|
||||
self._highlightCB = self.events.addEventCallback(
|
||||
coin.SoLocation2Event.getClassTypeId(), self.highlightCB)
|
||||
self._selectCB = self.events.addEventCallback(
|
||||
coin.SoMouseButtonEvent.getClassTypeId(), self.selectCB)
|
||||
self._grabCB = self.events.addEventCallback(
|
||||
coin.SoMouseButtonEvent.getClassTypeId(), self.grabCB)
|
||||
self._deleteCB = self.events.addEventCallback(
|
||||
coin.SoKeyboardEvent.getClassTypeId(), self.deleteCB)
|
||||
self._selectAllCB = self.events.addEventCallback(
|
||||
coin.SoKeyboardEvent.getClassTypeId(), self.selectAllCB)
|
||||
|
||||
def unregister(self):
|
||||
self.events.removeEventCallback(
|
||||
coin.SoLocation2Event.getClassTypeId(), self._highlightCB)
|
||||
self.events.removeEventCallback(
|
||||
coin.SoMouseButtonEvent.getClassTypeId(), self._selectCB)
|
||||
self.events.removeEventCallback(
|
||||
coin.SoMouseButtonEvent.getClassTypeId(), self._grabCB)
|
||||
self.events.removeEventCallback(
|
||||
coin.SoKeyboardEvent.getClassTypeId(), self._deleteCB)
|
||||
self.events.removeEventCallback(
|
||||
coin.SoKeyboardEvent.getClassTypeId(), self._selectAllCB)
|
||||
|
||||
|
||||
def addChild(self, child):
|
||||
if hasattr(child, "dynamic"):
|
||||
self.objects.addChild(child)
|
||||
if child.dynamic:
|
||||
self.dynamic_objects.append(child)
|
||||
else:
|
||||
self.static_objects.append(child)
|
||||
else:
|
||||
super(InteractionSeparator, self).addChild(child)
|
||||
|
||||
#-----------------------HIGHLIGHTING-----------------------#
|
||||
# a SoLocation2Event calling a function which sends rays #
|
||||
# int the scene. This will return the object the mouse is #
|
||||
# currently hoovering. #
|
||||
|
||||
def highlightObject(self, obj):
|
||||
if self.over_object:
|
||||
self.over_object.unset_mouse_over()
|
||||
self.over_object = obj
|
||||
if self.over_object:
|
||||
self.over_object.set_mouse_over()
|
||||
self.colorSelected()
|
||||
|
||||
def highlightCB(self, attr, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
pos = event.getPosition()
|
||||
obj = self.sendRay(pos)
|
||||
self.highlightObject(obj)
|
||||
|
||||
def sendRay(self, mouse_pos):
|
||||
"""sends a ray through the scene and return the nearest entity"""
|
||||
ray_pick = coin.SoRayPickAction(self.render_manager.getViewportRegion())
|
||||
ray_pick.setPoint(coin.SbVec2s(*mouse_pos))
|
||||
ray_pick.setRadius(InteractionSeparator.pick_radius)
|
||||
ray_pick.setPickAll(True)
|
||||
ray_pick.apply(self.render_manager.getSceneGraph())
|
||||
picked_point = ray_pick.getPickedPointList()
|
||||
return self.objByID(picked_point)
|
||||
|
||||
def objByID(self, picked_point):
|
||||
for point in picked_point:
|
||||
path = point.getPath()
|
||||
length = path.getLength()
|
||||
point = path.getNode(length - 2)
|
||||
for o in self.dynamic_objects:
|
||||
if point == o:
|
||||
return(o)
|
||||
# Code below was not working with python 2.7 (pb with getNodeId ?)
|
||||
#point = list(filter(
|
||||
#lambda ctrl: ctrl.getNodeId() == point.getNodeId(),
|
||||
#self.dynamic_objects))
|
||||
#if point != []:
|
||||
#return point[0]
|
||||
return None
|
||||
|
||||
|
||||
|
||||
#------------------------SELECTION------------------------#
|
||||
def selectObject(self, obj, multi=False):
|
||||
if not multi:
|
||||
for o in self.selected_objects:
|
||||
o.unselect()
|
||||
self.selected_objects = []
|
||||
if obj:
|
||||
if obj in self.selected_objects:
|
||||
self.selected_objects.remove(obj)
|
||||
else:
|
||||
self.selected_objects.append(obj)
|
||||
self.colorSelected()
|
||||
self.selectionChanged()
|
||||
|
||||
def selectCB(self, attr, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
if (event.getState() == coin.SoMouseButtonEvent.DOWN and
|
||||
event.getButton() == event.BUTTON1):
|
||||
pos = event.getPosition()
|
||||
obj = self.sendRay(pos)
|
||||
self.selectObject(obj, event.wasCtrlDown())
|
||||
|
||||
def select_all_cb(self, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
if (event.getKey() == ord(InteractionSeparator.ctrl_keys["select_all"])):
|
||||
if event.getState() == event.DOWN:
|
||||
if self.selected_objects:
|
||||
for o in self.selected_objects:
|
||||
o.unselect()
|
||||
self.selected_objects = []
|
||||
else:
|
||||
for obj in self.objects:
|
||||
if obj.dynamic:
|
||||
self.selected_objects.append(obj)
|
||||
self.ColorSelected()
|
||||
self.selection_changed()
|
||||
|
||||
def deselect_all(self):
|
||||
if self.selected_objects:
|
||||
for o in self.selected_objects:
|
||||
o.unselect()
|
||||
self.selected_objects = []
|
||||
|
||||
def colorSelected(self):
|
||||
for obj in self.selected_objects:
|
||||
obj.select()
|
||||
|
||||
def selectionChanged(self):
|
||||
pass
|
||||
|
||||
def selectAllCB(self, attr, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
if (event.getKey() == ord(InteractionSeparator.ctrl_keys["select_all"])):
|
||||
if event.getState() == event.DOWN:
|
||||
if self.selected_objects:
|
||||
for o in self.selected_objects:
|
||||
o.unselect()
|
||||
self.selected_objects = []
|
||||
else:
|
||||
for obj in self.dynamic_objects:
|
||||
if obj.dynamic:
|
||||
self.selected_objects.append(obj)
|
||||
self.colorSelected()
|
||||
self.selectionChanged()
|
||||
|
||||
|
||||
#------------------------INTERACTION------------------------#
|
||||
|
||||
def cursor_pos(self, event):
|
||||
pos = event.getPosition()
|
||||
# print(list(getPointOnScreen1(self.render_manager, pos)))
|
||||
return getPointOnScreen(self.render_manager, pos)
|
||||
|
||||
|
||||
def constrained_vector(self, vector):
|
||||
if self._direction is None:
|
||||
return vector
|
||||
if self._direction == InteractionSeparator.ctrl_keys["axis_x"]:
|
||||
return [vector[0], 0, 0]
|
||||
elif self._direction == InteractionSeparator.ctrl_keys["axis_y"]:
|
||||
return [0, vector[1], 0]
|
||||
elif self._direction == InteractionSeparator.ctrl_keys["axis_z"]:
|
||||
return [0, 0, vector[2]]
|
||||
|
||||
def grabCB(self, attr, event_callback):
|
||||
# press grab key to move an entity
|
||||
event = event_callback.getEvent()
|
||||
# get all drag objects, every selected object can add some drag objects
|
||||
# but the eventhandler is not allowed to call the drag twice on an object
|
||||
#if event.getKey() == ord(InteractionSeparator.ctrl_keys["grab"]):
|
||||
if (event.getState() == coin.SoMouseButtonEvent.DOWN and
|
||||
event.getButton() == event.BUTTON1):
|
||||
pos = event.getPosition()
|
||||
obj = self.sendRay(pos)
|
||||
if obj:
|
||||
#if not obj in self.selected_objects:
|
||||
#self.selectObject(obj, event.wasCtrlDown())
|
||||
self.drag_objects = set()
|
||||
for i in self.selected_objects:
|
||||
for j in i.drag_objects:
|
||||
self.drag_objects.add(j)
|
||||
# check if something is selected
|
||||
if self.drag_objects:
|
||||
# first delete the selection_cb, and higlight_cb
|
||||
self.unregister()
|
||||
# now add a callback that calls the dragfunction of the selected entities
|
||||
self.start_pos = self.cursor_pos(event)
|
||||
self._dragCB = self.events.addEventCallback(
|
||||
coin.SoEvent.getClassTypeId(), self.dragCB)
|
||||
for obj in self.drag_objects:
|
||||
obj.drag_start()
|
||||
for foo in self.on_drag_start:
|
||||
foo()
|
||||
|
||||
def dragCB(self, attr, event_callback, force=False):
|
||||
event = event_callback.getEvent()
|
||||
b = ""
|
||||
s = ""
|
||||
if type(event) == coin.SoMouseButtonEvent:
|
||||
if event.getButton() == coin.SoMouseButtonEvent.BUTTON1:
|
||||
b = "mb1"
|
||||
elif event.getButton() == coin.SoMouseButtonEvent.BUTTON2:
|
||||
b = "mb2"
|
||||
if event.getState() == coin.SoMouseButtonEvent.UP:
|
||||
s = "up"
|
||||
elif event.getState() == coin.SoMouseButtonEvent.DOWN:
|
||||
s = "down"
|
||||
import FreeCAD
|
||||
FreeCAD.Console.PrintMessage("{} {}\n".format(b,s))
|
||||
if ((type(event) == coin.SoMouseButtonEvent and
|
||||
event.getState() == coin.SoMouseButtonEvent.UP
|
||||
and event.getButton() == coin.SoMouseButtonEvent.BUTTON1) or
|
||||
force):
|
||||
self.register()
|
||||
if self._dragCB:
|
||||
self.events.removeEventCallback(
|
||||
coin.SoEvent.getClassTypeId(), self._dragCB)
|
||||
self._direction = None
|
||||
self._dragCB = None
|
||||
self.start_pos = None
|
||||
for obj in self.drag_objects:
|
||||
obj.drag_release()
|
||||
for foo in self.on_drag_release:
|
||||
foo()
|
||||
self.drag_objects = []
|
||||
elif (type(event) == coin.SoKeyboardEvent and
|
||||
event.getState() == coin.SoMouseButtonEvent.DOWN):
|
||||
if event.getKey() == InteractionSeparator.ctrl_keys["abort_grab"]: # esc
|
||||
for obj in self.drag_objects:
|
||||
obj.drag([0, 0, 0], 1) # set back to zero
|
||||
self.dragCB(attr, event_callback, force=True)
|
||||
return
|
||||
try:
|
||||
key = chr(event.getKey())
|
||||
except ValueError:
|
||||
# there is no character for this value
|
||||
key = "_"
|
||||
if key in [InteractionSeparator.ctrl_keys["axis_x"],
|
||||
InteractionSeparator.ctrl_keys["axis_y"],
|
||||
InteractionSeparator.ctrl_keys["axis_z"]] and key != self._direction:
|
||||
self._direction = key
|
||||
else:
|
||||
self._direction = None
|
||||
diff = self.cursor_pos(event) - self.start_pos
|
||||
diff = self.constrained_vector(diff)
|
||||
for obj in self.drag_objects:
|
||||
obj.drag(diff, 1)
|
||||
for foo in self.on_drag:
|
||||
foo()
|
||||
|
||||
elif type(event) == coin.SoLocation2Event:
|
||||
fact = 0.1 if event.wasShiftDown() else 1.
|
||||
diff = self.cursor_pos(event) - self.start_pos
|
||||
diff = self.constrained_vector(diff)
|
||||
for obj in self.drag_objects:
|
||||
obj.drag(diff, fact)
|
||||
for foo in self.on_drag:
|
||||
foo()
|
||||
|
||||
def deleteCB(self, attr, event_callback):
|
||||
event = event_callback.getEvent()
|
||||
# get all drag objects, every selected object can add some drag objects
|
||||
# but the eventhandler is not allowed to call the drag twice on an object
|
||||
if event.getKey() == ord(InteractionSeparator.ctrl_keys["delete"]) and (event.getState() == 1):
|
||||
self.removeSelected()
|
||||
|
||||
def removeSelected(self):
|
||||
temp = []
|
||||
for i in self.selected_objects:
|
||||
i.delete()
|
||||
for i in self.dynamic_objects + self.static_objects:
|
||||
i.check_dependency() #dependency length max = 1
|
||||
for i in self.dynamic_objects + self.static_objects:
|
||||
if i._delete:
|
||||
temp.append(i)
|
||||
self.selected_objects = []
|
||||
self.over_object = None
|
||||
self.selectionChanged()
|
||||
for i in temp:
|
||||
if i in self.dynamic_objects:
|
||||
self.dynamic_objects.remove(i)
|
||||
else:
|
||||
self.static_objects.remove(i)
|
||||
self.objects.removeChild(i)
|
||||
del(i)
|
||||
self.selectionChanged()
|
||||
|
||||
def removeAllChildren(self):
|
||||
for i in self.dynamic_objects:
|
||||
i.delete()
|
||||
self.dynamic_objects = []
|
||||
self.static_objects = []
|
||||
self.selected_objects = []
|
||||
self.over_object = None
|
||||
super(InteractionSeparator, self).removeAllChildren()
|
||||
|
||||
Reference in New Issue
Block a user