update to 0.15rc1
diff -ruN py-soya3d/Makefile py-soya3d.new/Makefile --- py-soya3d/Makefile 2010-04-28 01:58:27.000000000 +0400 +++ py-soya3d.new/Makefile 2011-11-25 14:26:36.000000000 +0400 @@ -6,12 +6,12 @@ # PORTNAME= soya3d -PORTVERSION= 0.14 -PORTREVISION= 5 +DISTVERSION= 0.15rc1 +PORTREVISION= 1 CATEGORIES= graphics python MASTER_SITES= http://download.gna.org/soya/ PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} -DISTNAME= Soya-${PORTVERSION} +DISTNAME= Soya-${DISTVERSION} DISTFILES= ${DISTNAME}${EXTRACT_SUFX} DIST_SUBDIR= python @@ -55,6 +55,9 @@ @${REINPLACE_CMD} -e \ 's|%%LOCALBASE%%|${LOCALBASE}|g' -e \ 's|/usr/include|${LOCALBASE}/include|g' ${WRKSRC}/setup.py +#Replace bad file (content binary simbols) + @${RM} ${WRKSRC}/editor/world.py && \ + ${CP} ${FILESDIR}/world.py ${WRKSRC}/editor post-install: .if !defined(NOPORTEXAMPLES) diff -ruN py-soya3d/distinfo py-soya3d.new/distinfo --- py-soya3d/distinfo 2011-07-03 18:12:02.000000000 +0400 +++ py-soya3d.new/distinfo 2011-11-25 14:24:56.000000000 +0400 @@ -1,4 +1,4 @@ -SHA256 (python/Soya-0.14.tar.bz2) = dcb93206d7154dc575ec6eeb7fa3ecfd6bfb78fa233db639e423857cd2a99590 -SIZE (python/Soya-0.14.tar.bz2) = 905659 +SHA256 (python/Soya-0.15rc1.tar.bz2) = 2567714bc312a171bb5b31cb854804a78cff878e8d5cd2352cf37f48c8eb6dd6 +SIZE (python/Soya-0.15rc1.tar.bz2) = 910576 SHA256 (python/SoyaTutorial-0.14.tar.bz2) = 86d5b8189e7f7b4269976a65f23a51291bb99c6272f2884cbd129a6e9cc6cbec SIZE (python/SoyaTutorial-0.14.tar.bz2) = 5223674 diff -ruN py-soya3d/files/patch-setup.py py-soya3d.new/files/patch-setup.py --- py-soya3d/files/patch-setup.py 2009-04-27 05:16:35.000000000 +0400 +++ py-soya3d.new/files/patch-setup.py 2011-11-25 14:24:56.000000000 +0400 @@ -1,14 +1,6 @@ ---- setup.py 2009-04-22 10:00:23.000000000 -0500 -+++ setup.py 2009-04-22 10:03:23.000000000 -0500 -@@ -21,6 +21,7 @@ - - # Modify the following if needed : - USE_OPENAL = 1 # use OpenAL -+HAVE_PYREX = 0 - #USE_OPENAL = 0 - - # Modify the following if needed : -@@ -32,7 +33,7 @@ +--- setup.py.bak 2010-01-19 00:39:57.000000000 +0300 ++++ setup.py 2011-11-25 05:43:09.000000000 +0400 +@@ -32,7 +32,7 @@ INCDIR = [ #"ode-0.5/include", "/usr/include", @@ -17,7 +9,7 @@ "/usr/X11R6/include", "/usr/X11/include", "/usr/include/freetype2", -@@ -48,7 +49,7 @@ +@@ -48,7 +48,7 @@ LIBDIR = [ #"ode-0.5/lib", "/usr/lib", @@ -26,19 +18,26 @@ "/opt/local/lib", # For Mac OS X "darwin port" "/usr/X11R6/lib", "/usr/X11/lib", -@@ -79,11 +80,6 @@ +@@ -81,12 +81,12 @@ SDISTING = ("sdist" in sys.argv[1:]) and not ("--help" in sys.argv[1:]) MACOSX_DEPLOYMENT_TARGET = os.getenv('MACOSX_DEPLOYMENT_TARGET') -try: - from Pyrex.Distutils import build_ext -- HAVE_PYREX = 1 --except: -- HAVE_PYREX = 0 - - # Only enable Pyrex compilation for SVN sources - if not os.path.exists(os.path.join(os.path.dirname(__file__), ".svn")): -@@ -159,6 +155,7 @@ +- USE_PYREX = 1 +-except ImportError: +- USE_PYREX = 0 +- print "No Pyrex found" ++#try: ++# from Pyrex.Distutils import build_ext ++# USE_PYREX = 1 ++#except ImportError: ++USE_PYREX = 0 ++# print "No Pyrex found" + + if USE_PYREX: print "Pyrex compilation enabled!" + else: print "Pyrex compilation disabled." +@@ -172,6 +172,7 @@ DEFINES.append(('SOYA_MACOSX',1)) else: LIBS.append("openal") diff -ruN py-soya3d/files/world.py py-soya3d.new/files/world.py --- py-soya3d/files/world.py 1970-01-01 03:00:00.000000000 +0300 +++ py-soya3d.new/files/world.py 2011-11-25 14:24:56.000000000 +0400 @@ -0,0 +1,723 @@ +# -*- indent-tabs-mode: t -*- + +# Soya 3D +# Copyright (C) 2001-2002 Jean-Baptiste LAMY +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +from editobj.observe import * +import editobj.custom as custom +import Tkinter, time, weakref +import soya, soya.opengl, soya.sdlconst, soya.cube as cube, soya.cursor as cursor + +STEP = 0.125 +EPSILON = 0.001 + +# Additionnal key binding. (A dict mapping key ID to a lambda taking 2 args, the root world and the edited object). +KEY_BINDINGS = {} + +class WorldEditor: + def __init__(self, world, dialog): + self.active = 0 + self.dialog = dialog + self.handles = [] + self.vertex_handles = [] + self.children_visibility = { world : 1 } + + self.world = self.current = world + + self.scene = soya.World() + self.scene.name = "__scene__" + self.scene.atmosphere = soya.Atmosphere() + self.scene.atmosphere.ambient = (0.5, 0.5, 0.5, 1.0) + + self.camera = soya.Camera(self.scene) + self.camera.set_xyz(0.0, 0.0, 5.0) + self.camera.rotate_y(45) + soya.set_root_widget(self.camera) + + self.light = soya.Light(self.scene) + self.light.set_xyz(0.2, 2.0, 2.2) + self.light.top_level = 1 + self.light.cast_shadow = 0 + + self.cursor = Cursor(self.scene, self.camera, self.handles, self.light) + self.cursor.name = "cursor" + + self.content = soya.World(self.scene) + self.content.name = "__content__" + self.content.append(world) + + self.add_handles_for(world) + + observe_tree(world, self.on_changed) + + self.last_click = 0 + self.camera_mode = 0 + + def add_handles_for(self, item): + if isinstance(item, soya.Sprite): + self.handles.append(PositionHandle(self.content, self, item)) + + elif isinstance(item, soya.Face): + for vertex in item.vertices: self.add_handles_for_vertex(vertex) + + elif isinstance(item, soya.CoordSyst): + self.handles.append(PositionHandle (self.content, self, item)) + self.handles.append(OrientationHandle(self.content, self, item)) + + if isinstance(item, soya.World) and self.children_visibility.get(item, 0): + for subitem in item.children: self.add_handles_for(subitem) + + def add_handles_for_vertex(self, vertex): + if getattr(vertex, "immature", 0): return + + for handle in self.vertex_handles: + if handle.is_for(vertex): return + + for handle in self.vertex_handles: + v = handle.vertices[0] + if (v.parent is vertex.parent) and (abs(v.x - vertex.x) < EPSILON) and (abs(v.y - vertex.y) < EPSILON) and (abs(v.z - vertex.z) < EPSILON): + handle.add_vertex(vertex) + return handle + else: + handle = VertexHandle(self.content, self, vertex) + self.handles.append(handle) + self.vertex_handles.append(handle) + + def remove_handles_of(self, item): + for handle in self.handles[:]: handle.del_for(item) + + if isinstance(item, soya.Face): + for handle in self.vertex_handles[:]: + for vertex in item.vertices: handle.del_for(vertex) + + elif isinstance(item, soya.World): + for subitem in item: self.remove_handles_of(subitem) + + def select_handles_for(self, item): + self.current = item + for handle in self.handles: + if handle.is_for(item): handle.select() + + def children_edited(self, world, visible): + self.children_visibility[world] = visible + if visible: + for item in world.children: + for handle in self.handles: + if handle.is_for(item): continue + self.add_handles_for(item) + else: + for item in world.children: self.remove_handles_of(item) + + def on_event(self, event): + #print event + if event[0] == soya.sdlconst.MOUSEMOTION: + if soya.get_mod() & soya.sdlconst.MOD_CTRL: + self.cursor.grid_step = STEP + else: self.cursor.grid_step = 0.0 + + if self.camera_mode: + self.camera.turn_y(float(event[3])) + self.camera.turn_x(float(event[4])) + + x, y = event[1], event[2] + if x == 0: self.camera += soya.Vector(self.camera, -0.1, 0.0, 0.0) + elif x == self.camera.get_screen_width() - 1: self.camera += soya.Vector(self.camera, 0.1, 0.0, 0.0) + if y == 0: self.camera += soya.Vector(self.camera, 0.0, 0.1, 0.0) + elif y == self.camera.get_screen_height() - 1: self.camera += soya.Vector(self.camera, 0.0, -0.1, 0.0) + + self.cursor.mouse_moved(x, y) + + elif event[0] == soya.sdlconst.MOUSEBUTTONDOWN: + if event[1] < 3: # Left or middle button + current = time.time() + if current - self.last_click < 0.2: + self.cursor.button_pressed(2, soya.get_mod() & soya.sdlconst.MOD_SHIFT) # Double-click is the same that middle click + else: + self.cursor.button_pressed(event[1], soya.get_mod() & soya.sdlconst.MOD_SHIFT) + self.last_click = current + elif event[1] == 3: self.camera_mode = 1 + + elif event[0] == soya.sdlconst.MOUSEBUTTONUP: + if self.camera_mode: + if event[1] == 3: self.camera_mode = 0 + elif event[1] == 4: self._zoom(-1.0) + elif event[1] == 5: self._zoom( 1.0) + else: + if event[1] < 3: self.cursor.button_released(event[1]) + elif event[1] == 4: self.cursor.mouse_rolled(-0.25) + elif event[1] == 5: self.cursor.mouse_rolled( 0.25) + + elif event[0] == soya.sdlconst.KEYDOWN: + # Page up, page down + if event[1] == 280: self.cursor.mouse_rolled(-1 - 9 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT)) + elif event[1] == 281: self.cursor.mouse_rolled( 1 + 9 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT)) + + # Left, right, up, down + elif event[1] == 276: self.camera += soya.Vector(self.camera, -1.0 - 9.0 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT), 0.0, 0.0) + elif event[1] == 275: self.camera += soya.Vector(self.camera, 1.0 + 9.0 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT), 0.0, 0.0) + elif event[1] == 273: self.camera += soya.Vector(self.camera, 0.0, 1.0 + 9.0 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT), 0.0) + elif event[1] == 274: self.camera += soya.Vector(self.camera, 0.0, -1.0 - 9.0 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT), 0.0) + + # o : toggle ortho camera + elif event[1] == 111: + self.camera.ortho = not self.camera.ortho + self.camera.fov = 60.0 + + # +, - : zoom + elif event[1] == 270: self._zoom(-1.0 - 9 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT)) + elif event[1] == 269: self._zoom( 1.0 + 9 * (soya.get_mod() & soya.sdlconst.MOD_SHIFT)) + + # 4, 6, 8, 2, 5, 0 : predefined views + elif event[1] == 260: + a, b = self.world.get_box() + cameray, cameraz = self.camera.y, self.camera.z + self.camera.set_identity() + self.camera.set_xyz(min((a % self.scene).x, (b % self.scene).x) - 3.0, cameray, cameraz) + self.camera.look_at(soya.Vector(None, 1.0, 0.0, 0.0)) + elif event[1] == 262: + a, b = self.world.get_box() + cameray, cameraz = self.camera.y, self.camera.z + self.camera.set_identity() + self.camera.set_xyz(max((a % self.scene).x, (b % self.scene).x) + 3.0, cameray, cameraz) + self.camera.look_at(soya.Vector(None, -1.0, 0.0, 0.0)) + elif event[1] == 264: + a, b = self.world.get_box() + camerax, cameraz = self.camera.x, self.camera.z + self.camera.set_identity() + self.camera.set_xyz(camerax, max((a % self.scene).y, (b % self.scene).y) + 3.0, cameraz) + self.camera.look_at(soya.Vector(None, 0.0, -1.0, 0.0)) + elif event[1] == 258: + a, b = self.world.get_box() + camerax, cameraz = self.camera.x, self.camera.z + self.camera.set_identity() + self.camera.set_xyz(camerax, min((a % self.scene).y, (b % self.scene).y) - 3.0, cameraz) + self.camera.look_at(soya.Vector(None, 0.0, 1.0, 0.0)) + elif event[1] == 261: + a, b = self.world.get_box() + camerax, cameray = self.camera.x, self.camera.y + self.camera.set_identity() + self.camera.set_xyz(camerax, cameray, min((a % self.scene).z, (b % self.scene).z) - 3.0) + self.camera.look_at(soya.Vector(None, 0.0, 0.0, 1.0)) + elif event[1] == 256: + a, b = self.world.get_box() + camerax, cameray = self.camera.x, self.camera.y + self.camera.set_identity() + self.camera.set_xyz(camerax, cameray, max((a % self.scene).z, (b % self.scene).z) + 3.0) + self.camera.look_at(soya.Vector(None, 0.0, 0.0, -1.0)) + + # q, t : new quad, new triangle + elif event[1] == 113: + if hasattr(self.current, "children"): into = self.current + else: into = self.current.parent + into.append(soya.Quad()) + elif event[1] == 116: + if hasattr(self.current, "children"): into = self.current + else: into = self.current.parent + into.append(soya.Triangle()) + else: + if KEY_BINDINGS.has_key(event[1]): + KEY_BINDINGS[event[1]](self.world, self.current) + + def _zoom(self, z): + if self.camera.ortho: self.camera.fov = self.camera.fov * (1.0 + z / 10.0) + else: self.camera += soya.Vector(self.camera, 0.0, 0.0, z) + + def render(self): + if self.active: + self.scene.begin_round() + self.scene.advance_time(1.0) + self.scene.begin_round() + self.scene.advance_time(1.0) + self.scene.begin_round() + self.scene.advance_time(1.0) + self.scene.begin_round() + self.scene.advance_time(1.0) + self.scene.begin_round() + self.scene.advance_time(1.0) + soya.render() + + def activate(self, event = None): + if not self.active: + self.active = 1 + soya.set_root_widget(self.camera) + soya.cursor_set_visible(0) + self.auto_render() + + def auto_render(self): + for event in soya.coalesce_motion_event(soya.process_event()): self.on_event(event) + self.render() + self.cancel = self.dialog.after(150, self.auto_render) + + def deactivate(self, event = None): + if self.active: + self.active = 0 + soya.cursor_set_visible(1) + self.dialog.after_cancel(self.cancel) + + def on_changed(self, obj, type, new, old): + if type is list: + for item in new: + if not item in old: + self.add_handles_for(item) + if isinstance(item, soya.Face): + for vertex in item.vertices: + if getattr(vertex, "immature", 0): + self.cursor.manage_click(FaceClickManager(self, item)) + break + elif hasattr(item.__class__, "__clickmanager__"): + self.cursor.manage_click(item.__class__.__clickmanager__(self, item)) + + for item in old: + if not item in new: self.remove_handles_of(item) + + else: + if (not hasattr(obj, "children")) and (not hasattr(obj, "items")): + unobserve_tree(obj, self.on_changed) + +RED = soya.Material(); RED .diffuse = (1.0, 0.0, 0.0, 1.0) +GREEN = soya.Material(); GREEN .diffuse = (0.0, 1.0, 0.0, 1.0) +BLUE = soya.Material(); BLUE .diffuse = (0.0, 0.0, 1.0, 1.0) +YELLOW = soya.Material(); YELLOW.diffuse = (1.0, 1.0, 0.0, 1.0) + +RED_HANDLE = GREEN_HANDLE = BLUE_HANDLE = YELLOW_HANDLE = None + +def build_handles(): + global RED_HANDLE, GREEN_HANDLE, BLUE_HANDLE, YELLOW_HANDLE + + red_cube = cube.Cube(None, RED); red_cube .scale(STEP, STEP, STEP) + green_cube = cube.Cube(None, GREEN); green_cube .scale(STEP, STEP, STEP) + blue_cube = cube.Cube(None, BLUE); blue_cube .scale(STEP, STEP, STEP) + yellow_cube = cube.Cube(None, YELLOW); yellow_cube.scale(STEP, STEP, STEP) + + RED_HANDLE = red_cube .to_model() + GREEN_HANDLE = green_cube .to_model() + BLUE_HANDLE = blue_cube .to_model() + YELLOW_HANDLE = yellow_cube.to_model() + +build_handles() + +class Cursor(cursor.Cursor): + def __init__(self, parent = None, camera = None, handles = None, light = None): + cursor.Cursor.__init__(self, parent, camera, GREEN_HANDLE) + + self.handles = handles + self.draging = 0 + self.light = light + self.click_managers = [] + + def manage_click(self, click_manager): + self.click_managers.append(click_manager) + + def move(self, pos): self.add_vector(self >> pos) + + def add_vector(self, dep): + cursor.Cursor.add_vector(self, dep) + for handle in self.handles: handle.cursor_moved(self, self.is_near, dep) + self.light.move(self) + + if self.click_managers: + if not self.click_managers[-1].on_motion(self): del self.click_managers[-1] + + __iadd__ = add_vector + + def is_near(self, position): return position.distance_to(self) < STEP + def near(self, a, b): return ((self.distance_to(a) < self.distance_to(b)) and a) or b + + def button_pressed(self, button, multiselect = 0): + if button == 1: + pred = self.is_near + print "%s, %s, %s" % (self.x, self.y, self.z) + else: pred = self.is_under_tester(STEP) + + if self.click_managers: + if not self.click_managers[-1].on_click(self): del self.click_managers[-1] + else: + handles = filter(pred, self.handles) + if handles: + handle = min(map(lambda handle: (self.distance_to(handle), handle), handles))[1] + # move the cursor at the handle's Z (in the camera coordinate system) + mouse = self % self.camera + self.mouse_rolled((handle % self.camera).z - mouse.z) + handle.select() + + if not multiselect: + for h in self.handles: + if not h is handle: h.highlight(0) + else: + for h in self.handles: h.highlight(0) + + self.draging = 1 + + def button_released(self, button): + for handle in self.selected_handles(): + handle.cursor_endmove(self) + + if self.click_managers: + if not self.click_managers[-1].on_release(self): del self.click_managers[-1] + else: self.draging = 0 + + def selected_handles (self): return filter(lambda handle: handle.selected , self.handles) + def highlighted_handles (self): return filter(lambda handle: handle.highlighted, self.handles) + def highlighted_only_handles(self): return filter(lambda handle: handle.highlighted and not handle.selected, self.handles) + def nearest_selected_handle(self): + selected_handles = self.selected_handles() + return selected_handles and min(map(lambda handle: (self.distance_to(handle), handle), selected_handles))[1] + def over_handle(self): + handles = self.highlighted_only_handles() + return handles and min(map(lambda handle: (self.distance_to(handle), handle), handles))[1] + +class ClickManager: + def on_motion(self, cursor): + """Called when the cursor is moved. Must returns true if this manager is still usefull, or false if this manager's task is achieved.""" + return 1 + def on_click(self, cursor): + """Called when the cursor is clicked. Must returns true if this manager is still usefull, or false if this manager's task is achieved.""" + return 1 + def on_release(self, cursor): + """Called when the cursor is released. Must returns true if this manager is still usefull, or false if this manager's task is achieved.""" + return 1 + +class FaceClickManager(ClickManager): + def __init__(self, editor, face): + self.editor = editor + self.face = face + + def on_motion(self, cursor): + i = 0 + while not getattr(self.face.vertices[i], "immature", 0): i = i + 1 + + while i < len(self.face.vertices): + self.face.vertices[i].parent = self.face.parent + self.face.vertices[i].move(cursor) + i = i + 1 + + return 1 + + def on_click(self, cursor): + i = 0 + while not getattr(self.face.vertices[i], "immature", 0): i = i + 1 + + vertex = self.face.vertices[i] + del vertex.immature + + handle = cursor.over_handle() + if handle: + if isinstance(handle, VertexHandle): + handle.add_vertex(self.face.vertices[i]) + else: + self.face.vertices[i].parent = self.face.parent + self.face.vertices[i].move(handle) + + self.editor.add_handles_for_vertex(vertex) + else: + self.face.vertices[i].parent = self.face.parent + self.face.vertices[i].move(cursor) + + self.editor.add_handles_for_vertex(vertex) + + return i < len(self.face.vertices) - 1 + +class MoveClickManager(ClickManager): + def __init__(self, editor, item): + self.editor = editor + self.item = item + + def on_motion(self, cursor): + self.item.move(cursor) + return 1 + + def on_click(self, cursor): + handle = cursor.over_handle() + if handle: + self.item.move(handle) + else: + self.item.move(cursor) + + return 0 + +# List of 3D items' classes that are positionned at the next mouse click's position. + +class Handle(soya.Body): + def __init__(self, parent, editor = None): + soya.Body.__init__(self, parent, self.NATURAL) + self.editor = editor + self.selected = 0 + self.highlighted = 0 + self.ideal = soya.Point(parent) + + def del_for(self, item): + if self.is_for(item): + self.parent.remove(self) + self.editor.handles.remove(self) + return 1 + + def highlight(self, value = 1): + self.highlighted = value + if value: + self.set_model(GREEN_HANDLE) + else: + if self.selected: self.select(0) + self.set_model(self.NATURAL) + + def select(self, value = 1): + self.selected = value + if value: + if not self.highlighted: self.highlight(1) + + def cursor_moved(self, cursor, pred, dep): + if self.selected: + if cursor.draging: + self.ideal += dep + if cursor.grid_step: + pos = self.ideal.copy() + step = cursor.grid_step + d = step / 2.0 + pos.x = ((pos.x + d) // step) * step + pos.y = ((pos.y + d) // step) * step + pos.z = ((pos.z + d) // step) * step + self.move(pos) + else: self.move(self.ideal) + else: + if self.highlighted: + if not pred(self): self.highlight(0) + elif pred(self): self.highlight() + + def cursor_endmove(self, cursor): pass + + +class PositionHandle(Handle): + NATURAL = BLUE_HANDLE + def __init__(self, parent, editor, position): + Handle.__init__(self, parent, editor) + + self.position = position + self.ideal.move(position) + Handle.move(self, position) + + observe(position, self.on_changed) + world = position.parent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def is_for (self, item): return item is self.position + + def move(self, position): + Handle.move(self, position) + self.position.move(position) + + def add_vector(self, vector): + Handle.add_vector(self, vector) + self.position.add_vector(vector) + __iadd__ = add_vector + + def on_changed(self, obj, type, new, old): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + Handle.move(self, obj) + self.ideal.move(obj) + if new["parent"] != old["parent"]: + self.update_hierarchy(new["parent"], old["parent"]) + Handle.move(self, self.position) + self.ideal.move(obj) + + def on_parent_changed(self, obj, type, new, old): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + Handle.move(self, self.position) + self.ideal.move(self.position) + if new["parent"] != old["parent"]: + self.update_hierarchy(new["parent"], old["parent"]) + Handle.move(self, self.position) + self.ideal.move(self.position) + + def update_hierarchy(self, newparent, oldparent): + world = oldparent + while world: + unobserve(world, self.on_parent_changed) + world = world.parent + + world = newparent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def __repr__(self): return "<PositionHandle for %s>" % (self.position,) + +class VertexHandle(Handle): + NATURAL = RED_HANDLE + def __init__(self, parent, editor, vertex): + Handle.__init__(self, parent, editor) + self.vertices = [vertex] + Handle.move(self, vertex) + self.ideal.move(vertex) + + observe(vertex, self.on_changed) + world = vertex.parent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def is_for(self, item): + for vertex in self.vertices: + if vertex is item: return 1 + return 0 + + def del_for(self, item): + for vertex in self.vertices: + if vertex is item: + self.vertices.remove(vertex) + unobserve(vertex, self.on_changed) + if not self.vertices: + self.parent.remove(self) + self.editor.handles.remove(self) + self.editor.vertex_handles.remove(self) + + def del_for_all(self): + for vertex in self.vertices: + unobserve(vertex, self.on_changed) + + self.parent.remove(self) + self.editor.handles.remove(self) + + def move(self, position): + Handle.move(self, position) + for vertex in self.vertices: vertex.move(position) + + def add_vector(self, vector): + Handle.add_vector(self, vector) + for vertex in self.vertices: + vertex.add_vector(vector) + __iadd__ = add_vector + + def on_changed(self, obj, type, new, old): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + if len(self.vertices) == 1: + Handle.move(self, obj) + self.ideal.move(obj) + else: + self.give_up_vertex(obj) + + if new["parent"] != old["parent"]: self.give_up_vertex(obj) + + def on_parent_changed(self, obj, type, old, new): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + Handle.move(self, self.vertices[0]) + self.ideal.move(self.vertices[0]) + elif new["parent"] != old["parent"]: + self.update_hierarchy(new["parent"], old["parent"]) + Handle.move(self, self.vertices[0]) + self.ideal.move(self.vertices[0]) + + def update_hierarchy(self, newparent, oldparent): + world = oldparent + while world: + unobserve(world, self.on_parent_changed) + world = world.parent + + world = newparent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def add_vertex(self, vertex): + vertex.parent = self.vertices[0].parent + vertex.move(self) + self.vertices.append(vertex) + observe(vertex, self.on_changed) + + def give_up_vertex(self, vertex): + self.del_for(vertex) + self.editor.add_handles_for_vertex(vertex) + + def cursor_endmove(self, cursor): + handle = cursor.over_handle() + if handle: + if isinstance(handle, VertexHandle): + self.del_for_all() + for vertex in self.vertices: handle.add_vertex(vertex) + else: + self.move(handle) + + def __repr__(self): return "<VertexHandle for %s>" % (self.vertices,) + +class OrientationHandle(Handle): + NATURAL = YELLOW_HANDLE + def __init__(self, parent, editor, orientation): + Handle.__init__(self, parent, editor) + + self.orientation = orientation + self.place() + self.ideal.move(soya.Point(orientation, 0.0, 0.0, -1.0)) + + observe(orientation, self.on_changed) + world = orientation.parent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def is_for (self, item): return item is self.orientation + + def place(self): Handle.move(self, soya.Point(self.orientation, 0.0, 0.0, -1.0)) + + def move(self, position): + if soya.get_mod() & soya.sdlconst.MOD_SHIFT: + position = soya.Point(position.parent, position.x, position.y, position.z) + position.convert_to(self.orientation.parent) + position.y = self.orientation.y + self.orientation.look_at(position) + self.place() + + def add_vector(self, vector): + self.move(self.position() + vector) + __iadd__ = add_vector + + def on_changed(self, obj, type, new, old): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + self.place() + self.ideal.move(self) + if new["parent"] != old["parent"]: + self.update_hierarchy(new["parent"], old["parent"]) + self.ideal.move(self) + self.place() + + def on_parent_changed(self, obj, type, new, old): + if type is object: + if (new["x"] != old["x"]) or (new["y"] != old["y"]) or (new["z"] != old["z"]): + self.place() + self.ideal.move(self) + if new["parent"] != old["parent"]: + self.update_hierarchy(new["parent"], old["parent"]) + self.place() + self.ideal.move(self) + + def update_hierarchy(self, newparent, oldparent): + world = oldparent + while world: + unobserve(world, self.on_parent_changed) + world = world.parent + + world = newparent + while world: + observe(world, self.on_parent_changed) + world = world.parent + + def __repr__(self): return "<OrientationHandle for %s>" % (self.orientation,)
_______________________________________________ freebsd-ports@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-ports To unsubscribe, send any mail to "freebsd-ports-unsubscr...@freebsd.org"