using System;
using System.Windows.Forms;
using System.Drawing;

namespace Mix.Tool.ModelEditor
{
    /// <summary>
    /// アセットフォームクラス
    /// </summary>
    public partial class AssetForm : Mix.Tool.Docking.DockContent
    {
        #region Private Constant

        const string IK_MODEL_NODE = "modelNode";
        const string IK_EMPTY_NODE = "emptyNode";
        const string IK_MESH_NODE = "meshNode";
        const string IK_BONE_NODE = "boneNode";
        const string IK_MATERIAL_SLOT = "materialSlot";
        const string IK_MATERIAL_DEF = "materialDef";
        const string IK_MATERIAL = "material";
        const string IK_KINEMATIC_CHARACTER = "kinematicCharacter";
        const string IK_COLLIDER = "collider";
        const string IK_SENSOR = "sensor";
        const string IK_BOX_SHAPE = "boxShape";
        const string IK_CAPSULE_SHAPE = "capsuleShape";
        const string IK_SPHERE_SHAPE = "sphereShape";
        const string IK_POINT_JOINT = "pointJoint";
        const string IK_HINGE_JOINT = "hingeJoint";
        const string IK_BALL_JOINT = "ballJoint";

        #endregion

        #region Public EventArgs

        /// <summary>
        /// マテリアルイベントデータクラス
        /// </summary>
        public class MaterialEventArgs : EventArgs
        {
            private Mix.Tool.Graphics.MaterialSlot materialSlot;
            Mix.Tool.Graphics.Material material;

            public MaterialEventArgs(Mix.Tool.Graphics.MaterialSlot _materialSlot, Mix.Tool.Graphics.Material _material)
            {
                this.materialSlot = _materialSlot;
                this.material = _material;
            }

            public Mix.Tool.Graphics.MaterialSlot MaterialSlot
            {
                get { return this.materialSlot; }
            }

            public Mix.Tool.Graphics.Material Material
            {
                get { return this.material; }
            }

            public bool IsAvailable
            {
                get
                {
                    if ((this.materialSlot == null) ||
                        (this.material == null))
                    {
                        return false;
                    }

                    return true;
                }
            }
        };

        /// <summary>
        /// キネマティックキャラクターイベントデータクラス
        /// </summary>
        public class KinematicCharacterEventArgs : EventArgs
        {
            private Mix.Tool.Dynamics.Design.Actor dynActor;

            public KinematicCharacterEventArgs(Mix.Tool.Dynamics.Design.Actor _dynActor)
            {
                this.dynActor = _dynActor;
            }

            public Mix.Tool.Dynamics.Design.Actor DynamicsDesigner
            {
                get { return this.dynActor; }
            }
        };

        /// <summary>
        /// リジッドボディイベントデータクラス
        /// </summary>
        public class RigidBodyEventArgs : EventArgs
        {
            private Mix.Tool.Dynamics.Design.BasicChild basicChild;

            public RigidBodyEventArgs(Mix.Tool.Dynamics.Design.BasicChild _basicChild)
            {
                this.basicChild = _basicChild;
            }

            public Mix.Tool.Dynamics.Design.BasicChild BasicChild
            {
                get { return this.basicChild; }
            }
        };

        /// <summary>
        /// シェイプイベントデータクラス
        /// </summary>
        public class ShapeEventArgs : EventArgs
        {
            private Mix.Tool.Dynamics.Design.IBasicDocument doc = null;
            private Mix.Tool.Dynamics.Design.Shape shape = null;

            public ShapeEventArgs(Mix.Tool.Dynamics.Design.IBasicDocument _doc, Mix.Tool.Dynamics.Design.Shape _shape)
            {
                if (_doc == null)
                {
                    throw new System.ArgumentNullException("_doc");
                }

                this.doc = _doc;
                this.shape = _shape;
            }

            public Mix.Tool.Dynamics.Design.IBasicDocument Document
            {
                get { return this.doc; }
            }

            public Mix.Tool.Dynamics.Design.Shape Shape
            {
                get { return this.shape; }
            }

            public bool IsAvailable
            {
                get
                {
                    if ((this.doc == null) ||
                        (this.shape == null))
                    {
                        return false;
                    }

                    return true;
                }
            }
        }

        /// <summary>
        /// ジョイントイベントデータクラス
        /// </summary>
        public class JointEventArgs : EventArgs
        {
            private Mix.Tool.Dynamics.Design.Part dynPart;

            public JointEventArgs(Mix.Tool.Dynamics.Design.Part _dynPart)
            {
                this.dynPart = _dynPart;
            }

            public Mix.Tool.Dynamics.Design.Part DynamicsDesigner
            {
                get { return this.dynPart; }
            }
        }

        /// <summary>
        /// 地形イベントデータクラス
        /// </summary>
        public class TerrainEventArgs : EventArgs
        {
            private Mix.Tool.Dynamics.Design.ITerrainDocument doc = null;
            private bool isAvailable = false;

            public TerrainEventArgs(Mix.Tool.Dynamics.Design.ITerrainDocument _doc)
            {
                if (_doc == null)
                {
                    throw new System.ArgumentNullException("_doc");
                }

                this.doc = _doc;
                this.isAvailable = true;
            }

            public TerrainEventArgs(Mix.Tool.Dynamics.Design.ITerrainDocument _doc, bool imported)
            {
                if (_doc == null)
                {
                    throw new System.ArgumentNullException("_doc");
                }

                this.doc = _doc;
                this.isAvailable = (_doc.DynamicsDesigner != null) ? imported : false;
            }

            public Mix.Tool.Dynamics.Design.ITerrainDocument Document
            {
                get { return this.doc; }
            }

            public bool IsAvailable
            {
                get { return this.isAvailable; }
            }
        };

        #endregion

        #region Public EventHandler

        /// <summary>
        /// マテリアルイベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void MaterialEventHandler(object sender, MaterialEventArgs e);
        /// <summary>
        /// キネマティックキャラクターイベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void KinematicCharacterEventHandler(object sender, KinematicCharacterEventArgs e);
        /// <summary>
        /// 地形イベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void TerrainEventHandler(object sender, TerrainEventArgs e);
        /// <summary>
        /// シェイプイベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ShapeEventHandler(object sender, ShapeEventArgs e);
        /// <summary>
        /// リジッドボディイベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void RigidBodyEventHandler(object sender, RigidBodyEventArgs e);
        /// <summary>
        /// ジョイントイベントハンドラー
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void JointEventHandler(object sender, JointEventArgs e);

        #endregion

        #region Public Event

        /// <summary>
        /// マテリアルの選択が変更された際に発生します
        /// </summary>
        public event MaterialEventHandler SelectedMaterialChanged = null;
        /// <summary>
        /// キネマティックキャラクターの選択が変更された際に発生します
        /// </summary>
        public event KinematicCharacterEventHandler SelectedKinematicCharacterChanged = null;
        /// <summary>
        /// リジッドボディの選択が変更された際に発生します
        /// </summary>
        public event RigidBodyEventHandler SelectedRigidBodyChanged = null;
        /// <summary>
        /// シェイプの選択が変更された際に発生します
        /// </summary>
        public event ShapeEventHandler SelectedShapeChanged = null;
        /// <summary>
        /// ジョイントの選択が変更された際に発生します
        /// </summary>
        public event JointEventHandler SelectedJointChanged = null;
        /// <summary>
        /// 地形の選択が変更された際に発生します
        /// </summary>
        public event TerrainEventHandler SelectedTerrainChanged = null;

        #endregion

        #region Private Member

        private Mix.Tool.ModelEditor.Project.BackgroundWorker backgroundWorker = null;
        private object src = null;

        StringFormat tvAssetTextFormat = new System.Drawing.StringFormat();
        Font tvAssetSelectedFont = null;

        #endregion

        #region Public Property

        /// <summary>
        /// ソースの取得、または設定
        /// </summary>
        public object Source
        {
            get { return this.src; }
            set
            {
                this.tvAsset.BeginUpdate();
                this.tvAsset.Nodes.Clear();

                this.src = value;

                if (this.src != null)
                {
                    // ルートツリーノード
                    TreeNode rootTreeNode = this.AddTreeNode(null, this.src);

                    // チャイルドツリーノード
                    if (this.src is Mix.Tool.Graphics.ObjectModel)
                    {
                        // オブジェクトモデル
                        Mix.Tool.Graphics.ObjectModel objModel = this.src as Mix.Tool.Graphics.ObjectModel;

                        this.AddMaterialSlots(rootTreeNode, objModel.MaterialSlots);
                        this.AddPhysics(rootTreeNode, objModel);
                    }
                    else if (this.src is Mix.Tool.Graphics.MapModel)
                    {
                        // マップモデルモデル
                        Mix.Tool.Graphics.MapModel mapModel = this.src as Mix.Tool.Graphics.MapModel;

                        this.AddMaterialSlots(rootTreeNode, mapModel.MaterialSlots);
                        this.AddPhysics(rootTreeNode, mapModel);
                    }
                    else if (this.src is Mix.Tool.Graphics.Node)
                    {
                        //ノード
                        Mix.Tool.Graphics.Node node = this.src as Mix.Tool.Graphics.Node;

                        if (node is Mix.Tool.Graphics.MeshNode)
                        {
                            //メッシュノード
                            Mix.Tool.Graphics.MeshNode meshNode = node as Mix.Tool.Graphics.MeshNode;

                            this.AddMaterialSlots(rootTreeNode, meshNode.MaterialSlots);
                        }
                        else
                        {
                            this.NotifySelectedMaterialChanged(null);
                        }

                        this.AddPhysics(rootTreeNode, node);
                    }

                    rootTreeNode.Expand();
                }

                this.UpdateControlState();
                this.tvAsset.EndUpdate();
            }
        }

        #endregion

        #region Public Method

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public AssetForm(Mix.Tool.ModelEditor.Project.BackgroundWorker _backgroundWorker)
        {
            InitializeComponent();

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // バックグラウンドワーカー
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            this.backgroundWorker = _backgroundWorker;

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // イメージリストの作成
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            this.imageList.Images.Add(IK_MODEL_NODE, Properties.Resources.Node_Model);
            this.imageList.Images.Add(IK_EMPTY_NODE, Properties.Resources.Node_Empty);
            this.imageList.Images.Add(IK_MESH_NODE, Properties.Resources.Node_Mesh);
            this.imageList.Images.Add(IK_BONE_NODE, Properties.Resources.Node_Bone);
            this.imageList.Images.Add(IK_MATERIAL_SLOT, Properties.Resources.MaterialSlot);
            this.imageList.Images.Add(IK_MATERIAL_DEF, Properties.Resources.MaterialDef);
            this.imageList.Images.Add(IK_MATERIAL, Properties.Resources.Material);
            this.imageList.Images.Add(IK_KINEMATIC_CHARACTER, Properties.Resources.KinematicCharacter);
            this.imageList.Images.Add(IK_COLLIDER, Properties.Resources.Collider);
            this.imageList.Images.Add(IK_SENSOR, Properties.Resources.Sensor);
            this.imageList.Images.Add(IK_BOX_SHAPE, Properties.Resources.BoxShape);
            this.imageList.Images.Add(IK_CAPSULE_SHAPE, Properties.Resources.CapsuleShape);
            this.imageList.Images.Add(IK_SPHERE_SHAPE, Properties.Resources.SphereShape);
            this.imageList.Images.Add(IK_POINT_JOINT, Properties.Resources.PointJoint);
            this.imageList.Images.Add(IK_HINGE_JOINT, Properties.Resources.HingeJoint);
            this.imageList.Images.Add(IK_BALL_JOINT, Properties.Resources.BallJoint);

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // オーナードローのテキストフォーマット
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            this.tvAssetTextFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
            this.tvAssetTextFormat.Alignment = StringAlignment.Near;
            this.tvAssetTextFormat.LineAlignment = StringAlignment.Center;

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // オーナードローのフォント
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            this.tvAssetSelectedFont = new Font(this.tvAsset.Font, FontStyle.Underline);
        }

        /// <summary>
        /// マテリアルイベントを要求します
        /// </summary>
        public void RequestMaterialEvent()
        {
            if (this.src is Mix.Tool.Graphics.ObjectModel)
            {
                Mix.Tool.Graphics.ObjectModel objModel = this.src as Mix.Tool.Graphics.ObjectModel;

                this.NotifySelectedMaterialChanged(objModel.MaterialSlots.Selected);
            }
            else if (this.src is Mix.Tool.Graphics.MapModel)
            {
                Mix.Tool.Graphics.MapModel mapModel = this.src as Mix.Tool.Graphics.MapModel;

                this.NotifySelectedMaterialChanged(mapModel.MaterialSlots.Selected);
            }
            else if (this.src is Mix.Tool.Graphics.MeshNode)
            {
                Mix.Tool.Graphics.MeshNode meshNode = this.src as Mix.Tool.Graphics.MeshNode;

                this.NotifySelectedMaterialChanged(meshNode.MaterialSlots.Selected);
            }
        }

        /// <summary>
        /// キネマティックキャラクターイベントを要求します
        /// </summary>
        public void RequestKinematicCharacterEvent()
        {
            if ((this.src != null) &&
                (this.src is Mix.Tool.Dynamics.Design.IBasicDocument))
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;

                if (dynDoc.DynamicsDesigner is Mix.Tool.Dynamics.Design.Actor)
                {
                    Mix.Tool.Dynamics.Design.Actor dynActor = dynDoc.DynamicsDesigner as Mix.Tool.Dynamics.Design.Actor;

                    this.NotifySelectedKinematicCharacterChanged((dynActor.KinematicCharacter != null) ? dynActor : null);
                }
            }
        }

        /// <summary>
        /// コリジョンイベントを要求します
        /// </summary>
        public void RequestCollisionEvent()
        {
            if (this.src != null)
            {
                if (this.src is Mix.Tool.Dynamics.Design.ITerrainDocument)
                {
                    Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.ITerrainDocument;

                    this.NotifySelectedTerrainChanged(dynDoc);
                }
            }
        }

        /// <summary>
        /// リジッドボディイベントを要求します
        /// </summary>
        public void RequestRigidBodyEvent()
        {
            if ((this.src != null) &&
                (this.src is Mix.Tool.Dynamics.Design.IBasicDocument))
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = dynDoc.DynamicsDesigner.Childs.Selected;

                this.NotifySelectedRigidBodyChanged(dynBasicChild);
            }
        }

        /// <summary>
        /// シェイプイベントを要求します
        /// </summary>
        public void RequestShapeEvent()
        {
            if ((this.src != null) &&
                (this.src is Mix.Tool.Dynamics.Design.IBasicDocument))
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = dynDoc.DynamicsDesigner.Childs.Selected;
                Mix.Tool.Dynamics.Design.Shape dynShape = (dynBasicChild != null) ? dynBasicChild.Shapes.Selected : null;

                this.NotifySelectedShapeChanged(dynDoc, dynBasicChild, dynShape);
            }
        }

        /// <summary>
        /// ジョイントイベントを要求します
        /// </summary>
        public void RequestJointEvent()
        {
            if ((this.src != null) &&
                (this.src is Mix.Tool.Dynamics.Design.IBasicDocument))
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;

                if (dynDoc.DynamicsDesigner is Mix.Tool.Dynamics.Design.Part)
                {
                    Mix.Tool.Dynamics.Design.Part dynPart = dynDoc.DynamicsDesigner as Mix.Tool.Dynamics.Design.Part;

                    this.NotifySelectedJointChanged((dynPart.Joint != null) ? dynPart : null);
                }
            }
        }

        #endregion

        #region Private tvAsset Method

        private void tvAsset_KeyUp(object sender, KeyEventArgs e)
        {
            TreeView treeView = sender as TreeView;

            if ((e.KeyCode == Keys.F2) &&
                (treeView.SelectedNode != null) &&
                (treeView.LabelEdit == true))
            {
                treeView.SelectedNode.BeginEdit();
            }
        }

        private void tvAsset_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if ((e.Button == MouseButtons.Right) &&
                (e.Node != null))
            {
                TreeView treeView = sender as TreeView;
                treeView.SelectedNode = e.Node;
            }
        }

        private void tvAsset_AfterSelect(object sender, TreeViewEventArgs e)
        {
            object tag = e.Node.Tag;

            if (tag is Mix.Tool.Graphics.MaterialSlot)
            {
                //Model : マテリアルスロット
                Mix.Tool.Graphics.MaterialSlot materialSlot = tag as Mix.Tool.Graphics.MaterialSlot;

                this.NotifySelectedMaterialChanged(materialSlot);
            }
            else if (tag is Mix.Tool.Graphics.Material)
            {
                //Model : マテリアル
                Mix.Tool.Graphics.MaterialSlot materialSlot = e.Node.Parent.Tag as Mix.Tool.Graphics.MaterialSlot;
                Mix.Tool.Graphics.Material material = tag as Mix.Tool.Graphics.Material;

                this.NotifySelectedMaterialChanged(materialSlot, material);
            }
            else if (tag is Mix.Tool.Dynamics.Design.Actor)
            {
                //Dynamics Actor : キネマティックキャラクター
                Mix.Tool.Dynamics.Design.Actor dynActor = tag as Mix.Tool.Dynamics.Design.Actor;

                this.NotifySelectedKinematicCharacterChanged(dynActor);
            }
            else if (tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                //Dynamics Basic : リジッドボディ
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.Basic dynBasic = dynDoc.DynamicsDesigner;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = tag as Mix.Tool.Dynamics.Design.BasicChild;
                Mix.Tool.Dynamics.Design.Shape dynShape = dynBasicChild.Shapes.Selected;

                this.NotifySelectedRigidBodyChanged(dynBasic, dynBasicChild);
                this.NotifySelectedShapeChanged(dynDoc, dynShape); //既に選択されているものを通知するので、選択はしない
            }
            else if (tag is Mix.Tool.Dynamics.Design.Shape)
            {
                //Dynamics Basic : シェイプ
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.Basic dynBasic = dynDoc.DynamicsDesigner;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = e.Node.Parent.Tag as Mix.Tool.Dynamics.Design.BasicChild;
                Mix.Tool.Dynamics.Design.Shape dynShape = tag as Mix.Tool.Dynamics.Design.Shape;

                this.NotifySelectedShapeChanged(dynDoc, dynBasicChild, dynShape);
                this.NotifySelectedRigidBodyChanged(dynBasic, dynBasicChild);

                //リジッドボディを直接選択していないので、選択状態の描画を有効にするため再描画を行わせる
                this.RedrawTreeNodeFromTag(dynBasicChild);
            }
            else if (tag is Mix.Tool.Dynamics.Design.Part)
            {
                //Dynamics Part : ジョイント
                Mix.Tool.Dynamics.Design.Part dynPart = tag as Mix.Tool.Dynamics.Design.Part;

                this.NotifySelectedJointChanged(dynPart);
            }
            else if (tag is Mix.Tool.Dynamics.Design.Terrain)
            {
                //Dynamics Terrain : リジッドボディ( コライダー )
                Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.ITerrainDocument;

                this.NotifySelectedTerrainChanged(dynDoc);
            }
        }

        private void tvAsset_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if ((e.Node.Tag is Mix.Tool.Graphics.MaterialSlot) ||
                (e.Node.Tag is Mix.Tool.Graphics.Material) ||
                (e.Node.Tag is Mix.Tool.Dynamics.Design.BasicChild))
            {
            }
            else
            {
                e.CancelEdit = true;
            }
        }

        private void tvAsset_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Node.Tag is Mix.Tool.Graphics.MaterialSlot)
            {
                //マテリアルスロット
                Mix.Tool.Graphics.MaterialSlot materialSlot = e.Node.Tag as Mix.Tool.Graphics.MaterialSlot;

                materialSlot.Name = e.Label;

                if (materialSlot.Name.Equals(e.Label) == false)
                {
                    e.Node.Text = materialSlot.Name;
                    e.CancelEdit = true;
                }
            }
            else if (e.Node.Tag is Mix.Tool.Graphics.Material)
            {
                //マテリアル
                Mix.Tool.Graphics.Material material = e.Node.Tag as Mix.Tool.Graphics.Material;

                material.Name = e.Label;

                if (material.Name.Equals(e.Label) == false)
                {
                    e.Node.Text = material.Name;
                    e.CancelEdit = true;
                }
            }
            else if (e.Node.Tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                //リジッドボディ(重複チェックはしない)
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = e.Node.Tag as Mix.Tool.Dynamics.Design.BasicChild;

                dynBasicChild.Name = e.Label;
                e.Node.Text = e.Label;
            }
        }

        private void tvAsset_DrawNode(object sender, DrawTreeNodeEventArgs e)
        {
            System.Drawing.Rectangle textRect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width + 2, e.Bounds.Height);
            System.Drawing.Brush textBrush = null;
            bool highLightText = false;

            //ブラッシュを決定
            if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
            {
                if ((e.State & TreeNodeStates.Focused) == TreeNodeStates.Focused)
                {
                    textBrush = System.Drawing.SystemBrushes.HighlightText;
                }
                else
                {
                    textBrush = System.Drawing.SystemBrushes.WindowText;
                }
            }
            else
            {
                textBrush = System.Drawing.SystemBrushes.WindowText;
            }

            //フォントを決定( アセットに複数存在するものテキストに下線を引くため )
            if (e.Node.Tag is Mix.Tool.Graphics.MaterialSlot)
            {
                //マテリアルスロット
                Mix.Tool.Graphics.MaterialSlotCollection materialSlots = this.MaterialSlotCollection;
                Mix.Tool.Graphics.MaterialSlot materialSlot = e.Node.Tag as Mix.Tool.Graphics.MaterialSlot;

                highLightText = (materialSlots.Selected == materialSlot);
            }
            else if (e.Node.Tag is Mix.Tool.Graphics.Material)
            {
                //マテリアル
                Mix.Tool.Graphics.Material material = e.Node.Tag as Mix.Tool.Graphics.Material;

                highLightText = material.IsActive;
            }
            else if (e.Node.Tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                //リジッドボディ(Actor)
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = e.Node.Tag as Mix.Tool.Dynamics.Design.BasicChild;

                highLightText = (dynDoc.DynamicsDesigner.Childs.Selected == dynBasicChild);
            }
            else if (e.Node.Tag is Mix.Tool.Dynamics.Design.Shape)
            {
                //シェイプ(Actor)
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = e.Node.Parent.Tag as Mix.Tool.Dynamics.Design.BasicChild;
                Mix.Tool.Dynamics.Design.Shape dynShape = e.Node.Tag as Mix.Tool.Dynamics.Design.Shape;

                highLightText = (dynBasicChild.Shapes.Selected == dynShape);
            }

            //テキストを描画
            e.Graphics.DrawString(e.Node.Text,
                (highLightText == true) ? this.tvAssetSelectedFont : this.tvAsset.Font,
                textBrush, textRect,
                tvAssetTextFormat);
        }

        #endregion

        #region Private ctxMenu Method

        private void ctxMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            TreeNode selectedTreeNode = this.tvAsset.SelectedNode;
            object tag = selectedTreeNode.Tag;

            if (tag is Mix.Tool.Graphics.ObjectModel)
            {
                Mix.Tool.Graphics.ObjectModel objModel = tag as Mix.Tool.Graphics.ObjectModel;
                Mix.Tool.Dynamics.Design.Actor dynDesigner = objModel.DynamicsDesigner as Mix.Tool.Dynamics.Design.Actor;

                this.cmAdd.Enabled = true;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = (dynDesigner.KinematicCharacter == null);
                this.cmAddController_Character.Enabled = (dynDesigner.KinematicCharacter == null);
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = true;
                this.cmAddRigidBody_Collider.Enabled = dynDesigner.Childs.Addable(Mix.Tool.Dynamics.Design.BasicChildType.Collider);
                this.cmAddRigidBody_Sensor.Enabled = dynDesigner.Childs.Addable(Mix.Tool.Dynamics.Design.BasicChildType.Sensor);
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = false;
                this.cmRename.Enabled = false;
            }
            else if (tag is Mix.Tool.Graphics.MapModel)
            {
                Mix.Tool.Graphics.MapModel mapModel = tag as Mix.Tool.Graphics.MapModel;

                this.cmAdd.Enabled = true;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = true;
                this.cmAddRigidBody_Collider.Enabled = (mapModel.DynamicsDesigner.Status == Mix.Tool.Dynamics.Design.TerrainStatus.Destroyed);
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = false;
                this.cmRename.Enabled = false;
            }
            else if (tag is Mix.Tool.Graphics.Node)
            {
                Mix.Tool.Graphics.Node node = tag as Mix.Tool.Graphics.Node;

                if (node.DynamicsDesigner != null)
                {
                    Mix.Tool.Dynamics.Design.Part dynDesigner = node.DynamicsDesigner as Mix.Tool.Dynamics.Design.Part;

                    this.cmAdd.Enabled = true;
                    this.cmAddMaterial.Enabled = false;
                    this.cmAddController.Enabled = true;
                    this.cmAddController_Character.Enabled = false;
                    this.cmAddController_Wheel.Enabled = false;
                    this.cmAddRigidBody.Enabled = true;
                    this.cmAddRigidBody_Collider.Enabled = dynDesigner.Childs.Addable(Mix.Tool.Dynamics.Design.BasicChildType.Collider);
                    this.cmAddRigidBody_Sensor.Enabled = dynDesigner.Childs.Addable(Mix.Tool.Dynamics.Design.BasicChildType.Sensor);
                    this.cmAddShape.Enabled = false;
                    this.cmAddShape_Box.Enabled = false;
                    this.cmAddShape_Capsule.Enabled = false;
                    this.cmAddShape_Sphere.Enabled = false;
                    this.cmAddJoint.Enabled = (dynDesigner.Joint == null);
                    this.cmRemove.Enabled = false;
                    this.cmRename.Enabled = false;
                }
                else
                {
                    this.cmAdd.Enabled = false;
                    this.cmAddMaterial.Enabled = false;
                    this.cmAddController.Enabled = false;
                    this.cmAddController_Character.Enabled = false;
                    this.cmAddController_Wheel.Enabled = false;
                    this.cmAddRigidBody.Enabled = false;
                    this.cmAddRigidBody_Collider.Enabled = false;
                    this.cmAddRigidBody_Sensor.Enabled = false;
                    this.cmAddShape.Enabled = false;
                    this.cmAddShape_Box.Enabled = false;
                    this.cmAddShape_Capsule.Enabled = false;
                    this.cmAddShape_Sphere.Enabled = false;
                    this.cmAddJoint.Enabled = false;
                    this.cmRemove.Enabled = false;
                    this.cmRename.Enabled = false;
                }
            }
            else if (tag is Mix.Tool.Graphics.MaterialSlot)
            {
                this.cmAdd.Enabled = true;
                this.cmAddMaterial.Enabled = true;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = false;
                this.cmAddRigidBody_Collider.Enabled = false;
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = false;
                this.cmRename.Enabled = true;
            }
            else if (tag is Mix.Tool.Graphics.Material)
            {
                Mix.Tool.Graphics.Material material = tag as Mix.Tool.Graphics.Material;

                this.cmAdd.Enabled = false;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = false;
                this.cmAddRigidBody_Collider.Enabled = false;
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = (material.IsDefault == false);
                this.cmRename.Enabled = true;
            }
            else if (tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = tag as Mix.Tool.Dynamics.Design.BasicChild;

                this.cmAdd.Enabled = true;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = false;
                this.cmAddRigidBody_Collider.Enabled = false;
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = true;
                this.cmAddShape_Box.Enabled = true;
                this.cmAddShape_Capsule.Enabled = true;
                this.cmAddShape_Sphere.Enabled = true;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = true;
                this.cmRename.Enabled = true;
            }
            else if (tag is Mix.Tool.Dynamics.Design.Shape)
            {
                this.cmAdd.Enabled = false;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = false;
                this.cmAddRigidBody_Collider.Enabled = false;
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = true;
                this.cmRename.Enabled = false;
            }
            else
            {
                this.cmAdd.Enabled = false;
                this.cmAddMaterial.Enabled = false;
                this.cmAddController.Enabled = false;
                this.cmAddController_Character.Enabled = false;
                this.cmAddController_Wheel.Enabled = false;
                this.cmAddRigidBody.Enabled = false;
                this.cmAddRigidBody_Collider.Enabled = false;
                this.cmAddRigidBody_Sensor.Enabled = false;
                this.cmAddShape.Enabled = false;
                this.cmAddShape_Box.Enabled = false;
                this.cmAddShape_Capsule.Enabled = false;
                this.cmAddShape_Sphere.Enabled = false;
                this.cmAddJoint.Enabled = false;
                this.cmRemove.Enabled = true;
                this.cmRename.Enabled = false;
            }
        }

        private void cmAddMaterial_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = this.tvAsset.SelectedNode;

            if ((selectedNode != null) &&
                (selectedNode.Tag is Mix.Tool.Graphics.MaterialSlot))
            {
                Mix.Tool.Graphics.MaterialSlot materialSlot = selectedNode.Tag as Mix.Tool.Graphics.MaterialSlot;
                Mix.Tool.Graphics.Material material = materialSlot.Materials.Add();

                if (material != null)
                {
                    this.tvAsset.SelectedNode = this.AddTreeNode(selectedNode, material);
                }
            }
        }

        private void cmAddKinematicCharacter_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = this.tvAsset.SelectedNode;

            if (treeNode.Tag is Mix.Tool.Graphics.ObjectModel)
            {
                Mix.Tool.Graphics.ObjectModel objModel = treeNode.Tag as Mix.Tool.Graphics.ObjectModel;
                Mix.Tool.Dynamics.Design.Actor dynActor = objModel.DynamicsDesigner as Mix.Tool.Dynamics.Design.Actor;

                if (dynActor.KinematicCharacter == null)
                {
                    dynActor.KinematicCharacter = new Mix.Tool.Dynamics.KinematicCharacter();
                    this.tvAsset.SelectedNode = this.AddTreeNode(treeNode, dynActor);
                }
                else
                {
                    throw new System.Exception("アセット : キネマティックキャラクターの追加に失敗しました");
                }
            }
        }

        private void cmAddRigidBody_Collider_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = this.tvAsset.SelectedNode;

            if (treeNode.Tag is Mix.Tool.Dynamics.Design.IBasicDocument)
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = treeNode.Tag as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = dynDoc.DynamicsDesigner.Childs.Add(Mix.Tool.Dynamics.Design.BasicChildType.Collider);

                this.tvAsset.SelectedNode = this.AddTreeNode(treeNode, dynBasicChild);
            }
            else if (treeNode.Tag is Mix.Tool.Dynamics.Design.ITerrainDocument)
            {
                //ここではツリービューにノードは追加しない
                //インポートが完了した際に追加されます

                Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc = treeNode.Tag as Mix.Tool.Dynamics.Design.ITerrainDocument;

                using (OpenFileDialog dlg = new OpenFileDialog())
                {
                    dlg.Filter = Properties.Resources.FILE_FILTER_INPUTMODEL;
                    dlg.FilterIndex = 1;

                    if (dlg.ShowDialog() == DialogResult.OK)
                    {
                        this.backgroundWorker.AddTask(new Project.Manager.ImportMapCollisionTask(dynDoc.DynamicsDesigner, dlg.FileName, 5), new System.EventHandler(this.MapCollision_ImportFinished));
                    }
                }
            }
        }

        private void cmAddRigidBody_Sensor_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = this.tvAsset.SelectedNode;

            if (treeNode.Tag is Mix.Tool.Dynamics.Design.IBasicDocument)
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = treeNode.Tag as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = dynDoc.DynamicsDesigner.Childs.Add(Mix.Tool.Dynamics.Design.BasicChildType.Sensor);

                this.tvAsset.SelectedNode = this.AddTreeNode(treeNode, dynBasicChild);
            }
        }

        private void cmAddShape_Box_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsShape(typeof(Mix.Tool.Dynamics.Design.BoxShape));
        }

        private void cmAddShape_Capsule_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsShape(typeof(Mix.Tool.Dynamics.Design.CapsuleShape));
        }

        private void cmAddShape_Sphere_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsShape(typeof(Mix.Tool.Dynamics.Design.SphereShape));
        }

        private void cmAddJoint_Point_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsJoint(typeof(Mix.Tool.Dynamics.PointJoint));
        }

        private void cmAddJoint_Hinge_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsJoint(typeof(Mix.Tool.Dynamics.HingeJoint));
        }

        private void cmAddJoint_Ball_Click(object sender, EventArgs e)
        {
            this.TryAddDynamicsJoint(typeof(Mix.Tool.Dynamics.BallJoint));
        }

        private void cmRemove_Click(object sender, EventArgs e)
        {
            TreeNode removeTreeNode = this.tvAsset.SelectedNode;
            TreeNode parentTreeNode = removeTreeNode.Parent;
            object removeObj = removeTreeNode.Tag;

            if (removeObj is Mix.Tool.Graphics.Material)
            {
                //Model : マテリアル
                if (parentTreeNode.Tag is Mix.Tool.Graphics.MaterialSlot)
                {
                    Mix.Tool.Graphics.MaterialSlot materialSlot = parentTreeNode.Tag as Mix.Tool.Graphics.MaterialSlot;
                    Mix.Tool.Graphics.Material material = removeTreeNode.Tag as Mix.Tool.Graphics.Material;

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    materialSlot.Materials.Remove(material);

                    this.NotifySelectedMaterialChanged(materialSlot);
                }
                else
                {
                    throw new System.Exception("マテリアルの削除に失敗。\n親ノードのタグがマテリアルスロットではありません。");
                }
            }
            else if (removeObj is Mix.Tool.Dynamics.Design.Actor)
            {
                //Dynamics Actor : キネマティックキャラクター
                if (this.src is Mix.Tool.Graphics.ObjectModel)
                {
                    Mix.Tool.Dynamics.Design.Actor dynActor = removeObj as Mix.Tool.Dynamics.Design.Actor;

                    this.NotifySelectedKinematicCharacterChanged(null);

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    dynActor.KinematicCharacter = null;
                }
                else
                {
                    throw new System.Exception("キネマティックキャラクターの削除に失敗。\n不正なソースが渡されています。");
                }
            }
            else if (removeObj is Mix.Tool.Dynamics.Design.BasicChild)
            {
                //Dynamics Basic : リジッドボディ
                if (this.src is Mix.Tool.Dynamics.Design.IBasicDocument)
                {
                    Mix.Tool.Dynamics.Design.IBasicDocument dynBasicDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                    Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = removeObj as Mix.Tool.Dynamics.Design.BasicChild;

                    this.NotifySelectedRigidBodyChanged(null);

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    dynBasicDoc.DynamicsDesigner.Childs.Remove(dynBasicChild);

                    if (dynBasicDoc.DynamicsDesigner.Childs.Selected != null)
                    {
                        this.NotifySelectedRigidBodyChanged(dynBasicDoc.DynamicsDesigner.Childs.Selected);
                    }
                }
                else
                {
                    throw new System.Exception("リジッドボディ(ActorCollider)の削除に失敗。\n不正なソースが渡されています。");
                }
            }
            else if (removeObj is Mix.Tool.Dynamics.Design.Shape)
            {
                //Dynamics Basic : シェイプ
                if (this.src is Mix.Tool.Dynamics.Design.IBasicDocument)
                {
                    Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                    Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = parentTreeNode.Tag as Mix.Tool.Dynamics.Design.BasicChild;
                    Mix.Tool.Dynamics.Design.Shape dynShape = removeTreeNode.Tag as Mix.Tool.Dynamics.Design.Shape;

                    this.NotifySelectedShapeChanged(dynDoc, null);

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    dynBasicChild.Shapes.Remove(dynShape);

                    if (dynBasicChild.Shapes.Selected != null)
                    {
                        this.NotifySelectedShapeChanged(dynDoc, dynBasicChild.Shapes.Selected);
                    }
                }
                else
                {
                    throw new System.Exception("シェイプの削除に失敗。\n不正なソースが渡されています。");
                }
            }
            else if (removeObj is Mix.Tool.Dynamics.Design.Part)
            {
                //Dynamics Part : ジョイント
                if (this.src is Mix.Tool.Graphics.Node)
                {
                    Mix.Tool.Graphics.Node node = this.src as Mix.Tool.Graphics.Node;
                    Mix.Tool.Dynamics.Design.Part dynPart = removeObj as Mix.Tool.Dynamics.Design.Part;
                    Mix.Tool.Dynamics.Joint dynOldJoint = dynPart.Joint;

                    this.NotifySelectedJointChanged(null);

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    dynPart.Joint = null;
                }
                else
                {
                    throw new System.Exception("ジョイントの削除に失敗。\n不正なソースが渡されています。");
                }
            }
            else if (removeObj is Mix.Tool.Dynamics.Design.Terrain)
            {
                //Dynamics Terrain : リジッドボディ(コライダー)
                if (this.src is Mix.Tool.Dynamics.Design.ITerrainDocument)
                {
                    Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.ITerrainDocument;

                    this.NotifySelectedTerrainChanged(dynDoc, false);

                    parentTreeNode.Nodes.Remove(removeTreeNode);
                    dynDoc.DynamicsDesigner.Destroy();
                }
                else
                {
                    throw new System.Exception("リジッドボディ(TerrainCollider)の削除に失敗。\n不正なソースが渡されています。");
                }
            }
        }

        private void cmRename_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = this.tvAsset.SelectedNode;

            if (selectedNode != null)
            {
                selectedNode.BeginEdit();
            }
        }

        #endregion

        #region Private Misc Property

        private Mix.Tool.Graphics.MaterialSlotCollection MaterialSlotCollection
        {
            get
            {
                Mix.Tool.Graphics.MaterialSlotCollection materialSlots = null;

                if (this.src is Mix.Tool.Graphics.ObjectModel)
                {
                    Mix.Tool.Graphics.ObjectModel objModel = this.src as Mix.Tool.Graphics.ObjectModel;
                    materialSlots = objModel.MaterialSlots;
                }
                else if (this.src is Mix.Tool.Graphics.MapModel)
                {
                    Mix.Tool.Graphics.MapModel mapModel = this.src as Mix.Tool.Graphics.MapModel;
                    materialSlots = mapModel.MaterialSlots;
                }
                else if (this.src is Mix.Tool.Graphics.MeshNode)
                {
                    Mix.Tool.Graphics.MeshNode meshNode = this.src as Mix.Tool.Graphics.MeshNode;
                    materialSlots = meshNode.MaterialSlots;
                }

                return materialSlots;
            }
        }

        #endregion

        #region Private Misc Method

        private void UpdateControlState()
        {
            bool enabled = this.src != null;

            foreach (Control ctrl in this.Controls)
            {
                ctrl.Enabled = enabled;
            }
        }

        private void AddMaterialSlots(TreeNode parentTreeNode, Mix.Tool.Graphics.MaterialSlotCollection materialSlots)
        {
            foreach (Mix.Tool.Graphics.MaterialSlot materialSlot in materialSlots)
            {
                TreeNode msTreeNode = this.AddTreeNode(parentTreeNode, materialSlot);

                foreach (Mix.Tool.Graphics.Material material in materialSlot.Materials)
                {
                    this.AddTreeNode(msTreeNode, material);
                }

                if (materialSlots.Selected == materialSlot)
                {
                    //選択されているものを開いておく
                    msTreeNode.Expand();
                }
            }

            this.NotifySelectedMaterialChanged(materialSlots.Selected);
        }

        private void AddPhysics(TreeNode parentTreeNode, Mix.Tool.Dynamics.Design.IBasicDocument dynDoc)
        {
            Mix.Tool.Dynamics.Design.Basic dynBasic = dynDoc.DynamicsDesigner;

            if (dynBasic == null)
            {
                //マップモデルのノードである
                return;
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // キネマティックキャラクター
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            if (dynBasic is Mix.Tool.Dynamics.Design.Actor)
            {
                Mix.Tool.Dynamics.Design.Actor dynActor = dynBasic as Mix.Tool.Dynamics.Design.Actor;

                if (dynActor.KinematicCharacter != null)
                {
                    this.AddTreeNode(parentTreeNode, dynActor);
                    this.NotifySelectedKinematicCharacterChanged(dynActor);
                }
                else
                {
                    this.NotifySelectedKinematicCharacterChanged(null);
                }
            }
            else
            {
                this.NotifySelectedKinematicCharacterChanged(null);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // リジッドボディ
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            foreach (Mix.Tool.Dynamics.Design.BasicChild child in dynDoc.DynamicsDesigner.Childs)
            {
                TreeNode rigidBodyTreeNode = this.AddTreeNode(parentTreeNode, child);

                foreach (Mix.Tool.Dynamics.Design.Shape shape in child.Shapes)
                {
                    this.AddTreeNode(rigidBodyTreeNode, shape);
                }

                if (dynDoc.DynamicsDesigner.Childs.Selected == child)
                {
                    rigidBodyTreeNode.Expand();
                }
            }

            //リジッドボディの選択を通知
            this.NotifySelectedRigidBodyChanged(dynDoc.DynamicsDesigner.Childs.Selected);

            //シェイプの選択を通知
            if( dynDoc.DynamicsDesigner.Childs.Selected != null )
            {
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = dynDoc.DynamicsDesigner.Childs.Selected;
                this.NotifySelectedShapeChanged(dynDoc, dynBasicChild, dynBasicChild.Shapes.Selected);
            }
            else
            {
                this.NotifySelectedShapeChanged(dynDoc, null, null);
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // ジョイント
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            if (dynBasic is Mix.Tool.Dynamics.Design.Part)
            {
                Mix.Tool.Dynamics.Design.Part dynPart = dynBasic as Mix.Tool.Dynamics.Design.Part;

                if (dynPart.Joint != null)
                {
                    this.AddTreeNode(parentTreeNode, dynPart);
                    this.NotifySelectedJointChanged(dynPart);
                }
                else
                {
                    this.NotifySelectedJointChanged(null);
                }
            }
        }

        private void AddPhysics(TreeNode parentTreeNode, Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc)
        {
            Mix.Tool.Dynamics.Design.Terrain dynTerrain = dynDoc.DynamicsDesigner;

            ////////////////////////////////////////////////////////////////////////////////////////////////////
            // コリジョン
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            if (dynTerrain.Status == Mix.Tool.Dynamics.Design.TerrainStatus.Available)
            {
                this.AddTreeNode(parentTreeNode, dynTerrain);
            }

            this.NotifySelectedTerrainChanged(dynDoc);
        }

        private void TryAddDynamicsShape(Type type)
        {
            if ((type.Equals(typeof(Mix.Tool.Dynamics.Design.BoxShape)) == false) &&
                (type.Equals(typeof(Mix.Tool.Dynamics.Design.CapsuleShape)) == false) &&
                (type.Equals(typeof(Mix.Tool.Dynamics.Design.SphereShape)) == false))
            {
                return;
            }

            TreeNode treeNode = this.tvAsset.SelectedNode;

            if (treeNode.Tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = this.src as Mix.Tool.Dynamics.Design.IBasicDocument;
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = treeNode.Tag as Mix.Tool.Dynamics.Design.BasicChild;
                Mix.Tool.Dynamics.Design.Shape dynShape = (Mix.Tool.Dynamics.Design.Shape)Activator.CreateInstance(type, new object[]{dynDoc.BoundingBoxes[0]});

                dynBasicChild.Shapes.Add(dynShape);
                this.tvAsset.SelectedNode = this.AddTreeNode(treeNode, dynShape);
            }
        }

        private void TryAddDynamicsJoint(Type type)
        {
            if (((type.Equals(typeof(Mix.Tool.Dynamics.PointJoint)) == false) &&
                (type.Equals(typeof(Mix.Tool.Dynamics.HingeJoint)) == false) &&
                (type.Equals(typeof(Mix.Tool.Dynamics.BallJoint)) == false)))
            {
                return;
            }

            TreeNode treeNode = this.tvAsset.SelectedNode;

            if (treeNode.Tag is Mix.Tool.Dynamics.Design.IBasicDocument)
            {
                Mix.Tool.Dynamics.Design.IBasicDocument dynDoc = treeNode.Tag as Mix.Tool.Dynamics.Design.IBasicDocument;

                if ((dynDoc.DynamicsDesigner != null) &&
                    (dynDoc.DynamicsDesigner is Mix.Tool.Dynamics.Design.Part))
                {
                    Mix.Tool.Dynamics.Design.Part dynPart = dynDoc.DynamicsDesigner as Mix.Tool.Dynamics.Design.Part;

                    dynPart.Joint = (Mix.Tool.Dynamics.Joint)Activator.CreateInstance(type);
                    this.tvAsset.SelectedNode = this.AddTreeNode(treeNode, dynPart);
                }
            }
        }

        private TreeNode AddTreeNode(TreeNode parentTreeNode, object tag)
        {
            TreeNode treeNode = new TreeNode();
            string text = "";
            string imageKey = "";

            if (tag is Mix.Tool.Graphics.Model)
            {
                // モデル
                Mix.Tool.Graphics.Model model = tag as Mix.Tool.Graphics.Model;

                text = model.Name;
                imageKey = IK_MODEL_NODE;
            }
            else if (tag is Mix.Tool.Graphics.Node)
            {
                // ノード
                Mix.Tool.Graphics.Node node = tag as Mix.Tool.Graphics.Node;

                text = node.Name;

                if (node is Mix.Tool.Graphics.EmptyNode)
                {
                    imageKey = IK_EMPTY_NODE;
                }
                else if (node is Mix.Tool.Graphics.MeshNode)
                {
                    imageKey = IK_MESH_NODE;
                }
                else if (node is Mix.Tool.Graphics.BoneNode)
                {
                    imageKey = IK_BONE_NODE;
                }
            }
            else if (tag is Mix.Tool.Graphics.MaterialSlot)
            {
                // マテリアルスロット
                Mix.Tool.Graphics.MaterialSlot materialSlot = tag as Mix.Tool.Graphics.MaterialSlot;

                text = materialSlot.Name;
                imageKey = IK_MATERIAL_SLOT;
            }
            else if (tag is Mix.Tool.Graphics.Material)
            {
                // マテリアル
                Mix.Tool.Graphics.Material material = tag as Mix.Tool.Graphics.Material;

                text = material.Name;
                imageKey = (material.IsDefault == true) ? IK_MATERIAL_DEF : IK_MATERIAL;
            }
            else if (tag is Mix.Tool.Dynamics.Design.Actor)
            {
                // キネマティックキャラクター
                text = Properties.Resources.EN_CHARACTER;
                imageKey = IK_KINEMATIC_CHARACTER;
            }
            else if (tag is Mix.Tool.Dynamics.Design.Terrain)
            {
                // リジッドボディ( Terrain )
                text = Properties.Resources.EN_COLLIDER;
                imageKey = IK_COLLIDER;
            }
            else if (tag is Mix.Tool.Dynamics.Design.BasicChild)
            {
                // リジッドボディ( Actor )
                Mix.Tool.Dynamics.Design.BasicChild dynBasicChild = tag as Mix.Tool.Dynamics.Design.BasicChild;

                if (dynBasicChild.Type == Mix.Tool.Dynamics.Design.BasicChildType.Collider)
                {
                    text = dynBasicChild.Name;
                    imageKey = IK_COLLIDER;
                }
                else if (dynBasicChild.Type == Mix.Tool.Dynamics.Design.BasicChildType.Sensor)
                {
                    text = dynBasicChild.Name;
                    imageKey = IK_SENSOR;
                }
                else
                {
                    text = Properties.Resources.EN_UNKNOWN;
                    imageKey = IK_COLLIDER;
                }
            }
            else if (tag is Mix.Tool.Dynamics.Design.Shape)
            {
                // シェイプ
                if (tag is Mix.Tool.Dynamics.Design.BoxShape)
                {
                    text = Properties.Resources.EN_BOX_SHAPE;
                    imageKey = IK_BOX_SHAPE;
                }
                else if (tag is Mix.Tool.Dynamics.Design.CapsuleShape)
                {
                    text = Properties.Resources.EN_CAPSULE_SHAPE;
                    imageKey = IK_CAPSULE_SHAPE;
                }
                else if (tag is Mix.Tool.Dynamics.Design.SphereShape)
                {
                    text = Properties.Resources.EN_SPHERE_SHAPE;
                    imageKey = IK_SPHERE_SHAPE;
                }
                else
                {
                    text = Properties.Resources.EN_UNKNOWN;
                    imageKey = IK_BOX_SHAPE;
                }
            }
            else if (tag is Mix.Tool.Dynamics.Design.Part)
            {
                // ジョイント
                Mix.Tool.Dynamics.Design.Part dynPart = tag as Mix.Tool.Dynamics.Design.Part;

                if (dynPart.Joint != null)
                {
                    Mix.Tool.Dynamics.Joint dynJoint = dynPart.Joint;

                    if (dynJoint is Mix.Tool.Dynamics.PointJoint)
                    {
                        text = Properties.Resources.EN_POINT_JOINT;
                        imageKey = IK_POINT_JOINT;
                    }
                    else if (dynJoint is Mix.Tool.Dynamics.HingeJoint)
                    {
                        text = Properties.Resources.EN_HINGE_JOINT;
                        imageKey = IK_HINGE_JOINT;
                    }
                    else if (dynJoint is Mix.Tool.Dynamics.BallJoint)
                    {
                        text = Properties.Resources.EN_BALL_JOINT;
                        imageKey = IK_BALL_JOINT;
                    }
                    else
                    {
                        text = Properties.Resources.EN_UNKNOWN;
                        imageKey = IK_POINT_JOINT;
                    }
                }
                else
                {
                    text = Properties.Resources.EN_UNKNOWN;
                    imageKey = IK_POINT_JOINT;
                }
            }
            else
            {
                throw new System.Exception("サポートされないアセットを追加しようとしました");
            }

            treeNode.Text = text;
            treeNode.ImageKey = treeNode.SelectedImageKey = imageKey;
            treeNode.Tag = tag;

            if (parentTreeNode != null)
            {
                parentTreeNode.Nodes.Add(treeNode);
            }
            else
            {
                this.tvAsset.Nodes.Add(treeNode);
            }

            return treeNode;
        }

        private void RedrawTreeNodeFromTag(object tag)
        {
            if ((this.tvAsset.Nodes.Count == 0) ||
                (tag == null))
            {
                return;
            }

            this.RedrawTreeNodeFromTag(this.tvAsset.Nodes[0], tag);
        }

        private void RedrawTreeNodeFromTag(TreeNode treeNode, object tag)
        {
            if (treeNode.Tag == tag)
            {
                this.tvAsset.Invalidate(treeNode.Bounds);
                return;
            }

            foreach (TreeNode childTreeNode in treeNode.Nodes)
            {
                this.RedrawTreeNodeFromTag(childTreeNode, tag);
            }
        }

        private void NotifySelectedMaterialChanged(Mix.Tool.Graphics.MaterialSlot materialSlot)
        {
            this.NotifySelectedMaterialChanged(materialSlot, null);
        }

        private void NotifySelectedMaterialChanged(Mix.Tool.Graphics.MaterialSlot materialSlot, Mix.Tool.Graphics.Material material)
        {
            if (materialSlot != null)
            {
                Mix.Tool.Graphics.MaterialSlotCollection materialSlots = this.MaterialSlotCollection;

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // マテリアルスロット
                ////////////////////////////////////////////////////////////////////////////////////////////////////

                if (materialSlots.Selected != materialSlot)
                {
                    Mix.Tool.Graphics.MaterialSlot preMaterialSlot = materialSlots.Selected;

                    materialSlots.Selected = materialSlot;
                    this.RedrawTreeNodeFromTag(preMaterialSlot);
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // マテリアル
                ////////////////////////////////////////////////////////////////////////////////////////////////////

                if (material != null)
                {
                    Mix.Tool.Graphics.Material preMaterial = materialSlot.Materials.ActiveMaterial;

                    materialSlot.Materials.ActiveMaterial = material;
                    this.RedrawTreeNodeFromTag(preMaterial);
                }
                else
                {
                    material = materialSlot.Materials.ActiveMaterial;
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 通知
                ////////////////////////////////////////////////////////////////////////////////////////////////////

                if (this.SelectedMaterialChanged != null)
                {
                    if (material != null)
                    {
                        this.SelectedMaterialChanged(this, new MaterialEventArgs(materialSlot, material));
                    }
                    else
                    {
                        this.SelectedMaterialChanged(this, new MaterialEventArgs(null, null));
                    }
                }
            }
            else
            {
                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 通知
                ////////////////////////////////////////////////////////////////////////////////////////////////////

                if (this.SelectedMaterialChanged != null)
                {
                    this.SelectedMaterialChanged(this, new MaterialEventArgs(null, null));
                }
            }
        }

        private void NotifySelectedKinematicCharacterChanged(Mix.Tool.Dynamics.Design.Actor dynActor)
        {
            if (this.SelectedKinematicCharacterChanged != null)
            {
                this.SelectedKinematicCharacterChanged(this, new KinematicCharacterEventArgs(dynActor));
            }
        }

        private void NotifySelectedTerrainChanged(Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc)
        {
            if (this.SelectedTerrainChanged != null)
            {
                this.SelectedTerrainChanged(this, new TerrainEventArgs(dynDoc));
            }
        }

        private void NotifySelectedTerrainChanged(Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc, bool imported)
        {
            if (this.SelectedTerrainChanged != null)
            {
                this.SelectedTerrainChanged(this, new TerrainEventArgs(dynDoc, imported));
            }
        }

        private void NotifySelectedRigidBodyChanged(Mix.Tool.Dynamics.Design.BasicChild dynBasicChild)
        {
            if (this.SelectedRigidBodyChanged != null)
            {
                this.SelectedRigidBodyChanged(this, new RigidBodyEventArgs(dynBasicChild));
            }
        }

        private void NotifySelectedRigidBodyChanged(Mix.Tool.Dynamics.Design.Basic dynBasic, Mix.Tool.Dynamics.Design.BasicChild dynBasicChild)
        {
            if (this.SelectedRigidBodyChanged != null)
            {
                Mix.Tool.Dynamics.Design.BasicChild preDynBasicChild = dynBasic.Childs.Selected;

                //選択リジッドボディを変更
                dynBasic.Childs.Selected = dynBasicChild;

                //直前まで選択されていたリジッドボディを再描画して、選択状態での描画を解除
                this.RedrawTreeNodeFromTag(preDynBasicChild);

                this.SelectedRigidBodyChanged(this, new RigidBodyEventArgs(dynBasicChild));
            }
        }

        private void NotifySelectedShapeChanged(Mix.Tool.Dynamics.Design.IBasicDocument dynDoc, Mix.Tool.Dynamics.Design.Shape dynShape)
        {
            if (dynDoc == null)
            {
                throw new System.ArgumentNullException("dynDoc");
            }

            //通知
            if (this.SelectedShapeChanged != null)
            {
                this.SelectedShapeChanged(this, new ShapeEventArgs(dynDoc, dynShape));
            }
        }

        private void NotifySelectedShapeChanged(Mix.Tool.Dynamics.Design.IBasicDocument dynDoc, Mix.Tool.Dynamics.Design.BasicChild dynBasicChild, Mix.Tool.Dynamics.Design.Shape dynShape)
        {
            if (dynDoc == null)
            {
                throw new System.ArgumentNullException("dynDoc");
            }

            if (dynBasicChild != null)
            {
                Mix.Tool.Dynamics.Design.Shape preDynShape = dynBasicChild.Shapes.Selected;

                //選択シェイプを変更
                dynBasicChild.Shapes.Selected = dynShape;

                //直前まで選択されていたシェイプを再描画して、選択状態での描画を解除
                this.RedrawTreeNodeFromTag(preDynShape);
            }

            //通知
            if (this.SelectedShapeChanged != null)
            {
                this.SelectedShapeChanged(this, new ShapeEventArgs(dynDoc, dynShape));
            }
        }

        private void NotifySelectedJointChanged(Mix.Tool.Dynamics.Design.Part dynPart)
        {
            if (this.SelectedJointChanged != null)
            {
                this.SelectedJointChanged(this, new JointEventArgs(dynPart));
            }
        }

        private void MapCollision_ImportFinished(object sender, System.EventArgs e)
        {
            if (this.tvAsset.Nodes.Count > 0)
            {
                TreeNode rootTreeNode = this.tvAsset.Nodes[0];

                if (rootTreeNode.Tag is Mix.Tool.Dynamics.Design.ITerrainDocument)
                {
                    Mix.Tool.Dynamics.Design.ITerrainDocument dynDoc = rootTreeNode.Tag as Mix.Tool.Dynamics.Design.ITerrainDocument;

                    if (dynDoc.DynamicsDesigner.Status == Mix.Tool.Dynamics.Design.TerrainStatus.Available)
                    {
                        //インポートに成功してたらツリーノードを追加
                        this.tvAsset.SelectedNode = this.AddTreeNode(rootTreeNode, dynDoc.DynamicsDesigner);
                    }
                }
            }
        }

        #endregion
    }
}
