ModelPanel.cpp
#include "StdAfx.h"
#include "ModelPanel.h"
#include "Model.h"
#include "ModelFactory.h"
#include "Link.h"
#include "Joint.h"
#include "Draw.h"
#include "DrawModel.h"
using namespace Core;
using namespace System;
using namespace System::Diagnostics;
/// [ Constructor ]
ModelPanel::ModelPanel( void )
{
// コンポーネントを初期化する
InitializeComponent();
// モデルの生成を行うメソッドを生成する
ModelFactory^ factory = gcnew ModelFactory();
// ... モデルを生成する
m_model = factory->Create( "ModelData.xml" );
/// @note 作業フォルダから読み込んでいる。
}
/// [ Destructor ]
ModelPanel::~ModelPanel()
{
if( components != nullptr )
{
delete components;
}
}
#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void ModelPanel::InitializeComponent(void)
{
this->m_drawPanel = (gcnew System::Windows::Forms::Panel());
this->SuspendLayout();
//
// m_drawPanel
//
this->m_drawPanel->BackColor = System::Drawing::SystemColors::Control;
this->m_drawPanel->Dock = System::Windows::Forms::DockStyle::Fill;
this->m_drawPanel->Location = System::Drawing::Point(0, 0);
this->m_drawPanel->Name = L"m_drawPanel";
this->m_drawPanel->Size = System::Drawing::Size(292, 266);
this->m_drawPanel->TabIndex = 0;
this->m_drawPanel->MouseWheel += gcnew System::Windows::Forms::MouseEventHandler(this, &ModelPanel::PanelMouseWheel);
this->m_drawPanel->MouseDown += gcnew System::Windows::Forms::MouseEventHandler(this, &ModelPanel::PanelMouseDown);
this->m_drawPanel->MouseMove += gcnew System::Windows::Forms::MouseEventHandler(this, &ModelPanel::PanelMouseMove);
this->m_drawPanel->MouseDoubleClick += gcnew System::Windows::Forms::MouseEventHandler(this, &ModelPanel::PanelMouseDoubleClick);
this->m_drawPanel->Resize += gcnew System::EventHandler(this, &ModelPanel::PanelResize);
this->m_drawPanel->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &ModelPanel::PanelPaint);
//
// ModelPanel
//
this->AllowEndUserDocking = false;
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 266);
this->CloseButton = false;
this->Controls->Add(this->m_drawPanel);
this->DockAreas = WeifenLuo::WinFormsUI::Docking::DockAreas::Document;
this->Name = L"ModelPanel";
this->TabText = L"Model";
this->Text = L"Model";
this->ResumeLayout(false);
}
#pragma endregion
/// フォームが初めて表示される
void ModelPanel::OnLoad( System::EventArgs^ e )
{
// 基本クラスの同一関数を呼び出す
WeifenLuo::WinFormsUI::Docking::DockContent::OnLoad( e );
// 描画クラスを生成する
m_draw = gcnew Draw();
// ... 初期化する
if( !m_draw->Initialize( m_drawPanel, m_model ) )
{
Debug::Fail( "描画クラスの初期化に失敗した" );
/// @todo
/// エラー情報を表示して、アプリケーションを終了させる。
}
// 表示モードを初期化する
m_draw->Model->ExpressionMode = ExpressionModel::RealModel;
m_draw->RotateViewpoint( -0.5f, 1.2f ); // 視点回転角 (値は適当)
m_draw->Scale = 45.0f; // 縮尺 (値は適当)
// @todo ここで視点の位置も設定するようにする。
// 再描画イベントのハンドラを生成する
System::EventHandler^ eventHandler = gcnew System::EventHandler( this, &ModelPanel::Redraw );
// ... それを登録する
m_model->StateChanged += eventHandler; // モデルの状態変化イベント
Link::StandardChanged += eventHandler; // 基準リンクの変更イベント
Link::MechanicsChanged += eventHandler; // リンクの構造変化イベント
Joint::MechanicsChanged += eventHandler; // 関節の構造変化イベント
}
/// 再描画する
System::Void ModelPanel::PanelPaint( System::Object^, System::Windows::Forms::PaintEventArgs^ )
{
Redraw( this, nullptr );
}
/// 再描画する
void ModelPanel::Redraw( System::Object^, System::EventArgs^ )
{
m_draw->Render();
}
/// サイズが変更された
System::Void ModelPanel::PanelResize( System::Object^, System::EventArgs^ )
{
/// @note この処理は不要と思われる。
/*
if( m_draw == nullptr )
{
// 描画クラスが生成されていないならば、処理を中断する。
// (フォームの生成時、Loadイベント発生前に Resizeイベントが発生することへの対処)
return;
}
m_draw->SetupScreenSize( Width, Height ); // 画面サイズ
// ... 再描画する
Redraw( this, nullptr );
*/
}
/// マウスがクリックされた
System::Void ModelPanel::PanelMouseDown( System::Object^, System::Windows::Forms::MouseEventArgs^ e )
{
switch( e->Button )
{
case Windows::Forms::MouseButtons::Left:
// 左ボタンが押されたならば、オブジェクトを選択する
SelecetObject( e->Location );
break;
case Windows::Forms::MouseButtons::Right:
case Windows::Forms::MouseButtons::Middle:
// 右ボタンまたは中央ボタンが押されたならば、位置を保存する
m_mousePosition = e->Location;
break;
}
}
/// マウスがダブルクリックされた
System::Void ModelPanel::PanelMouseDoubleClick( System::Object^, System::Windows::Forms::MouseEventArgs^ e )
{
switch( e->Button )
{
case Windows::Forms::MouseButtons::Left: // 左ボタン
// 選択されているオブジェクトを接地させる
m_model->LinkGrounded( m_draw->Model->SelectedLink );
break;
case Windows::Forms::MouseButtons::Right: // 右ボタン
// モデルの図形を再構築する
m_draw->Model->CreateModelFigure();
// ... 表示モードを再設定する
m_draw->Model->ExpressionMode = m_draw->Model->ExpressionMode;
break;
}
}
/// マウスポインタが移動した
System::Void ModelPanel::PanelMouseMove( System::Object^, System::Windows::Forms::MouseEventArgs^ e )
{
switch( e->Button )
{
case Windows::Forms::MouseButtons::Right:
// 右ボタンが押されているならば、視点を回転させる
RotateViewpoint( e->Location );
break;
case Windows::Forms::MouseButtons::Middle:
// 中央ボタンが押されているならば、視点を移動する
TranslateViewpoint( e->Location );
break;
}
if( e->Button == ( Windows::Forms::MouseButtons::Right | Windows::Forms::MouseButtons::Left ) )
{
/// 左右ボタンが両方とも押されているならば、視点を移動する
TranslateViewpoint( e->Location );
/// @note
/// 同時押しは switch文で処理できないため、分けて記述している。
}
}
/// マウスホイールが動いた
System::Void ModelPanel::PanelMouseWheel( System::Object^, System::Windows::Forms::MouseEventArgs^ e )
{
const float ScallCoefficient = 0.03f; // 縮尺の補正係数
m_draw->Scale += e->Delta * ScallCoefficient; // 縮尺
}
/// 視点を回転させる
void ModelPanel::RotateViewpoint( System::Drawing::Point location )
{
// ドラッグの移動量を求める
Drawing::Point distanceOfDrag = location - Drawing::Size( m_mousePosition );
// ... ドラッグの開始位置を保存する
m_mousePosition = location;
const float TurnCoefficient = -0.005f; // 回転角度の補正係数
// 視点を回転させる
m_draw->RotateViewpoint(
distanceOfDrag.X * TurnCoefficient,
distanceOfDrag.Y * TurnCoefficient
);
}
/// 視点を移動させる
void ModelPanel::TranslateViewpoint( System::Drawing::Point location )
{
// ドラッグの移動量を求める
Drawing::Point distanceOfDrag = location - Drawing::Size( m_mousePosition );
// ... ドラッグの開始位置を保存する
m_mousePosition = location;
const float MoveCoefficient = 0.001f; // 移動量の補正係数
// 視点を移動させる
m_draw->TranslateViewpoint(
distanceOfDrag.X * MoveCoefficient,
distanceOfDrag.Y * MoveCoefficient
);
}
/// オブジェクトを選択する
void ModelPanel::SelecetObject( System::Drawing::Point location )
{
if( m_draw->SelectObject( location ) )
{
// 選択が変更されたならば、選択されたオブジェクトを取得する
Distinction^ selected = m_draw->Model->SelectedLink;
// ... 選択イベントを発生する
Selected( this, gcnew SelectEventArgs( selected ) );
}
}
/// 表示モードを取得する [ Delegate ]
ExpressionModel ModelPanel::ExpressionMode::get()
{
return m_draw->Model->ExpressionMode;
}
/// 表示モードを切り替える
void ModelPanel::ChangeExpressionMode()
{
// 現在の設定とは異なるものに設定する
m_draw->Model->ExpressionMode =
( m_draw->Model->ExpressionMode == ExpressionModel::MechanismModel )?
ExpressionModel::RealModel :
ExpressionModel::MechanismModel;
// 再描画する
Redraw( this, nullptr );
}