Hi all. I can't be bothered blogging so thought I would share this with anyone who is interested. It is the source for a rotating picture cube, similar to the Telerik control - although I haven't turned it into a control (this shouldn't be hard) or handled clicks yet (this might be). The images are stored in an images folder in the root directory. I used photos from the photoviewer example and cropped them square. The pictures array contains the image names.
This is my first real experimentation with IronPython and I must tell you that it is really very nice and succinct to develop with compared to C#. Also much faster since don't need to compile. I have just been developing from notepad.
The brains behind the code actually comes from the following flash tutorial so full props to them. I encourage other users to get busy converting interesting flash examples across to Silverlight so the community can learn:
http://www.senocular.com/flash/tutorials/transformmatrix/
Anyway I hope someone finds this useful
Cheers
Mark
XAML CODE
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="1000" Height="800"
x:Name="Root"
Background="#FF000000"
>
<x:Code Source="Code.py" Type="text/python" />
<Canvas Loaded="Loaded" />
<Canvas.Resources>
<Storyboard x:Name="timer"><DoubleAnimation Duration="00:00:0.02" /></Storyboard>
</Canvas.Resources>
<Canvas x:Name="Inner" Width="300" Height="300" Canvas.Top="200" Canvas.Left="300"/>
<Rectangle x:Name="rec" Width="30" Height="30" Fill="Blue" Opacity="0"/>
</Canvas>
Python Code
import clr
import System
from System.Windows.Controls import *
from System.Windows.Media import *
from System.Windows import *
from System.Windows.Shapes import *
from System.Windows.Media.Animation import *
from System.Math import *
pictures = ['sqjaguar', 'sqgorilla', 'sqgyr', 'sqheron', 'sqeagle', 'sqtamarin']
rotations = {'x': 0, 'y': 0, 'z': 0}
boxPoints = [{'x': -50, 'y': -50, 'z': -50}, {'x': 50, 'y': 50, 'z': -50}, {'x': -50, 'y': 50, 'z': -50}, {'x': -50, 'y': -50, 'z': 50}, {'x': 50, 'y': -50, 'z': 50}, {'x': 50, 'y': 50, 'z': 50}]
curX = 0
curY = 0
def pointsTransform(tripoints, rotations):
v10 = Sin(rotations['x'])
v12 = Cos(rotations['x'])
v8 = Sin(rotations['y'])
v11 = Cos(rotations['y'])
v7 = Sin(rotations['z'])
v9 = Cos(rotations['z'])
v1 = len(tripoints)-1
v17 = [{'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}]
while (v1>=0):
v16 = tripoints[v1]['x']
v15 = tripoints[v1]['y']
v3 = tripoints[v1]['z']
v5 = v12 * v15 - v10 * v3
v4 = v10 * v15 + v12 * v3
v18 = v11 * v4 - v8 * v16
v6 = v8 * v4 + v11 * v16
v14 = v9 * v6 - v7 * v5
v13 = v7 * v6 + v9 * v5
v17[v1] = {'x': v14, 'y': v13}
v1 -= 1
return v17
def canvasPointTransform(i, a, b, c):
photo = Root.FindName("Photo%i" % i)
photo.Opacity = pointsIsVisible(a, b, c)
if (photo.Opacity==0):
return
mt = Root.FindName("Matrix%i" % i)
matrix = mt.Matrix
matrix.OffsetX = b['x']
matrix.OffsetY = b['y']
matrix.M11 = (a['x'] - b['x']) / photo.Width
matrix.M12 = (a['y'] - b['y']) / photo.Width
matrix.M21 = (c['x'] - b['x']) / photo.Height
matrix.M22 = (c['y'] - b['y']) / photo.Height
mt.Matrix = matrix
def pointsIsVisible(a, b, c):
v5 = b['x'] - a['x']
if (v5==0):
return (a['y'] > b['y']) == (c['x'] > a['x'])
v4 = c['x'] - a['x']
if (v4==0):
return (a['y'] > c['y']) == (b['x'] < a['x'])
return (((b['y'] - a['y']) / v5) < ((c['y'] - a['y']) / v4)) != ((a['x'] < b['x']) == (a['x'] > c['x']))
def CreatePhoto(sequence, x, y, path):
t = XamlReader.Load("""
<Canvas xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' x:Name='Photo%i' Width='111' Height='111' Canvas.Left='%d' Canvas.Top='%d' Background='#FFFFFFFF'>
<Image Width='111' Height='111' Canvas.Left='0' Canvas.Top='0' Source='%s' />
<Canvas.RenderTransform>
<MatrixTransform x:Name='Matrix%i' Matrix="1,0,0,1,0,0"/>
</Canvas.RenderTransform>
</Canvas>""" % (sequence,x, y, path,sequence))
Inner.Children.Add(t)
def timer_Completed(sender, e):
rotations['x'] -= curY / 2000
rotations['y'] += curX / 2000
try:
v2 = pointsTransform(boxPoints, rotations)
canvasPointTransform(0, v2[2], v2[0], v2[3])
canvasPointTransform(1, v2[5], v2[1], v2[2])
canvasPointTransform(2, v2[0], v2[2], v2[1])
canvasPointTransform(3, v2[4], v2[3], v2[0])
canvasPointTransform(4, v2[3], v2[4], v2[5])
canvasPointTransform(5, v2[1], v2[5], v2[4])
except System.Exception, e:
debug.TextWrapping = System.Windows.TextWrapping.Wrap
debug.Text = e.ToString()
timer.Begin()
def mouseMove(sender, e):
global curX
global curY
pt = e.GetPosition(Inner)
curX = pt.X
curY = pt.Y
def Loaded(sender, e):
global pictures
global boxPoints
global rotations
elt = System.Windows.XamlReader.Load("""
<Canvas xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Canvas.Top="50" Width="500" Height="500">
<TextBlock x:Name='debug' Foreground="White" Width="500" Height="500" Text='' />
</Canvas>""" )
Root.Children.Add(elt)
sequence = 0
while sequence < len(pictures):
CreatePhoto(sequence,0, 0,"images/%s.jpg" % pictures[sequence])
sequence += 1
Inner.MouseMove += mouseMove
timer.Completed += timer_Completed
timer.Begin()