Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Shapes

Imports Microsoft.Kinect

''' <summary>
''' Interaction logic for SkeletonViewer.xaml
''' </summary>
''' <remarks></remarks>
Public Class SkeletonViewer
#Region "メンバー変数"
    Private ReadOnly _SkeletonBrushes() As Brush = New Brush() {Brushes.Black,
                                                                Brushes.Crimson,
                                                                Brushes.Indigo,
                                                                Brushes.DodgerBlue,
                                                                Brushes.Purple,
                                                                Brushes.Pink}
    Private _FrameSkeletons() As Skeleton
#End Region


#Region "コンストラクタ"
    Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

    End Sub
#End Region


#Region "メソッド"
    Private Sub KinectDevice_SkeletonFrameReady(sender As Object, e As SkeletonFrameReadyEventArgs)
        SkeletonsPanel.Children.Clear()

        Using frame As SkeletonFrame = e.OpenSkeletonFrame()
            If frame IsNot Nothing Then
                If Me.IsEnabled Then
                    frame.CopySkeletonDataTo(Me._FrameSkeletons)

                    For i As Integer = 0 To Me._FrameSkeletons.Length - 1
                        DrawSkeleton(Me._FrameSkeletons(i), Me._SkeletonBrushes(i))
                    Next
                End If
            End If
        End Using
    End Sub


    Private Sub DrawSkeleton(_skeleton As Skeleton, _brush As Brush)
        If _skeleton IsNot Nothing AndAlso _skeleton.TrackingState = SkeletonTrackingState.Tracked Then
            '骨格の頭と胴体を描画する
            Dim figure As Polyline = CreateFigure(_skeleton,
                                                  _brush,
                                                  New JointType() {JointType.Head,
                                                                   JointType.ShoulderCenter,
                                                                   JointType.ShoulderLeft,
                                                                   JointType.Spine,
                                                                   JointType.ShoulderRight,
                                                                   JointType.ShoulderCenter,
                                                                   JointType.HipCenter,
                                                                   JointType.HipLeft,
                                                                   JointType.Spine,
                                                                   JointType.HipRight,
                                                                   JointType.HipCenter
                                                                  })
            SkeletonsPanel.Children.Add(figure)

            figure = CreateFigure(_skeleton,
                                  _brush,
                                  New JointType() {JointType.HipLeft,
                                                   JointType.KneeLeft,
                                                   JointType.AnkleLeft,
                                                   JointType.FootLeft
                                                  })
            SkeletonsPanel.Children.Add(figure)

            '骨格の左足を描画する
            figure = CreateFigure(_skeleton,
                                  _brush,
                                  New JointType() {JointType.HipLeft,
                                                   JointType.KneeLeft,
                                                   JointType.AnkleLeft,
                                                   JointType.FootLeft
                                                  })
            SkeletonsPanel.Children.Add(figure)
            '骨格の右足を描画する
            figure = CreateFigure(_skeleton,
                                  _brush,
                                  New JointType() {JointType.HipRight,
                                                   JointType.KneeRight,
                                                   JointType.AnkleRight,
                                                   JointType.FootRight
                                                  })
            SkeletonsPanel.Children.Add(figure)

            '骨格の左腕を描画する
            figure = CreateFigure(_skeleton,
                                  _brush,
                                  New JointType() {JointType.ShoulderLeft,
                                                   JointType.ElbowLeft,
                                                   JointType.WristLeft,
                                                   JointType.HandLeft
                                                  })
            SkeletonsPanel.Children.Add(figure)

            '骨格の右腕を描画する
            figure = CreateFigure(_skeleton,
                                  _brush,
                                  New JointType() {JointType.ShoulderRight,
                                                   JointType.ElbowRight,
                                                   JointType.WristRight,
                                                   JointType.HandRight})
            SkeletonsPanel.Children.Add(figure)
        End If
    End Sub

    Private Function CreateFigure(_skeleton As Skeleton, _brush As Brush, joints() As JointType) As Polyline
        Dim figure As Polyline = New Polyline()

        Figure.StrokeThickness = 18
        Figure.Stroke = _brush

        For i As Integer = 0 To joints.Length - 1
            figure.Points.Add(GetJointPoint(_skeleton.Joints(joints(i))))
        Next
        Return figure
    End Function

    Private Function GetJointPoint(_joint As Joint) As Point
        Dim _point As DepthImagePoint = Me.KinectDevice.MapSkeletonPointToDepth(_joint.Position,
                                                                               Me.KinectDevice.DepthStream.Format)
        _point.X *= Fix(Me.LayoutRoot.ActualWidth / KinectDevice.DepthStream.FrameWidth)
        _point.Y *= Fix(Me.LayoutRoot.ActualHeight / KinectDevice.DepthStream.FrameHeight)

        Return New Point(_point.X, _point.Y)
    End Function
#End Region


#Region "プロパティ"
#Region "KinectDevice"
    Protected Const KinectDevicePropertyName As String = "KinectDevice"
    Public Shared ReadOnly KinectDeviceProperty As DependencyProperty = DependencyProperty.Register(KinectDevicePropertyName,
                                                                                                     GetType(KinectSensor),
                                                                                                     GetType(SkeletonViewer),
                                                                                                     New PropertyMetadata(Nothing,
                                                                                                                         AddressOf KinectDeviceChanged))


    Private Shared Sub KinectDeviceChanged(owner As DependencyObject, e As DependencyPropertyChangedEventArgs)
        Dim viewer As SkeletonViewer = CType(owner, SkeletonViewer)

        If e.OldValue IsNot Nothing Then
            RemoveHandler CType(e.OldValue, KinectSensor).SkeletonFrameReady, AddressOf viewer.KinectDevice_SkeletonFrameReady
            viewer._FrameSkeletons = Nothing
        End If

        If e.NewValue IsNot Nothing Then
            viewer.KinectDevice = CType(e.NewValue, KinectSensor)
            AddHandler viewer.KinectDevice.SkeletonFrameReady, AddressOf viewer.KinectDevice_SkeletonFrameReady
            ReDim viewer._FrameSkeletons(viewer.KinectDevice.SkeletonStream.FrameSkeletonArrayLength - 1)
        End If
    End Sub


    Public Property KinectDevice As KinectSensor
        Get
            Return CType(GetValue(KinectDeviceProperty), KinectSensor)
        End Get
        Set(value As KinectSensor)
            SetValue(KinectDeviceProperty, value)
        End Set
    End Property
#End Region
#End Region
End Class
