MotionPanel.cpp
#include "StdAfx.h"
#include "MotionPanel.h"
#include "Motion.h"
#include "Pose.h"
#include "TextInputDialog.h"
using namespace Core;
using namespace System;
using namespace System::Diagnostics;
/// [ Constructor ]
MotionPanel::MotionPanel( void )
{
// コンポーネントを初期化する
InitializeComponent();
// 時間トラックバーの目盛りを 1[ sec ]ごとに設定する
this->m_timeTrackBar->TickFrequency
= safe_cast< int >( 1.0 / Core::Motion::UnitTime );
// タイマのインターバル[ msec ]を モーションの単位時間[ sec ]に合わせる
m_timer->Interval
= safe_cast< int >( Core::Motion::UnitTime * 1000.0 );
}
/// [ Destructor ]
MotionPanel::~MotionPanel()
{
if( components != nullptr )
{
delete components;
}
}
#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void MotionPanel::InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(MotionPanel::typeid));
this->m_timeLabel = (gcnew System::Windows::Forms::Label());
this->m_timeTextBox = (gcnew System::Windows::Forms::TextBox());
this->m_timeTrackBar = (gcnew System::Windows::Forms::TrackBar());
this->m_unitLabel = (gcnew System::Windows::Forms::Label());
this->m_appendButton = (gcnew System::Windows::Forms::Button());
this->m_fastforwardButton = (gcnew System::Windows::Forms::Button());
this->m_rewindButton = (gcnew System::Windows::Forms::Button());
this->m_playButton = (gcnew System::Windows::Forms::Button());
this->m_controlImageList = (gcnew System::Windows::Forms::ImageList(this->components));
this->m_repeatCheckBox = (gcnew System::Windows::Forms::CheckBox());
this->m_timer = (gcnew System::Windows::Forms::Timer(this->components));
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->m_timeTrackBar))->BeginInit();
this->SuspendLayout();
//
// m_timeLabel
//
this->m_timeLabel->AutoSize = true;
this->m_timeLabel->Location = System::Drawing::Point(5, 42);
this->m_timeLabel->Name = L"m_timeLabel";
this->m_timeLabel->Size = System::Drawing::Size(29, 12);
this->m_timeLabel->TabIndex = 0;
this->m_timeLabel->Text = L"時間";
//
// m_timeTextBox
//
this->m_timeTextBox->Location = System::Drawing::Point(40, 39);
this->m_timeTextBox->Name = L"m_timeTextBox";
this->m_timeTextBox->Size = System::Drawing::Size(36, 19);
this->m_timeTextBox->TabIndex = 1;
this->m_timeTextBox->Text = L"00.0";
this->m_timeTextBox->TextAlign = System::Windows::Forms::HorizontalAlignment::Right;
//
// m_timeTrackBar
//
this->m_timeTrackBar->Anchor = static_cast<System::Windows::Forms::AnchorStyles>(((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Left)
| System::Windows::Forms::AnchorStyles::Right));
this->m_timeTrackBar->AutoSize = false;
this->m_timeTrackBar->LargeChange = 10;
this->m_timeTrackBar->Location = System::Drawing::Point(3, 3);
this->m_timeTrackBar->Name = L"m_timeTrackBar";
this->m_timeTrackBar->Size = System::Drawing::Size(425, 30);
this->m_timeTrackBar->TabIndex = 2;
this->m_timeTrackBar->TabStop = false;
this->m_timeTrackBar->ValueChanged += gcnew System::EventHandler(this, &MotionPanel::TimeTrackBarValueChanged);
//
// m_unitLabel
//
this->m_unitLabel->AutoSize = true;
this->m_unitLabel->Location = System::Drawing::Point(79, 42);
this->m_unitLabel->Margin = System::Windows::Forms::Padding(0, 0, 3, 0);
this->m_unitLabel->Name = L"m_unitLabel";
this->m_unitLabel->Size = System::Drawing::Size(39, 12);
this->m_unitLabel->TabIndex = 3;
this->m_unitLabel->Text = L"( sec )";
//
// m_appendButton
//
this->m_appendButton->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Right));
this->m_appendButton->FlatAppearance->BorderSize = 0;
this->m_appendButton->Location = System::Drawing::Point(427, 7);
this->m_appendButton->Name = L"m_appendButton";
this->m_appendButton->Size = System::Drawing::Size(70, 24);
this->m_appendButton->TabIndex = 4;
this->m_appendButton->Text = L"追加(&A)";
this->m_appendButton->UseVisualStyleBackColor = true;
this->m_appendButton->Click += gcnew System::EventHandler(this, &MotionPanel::AppendButtonClick);
//
// m_fastforwardButton
//
this->m_fastforwardButton->FlatAppearance->BorderSize = 0;
this->m_fastforwardButton->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->m_fastforwardButton->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"m_fastforwardButton.Image")));
this->m_fastforwardButton->Location = System::Drawing::Point(231, 33);
this->m_fastforwardButton->Name = L"m_fastforwardButton";
this->m_fastforwardButton->Size = System::Drawing::Size(45, 30);
this->m_fastforwardButton->TabIndex = 5;
this->m_fastforwardButton->UseVisualStyleBackColor = true;
this->m_fastforwardButton->Click += gcnew System::EventHandler(this, &MotionPanel::FastforwardButtonClick);
//
// m_rewindButton
//
this->m_rewindButton->FlatAppearance->BorderSize = 0;
this->m_rewindButton->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->m_rewindButton->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"m_rewindButton.Image")));
this->m_rewindButton->Location = System::Drawing::Point(180, 33);
this->m_rewindButton->Name = L"m_rewindButton";
this->m_rewindButton->Size = System::Drawing::Size(45, 30);
this->m_rewindButton->TabIndex = 6;
this->m_rewindButton->UseVisualStyleBackColor = true;
this->m_rewindButton->Click += gcnew System::EventHandler(this, &MotionPanel::RewindButtonClick);
//
// m_playButton
//
this->m_playButton->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Right));
this->m_playButton->FlatAppearance->BorderSize = 0;
this->m_playButton->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->m_playButton->ImageIndex = 0;
this->m_playButton->ImageList = this->m_controlImageList;
this->m_playButton->Location = System::Drawing::Point(427, 37);
this->m_playButton->Name = L"m_playButton";
this->m_playButton->Size = System::Drawing::Size(45, 30);
this->m_playButton->TabIndex = 7;
this->m_playButton->UseVisualStyleBackColor = true;
this->m_playButton->Click += gcnew System::EventHandler(this, &MotionPanel::PlayButtonClick);
//
// m_controlImageList
//
this->m_controlImageList->ImageStream = (cli::safe_cast<System::Windows::Forms::ImageListStreamer^ >(resources->GetObject(L"m_controlImageList.ImageStream")));
this->m_controlImageList->TransparentColor = System::Drawing::Color::Transparent;
this->m_controlImageList->Images->SetKeyName(0, L"control_play_blue.png");
this->m_controlImageList->Images->SetKeyName(1, L"control_stop_blue.png");
//
// m_repeatCheckBox
//
this->m_repeatCheckBox->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Right));
this->m_repeatCheckBox->Appearance = System::Windows::Forms::Appearance::Button;
this->m_repeatCheckBox->AutoSize = true;
this->m_repeatCheckBox->FlatAppearance->BorderSize = 0;
this->m_repeatCheckBox->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->m_repeatCheckBox->Image = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"m_repeatCheckBox.Image")));
this->m_repeatCheckBox->Location = System::Drawing::Point(475, 40);
this->m_repeatCheckBox->Name = L"m_repeatCheckBox";
this->m_repeatCheckBox->Size = System::Drawing::Size(22, 22);
this->m_repeatCheckBox->TabIndex = 8;
this->m_repeatCheckBox->UseVisualStyleBackColor = true;
//
// m_timer
//
this->m_timer->Tick += gcnew System::EventHandler(this, &MotionPanel::TimerTick);
//
// MotionPanel
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->Controls->Add(this->m_repeatCheckBox);
this->Controls->Add(this->m_playButton);
this->Controls->Add(this->m_rewindButton);
this->Controls->Add(this->m_fastforwardButton);
this->Controls->Add(this->m_appendButton);
this->Controls->Add(this->m_unitLabel);
this->Controls->Add(this->m_timeTrackBar);
this->Controls->Add(this->m_timeTextBox);
this->Controls->Add(this->m_timeLabel);
this->Name = L"MotionPanel";
this->Size = System::Drawing::Size(500, 70);
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->m_timeTrackBar))->EndInit();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
/// 初期化する
void MotionPanel::Initialize( Model^ model )
{
// モーションを生成する
m_motion = gcnew Core::Motion( model );
// ... 初期のポーズを追加する
AppendButtonClick( this, nullptr );
}
/// 時間トラックバーの値が変更された
System::Void MotionPanel::TimeTrackBarValueChanged( System::Object^, System::EventArgs^ )
{
m_motion->CurrentPoseIndex = m_timeTrackBar->Value; // 現在のポーズのインデックス
m_timeTextBox->Text = m_motion->CurrentTime.ToString( "0.0" ); // 時間テキスト
// 現在の時間が最初でなければ 巻戻しボタンを有効にする
m_rewindButton->Enabled = ( m_timeTrackBar->Value != m_timeTrackBar->Minimum );
// 現在の時間が最後でなければ 早送りボタンを有効にする
m_fastforwardButton->Enabled = ( m_timeTrackBar->Value != m_timeTrackBar->Maximum );
}
/// 追加ボタンがクリックされた
System::Void MotionPanel::AppendButtonClick( System::Object^, System::EventArgs^ )
{
Debug::WriteLine( "ポーズを追加する" );
Debug::Assert( m_motion->PoseCount != 0, "ポーズは存在する" );
const double AdditionalTime = 1.0; // 追加時間[ sec ]
// 最後のポーズを取得する
Pose^ lastPose = m_motion[ m_motion->PoseCount - 1 ];
// ... 新しい最後のポーズを生成する
Pose^ newLastPose = gcnew Pose( lastPose->Time + AdditionalTime, lastPose );
// ... ポーズに追加する
m_motion->AddToTypicalPose( newLastPose );
// 時間を 最後のポーズの時間に合わせる
SetTimeByLastPoseTime();
}
/// 巻戻しボタンがクリックされた
System::Void MotionPanel::RewindButtonClick( System::Object^, System::EventArgs^ )
{
// 直前の特徴ポーズを取得する
Pose^ typicalPose = m_motion->GetTypicalPoseJustBefore( m_motion->CurrentPose );
// ... 時間トラックバーの値を それのインデックスに設定する
m_timeTrackBar->Value = m_motion->GetPoseIndex( typicalPose );
}
/// 早送りボタンがクリックされた
System::Void MotionPanel::FastforwardButtonClick( System::Object^, System::EventArgs^ )
{
// 直後の特徴ポーズを取得する
Pose^ typicalPose = m_motion->GetTypicalPoseJustAfter( m_motion->CurrentPose );
// ... 時間トラックバーの値を それのインデックスに設定する
m_timeTrackBar->Value = m_motion->GetPoseIndex( typicalPose );
}
/// 再生ボタンがクリックされた
System::Void MotionPanel::PlayButtonClick( System::Object^, System::EventArgs^ )
{
if( !m_timer->Enabled )
{
// タイマが停止しているならば、時間を最初に設定する
m_timeTrackBar->Value = 0;
// タイマを起動する
m_timer->Start();
// ... 再生ボタンのイメージを変更する
m_playButton->ImageIndex = 1;
}
else
{
// タイマを停止する
StopTimer( this, nullptr );
}
}
/// タイマの時間が経過した
System::Void MotionPanel::TimerTick( System::Object^, System::EventArgs^ )
{
// 時間トラックバーの値を進める
m_timeTrackBar->Value++;
/// @note
/// トラックバーの単位とタイマのインターバルを合わせてあるので、
/// インクリメントするだけで良い。
// 時間が最後に到達した
if( m_timeTrackBar->Value == m_timeTrackBar->Maximum )
{
if( m_repeatCheckBox->Checked )
{
// リピートが設定されているならば、時間を最初に戻す
m_timeTrackBar->Value = 0;
}
else
{
// タイマを停止する
StopTimer( this, nullptr );
}
}
}
/// タイマを停止する
void MotionPanel::StopTimer( System::Object^, System::EventArgs^ )
{
if( m_timer->Enabled )
{
// タイマが起動しているならば、それ停止する
m_timer->Stop();
// 再生ボタンのイメージを元に戻す
m_playButton->ImageIndex = 0;
}
/// @todo
/// モデルに変更を加えられたときに、このハンドラを呼び出して
/// タイマを停止させる必要がある。
/// (モデルの状態変化イベントは モーション再生中にも発生するので使えない)
}
/// 時間を 最後のポーズの時間に合わせる
void MotionPanel::SetTimeByLastPoseTime()
{
int lastPoseIndex = m_motion->PoseCount - 1;// 最後のポーズのインデックス
m_timeTrackBar->Maximum = lastPoseIndex; // 時間トラックバーの最大値
m_timeTrackBar->Value = lastPoseIndex; // 時間トラックバーの値
// 時間トラックバーの値 変更イベントを呼び出す
TimeTrackBarValueChanged( this, nullptr );
/// @note
/// 最大値の変更によって、トラックバーの値が変更された場合、
/// トラックバーの値 変更イベントが発生しない。
/// よって、明示的にイベントを呼び出している。
}
/// 設定を書き込む
System::Xml::XmlElement^ MotionPanel::SaveSettings( System::Xml::XmlDocument^ document )
{
if( m_motion->Name == String::Empty )
{
// モーション名が設定されていなければ、それを設定する
if( !SetMotionName() )
{
// 設定されなければ、処理を中断する
return nullptr;
}
}
// モーションに、設定を書き込ませる
return m_motion->SaveSettings( document );
}
/// 設定を読み込む
void MotionPanel::LoadSettings( System::Xml::XmlDocument^ document )
{
// タイマを停止する
StopTimer( this, nullptr );
// モーションに、設定を読み込ませる
m_motion->LoadSettings( document );
// 時間を 最後のポーズの時間に合わせる
SetTimeByLastPoseTime();
}
/// モーション名を取得する [ Property ] [ Delegate ]
System::String^ MotionPanel::MotionName::get()
{
return m_motion->Name;
}
/// モーション名を設定する
bool MotionPanel::SetMotionName()
{
// テキスト入力ダイアログを表示する
TextInputDialog^ dialog = gcnew TextInputDialog( "モーション名" );
// ... 空のテキストを禁止する
dialog->ProhibitEmptyText();
// ダイアログを表示する
if( dialog->ShowDialog() == Windows::Forms::DialogResult::OK )
{
/// @todo
/// 同名のモーションが存在するならば、上書きの確認をする
m_motion->Name = dialog->Value; // モーションの名称
return true;
}
return false;
}