Macro Rubik Cube: Difference between revisions
(Fix problems when macro is used to create more than one document) |
No edit summary |
||
Line 13: | Line 13: | ||
{{clear}} |
{{clear}} |
||
==Script== <!--T:7--> |
|||
<pre> |
|||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
""" |
""" |
||
Line 26: | Line 24: | ||
* The central and largest view is an axonometric projection. * |
* The central and largest view is an axonometric projection. * |
||
* This has arrows around it which you can click on to rotate slices. * |
* This has arrows around it which you can click on to rotate slices. * |
||
* There are some text direction labels near the arrows: clicking on one * |
|||
* of those rotates the whole cube. You have to click on the actual * |
|||
* letter: FreeCAD doesn't see clicks on the text background * |
|||
* Another view is an axonometric projection from the other side. * |
* Another view is an axonometric projection from the other side. * |
||
* Another view combines views towards each face so as to * |
* Another view combines views towards each face so as to * |
||
Line 39: | Line 40: | ||
* The third button resets the cube to its initial state * |
* The third button resets the cube to its initial state * |
||
* and clears the history. * |
* and clears the history. * |
||
* * |
|||
* There are also some functions defined which can be called from the * |
|||
* python console window: * |
|||
* fix_reload() modifies a restored FreeCAD save file to add the extra * |
|||
* views and interactive controls that this macro and its functions use; * |
|||
* ramdomise() randomises the cube; * |
|||
* reverse_history(), reflectX_history(), reflectY_history(), * |
|||
* reflectZ_history(), rotpX_history(), rotmX_history(), * |
|||
* rotpY_history(), rotmY_history(), rotpZ_history(), and * |
|||
* rotmZ_history() each replace the history by a version modified in the * |
|||
* manner indicated - these are useful for creating modified operators. * |
|||
* * |
* * |
||
*************************************************************************** |
*************************************************************************** |
||
Line 65: | Line 77: | ||
__title__ = "Rubik_cube" |
__title__ = "Rubik_cube" |
||
__author__ = "Aleph0" |
__author__ = "Aleph0" |
||
__version__ = "00. |
__version__ = "00.04" |
||
__date__ = " |
__date__ = "05/12/2017" |
||
__Comment__ = "Virtual Rubik Cube" |
__Comment__ = "Virtual Rubik Cube" |
||
__Wiki__ = "http://www.freecadweb.org/wiki/index.php?title=Macro_Rubik_Cube" |
__Wiki__ = "http://www.freecadweb.org/wiki/index.php?title=Macro_Rubik_Cube" |
||
Line 94: | Line 106: | ||
import FreeCAD |
import FreeCAD |
||
import Part |
import Part |
||
import Draft |
|||
import time |
import time |
||
import random |
|||
from FreeCAD import Base |
from FreeCAD import Base |
||
from FreeCAD import Console |
from FreeCAD import Console |
||
Line 181: | Line 195: | ||
if event.getButton() == 1: |
if event.getButton() == 1: |
||
pos = event.getPosition().getValue() |
pos = event.getPosition().getValue() |
||
obInfo = self.view.getObjectInfo((int(pos[0]),int(pos[1]))) |
|||
if |
if obInfo != None: |
||
obj = App.ActiveDocument.getObject(obInfo["Object"]) |
|||
obname = obj.Label |
|||
if obname[:5] == "arrow": |
if obname[:5] == "arrow": |
||
if event.getState() == 1: |
if event.getState() == 1: |
||
Line 189: | Line 204: | ||
i = int(obname[7:]) |
i = int(obname[7:]) |
||
if wh == "mX": |
if wh == "mX": |
||
mrotmX(i,i+1) |
|||
elif wh == "pX": |
elif wh == "pX": |
||
mrotpX(i,i+1) |
|||
elif wh == "mY": |
elif wh == "mY": |
||
mrotmY(i,i+1) |
|||
elif wh == "pY": |
elif wh == "pY": |
||
mrotpY(i,i+1) |
|||
elif wh == "mZ": |
elif wh == "mZ": |
||
mrotmZ(i,i+1) |
|||
elif wh == "pZ": |
elif wh == "pZ": |
||
mrotpZ(i,i+1) |
|||
event_cb.setHandled() |
event_cb.setHandled() |
||
elif obname[:5] == "label": |
|||
if event.getState() == 1: |
|||
wh = obname[5:7] |
|||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
|||
if wh == "mX": |
|||
mrotmX(0,n) |
|||
elif wh == "pX": |
|||
mrotpX(0,n) |
|||
elif wh == "mY": |
|||
mrotmY(0,n) |
|||
elif wh == "pY": |
|||
mrotpY(0,n) |
|||
elif wh == "mZ": |
|||
mrotmZ(0,n) |
|||
elif wh == "pZ": |
|||
mrotpZ(0,n) |
|||
event_cb.setHandled() |
|||
Dictionary[str(App.ActiveDocument.Name)+"ViewObserver"] = ViewObserver() |
Dictionary[str(App.ActiveDocument.Name)+"ViewObserver"] = ViewObserver() |
||
Line 206: | Line 239: | ||
# It is composed of faces rather than cubes because I haven't found a way of making |
# It is composed of faces rather than cubes because I haven't found a way of making |
||
# a cube with different coloured faces |
# a cube with different coloured faces |
||
# Each face has a name and a label |
|||
# The name is persistent regardless of how the face moves about the cube |
|||
# The label changes and tells where the face is now: this is needed for fix_reload |
|||
fcd = App.ActiveDocument |
fcd = App.ActiveDocument |
||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
||
fc = [[range(n) for iy in range(n)] for ix in range(n)] |
fc = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
||
Dictionary[str(App.ActiveDocument.Name)+"cubies"] = fc |
Dictionary[str(App.ActiveDocument.Name)+"cubies"] = fc |
||
for ix in range(n): |
for ix in range(n): |
||
Line 216: | Line 252: | ||
for iz in range(n): |
for iz in range(n): |
||
fz = iz - (n - 1) / 2.0 |
fz = iz - (n - 1) / 2.0 |
||
fs = |
fs = str(ix)+"q"+str(iy)+"q"+str(iz) |
||
x0y0z0 = Base.Vector(fx-0.5,fy-0.5,fz-0.5) |
x0y0z0 = Base.Vector(fx-0.5,fy-0.5,fz-0.5) |
||
x0y0z1 = Base.Vector(fx-0.5,fy-0.5,fz+0.5) |
x0y0z1 = Base.Vector(fx-0.5,fy-0.5,fz+0.5) |
||
Line 226: | Line 262: | ||
x1y1z1 = Base.Vector(fx+0.5,fy+0.5,fz+0.5) |
x1y1z1 = Base.Vector(fx+0.5,fy+0.5,fz+0.5) |
||
face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x0y1z1,x0y1z0,x0y0z0])) |
face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x0y1z1,x0y1z0,x0y0z0])) |
||
f1 = fcd.addObject("Part::Feature", fs+"x0") |
f1 = fcd.addObject("Part::Feature", "ff"+fs+"x0") |
||
f1.Shape = face |
f1.Shape = face |
||
f1.Label = "fs"+fs+"x0" |
|||
if ix == 0: |
if ix == 0: |
||
f1.ViewObject.DiffuseColor=[(1.0,1.0,1.0)] |
f1.ViewObject.DiffuseColor=[(1.0,1.0,1.0)] |
||
else: |
else: |
||
f1.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f1.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f1.ViewObject.RootNode.setName(coin.SbName(fs+"x0")) |
f1.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"x0")) |
||
face = Part.Face(Part.makePolygon([x1y0z0,x1y0z1,x1y1z1,x1y1z0,x1y0z0])) |
face = Part.Face(Part.makePolygon([x1y0z0,x1y0z1,x1y1z1,x1y1z0,x1y0z0])) |
||
f2 = fcd.addObject("Part::Feature", fs+"x1") |
f2 = fcd.addObject("Part::Feature", "ff"+fs+"x1") |
||
f2.Shape = face |
f2.Shape = face |
||
f2.Label = "fs"+fs+"x1" |
|||
if ix == n - 1: |
if ix == n - 1: |
||
f2.ViewObject.DiffuseColor=[(1.0,0.0,0.0)] |
f2.ViewObject.DiffuseColor=[(1.0,0.0,0.0)] |
||
else: |
else: |
||
f2.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f2.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f2.ViewObject.RootNode.setName(coin.SbName(fs+"x1")) |
f2.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"x1")) |
||
face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x1y0z1,x1y0z0,x0y0z0])) |
face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x1y0z1,x1y0z0,x0y0z0])) |
||
f3 = fcd.addObject("Part::Feature", fs+"y0") |
f3 = fcd.addObject("Part::Feature", "ff"+fs+"y0") |
||
f3.Shape = face |
f3.Shape = face |
||
f3.Label = "fs"+fs+"y0" |
|||
if iy == 0: |
if iy == 0: |
||
f3.ViewObject.DiffuseColor=[(0.0,1.0,0.0)] |
f3.ViewObject.DiffuseColor=[(0.0,1.0,0.0)] |
||
else: |
else: |
||
f3.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f3.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f3.ViewObject.RootNode.setName(coin.SbName(fs+"y0")) |
f3.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"y0")) |
||
face = Part.Face(Part.makePolygon([x0y1z0,x0y1z1,x1y1z1,x1y1z0,x0y1z0])) |
face = Part.Face(Part.makePolygon([x0y1z0,x0y1z1,x1y1z1,x1y1z0,x0y1z0])) |
||
f4 = fcd.addObject("Part::Feature", fs+"y1") |
f4 = fcd.addObject("Part::Feature", "ff"+fs+"y1") |
||
f4.Shape = face |
f4.Shape = face |
||
f4.Label = "fs"+fs+"y1" |
|||
if iy == n - 1: |
if iy == n - 1: |
||
f4.ViewObject.DiffuseColor=[(1.0,0.0,1.0)] |
f4.ViewObject.DiffuseColor=[(1.0,0.0,1.0)] |
||
else: |
else: |
||
f4.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f4.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f4.ViewObject.RootNode.setName(coin.SbName(fs+"y1")) |
f4.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"y1")) |
||
face = Part.Face(Part.makePolygon([x0y0z0,x0y1z0,x1y1z0,x1y0z0,x0y0z0])) |
face = Part.Face(Part.makePolygon([x0y0z0,x0y1z0,x1y1z0,x1y0z0,x0y0z0])) |
||
f5 = fcd.addObject("Part::Feature", fs+"z0") |
f5 = fcd.addObject("Part::Feature", "ff"+fs+"z0") |
||
f5.Shape = face |
f5.Shape = face |
||
f5.Label = "fs"+fs+"z0" |
|||
if iz == 0: |
if iz == 0: |
||
f5.ViewObject.DiffuseColor=[(1.0,1.0,0.0)] |
f5.ViewObject.DiffuseColor=[(1.0,1.0,0.0)] |
||
else: |
else: |
||
f5.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f5.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f5.ViewObject.RootNode.setName(coin.SbName(fs+"z0")) |
f5.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"z0")) |
||
face = Part.Face(Part.makePolygon([x0y0z1,x0y1z1,x1y1z1,x1y0z1,x0y0z1])) |
face = Part.Face(Part.makePolygon([x0y0z1,x0y1z1,x1y1z1,x1y0z1,x0y0z1])) |
||
f6 = fcd.addObject("Part::Feature", fs+"z1") |
f6 = fcd.addObject("Part::Feature", "ff"+fs+"z1") |
||
f6.Shape = face |
f6.Shape = face |
||
f6.Label = "fs"+fs+"z1" |
|||
if iz == n - 1: |
if iz == n - 1: |
||
f6.ViewObject.DiffuseColor=[(0.0,0.0,1.0)] |
f6.ViewObject.DiffuseColor=[(0.0,0.0,1.0)] |
||
else: |
else: |
||
f6.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
f6.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
||
f6.ViewObject.RootNode.setName(coin.SbName(fs+"z1")) |
f6.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"z1")) |
||
fc[ix][iy][iz]=[f1,f2,f3,f4,f5,f6] |
fc[ix][iy][iz]=[f1,f2,f3,f4,f5,f6] |
||
Line 292: | Line 334: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
Line 307: | Line 349: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
Line 323: | Line 365: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
Line 339: | Line 381: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
Line 355: | Line 397: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
Line 371: | Line 413: | ||
arrow = fcd.addObject("Part::Feature", fs) |
arrow = fcd.addObject("Part::Feature", fs) |
||
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) |
||
arrow.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] |
arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] |
||
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
arrow.ViewObject.RootNode.setName(coin.SbName(fs)) |
||
arrow.ViewObject.Selectable = False |
arrow.ViewObject.Selectable = False |
||
# This bit of code creates some labels for the arrows |
|||
# This gets FreeCAD's top level SceneGraph (including camera node), |
|||
# Clicking on one rotates the whole cube |
|||
# not the document's SceneGraph which hangs off of it |
|||
def makeLabel(text, mat): |
|||
sceneGraph = Gui.ActiveDocument.ActiveView.getViewer().getSoEventManager().getSceneGraph() |
|||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
|||
tx = Draft.makeText(text) |
|||
tx.Label = "label"+text |
|||
tx.ViewObject.TextColor = (0.0,0.0,0.0) |
|||
tx.ViewObject.FontSize = 0.2 * n |
|||
tx.ViewObject.Justification = 'Center' |
|||
node = tx.ViewObject.RootNode |
|||
node.setName(coin.SbName("label"+text)) |
|||
if node.getNumChildren() > 0: |
|||
child = node.getChild(0) |
|||
if child.getTypeId().getName().__str__() == "Transform": |
|||
child.setMatrix(mat) |
|||
def doLabels(): |
|||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(0.0, - n / 2.0, -(1.0 + n * 0.7)), |
|||
coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
makeLabel("pX", m) |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(0.0, 1.1 + n / 2.0, n / 2.0), |
|||
coin.SbRotation(coin.SbVec3f(0.0, 1.0, 0.0), 0.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
makeLabel("mX", m) |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(n / 2.0, 0.0, -(1.0 + n * 0.7)), |
|||
coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
m1 = coin.SbMatrix() |
|||
m1.makeIdentity() |
|||
m1.setTransform( |
|||
coin.SbVec3f(0.0, 0.0, 0.0), |
|||
coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
m1.multRight(m) |
|||
makeLabel("pY", m1) |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(-1.1 - n / 2.0, 0.0, n / 2.0), |
|||
coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
makeLabel("mY", m) |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(n / 2.0, 0.7 + n * 0.6, 0.0), |
|||
coin.SbRotation(coin.SbVec3f(0.0, 1.0, 0.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
makeLabel("pZ", m) |
|||
m = coin.SbMatrix() |
|||
m.makeIdentity() |
|||
m.setTransform( |
|||
coin.SbVec3f(-1.1 - n / 2.0, - n / 2.0, 0.0), |
|||
coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
m1 = coin.SbMatrix() |
|||
m1.makeIdentity() |
|||
m1.setTransform( |
|||
coin.SbVec3f(0.0, 0.0, 0.0), |
|||
coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), |
|||
coin.SbVec3f(1.0, 1.0, 1.0)) |
|||
m1.multRight(m) |
|||
makeLabel("mZ", m1) |
|||
doLabels() |
|||
# Viewfit doesn't seem to do the right thing with MultiViews |
|||
# so we adjust the camera height manually before creating them |
|||
Gui.ActiveDocument.ActiveView.viewAxonometric() |
Gui.ActiveDocument.ActiveView.viewAxonometric() |
||
Gui.SendMsgToActiveView("ViewFit") |
Gui.SendMsgToActiveView("ViewFit") |
||
# Viewfit doesn't seem to do the right thing with MultiViews |
|||
camera = sceneGraph.getChild(2) |
|||
# so we adjust the camera height manually before creating them |
|||
if camera.getTypeId().getName().__str__() == "OrthographicCamera": |
|||
def fixCamera(lift): |
|||
camera.height.setValue((2.2 + n / 12.0) * camera.height.getValue()) |
|||
# This gets FreeCAD's top level SceneGraph (including camera node), |
|||
rotation = camera.orientation.getValue() # will be needed later |
|||
# not the document's SceneGraph which hangs off of it |
|||
v = Gui.ActiveDocument.ActiveView.getViewer() |
|||
sceneGraph = v.getSoEventManager().getSceneGraph() |
|||
camera = sceneGraph.getChild(2) |
|||
if camera.getTypeId().getName().__str__() == "OrthographicCamera": |
|||
if lift: |
|||
camera.height.setValue((2.0 + n / 20.0) * camera.height.getValue()) |
|||
return camera.orientation.getValue() |
|||
rotation = fixCamera(True) |
|||
# This bit of code finds the widget corresponding to the View3DInventor |
# This bit of code finds the widget corresponding to the View3DInventor |
||
Line 399: | Line 520: | ||
result = v |
result = v |
||
return result |
return result |
||
view3DWidget = findView(QtGui.qApp.activeWindow().centralWidget()) |
|||
# This bit of code creates the buttons at the top of the view window |
# This bit of code creates the buttons at the top of the view window |
||
Line 407: | Line 527: | ||
def __init__(self): |
def __init__(self): |
||
super(ButtonRow, self).__init__() |
super(ButtonRow, self).__init__() |
||
view3DWidget = findView(QtGui.qApp.activeWindow().centralWidget()) |
|||
self.setParent(view3DWidget) |
|||
if view3DWidget != None: |
|||
self.setParent(view3DWidget) |
|||
self.setAutoFillBackground(True) |
self.setAutoFillBackground(True) |
||
xpos = 0 |
xpos = 0 |
||
Line 438: | Line 560: | ||
def onSave(self): |
def onSave(self): |
||
saveHistory() |
saveHistory() |
||
Dictionary[str(App.ActiveDocument.Name)+"buttons"] = ButtonRow() |
|||
if view3DWidget != None: |
|||
Dictionary[str(App.ActiveDocument.Name)+"buttons"] = ButtonRow() |
|||
# This bit of code disables the default Phong shading |
# This bit of code disables the default Phong shading |
||
# and avoids the face colours appearing to change during rotation |
# and avoids the face colours appearing to change during rotation |
||
def fixLightModel(): |
|||
if str(sceneGraph.getChild(0).getName()) <> "LightModel": |
|||
v = Gui.ActiveDocument.ActiveView.getViewer() |
|||
lm=coin.SoLightModel() |
|||
sceneGraph = v.getSoEventManager().getSceneGraph() |
|||
lm.model.setValue(0) |
|||
if str(sceneGraph.getChild(0).getName()) <> "LightModel": |
|||
lm=coin.SoLightModel() |
|||
lm.model.setValue(0) |
|||
lm.setName("LightModel") |
|||
sceneGraph.insertChild(lm,0) |
|||
fixLightModel() |
|||
# This bit of code persuades FreeCAD'a renderer to put |
# This bit of code persuades FreeCAD'a renderer to put |
||
# several views of the cube into the same window |
# several views of the cube into the same window |
||
def MultiViews(parent, child, i): |
def MultiViews(parent, child, i, rotation): |
||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
|||
newchild=coin.SoMultipleCopy() |
newchild=coin.SoMultipleCopy() |
||
newchild.addChild(child) |
newchild.addChild(child) |
||
Line 461: | Line 587: | ||
m2=coin.SbMatrix() |
m2=coin.SbMatrix() |
||
m2.setTransform( |
m2.setTransform( |
||
coin.SbVec3f(n,n,0.0), |
coin.SbVec3f(n * 0.9 + 0.4, n * 0.9 + 0.4, 0.0), |
||
coin.SbRotation(coin.SbVec3f(-0.5,0.5,1),3.14159), |
coin.SbRotation(coin.SbVec3f(-0.5,0.5,1),3.14159), |
||
coin.SbVec3f(0.5,0.5,0.5)) |
coin.SbVec3f(0.5,0.5,0.5)) |
||
Line 467: | Line 593: | ||
m3=coin.SbMatrix() |
m3=coin.SbMatrix() |
||
m3.setTransform( |
m3.setTransform( |
||
coin.SbVec3f(- |
coin.SbVec3f(- n * 1.15 - 0.7, - n * 1.15 - 0.7, 0.0), |
||
rotation, |
rotation, |
||
coin.SbVec3f(0.5,0.5,0.5)) |
coin.SbVec3f(0.5,0.5,0.5)) |
||
Line 509: | Line 635: | ||
newchild.matrix=views |
newchild.matrix=views |
||
parent.replaceChild(i,newchild) |
parent.replaceChild(i,newchild) |
||
def createMultiViews(): |
def createMultiViews(rotation): |
||
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() |
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() |
||
if sg.getNumChildren() != 0: |
if sg.getNumChildren() != 0: |
||
Line 516: | Line 642: | ||
type = child.getTypeId().getName().__str__() |
type = child.getTypeId().getName().__str__() |
||
if child.getTypeId().getName().__str__() == 'Separator': |
if child.getTypeId().getName().__str__() == 'Separator': |
||
name = child.getName().__str__()[:5] |
|||
if name != "arrow" and name != "label": |
|||
MultiViews(sg,child,i,rotation) |
|||
if child.getTypeId().getName().__str__() == 'MultipleCopy': |
if child.getTypeId().getName().__str__() == 'MultipleCopy': |
||
if child.getNumChildren() != 0: |
if child.getNumChildren() != 0: |
||
Line 523: | Line 650: | ||
if fcd.getObject(name) == None: |
if fcd.getObject(name) == None: |
||
child.removeAllChildren() |
child.removeAllChildren() |
||
createMultiViews() |
createMultiViews(rotation) |
||
# Restore the normal cursor now that we have done all the slow stuff |
# Restore the normal cursor now that we have done all the slow stuff |
||
Line 529: | Line 656: | ||
# This bit of code animates a slice rotation |
# This bit of code animates a slice rotation |
||
def |
def rotate(dir, rs, re, steps): |
||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
||
fc = Dictionary[str(App.ActiveDocument.Name)+"cubies"] |
fc = Dictionary[str(App.ActiveDocument.Name)+"cubies"] |
||
fd = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
|||
fp = [[[[Base.Placement() for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
fp = [[[[Base.Placement() for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
||
xyz = ["x0","x1","y0","y1","z0","z1"] |
|||
fq = [[[[Part.Shape() for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
|||
steps = slowness / (n * n) |
|||
if dir.x > 0: |
if dir.x > 0: |
||
# We need an explicit matrix for the final rotation step |
|||
# to prevent rounding errors accumulating over time |
|||
ff = Base.Matrix(1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1) |
|||
kk =[0,1,5,4,2,3] |
|||
for iy in range(n): |
for iy in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[j][iy][iz][k] |
|||
c.Label = c.Name |
|||
fd[j][iy][iz][k] = c |
|||
fp[j][iy][iz][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateX |
fm.rotateX(1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for iy in range(n): |
||
for |
for iz in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[j][iy][iz][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
for iy in range(n): |
|||
Gui.updateGui() |
|||
for j in range(6): |
|||
fq[num][iy][iz][j]=fc[num][iz][n-1-iy][j] |
|||
for iy in range(n): |
for iy in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[j][iz][n-1-iy][kk[k]] |
|||
p = fp[j][iz][n-1-iy][kk[k]] |
|||
c.Label = "fs"+str(j)+"q"+str(iy)+"q"+str(iz)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[j][iy][iz][k] = c |
|||
elif dir.x < 0: |
elif dir.x < 0: |
||
ff = Base.Matrix(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1) |
|||
kk =[0,1,4,5,3,2] |
|||
for iy in range(n): |
for iy in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[j][iy][iz][k] |
|||
c.Label = c.Name |
|||
fd[j][iy][iz][k] = c |
|||
fp[j][iy][iz][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateX |
fm.rotateX(-1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for iy in range(n): |
||
for |
for iz in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[j][iy][iz][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
for iy in range(n): |
|||
Gui.updateGui() |
|||
for j in range(6): |
|||
fq[num][iy][iz][j]=fc[num][n-1-iz][iy][j] |
|||
for iy in range(n): |
for iy in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[j][n-1-iz][iy][kk[k]] |
|||
p = fp[j][n-1-iz][iy][kk[k]] |
|||
c.Label = "fs"+str(j)+"q"+str(iy)+"q"+str(iz)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[j][iy][iz][k] = c |
|||
elif dir.y > 0: |
elif dir.y > 0: |
||
ff = Base.Matrix(0,0,1,0,0,1,0,0,-1,0,0,0,0,0,0,1) |
|||
kk =[4,5,2,3,1,0] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[ix][j][iz][k] |
|||
c.Label = c.Name |
|||
fd[ix][j][iz][k] = c |
|||
fp[ix][j][iz][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateY |
fm.rotateY(1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for ix in range(n): |
||
for |
for iz in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[ix][j][iz][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
Gui.updateGui() |
|||
for ix in range(n): |
for ix in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[n-1-iz][j][ix][kk[k]] |
|||
p = fp[n-1-iz][j][ix][kk[k]] |
|||
c.Label = "fs"+str(ix)+"q"+str(j)+"q"+str(iz)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[ix][j][iz][k] = c |
|||
elif dir.y < 0: |
elif dir.y < 0: |
||
ff = Base.Matrix(0,0,-1,0,0,1,0,0,1,0,0,0,0,0,0,1) |
|||
kk =[5,4,2,3,0,1] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[ix][j][iz][k] |
|||
c.Label = c.Name |
|||
fd[ix][j][iz][k] = c |
|||
fp[ix][j][iz][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateY |
fm.rotateY(-1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for ix in range(n): |
||
for |
for iz in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[ix][j][iz][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
Gui.updateGui() |
|||
for ix in range(n): |
for ix in range(n): |
||
for iz in range(n): |
for iz in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[iz][j][n-1-ix][kk[k]] |
|||
p = fp[iz][j][n-1-ix][kk[k]] |
|||
c.Label = "fs"+str(ix)+"q"+str(j)+"q"+str(iz)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[ix][j][iz][k] = c |
|||
elif dir.z > 0: |
elif dir.z > 0: |
||
ff = Base.Matrix(0,-1,0,0,1,0,0,0,0,0,1,0,0,0,0,1) |
|||
kk = [3,2,0,1,4,5] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iy in range(n): |
for iy in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[ix][iy][j][k] |
|||
c.Label = c.Name |
|||
fd[ix][iy][j][k] = c |
|||
fp[ix][iy][j][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateZ |
fm.rotateZ(1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for ix in range(n): |
||
for |
for iy in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[ix][iy][j][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
for ix in range(n): |
|||
Gui.updateGui() |
|||
for j in range(6): |
|||
fq[ix][iy][num][j]=fc[iy][n-1-ix][num][j] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iy in range(n): |
for iy in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[iy][n-1-ix][j][kk[k]] |
|||
p = fp[iy][n-1-ix][j][kk[k]] |
|||
c.Label = "fs"+str(ix)+"q"+str(iy)+"q"+str(j)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[ix][iy][j][k] = c |
|||
elif dir.z < 0: |
elif dir.z < 0: |
||
ff = Base.Matrix(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1) |
|||
kk = [2,3,1,0,5,4] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iy in range(n): |
for iy in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fc[ix][iy][j][k] |
|||
c.Label = c.Name |
|||
fd[ix][iy][j][k] = c |
|||
fp[ix][iy][j][k] = c.Placement |
|||
if steps > 0: |
|||
fm = Base.Matrix() |
fm = Base.Matrix() |
||
fm.rotateZ |
fm.rotateZ(-1.570795 / steps) |
||
for |
for i in range(steps): |
||
for |
for ix in range(n): |
||
for |
for iy in range(n): |
||
for j in range(rs, re): |
|||
for k in range(6): |
|||
c |
c = fc[ix][iy][j][k] |
||
p = c.Placement |
|||
c.Placement = Base.Placement(fm).multiply(p) |
|||
for ix in range(n): |
|||
Gui.updateGui() |
|||
for j in range(6): |
|||
fq[ix][iy][num][j]=fc[n-1-iy][ix][num][j] |
|||
for ix in range(n): |
for ix in range(n): |
||
for iy in range(n): |
for iy in range(n): |
||
for j in range( |
for j in range(rs, re): |
||
for k in range(6): |
|||
c = fd[n-1-iy][ix][j][kk[k]] |
|||
p = fp[n-1-iy][ix][j][kk[k]] |
|||
c.Label = "fs"+str(ix)+"q"+str(iy)+"q"+str(j)+xyz[k] |
|||
c.Placement = Base.Placement(ff).multiply(p) |
|||
fc[ix][iy][j][k] = c |
|||
def slowrotate(dir, rs, re): |
|||
# This bit of code manages the history |
|||
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] |
|||
steps = slowness / (n * n) |
|||
if re > rs: |
|||
rotate(dir, rs, re, steps / (re - rs)) |
|||
Gui.updateGui() |
|||
# Quick rotation for use when randomising or modifying history |
|||
def fastrotate(dir, rs, re): |
|||
rotate(dir, rs, re, 0) |
|||
# These functions manage the history |
|||
# Once you have created a cube, these functions will be defined and in scope |
# Once you have created a cube, these functions will be defined and in scope |
||
# and you can call them from another macro |
# and you can call them from another macro created by saving history |
||
# or by hand from the python console window |
|||
history = [] |
history = [] |
||
Dictionary[str(App.ActiveDocument.Name)+"history"] = history |
Dictionary[str(App.ActiveDocument.Name)+"history"] = history |
||
def |
def mrotpX(i,j): |
||
slowrotate(Base.Vector(1,0,0),i) |
slowrotate(Base.Vector(1,0,0),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpX("+str(i)+","+str(j)+")") |
||
def |
def mrotpY(i,j): |
||
slowrotate(Base.Vector(0,1,0),i) |
slowrotate(Base.Vector(0,1,0),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpY("+str(i)+","+str(j)+")") |
||
def |
def mrotpZ(i,j): |
||
slowrotate(Base.Vector(0,0,1),i) |
slowrotate(Base.Vector(0,0,1),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpZ("+str(i)+","+str(j)+")") |
||
def |
def mrotmX(i,j): |
||
slowrotate(Base.Vector(-1,0,0),i) |
slowrotate(Base.Vector(-1,0,0),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmX("+str(i)+","+str(j)+")") |
||
def |
def mrotmY(i,j): |
||
slowrotate(Base.Vector(0,-1,0),i) |
slowrotate(Base.Vector(0,-1,0),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmY("+str(i)+","+str(j)+")") |
||
def |
def mrotmZ(i,j): |
||
slowrotate(Base.Vector(0,0,-1),i) |
slowrotate(Base.Vector(0,0,-1),i,j) |
||
Dictionary[str(App.ActiveDocument.Name)+"history"].append(" |
Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmZ("+str(i)+","+str(j)+")") |
||
def undo(): |
def undo(): |
||
history = Dictionary[str(App.ActiveDocument.Name)+"history"] |
history = Dictionary[str(App.ActiveDocument.Name)+"history"] |
||
if len(history) > 0: |
if len(history) > 0: |
||
fs = history.pop() |
fs = history.pop() |
||
wh = fs[: |
wh = fs[:6] |
||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[(p+1):(len(fs)-1)]) |
|||
if wh == "mrotmX": |
|||
slowrotate(Base.Vector( |
slowrotate(Base.Vector(1,0,0),i,j) |
||
elif wh == " |
elif wh == "mrotpX": |
||
slowrotate(Base.Vector( |
slowrotate(Base.Vector(-1,0,0),i,j) |
||
elif wh == " |
elif wh == "mrotmY": |
||
slowrotate(Base.Vector(0, |
slowrotate(Base.Vector(0,1,0),i,j) |
||
elif wh == " |
elif wh == "mrotpY": |
||
slowrotate(Base.Vector(0, |
slowrotate(Base.Vector(0,-1,0),i,j) |
||
elif wh == " |
elif wh == "mrotmZ": |
||
slowrotate(Base.Vector(0,0, |
slowrotate(Base.Vector(0,0,1),i,j) |
||
elif wh == "mrotpZ": |
|||
slowrotate(Base.Vector(0,0,-1),i,j) |
|||
def itostring(i, n): |
|||
if 2 * i == n - 1: |
|||
return "n/2" |
|||
elif i <= n / 2: |
|||
return str(i) |
|||
elif i == n - 1: |
|||
return "n-1" |
|||
else: |
|||
return "n-" + str(n-i) |
|||
def jtostring(j, n): |
|||
if j <= n / 2: |
|||
return str(j) |
|||
elif 2 * j == n + 1: |
|||
return "n/2+1" |
|||
elif j == n: |
|||
return "n" |
|||
elif j == n - 1: |
|||
return "n-1" |
|||
else: |
|||
return "n-" + str(n-j) |
|||
def saveHistory(): |
def saveHistory(): |
||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
if len(history) > 0: |
if len(history) > 0: |
||
# This statement will be needed at the start of any macro |
|||
fs = "" |
|||
# to get the size of the cube in the currently active document |
|||
while len(history) > 0: |
|||
# in case we have several documents open at once |
|||
fs = "n = Dictionary[str(App.ActiveDocument.Name)+'Size']\n" |
|||
for s in history: |
|||
p = s.index(",") |
|||
i = int(s[7:p]) |
|||
j = int(s[(p+1):(len(s)-1)]) |
|||
fs = fs + s[:7] + itostring(i, n) + "," |
|||
fs = fs + jtostring(j, n) + ")\n" |
|||
clip = QtCore.QCoreApplication.instance().clipboard() |
clip = QtCore.QCoreApplication.instance().clipboard() |
||
clip.setText(fs) |
clip.setText(fs) |
||
def reset(): |
def reset(): |
||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
fcd = App.ActiveDocument |
||
Dictionary[str(fcd.Name)+"history"] = [] |
Dictionary[str(fcd.Name)+"history"] = [] |
||
n = Dictionary[str(fcd.Name)+"Size"] |
n = Dictionary[str(fcd.Name)+"Size"] |
||
fc = Dictionary[str(fcd.Name)+"cubies"] |
fc = Dictionary[str(fcd.Name)+"cubies"] |
||
for |
for obj in fcd.Objects: |
||
fs = obj.Name |
|||
if fs[0:2] == "ff": |
|||
obj.Label = fs |
|||
for obj in fcd.Objects: |
|||
fs = obj.Name |
|||
if fs[0:2] == "ff": |
|||
obj.Label = "fs"+fs[2:] |
|||
obj.Placement = Base.Placement() |
|||
l = len(fs) |
|||
q1 = fs.find("q") |
|||
q2 = fs.find("q",q1+1) |
|||
ix = int(fs[2:q1]) |
|||
iy = int(fs[q1+1:q2]) |
|||
iz = int(fs[q2+1:l-2]) |
|||
k = "x0x1y0y1z0z1".find(fs[l-2:])/2 |
|||
fc[ix][iy][iz][k] = obj |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
c = fcd.getObject(fs+"z0") |
|||
c.Placement = Base.Placement() |
|||
# Randomise the cube |
|||
fc[ix][iy][iz][4] = c |
|||
def randomise(): |
|||
c = fcd.getObject(fs+"z1") |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
c.Placement = Base.Placement() |
|||
fcd = App.ActiveDocument |
|||
fc[ix][iy][iz][5] = c |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
</pre> |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
random.seed() |
|||
i = random.randrange(0,6) |
|||
for x in range(n*24): |
|||
i = (i + 2 - i % 2 +random.randrange(0,4)) % 6 |
|||
j = random.randrange(0,n) |
|||
if i == 0: |
|||
fastrotate(Base.Vector(1,0,0),j,j+1) |
|||
history.append("mrotpX("+str(j)+","+str(j+1)+")") |
|||
elif i == 1: |
|||
fastrotate(Base.Vector(-1,0,0),j,j+1) |
|||
history.append("mrotmX("+str(j)+","+str(j+1)+")") |
|||
elif i == 2: |
|||
fastrotate(Base.Vector(0,1,0),j,j+1) |
|||
history.append("mrotpY("+str(j)+","+str(j+1)+")") |
|||
elif i == 3: |
|||
fastrotate(Base.Vector(0,-1,0),j,j+1) |
|||
history.append("mrotmY("+str(j)+","+str(j+1)+")") |
|||
elif i == 4: |
|||
fastrotate(Base.Vector(0,0,1),j,j+1) |
|||
history.append("mrotpZ("+str(j)+","+str(j+1)+")") |
|||
elif i == 5: |
|||
fastrotate(Base.Vector(0,0,-1),j,j+1) |
|||
history.append("mrotmZ("+str(j)+","+str(j+1)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
# Various macros to modify the history |
|||
# They all read the history and undo it, and then perform some modified version |
|||
# of the history. The modifications can be time-reversal, reflection along an |
|||
# axis (as if the cube were reflected, the history replayed, |
|||
# and the cube reflected back again), or rotation (as if the cube were rotated, |
|||
# the history replayed, and the cube rotated back again). |
|||
def slow_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
Gui.updateGui() |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
mrotpX(i,j) |
|||
elif wh == "mrotmX": |
|||
mrotmX(i,j) |
|||
elif wh == "mrotpY": |
|||
mrotpY(i,j) |
|||
elif wh == "mrotmY": |
|||
mrotmY(i,j) |
|||
elif wh == "mrotpZ": |
|||
mrotpZ(i,j) |
|||
elif wh == "mrotmZ": |
|||
mrotmZ(i,j) |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def reverse_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
for fs in nh: |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def undo_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
for fs in nh: |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def reflectX_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(1,0,0),n-j,n-i) |
|||
history.append("mrotpX("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(-1,0,0),n-j,n-i) |
|||
history.append("mrotmX("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def reflectY_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,1,0),n-j,n-i) |
|||
history.append("mrotpY("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,-1,0),n-j,n-i) |
|||
history.append("mrotmY("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def reflectZ_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,1),n-j,n-i) |
|||
history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,-1),n-j,n-i) |
|||
history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotpX_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,-1,0),n-j,n-i) |
|||
history.append("mrotmY("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,1,0),n-j,n-i) |
|||
history.append("mrotpY("+str(n-j)+","+str(n-i)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotmX_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,0,-1),n-j,n-i) |
|||
history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,0,1),n-j,n-i) |
|||
history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotpY_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(0,0,-1),n-j,n-i) |
|||
history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(0,0,1),n-j,n-i) |
|||
history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotmY_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(-1,0,0),n-j,n-i) |
|||
history.append("mrotmX("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(1,0,0),n-j,n-i) |
|||
history.append("mrotpX("+str(n-j)+","+str(n-i)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotpZ_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(0,1,0),i,j) |
|||
history.append("mrotpY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(0,-1,0),i,j) |
|||
history.append("mrotmY("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(-1,0,0),n-j,n-i) |
|||
history.append("mrotmX("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(1,0,0),n-j,n-i) |
|||
history.append("mrotpX("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
def rotmZ_history(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
n = Dictionary[str(fcd.Name)+"Size"] |
|||
nh = [] |
|||
while len(history) > 0: |
|||
nh.append(history.pop()) |
|||
reset() |
|||
history = Dictionary[str(fcd.Name)+"history"] |
|||
while len(nh) > 0: |
|||
fs = nh.pop() |
|||
wh = fs[:6] |
|||
p = fs.index(",") |
|||
i = int(fs[7:p]) |
|||
j = int(fs[p+1:len(fs)-1]) |
|||
if wh == "mrotpX": |
|||
fastrotate(Base.Vector(0,-1,0),n-j,n-i) |
|||
history.append("mrotmY("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotmX": |
|||
fastrotate(Base.Vector(0,1,0),n-j,n-i) |
|||
history.append("mrotpY("+str(n-j)+","+str(n-i)+")") |
|||
elif wh == "mrotpY": |
|||
fastrotate(Base.Vector(1,0,0),i,j) |
|||
history.append("mrotpX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmY": |
|||
fastrotate(Base.Vector(-1,0,0),i,j) |
|||
history.append("mrotmX("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotpZ": |
|||
fastrotate(Base.Vector(0,0,1),i,j) |
|||
history.append("mrotpZ("+str(i)+","+str(j)+")") |
|||
elif wh == "mrotmZ": |
|||
fastrotate(Base.Vector(0,0,-1),i,j) |
|||
history.append("mrotmZ("+str(i)+","+str(j)+")") |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
# FreeCAD's file save only saves the state of the camera |
|||
# and the shapes, positions, orientations, names, and labels |
|||
# of the objects in the scene |
|||
# This function recreates all the other stuff after reloading a saved file |
|||
# I haven't found a way to make FreeCAD save the history, so it gets reset |
|||
def fix_reload(): |
|||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) |
|||
fcd = App.ActiveDocument |
|||
# first we find how big a cube we have |
|||
n = 0 |
|||
for obj in fcd.Objects: |
|||
fs = obj.Name |
|||
if fs[0:2] == "ff": |
|||
i = int(fs[2:fs.index("q")]) |
|||
if i > n: |
|||
n = i |
|||
elif fs[0:4] == "Text": |
|||
# get rid of this because it's incorrectly positioned |
|||
# we'll create a new one later |
|||
fcd.removeObject(fs) |
|||
elif fs[0:5] == "arrow": |
|||
obj.ViewObject.RootNode.setName(coin.SbName(fs)) |
|||
n = n + 1 |
|||
fc = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] |
|||
Dictionary[str(fcd.Name)+"Size"] = n |
|||
for obj in fcd.Objects: |
|||
fs = obj.Label |
|||
if fs[0:2] == "fs": |
|||
l = len(fs) |
|||
q1 = fs.find("q") |
|||
q2 = fs.find("q",q1+1) |
|||
ix = int(fs[2:q1]) |
|||
iy = int(fs[q1+1:q2]) |
|||
iz = int(fs[q2+1:l-2]) |
|||
k = "x0x1y0y1z0z1".find(fs[l-2:])/2 |
|||
fc[ix][iy][iz][k] = obj |
|||
Dictionary[str(fcd.Name)+"cubies"] = fc |
|||
Dictionary[str(fcd.Name)+"ViewObserver"] = ViewObserver() |
|||
doLabels() # create new labels |
|||
rotation = fixCamera(False) |
|||
Dictionary[str(fcd.Name)+"buttons"] = ButtonRow() |
|||
fixLightModel() |
|||
createMultiViews(rotation) |
|||
history = [] # according to Henry Ford |
|||
Dictionary[str(fcd.Name)+"history"] = history |
|||
QtGui.QApplication.restoreOverrideCursor() |
|||
FreeCAD.Console.PrintLog("fix_reload() done\n") |
Revision as of 20:53, 5 December 2017
Description
File:Text-x-python Macro_Rubik_Cube |
Description |
---|
Macro to Display a Rubik Cube and interactively do slice rotations. Macro version: 00.03 Last modified: 2017-10-25 Author: Aleph0 |
Author |
Aleph0 |
Download |
None |
Links |
Macros recipes How to install macros How to customize toolbars |
Macro Version |
00.03 |
Date last modified |
2017-10-25 |
FreeCAD Version(s) |
None |
Default shortcut |
None |
See also |
None |
Macro to Display a Rubik Cube and interactively do slice rotations.
- -*- coding: utf-8 -*-
"""
- *
- This macro creates a virtual Rubik Cube and enable you to manipulate *
- it. *
- You can chooose the size (number of small cubes along an edge). *
- It then makes the cube: large sizes can take a while. *
- It then displays several views of the cube. *
- The central and largest view is an axonometric projection. *
- This has arrows around it which you can click on to rotate slices. *
- There are some text direction labels near the arrows: clicking on one *
- of those rotates the whole cube. You have to click on the actual *
- letter: FreeCAD doesn't see clicks on the text background *
- Another view is an axonometric projection from the other side. *
- Another view combines views towards each face so as to *
- look like a net of the cube's surface unfolded. *
- The macro maintains a history of the slice rotations you have done. *
- It puts three buttons at the top of the window. *
- One undoes the last slice rotation and removes it from the history. *
- One saves the history to the clipboard as a sequence of function *
- calls which can be pasted into a macro which can then be called *
- to replay the same set of rotations. Thus you can save an "operator" *
- (a sequence of slice rotation which does something useful). *
- The third button resets the cube to its initial state *
- and clears the history. *
- *
- There are also some functions defined which can be called from the *
- python console window: *
- fix_reload() modifies a restored FreeCAD save file to add the extra *
- views and interactive controls that this macro and its functions use; *
- ramdomise() randomises the cube; *
- reverse_history(), reflectX_history(), reflectY_history(), *
- reflectZ_history(), rotpX_history(), rotmX_history(), *
- rotpY_history(), rotmY_history(), rotpZ_history(), and *
- rotmZ_history() each replace the history by a version modified in the *
- manner indicated - these are useful for creating modified operators. *
- *
- Copyright © 2017 Richard P. Parkins, M. A. *
- *
- This file is a supplement to the FreeCAD CAx development system. *
- *
- This program is free software; you can redistribute it and/or modify *
- it under the terms of the GNU Lesser General Public License (LGPL) *
- as published by the Free Software Foundation; either version 2 of *
- the License, or (at your option) any later version. *
- for detail see the LICENCE text file. *
- *
- This software 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 Library General Public License for more details. *
- *
- You should have received a copy of the GNU Library General Public *
- License along with this macro; if not, write to the Free Software *
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
- USA *
- *
""" __title__ = "Rubik_cube" __author__ = "Aleph0" __version__ = "00.04" __date__ = "05/12/2017" __Comment__ = "Virtual Rubik Cube" __Wiki__ = "http://www.freecadweb.org/wiki/index.php?title=Macro_Rubik_Cube" __Help__ = "see first few lines of macro text" __Status__ = "stable" __Requires__ = "freecad 0.16"
- OS: Ubuntu 14.04.5 LTS
- Word size of OS: 64-bit
- Word size of FreeCAD: 64-bit
- Version: 0.16.6703 (Git)
- Build type: None
- Branch: releases/FreeCAD-0-16
- Hash: 2ce5c8d2e3020d05005ed71f710e09e9aa561f40
- Python version: 2.7.6
- Qt version: 4.8.6
- Coin version: 4.0.0a
- OCC version: 6.8.0.oce-0.17
- This parameter determines the speed at which slice rotations are animated
- If you have a faster computer you can increase the value
- This will make the animation smoother
- If you have a slow computer you can decrease the value
- This will make the animation faster but more jerky for large cubes
slowness = 500
import FreeCAD import Part import Draft import time import random from FreeCAD import Base from FreeCAD import Console from pivy import coin from pivy.coin import * import PySide
- I copied this code from Macro_Mouse_Cross
- It seems a bit version dependent, but it works
try:
from PyQt4 import QtCore, QtGui
except Exception:
from PySide import QtCore, QtGui
- If this is the first time this macro has been run in this invocation of FreeCAD,
- create our dictionary of document-specific data structures
if not hasattr(FreeCAD, "Rubik_Cube_executed"):
FreeCAD.Rubik_Cube_executed = 1 Dictionary = {}
- Create a new document and make it current
App.ActiveDocument = App.newDocument("Rubik_Cube") Gui.ActiveDocument = Gui.getDocument(str(App.ActiveDocument.Name))
- This bit of code pops up the dialog to ask for the size
width = 300 height = 150 defaultSize = 3 class AskSizeWindow(QtGui.QDialog):
# automagically called when the window is created def __init__(self): super(AskSizeWindow, self).__init__() self.initUI() # Lay out the interactive elements def initUI(self): self.setWindowTitle("Rubik Cube Size") geom = Gui.getMainWindow().geometry() xpos = geom.center().x() - width / 2 ypos = geom.center().y() - height / 2 self.setGeometry(xpos, ypos, width, height) margin = 10 ypos = margin self.label_1 = QtGui.QLabel(self) self.label_1.setGeometry(QtCore.QRect(width/2 - 100, ypos, 200, 25)) self.label_1.setObjectName("label_1") self.label_1.setText("Number of small cubes") self.label_1.setAlignment(QtCore.Qt.AlignCenter) ypos = ypos + 25 self.label_2 = QtGui.QLabel(self) self.label_2.setGeometry(QtCore.QRect(width/2 - 100, ypos, 200, 25)) self.label_2.setObjectName("label_1") self.label_2.setText("along an edge") self.label_2.setAlignment(QtCore.Qt.AlignCenter) ypos = ypos + 25 self.spinBox = QtGui.QSpinBox(self) self.spinBox.setGeometry(QtCore.QRect(width/2 - 50, ypos, 100, 30)) self.spinBox.setMinimum(2) self.spinBox.setMaximum(100) Dictionary[str(App.ActiveDocument.Name)+"Size"] = defaultSize self.spinBox.setValue(defaultSize) self.spinBox.setSingleStep(1) self.spinBox.setObjectName("spinBox") self.spinBox.valueChanged.connect(self.on_spinBox_valueChanged) ypos = ypos + 40 self.OKbutton = QtGui.QPushButton(self) self.OKbutton.setGeometry(QtCore.QRect(width/2 - 40, ypos, 80, 40)) self.OKbutton.setText("OK") self.OKbutton.clicked.connect(self.onOK) def on_spinBox_valueChanged(self, val): Dictionary[str(App.ActiveDocument.Name)+"Size"] = val def onOK(self): self.close() self.destroy()
AskSizeWindow().exec_()
- Display a wait cursor while we are making the cube
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
- This bit of code catches clicks on the rotation arrows
class ViewObserver:
def __init__(self): self.view = FreeCADGui.ActiveDocument.ActiveView self.callback = self.view.addEventCallbackPivy(SoMouseButtonEvent.getClassTypeId(),self.getpoint) def getpoint(self,event_cb): event = event_cb.getEvent() if event.getButton() == 1: pos = event.getPosition().getValue() obInfo = self.view.getObjectInfo((int(pos[0]),int(pos[1]))) if obInfo != None: obj = App.ActiveDocument.getObject(obInfo["Object"]) obname = obj.Label if obname[:5] == "arrow": if event.getState() == 1: wh = obname[5:7] i = int(obname[7:]) if wh == "mX": mrotmX(i,i+1) elif wh == "pX": mrotpX(i,i+1) elif wh == "mY": mrotmY(i,i+1) elif wh == "pY": mrotpY(i,i+1) elif wh == "mZ": mrotmZ(i,i+1) elif wh == "pZ": mrotpZ(i,i+1) event_cb.setHandled() elif obname[:5] == "label": if event.getState() == 1: wh = obname[5:7] n = Dictionary[str(App.ActiveDocument.Name)+"Size"] if wh == "mX": mrotmX(0,n) elif wh == "pX": mrotpX(0,n) elif wh == "mY": mrotmY(0,n) elif wh == "pY": mrotpY(0,n) elif wh == "mZ": mrotmZ(0,n) elif wh == "pZ": mrotpZ(0,n) event_cb.setHandled()
Dictionary[str(App.ActiveDocument.Name)+"ViewObserver"] = ViewObserver()
- This bit of code creates the basic cube model
- It is composed of faces rather than cubes because I haven't found a way of making
- a cube with different coloured faces
- Each face has a name and a label
- The name is persistent regardless of how the face moves about the cube
- The label changes and tells where the face is now: this is needed for fix_reload
fcd = App.ActiveDocument n = Dictionary[str(App.ActiveDocument.Name)+"Size"] fc = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] Dictionary[str(App.ActiveDocument.Name)+"cubies"] = fc for ix in range(n):
fx = ix - (n - 1) / 2.0 for iy in range(n): fy = iy - (n - 1) / 2.0 for iz in range(n): fz = iz - (n - 1) / 2.0 fs = str(ix)+"q"+str(iy)+"q"+str(iz) x0y0z0 = Base.Vector(fx-0.5,fy-0.5,fz-0.5) x0y0z1 = Base.Vector(fx-0.5,fy-0.5,fz+0.5) x0y1z0 = Base.Vector(fx-0.5,fy+0.5,fz-0.5) x0y1z1 = Base.Vector(fx-0.5,fy+0.5,fz+0.5) x1y0z0 = Base.Vector(fx+0.5,fy-0.5,fz-0.5) x1y0z1 = Base.Vector(fx+0.5,fy-0.5,fz+0.5) x1y1z0 = Base.Vector(fx+0.5,fy+0.5,fz-0.5) x1y1z1 = Base.Vector(fx+0.5,fy+0.5,fz+0.5) face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x0y1z1,x0y1z0,x0y0z0])) f1 = fcd.addObject("Part::Feature", "ff"+fs+"x0") f1.Shape = face f1.Label = "fs"+fs+"x0" if ix == 0: f1.ViewObject.DiffuseColor=[(1.0,1.0,1.0)] else: f1.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f1.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"x0")) face = Part.Face(Part.makePolygon([x1y0z0,x1y0z1,x1y1z1,x1y1z0,x1y0z0])) f2 = fcd.addObject("Part::Feature", "ff"+fs+"x1") f2.Shape = face f2.Label = "fs"+fs+"x1" if ix == n - 1: f2.ViewObject.DiffuseColor=[(1.0,0.0,0.0)] else: f2.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f2.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"x1")) face = Part.Face(Part.makePolygon([x0y0z0,x0y0z1,x1y0z1,x1y0z0,x0y0z0])) f3 = fcd.addObject("Part::Feature", "ff"+fs+"y0") f3.Shape = face f3.Label = "fs"+fs+"y0" if iy == 0: f3.ViewObject.DiffuseColor=[(0.0,1.0,0.0)] else: f3.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f3.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"y0")) face = Part.Face(Part.makePolygon([x0y1z0,x0y1z1,x1y1z1,x1y1z0,x0y1z0])) f4 = fcd.addObject("Part::Feature", "ff"+fs+"y1") f4.Shape = face f4.Label = "fs"+fs+"y1" if iy == n - 1: f4.ViewObject.DiffuseColor=[(1.0,0.0,1.0)] else: f4.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f4.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"y1")) face = Part.Face(Part.makePolygon([x0y0z0,x0y1z0,x1y1z0,x1y0z0,x0y0z0])) f5 = fcd.addObject("Part::Feature", "ff"+fs+"z0") f5.Shape = face f5.Label = "fs"+fs+"z0" if iz == 0: f5.ViewObject.DiffuseColor=[(1.0,1.0,0.0)] else: f5.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f5.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"z0")) face = Part.Face(Part.makePolygon([x0y0z1,x0y1z1,x1y1z1,x1y0z1,x0y0z1])) f6 = fcd.addObject("Part::Feature", "ff"+fs+"z1") f6.Shape = face f6.Label = "fs"+fs+"z1" if iz == n - 1: f6.ViewObject.DiffuseColor=[(0.0,0.0,1.0)] else: f6.ViewObject.DiffuseColor=[(0.0,0.0,0.0)] f6.ViewObject.RootNode.setName(coin.SbName("ff"+fs+"z1")) fc[ix][iy][iz]=[f1,f2,f3,f4,f5,f6]
- This bit of code creates the clickable arrows
- Note we make them not selectable because mouse clicking on them
- does a slice rotation instead of selecting the arrow.
for i in range(n):
fx = i - (n - 1) / 2.0 fy = -(n / 2.0) fz = -(0.2 + n / 2.0) fs = "arrowpX"+str(i) v0 = Base.Vector(fx-0.1,fy,fz) v1 = Base.Vector(fx-0.1,fy,fz-0.5) v2 = Base.Vector(fx-0.2,fy,fz-0.5) v3 = Base.Vector(fx,fy,fz-0.7) v4 = Base.Vector(fx+0.2,fy,fz-0.5) v5 = Base.Vector(fx+0.1,fy,fz-0.5) v6 = Base.Vector(fx+0.1,fy,fz) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False fy = 0.2 + n / 2.0 fz = n / 2.0 fs = "arrowmX"+str(i) v0 = Base.Vector(fx-0.1,fy,fz) v1 = Base.Vector(fx-0.1,fy+0.5,fz) v2 = Base.Vector(fx-0.2,fy+0.5,fz) v3 = Base.Vector(fx,fy+0.7,fz) v4 = Base.Vector(fx+0.2,fy+0.5,fz) v5 = Base.Vector(fx+0.1,fy+0.5,fz) v6 = Base.Vector(fx+0.1,fy,fz) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False fx = n / 2.0 fy = i - (n - 1) / 2.0 fz = -(0.2 + n / 2.0) fs = "arrowpY"+str(i) v0 = Base.Vector(fx,fy-0.1,fz) v1 = Base.Vector(fx,fy-0.1,fz-0.5) v2 = Base.Vector(fx,fy-0.2,fz-0.5) v3 = Base.Vector(fx,fy,fz-0.7) v4 = Base.Vector(fx,fy+0.2,fz-0.5) v5 = Base.Vector(fx,fy+0.1,fz-0.5) v6 = Base.Vector(fx,fy+0.1,fz) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False fx = -(0.2 + n / 2.0) fy = i - (n - 1) / 2.0 fz = n / 2.0 fs = "arrowmY"+str(i) v0 = Base.Vector(fx,fy-0.1,fz) v1 = Base.Vector(fx-0.5,fy-0.1,fz) v2 = Base.Vector(fx-0.5,fy-0.2,fz) v3 = Base.Vector(fx-0.7,fy,fz) v4 = Base.Vector(fx-0.5,fy+0.2,fz) v5 = Base.Vector(fx-0.5,fy+0.1,fz) v6 = Base.Vector(fx,fy+0.1,fz) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False fx = n / 2.0 fy = 0.2 + n / 2.0 fz = i - (n - 1) / 2.0 fs = "arrowpZ"+str(i) v0 = Base.Vector(fx,fy,fz-0.1) v1 = Base.Vector(fx,fy+0.5,fz-0.1) v2 = Base.Vector(fx,fy+0.5,fz-0.2) v3 = Base.Vector(fx,fy+0.7,fz) v4 = Base.Vector(fx,fy+0.5,fz+0.2) v5 = Base.Vector(fx,fy+0.5,fz+0.1) v6 = Base.Vector(fx,fy,fz+0.1) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False fx = -(0.2 + n / 2.0) fy = -(n / 2.0) fz = i - (n - 1) / 2.0 fs = "arrowmZ"+str(i) v0 = Base.Vector(fx,fy,fz-0.1) v1 = Base.Vector(fx-0.5,fy,fz-0.1) v2 = Base.Vector(fx-0.5,fy,fz-0.2) v3 = Base.Vector(fx-0.7,fy,fz) v4 = Base.Vector(fx-0.5,fy,fz+0.2) v5 = Base.Vector(fx-0.5,fy,fz+0.1) v6 = Base.Vector(fx,fy,fz+0.1) arrow = fcd.addObject("Part::Feature", fs) arrow.Shape = Part.Face(Part.makePolygon([v0,v1,v2,v3,v4,v5,v6,v0])) arrow.ViewObject.DiffuseColor = [(0.0,0.0,0.0)] arrow.ViewObject.RootNode.setName(coin.SbName(fs)) arrow.ViewObject.Selectable = False
- This bit of code creates some labels for the arrows
- Clicking on one rotates the whole cube
def makeLabel(text, mat):
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] tx = Draft.makeText(text) tx.Label = "label"+text tx.ViewObject.TextColor = (0.0,0.0,0.0) tx.ViewObject.FontSize = 0.2 * n tx.ViewObject.Justification = 'Center' node = tx.ViewObject.RootNode node.setName(coin.SbName("label"+text)) if node.getNumChildren() > 0: child = node.getChild(0) if child.getTypeId().getName().__str__() == "Transform": child.setMatrix(mat)
def doLabels():
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(0.0, - n / 2.0, -(1.0 + n * 0.7)), coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) makeLabel("pX", m) m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(0.0, 1.1 + n / 2.0, n / 2.0), coin.SbRotation(coin.SbVec3f(0.0, 1.0, 0.0), 0.0), coin.SbVec3f(1.0, 1.0, 1.0)) makeLabel("mX", m) m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(n / 2.0, 0.0, -(1.0 + n * 0.7)), coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) m1 = coin.SbMatrix() m1.makeIdentity() m1.setTransform( coin.SbVec3f(0.0, 0.0, 0.0), coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) m1.multRight(m) makeLabel("pY", m1) m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(-1.1 - n / 2.0, 0.0, n / 2.0), coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) makeLabel("mY", m) m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(n / 2.0, 0.7 + n * 0.6, 0.0), coin.SbRotation(coin.SbVec3f(0.0, 1.0, 0.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) makeLabel("pZ", m) m = coin.SbMatrix() m.makeIdentity() m.setTransform( coin.SbVec3f(-1.1 - n / 2.0, - n / 2.0, 0.0), coin.SbRotation(coin.SbVec3f(1.0, 0.0, 0.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) m1 = coin.SbMatrix() m1.makeIdentity() m1.setTransform( coin.SbVec3f(0.0, 0.0, 0.0), coin.SbRotation(coin.SbVec3f(0.0, 0.0, 1.0), 3.14159 / 2.0), coin.SbVec3f(1.0, 1.0, 1.0)) m1.multRight(m) makeLabel("mZ", m1)
doLabels()
Gui.ActiveDocument.ActiveView.viewAxonometric() Gui.SendMsgToActiveView("ViewFit")
- Viewfit doesn't seem to do the right thing with MultiViews
- so we adjust the camera height manually before creating them
def fixCamera(lift):
# This gets FreeCAD's top level SceneGraph (including camera node), # not the document's SceneGraph which hangs off of it v = Gui.ActiveDocument.ActiveView.getViewer() sceneGraph = v.getSoEventManager().getSceneGraph() camera = sceneGraph.getChild(2) if camera.getTypeId().getName().__str__() == "OrthographicCamera": if lift: camera.height.setValue((2.0 + n / 20.0) * camera.height.getValue()) return camera.orientation.getValue()
rotation = fixCamera(True)
- This bit of code finds the widget corresponding to the View3DInventor
def findView(widget):
if widget.metaObject().className().__str__() == "Gui::View3DInventor": return widget else: result = None for child in widget.children(): v = findView(child) if v != None: result = v return result
- This bit of code creates the buttons at the top of the view window
- The buttons are in a frameless window to save screen space
height = 40 class ButtonRow(QtGui.QWidget):
def __init__(self): super(ButtonRow, self).__init__() view3DWidget = findView(QtGui.qApp.activeWindow().centralWidget()) if view3DWidget != None: self.setParent(view3DWidget) self.setAutoFillBackground(True) xpos = 0 geom = view3DWidget.geometry() self.setGeometry(xpos, 0, geom.width(), height) buttonWidth = 80 gap = geom.width() / 4 - buttonWidth if gap < 0: gap = 0 xpos = gap self.undoButton = QtGui.QPushButton(self) self.undoButton.setGeometry(xpos, 0, buttonWidth, 30) self.undoButton.setText("Undo") self.undoButton.clicked.connect(self.onUndo) xpos = xpos + buttonWidth + gap self.saveButton = QtGui.QPushButton(self) self.saveButton.setGeometry(xpos, 0, 3 * buttonWidth, 30) self.saveButton.setText("Copy history to clipboard") self.saveButton.clicked.connect(self.onSave) xpos = xpos + 3 * buttonWidth + gap self.resetButton = QtGui.QPushButton(self) self.resetButton.setGeometry(xpos, 0, buttonWidth, 30) self.resetButton.setText("Reset") self.resetButton.clicked.connect(self.onReset) self.show() def onUndo(self): undo() def onReset(self): reset() def onSave(self): saveHistory()
Dictionary[str(App.ActiveDocument.Name)+"buttons"] = ButtonRow()
- This bit of code disables the default Phong shading
- and avoids the face colours appearing to change during rotation
def fixLightModel():
v = Gui.ActiveDocument.ActiveView.getViewer() sceneGraph = v.getSoEventManager().getSceneGraph() if str(sceneGraph.getChild(0).getName()) <> "LightModel": lm=coin.SoLightModel() lm.model.setValue(0) lm.setName("LightModel") sceneGraph.insertChild(lm,0)
fixLightModel()
- This bit of code persuades FreeCAD'a renderer to put
- several views of the cube into the same window
def MultiViews(parent, child, i, rotation):
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] newchild=coin.SoMultipleCopy() newchild.addChild(child) views=coin.SoMFMatrix() views.setNum(8) m1=coin.SbMatrix() m1.makeIdentity() views.set1Value(0,m1) m2=coin.SbMatrix() m2.setTransform( coin.SbVec3f(n * 0.9 + 0.4, n * 0.9 + 0.4, 0.0), coin.SbRotation(coin.SbVec3f(-0.5,0.5,1),3.14159), coin.SbVec3f(0.5,0.5,0.5)) views.set1Value(1,m2) m3=coin.SbMatrix() m3.setTransform( coin.SbVec3f(- n * 1.15 - 0.7, - n * 1.15 - 0.7, 0.0), rotation, coin.SbVec3f(0.5,0.5,0.5)) views.set1Value(2,m3) m4=coin.SbMatrix() m4.setTransform( coin.SbVec3f(0,n,0), coin.SbRotation(coin.SbVec3f(1,0,0),3.14159*90/180.0), coin.SbVec3f(1,1,1)) m4.multRight(m3) views.set1Value(3,m4) m5=coin.SbMatrix() m5.setTransform( coin.SbVec3f(n,0,0), coin.SbRotation(coin.SbVec3f(0,1,0),-3.14159*90/180.0), coin.SbVec3f(1,1,1)) m5.multRight(m3) views.set1Value(4,m5) m6=coin.SbMatrix() m6.makeIdentity() m6.setTransform( coin.SbVec3f(-n,0,0), coin.SbRotation(coin.SbVec3f(0,1,0),3.14159*90/180.0), coin.SbVec3f(1,1,1)) m6.multRight(m3) views.set1Value(5,m6) m7=coin.SbMatrix() m7.setTransform( coin.SbVec3f(0,-n,0), coin.SbRotation(coin.SbVec3f(-1,0,0),3.14159*90/180.0), coin.SbVec3f(1,1,1)) m7.multRight(m3) views.set1Value(6,m7) m8=coin.SbMatrix() m8.setTransform( coin.SbVec3f(0,-n*2,0), coin.SbRotation(coin.SbVec3f(-1,0,0),3.14159), coin.SbVec3f(1,1,1)) m8.multRight(m3) views.set1Value(7,m8) newchild.matrix=views parent.replaceChild(i,newchild)
def createMultiViews(rotation):
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() if sg.getNumChildren() != 0: for i in range(sg.getNumChildren()): child = sg.getChild(i) type = child.getTypeId().getName().__str__() if child.getTypeId().getName().__str__() == 'Separator': name = child.getName().__str__()[:5] if name != "arrow" and name != "label": MultiViews(sg,child,i,rotation) if child.getTypeId().getName().__str__() == 'MultipleCopy': if child.getNumChildren() != 0: name = child.getChild(0).getName().__str__() if fcd.getObject(name) == None: child.removeAllChildren()
createMultiViews(rotation)
- Restore the normal cursor now that we have done all the slow stuff
QtGui.QApplication.restoreOverrideCursor()
- This bit of code animates a slice rotation
def rotate(dir, rs, re, steps):
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] fc = Dictionary[str(App.ActiveDocument.Name)+"cubies"] fd = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] fp = [[[[Base.Placement() for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] xyz = ["x0","x1","y0","y1","z0","z1"] if dir.x > 0: # We need an explicit matrix for the final rotation step # to prevent rounding errors accumulating over time ff = Base.Matrix(1,0,0,0,0,0,-1,0,0,1,0,0,0,0,0,1) kk =[0,1,5,4,2,3] for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[j][iy][iz][k] c.Label = c.Name fd[j][iy][iz][k] = c fp[j][iy][iz][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateX(1.570795 / steps) for i in range(steps): for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[j][iy][iz][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fd[j][iz][n-1-iy][kk[k]] p = fp[j][iz][n-1-iy][kk[k]] c.Label = "fs"+str(j)+"q"+str(iy)+"q"+str(iz)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[j][iy][iz][k] = c elif dir.x < 0: ff = Base.Matrix(1,0,0,0,0,0,1,0,0,-1,0,0,0,0,0,1) kk =[0,1,4,5,3,2] for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[j][iy][iz][k] c.Label = c.Name fd[j][iy][iz][k] = c fp[j][iy][iz][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateX(-1.570795 / steps) for i in range(steps): for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[j][iy][iz][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for iy in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fd[j][n-1-iz][iy][kk[k]] p = fp[j][n-1-iz][iy][kk[k]] c.Label = "fs"+str(j)+"q"+str(iy)+"q"+str(iz)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[j][iy][iz][k] = c elif dir.y > 0: ff = Base.Matrix(0,0,1,0,0,1,0,0,-1,0,0,0,0,0,0,1) kk =[4,5,2,3,1,0] for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][j][iz][k] c.Label = c.Name fd[ix][j][iz][k] = c fp[ix][j][iz][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateY(1.570795 / steps) for i in range(steps): for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][j][iz][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fd[n-1-iz][j][ix][kk[k]] p = fp[n-1-iz][j][ix][kk[k]] c.Label = "fs"+str(ix)+"q"+str(j)+"q"+str(iz)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[ix][j][iz][k] = c elif dir.y < 0: ff = Base.Matrix(0,0,-1,0,0,1,0,0,1,0,0,0,0,0,0,1) kk =[5,4,2,3,0,1] for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][j][iz][k] c.Label = c.Name fd[ix][j][iz][k] = c fp[ix][j][iz][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateY(-1.570795 / steps) for i in range(steps): for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][j][iz][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for ix in range(n): for iz in range(n): for j in range(rs, re): for k in range(6): c = fd[iz][j][n-1-ix][kk[k]] p = fp[iz][j][n-1-ix][kk[k]] c.Label = "fs"+str(ix)+"q"+str(j)+"q"+str(iz)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[ix][j][iz][k] = c elif dir.z > 0: ff = Base.Matrix(0,-1,0,0,1,0,0,0,0,0,1,0,0,0,0,1) kk = [3,2,0,1,4,5] for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][iy][j][k] c.Label = c.Name fd[ix][iy][j][k] = c fp[ix][iy][j][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateZ(1.570795 / steps) for i in range(steps): for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][iy][j][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fd[iy][n-1-ix][j][kk[k]] p = fp[iy][n-1-ix][j][kk[k]] c.Label = "fs"+str(ix)+"q"+str(iy)+"q"+str(j)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[ix][iy][j][k] = c elif dir.z < 0: ff = Base.Matrix(0,1,0,0,-1,0,0,0,0,0,1,0,0,0,0,1) kk = [2,3,1,0,5,4] for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][iy][j][k] c.Label = c.Name fd[ix][iy][j][k] = c fp[ix][iy][j][k] = c.Placement if steps > 0: fm = Base.Matrix() fm.rotateZ(-1.570795 / steps) for i in range(steps): for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fc[ix][iy][j][k] p = c.Placement c.Placement = Base.Placement(fm).multiply(p) Gui.updateGui() for ix in range(n): for iy in range(n): for j in range(rs, re): for k in range(6): c = fd[n-1-iy][ix][j][kk[k]] p = fp[n-1-iy][ix][j][kk[k]] c.Label = "fs"+str(ix)+"q"+str(iy)+"q"+str(j)+xyz[k] c.Placement = Base.Placement(ff).multiply(p) fc[ix][iy][j][k] = c
def slowrotate(dir, rs, re):
n = Dictionary[str(App.ActiveDocument.Name)+"Size"] steps = slowness / (n * n) if re > rs: rotate(dir, rs, re, steps / (re - rs)) Gui.updateGui()
- Quick rotation for use when randomising or modifying history
def fastrotate(dir, rs, re):
rotate(dir, rs, re, 0)
- These functions manage the history
- Once you have created a cube, these functions will be defined and in scope
- and you can call them from another macro created by saving history
- or by hand from the python console window
history = [] Dictionary[str(App.ActiveDocument.Name)+"history"] = history def mrotpX(i,j):
slowrotate(Base.Vector(1,0,0),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpX("+str(i)+","+str(j)+")")
def mrotpY(i,j):
slowrotate(Base.Vector(0,1,0),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpY("+str(i)+","+str(j)+")")
def mrotpZ(i,j):
slowrotate(Base.Vector(0,0,1),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotpZ("+str(i)+","+str(j)+")")
def mrotmX(i,j):
slowrotate(Base.Vector(-1,0,0),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmX("+str(i)+","+str(j)+")")
def mrotmY(i,j):
slowrotate(Base.Vector(0,-1,0),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmY("+str(i)+","+str(j)+")")
def mrotmZ(i,j):
slowrotate(Base.Vector(0,0,-1),i,j) Dictionary[str(App.ActiveDocument.Name)+"history"].append("mrotmZ("+str(i)+","+str(j)+")")
def undo():
history = Dictionary[str(App.ActiveDocument.Name)+"history"] if len(history) > 0: fs = history.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[(p+1):(len(fs)-1)]) if wh == "mrotmX": slowrotate(Base.Vector(1,0,0),i,j) elif wh == "mrotpX": slowrotate(Base.Vector(-1,0,0),i,j) elif wh == "mrotmY": slowrotate(Base.Vector(0,1,0),i,j) elif wh == "mrotpY": slowrotate(Base.Vector(0,-1,0),i,j) elif wh == "mrotmZ": slowrotate(Base.Vector(0,0,1),i,j) elif wh == "mrotpZ": slowrotate(Base.Vector(0,0,-1),i,j)
def itostring(i, n):
if 2 * i == n - 1: return "n/2" elif i <= n / 2: return str(i) elif i == n - 1: return "n-1" else: return "n-" + str(n-i)
def jtostring(j, n):
if j <= n / 2: return str(j) elif 2 * j == n + 1: return "n/2+1" elif j == n: return "n" elif j == n - 1: return "n-1" else: return "n-" + str(n-j)
def saveHistory():
fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] if len(history) > 0: # This statement will be needed at the start of any macro # to get the size of the cube in the currently active document # in case we have several documents open at once fs = "n = Dictionary[str(App.ActiveDocument.Name)+'Size']\n" for s in history: p = s.index(",") i = int(s[7:p]) j = int(s[(p+1):(len(s)-1)]) fs = fs + s[:7] + itostring(i, n) + "," fs = fs + jtostring(j, n) + ")\n" clip = QtCore.QCoreApplication.instance().clipboard() clip.setText(fs)
def reset():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument Dictionary[str(fcd.Name)+"history"] = [] n = Dictionary[str(fcd.Name)+"Size"] fc = Dictionary[str(fcd.Name)+"cubies"] for obj in fcd.Objects: fs = obj.Name if fs[0:2] == "ff": obj.Label = fs for obj in fcd.Objects: fs = obj.Name if fs[0:2] == "ff": obj.Label = "fs"+fs[2:] obj.Placement = Base.Placement() l = len(fs) q1 = fs.find("q") q2 = fs.find("q",q1+1) ix = int(fs[2:q1]) iy = int(fs[q1+1:q2]) iz = int(fs[q2+1:l-2]) k = "x0x1y0y1z0z1".find(fs[l-2:])/2 fc[ix][iy][iz][k] = obj QtGui.QApplication.restoreOverrideCursor()
- Randomise the cube
def randomise():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] random.seed() i = random.randrange(0,6) for x in range(n*24): i = (i + 2 - i % 2 +random.randrange(0,4)) % 6 j = random.randrange(0,n) if i == 0: fastrotate(Base.Vector(1,0,0),j,j+1) history.append("mrotpX("+str(j)+","+str(j+1)+")") elif i == 1: fastrotate(Base.Vector(-1,0,0),j,j+1) history.append("mrotmX("+str(j)+","+str(j+1)+")") elif i == 2: fastrotate(Base.Vector(0,1,0),j,j+1) history.append("mrotpY("+str(j)+","+str(j+1)+")") elif i == 3: fastrotate(Base.Vector(0,-1,0),j,j+1) history.append("mrotmY("+str(j)+","+str(j+1)+")") elif i == 4: fastrotate(Base.Vector(0,0,1),j,j+1) history.append("mrotpZ("+str(j)+","+str(j+1)+")") elif i == 5: fastrotate(Base.Vector(0,0,-1),j,j+1) history.append("mrotmZ("+str(j)+","+str(j+1)+")") QtGui.QApplication.restoreOverrideCursor()
- Various macros to modify the history
- They all read the history and undo it, and then perform some modified version
- of the history. The modifications can be time-reversal, reflection along an
- axis (as if the cube were reflected, the history replayed,
- and the cube reflected back again), or rotation (as if the cube were rotated,
- the history replayed, and the cube rotated back again).
def slow_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() Gui.updateGui() while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": mrotpX(i,j) elif wh == "mrotmX": mrotmX(i,j) elif wh == "mrotpY": mrotpY(i,j) elif wh == "mrotmY": mrotmY(i,j) elif wh == "mrotpZ": mrotpZ(i,j) elif wh == "mrotmZ": mrotmZ(i,j) QtGui.QApplication.restoreOverrideCursor()
def reverse_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] for fs in nh: wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def undo_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] for fs in nh: wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def reflectX_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(1,0,0),n-j,n-i) history.append("mrotpX("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmX": fastrotate(Base.Vector(-1,0,0),n-j,n-i) history.append("mrotmX("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def reflectY_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,1,0),n-j,n-i) history.append("mrotpY("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,-1,0),n-j,n-i) history.append("mrotmY("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def reflectZ_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,1),n-j,n-i) history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,-1),n-j,n-i) history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") QtGui.QApplication.restoreOverrideCursor()
def rotpX_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,-1,0),n-j,n-i) history.append("mrotmY("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,1,0),n-j,n-i) history.append("mrotpY("+str(n-j)+","+str(n-i)+")") QtGui.QApplication.restoreOverrideCursor()
def rotmX_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,0,-1),n-j,n-i) history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,0,1),n-j,n-i) history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def rotpY_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(0,0,-1),n-j,n-i) history.append("mrotmZ("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmX": fastrotate(Base.Vector(0,0,1),n-j,n-i) history.append("mrotpZ("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def rotmY_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(-1,0,0),n-j,n-i) history.append("mrotmX("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(1,0,0),n-j,n-i) history.append("mrotpX("+str(n-j)+","+str(n-i)+")") QtGui.QApplication.restoreOverrideCursor()
def rotpZ_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(0,1,0),i,j) history.append("mrotpY("+str(i)+","+str(j)+")") elif wh == "mrotmX": fastrotate(Base.Vector(0,-1,0),i,j) history.append("mrotmY("+str(i)+","+str(j)+")") elif wh == "mrotpY": fastrotate(Base.Vector(-1,0,0),n-j,n-i) history.append("mrotmX("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmY": fastrotate(Base.Vector(1,0,0),n-j,n-i) history.append("mrotpX("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
def rotmZ_history():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument history = Dictionary[str(fcd.Name)+"history"] n = Dictionary[str(fcd.Name)+"Size"] nh = [] while len(history) > 0: nh.append(history.pop()) reset() history = Dictionary[str(fcd.Name)+"history"] while len(nh) > 0: fs = nh.pop() wh = fs[:6] p = fs.index(",") i = int(fs[7:p]) j = int(fs[p+1:len(fs)-1]) if wh == "mrotpX": fastrotate(Base.Vector(0,-1,0),n-j,n-i) history.append("mrotmY("+str(n-j)+","+str(n-i)+")") elif wh == "mrotmX": fastrotate(Base.Vector(0,1,0),n-j,n-i) history.append("mrotpY("+str(n-j)+","+str(n-i)+")") elif wh == "mrotpY": fastrotate(Base.Vector(1,0,0),i,j) history.append("mrotpX("+str(i)+","+str(j)+")") elif wh == "mrotmY": fastrotate(Base.Vector(-1,0,0),i,j) history.append("mrotmX("+str(i)+","+str(j)+")") elif wh == "mrotpZ": fastrotate(Base.Vector(0,0,1),i,j) history.append("mrotpZ("+str(i)+","+str(j)+")") elif wh == "mrotmZ": fastrotate(Base.Vector(0,0,-1),i,j) history.append("mrotmZ("+str(i)+","+str(j)+")") QtGui.QApplication.restoreOverrideCursor()
- FreeCAD's file save only saves the state of the camera
- and the shapes, positions, orientations, names, and labels
- of the objects in the scene
- This function recreates all the other stuff after reloading a saved file
- I haven't found a way to make FreeCAD save the history, so it gets reset
def fix_reload():
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) fcd = App.ActiveDocument # first we find how big a cube we have n = 0 for obj in fcd.Objects: fs = obj.Name if fs[0:2] == "ff": i = int(fs[2:fs.index("q")]) if i > n: n = i elif fs[0:4] == "Text": # get rid of this because it's incorrectly positioned # we'll create a new one later fcd.removeObject(fs) elif fs[0:5] == "arrow": obj.ViewObject.RootNode.setName(coin.SbName(fs)) n = n + 1 fc = [[[[None for j in range(6)] for ix in range(n)] for iy in range(n)] for ix in range(n)] Dictionary[str(fcd.Name)+"Size"] = n for obj in fcd.Objects: fs = obj.Label if fs[0:2] == "fs": l = len(fs) q1 = fs.find("q") q2 = fs.find("q",q1+1) ix = int(fs[2:q1]) iy = int(fs[q1+1:q2]) iz = int(fs[q2+1:l-2]) k = "x0x1y0y1z0z1".find(fs[l-2:])/2 fc[ix][iy][iz][k] = obj Dictionary[str(fcd.Name)+"cubies"] = fc Dictionary[str(fcd.Name)+"ViewObserver"] = ViewObserver() doLabels() # create new labels rotation = fixCamera(False) Dictionary[str(fcd.Name)+"buttons"] = ButtonRow() fixLightModel() createMultiViews(rotation) history = [] # according to Henry Ford Dictionary[str(fcd.Name)+"history"] = history QtGui.QApplication.restoreOverrideCursor() FreeCAD.Console.PrintLog("fix_reload() done\n")