Imports System.Linq
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Shapes

Imports Microsoft.Kinect

''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
''' <remarks></remarks>
Class MainWindow
#Region "メンバー変数"
    Private _KinectDevice As KinectSensor
    Private ReadOnly _SkeletonBrushes() As Brush
    Private _FrameSkeletons() As Skeleton
#End Region


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

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

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        _SkeletonBrushes = New Brush() {Brushes.Black,
                                        Brushes.Crimson,
                                        Brushes.Indigo,
                                        Brushes.DodgerBlue,
                                        Brushes.Purple,
                                        Brushes.Pink}
        AddHandler KinectSensor.KinectSensors.StatusChanged, AddressOf KinectSensors_StatusChanged
        Me.KinectDevice = KinectSensor.KinectSensors.FirstOrDefault(Function(x)
                                                                        Return x.Status = KinectStatus.Connected
                                                                    End Function)
    End Sub
#End Region


#Region "メソッド"
    Private Sub KinectSensors_StatusChanged(sender As Object, e As StatusChangedEventArgs)
        Select Case e.Status
            Case KinectStatus.Initializing,
                KinectStatus.Connected,
                KinectStatus.NotPowered,
                KinectStatus.NotReady,
                KinectStatus.DeviceNotGenuine
                Me.KinectDevice = e.Sensor
            Case KinectStatus.Disconnected
                'TODO: Give the user feedback to plug-in a Kinect device.                    
                Me.KinectDevice = Nothing
            Case Else
                'TODO: Show an error state
        End Select
    End Sub


    ' Listing 4-2
    Private Sub KinectDevice_SkeletonFrameReady(sender As Object, e As SkeletonFrameReadyEventArgs)
        Using frame As SkeletonFrame = e.OpenSkeletonFrame()
            If frame IsNot Nothing Then
                Dim figure As Polyline
                Dim userBrush As Brush
                Dim _skeleton As Skeleton

                LayoutRoot.Children.Clear()
                frame.CopySkeletonDataTo(Me._FrameSkeletons)

                Dim dataSet2(Me._FrameSkeletons.Length - 1) As Skeleton
                frame.CopySkeletonDataTo(dataSet2)


                For i As Integer = 0 To Me._FrameSkeletons.Length - 1
                    _skeleton = Me._FrameSkeletons(i)

                    If _skeleton.TrackingState = SkeletonTrackingState.Tracked Then
                        userBrush = Me._SkeletonBrushes(i Mod Me._SkeletonBrushes.Length)

                        '骨格の頭と胴体を描画する
                        figure = CreateFigure(_skeleton,
                                              userBrush,
                                              New JointType() {JointType.Head,
                                                               JointType.ShoulderCenter,
                                                               JointType.ShoulderLeft,
                                                               JointType.Spine,
                                                               JointType.ShoulderRight,
                                                               JointType.ShoulderCenter,
                                                               JointType.HipCenter
                                                              })
                        LayoutRoot.Children.Add(figure)

                        figure = CreateFigure(_skeleton,
                                              userBrush,
                                              New JointType() {JointType.HipLeft,
                                                               JointType.HipRight
                                                              })
                        LayoutRoot.Children.Add(figure)

                        '骨格の左足を描画する
                        figure = CreateFigure(_skeleton,
                                              userBrush,
                                              New JointType() {JointType.HipCenter,
                                                               JointType.HipLeft,
                                                               JointType.KneeLeft,
                                                               JointType.AnkleLeft,
                                                               JointType.FootLeft
                                                              })
                        LayoutRoot.Children.Add(figure)

                        '骨格の右足を描画する
                        figure = CreateFigure(_skeleton,
                                              userBrush,
                                              New JointType() {JointType.HipCenter,
                                                               JointType.HipRight,
                                                               JointType.KneeRight,
                                                               JointType.AnkleRight,
                                                               JointType.FootRight
                                                              })
                        LayoutRoot.Children.Add(figure)

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

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


    ' Listing 4-3
    Private Function CreateFigure(_skeleton As Skeleton, _brush As Brush, joints() As JointType) As Polyline
        Dim Figure As New Polyline

        Figure.StrokeThickness = 8
        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 "プロパティ"
    Public Property KinectDevice As KinectSensor
        Get
            Return Me._KinectDevice
        End Get
        Set(value As KinectSensor)
            If Me._KinectDevice IsNot value Then
                'リソースを解放する
                If Me._KinectDevice IsNot Nothing Then
                    Me._KinectDevice.Stop()
                    RemoveHandler Me._KinectDevice.SkeletonFrameReady, AddressOf KinectDevice_SkeletonFrameReady
                    Me._KinectDevice.SkeletonStream.Disable()
                    Me._FrameSkeletons = Nothing
                End If

                Me._KinectDevice = value

                '初期化する
                If Me._KinectDevice IsNot Nothing Then
                    If Me._KinectDevice.Status = KinectStatus.Connected Then
                        Me._KinectDevice.SkeletonStream.Enable()
                        ReDim Me._FrameSkeletons(Me._KinectDevice.SkeletonStream.FrameSkeletonArrayLength - 1)
                        AddHandler Me.KinectDevice.SkeletonFrameReady, AddressOf KinectDevice_SkeletonFrameReady
                        Me._KinectDevice.Start()
                    End If
                End If
            End If
        End Set
    End Property
#End Region

End Class
