天天看點

Actor.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using Sharp3D.Math.Core;

using Sharp3D.Math.Geometry3D;

using System.IO;

using System.Xml;

using System.Xml.Serialization;

using HelpTools;

namespace Editor

{

    public class IFile

    {

    }

    // 全局唯一值,用來記錄其他物品

    public struct GIID

    {

        public GIID(int id, GIIDMng giidmng)

        {

            m_id = id;

            m_giid_mng = giidmng;

        }

        public GIID(int id) { m_id = id; m_giid_mng = null; }

        // 獲得唯一值

        public int value { get { return m_id; } }

        // 所記錄的唯一值

        int m_id;

        public override int GetHashCode()

        {

            return base.GetHashCode();

        }

        public override bool Equals(object obj)

        {

            if (obj is GIID)

            {

                return this.m_id == ((GIID)obj).m_id;

            }

            return false;

        }

        // 所記錄的唯一值

        public static bool operator ==(GIID giid1, GIID giid2)

        {

            return giid1.m_id == giid2.m_id;

        }

        public static bool operator !=(GIID giid1, GIID giid2)

        {

            return !(giid1 == giid2);

        }

        public override string ToString()

        {

            return m_giid_mng.getIDString(this);

        }

        public void Parse(string id_string)

        {

            m_giid_mng.setIDString(this, id_string);

        }

        GIIDMng m_giid_mng;

    }

    // 全局唯一值管理器

    // 沒有完成

    public class GIIDMng

    {

        public GIIDMng()

        {

        }

        // 生成一個全局唯一值

        public GIID getGIID()

        {

            GIID giid = new GIID(m_id_acc++, this);

            m_map[giid] = Guid.NewGuid().ToString();

            return giid;

        }

        public bool getGIID(string id_string, out GIID giid)

        {

            foreach (KeyValuePair<GIID, string> pair in m_map)

            {

                if (pair.Value == id_string)

                {

                    giid = pair.Key;

                    return true;

                }

            }

            giid = new GIID();

            return false;

        }

        public void setIDString(GIID id, string id_string)

        {

            m_map[id] = id_string;

        }

        public string getIDString(GIID id)

        {

            return m_map[id];

        }

        // 删除一個全局唯一值

        public void removeGIID(GIID id)

        {

            if (m_map.ContainsKey(id))

            {

                m_map.Remove(id);

            }

        }

        public void Clear()

        {

            m_map.Clear();

            //m_id_acc = 0;

        }

        int m_id_acc = 0;

        Dictionary<GIID, string> m_map = new Dictionary<GIID, string>();

        // 地圖編輯器社群使用,其他慎用!

        public void SetNextGiid(int next)

        {

            if (next <= m_id_acc)

                return;

            else

                m_id_acc = next;

        }

    }

    // 物品memento,用物品屬性清單建構

    public class ActorMemento : IMemento

    {

        public Dictionary<String, String> m_property_dic = new Dictionary<string, string>();

    }

    public enum ActorFlag

    {

        UNDELETEABLE = 0x01,  //是否可以删除

        UNEDITABLE = 0x02,    //是否可以編輯

        UNSELECTABLE = 0x04,  //是否可以選擇

        UNMOVEABLE = 0x08,    //是否可以移動

        UNSERIALIZABLE = 0x10,//是否可以序列化

        UNCOPYPASTABLE = 0x20,//是否可以複制粘貼

    }

    public interface ISelectableObject

    {

        // 滑鼠懸浮

        bool mouseHover(Rect<int> rect, IView view);

        // 滑鼠選擇

        bool mouseSelect(Rect<int> rect, IView view);

    }

    public interface ITransformableObject

    {

        // 移動物品

        void move(Vector3F v);

        // 移動到指定位置

        void moveTo(Vector3F pos);

        // 旋轉

        void rotate(Vector3F pos, Vector3F axis, float angle);

        // 縮放

        void scale(Vector3F scale_var);

        // 對齊

        void align(IActor dst_actor, bool x_axis, bool y_axis, bool z_axis);

    }

    //物品類型枚舉,炫舞1編輯器從炫舞2修改而來,遺留了很多無用或者不合适的定義和資料結構,這裡重新定義一個枚舉是為了減少之前的雜亂和引進的錯誤

    public enum ACTOR_TYPE

    {

        AT_DML,

        AT_CHR,

        AT_ACTOR,

        AT_NEWACTOR,

        AT_SPE,

        AT_SOUND,

        AT_AINODE,

        AT_LIGHT,

        AT_GROUP,

        AT_END

    }

    // 物品接口類

    public interface IActor : ISelectableObject, ITransformableObject, IDisposable

    {

        // 複制

        IActor clone(IEditItem edititem);

        // 獲得子物品容器,如果沒有子物品容器傳回null  

        IActorLayerMng getActorBuffer();

        // 2D的矩形位置

        Rect<int> rect { get; set; }

        //scale

        Vector3F Scale { get; }

        // 3D位置矩陣

        Matrix4F locationmat { get; set; }

        // 包圍盒

        AxisAlignedBox aabb { get; set; }

        // 中心

        Vector3F center { get; set; }

        // 是否隐藏

        bool hide { get; set; }

        // 是否當機

        bool freeze { get; set; }

        // 是否顯示名稱

        bool canDisplayName { get; set; }

        // 所屬物品層

        IActorLayerMng parentLayer { get; set; }

        // 父物品

        IActor parent { get; set; }

        // 物品名稱

        string name { get; set; }

        //是否生成陰影

        bool genlightmap { get; set; }

        //是否投射(實時)陰影

        bool castshadow { get; set; }

        //獲得标志

        int flag { get; }

        // 獲得設定memento

        IMemento getMemento(int mode);

        void setMemento(IMemento mem);

        // 更新

        void update(int t);

        void UpdateCpuSkin(float t);

        // 繪制

        void render(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制包圍盒

        void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color);

        // 繪制坐标軸

        void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制圓

        void renderCircles(int t, ClientBridge.ClientRenderSys rendersys);

        // 全局唯一ID,主要用來儲存連結的内容

        GIID giid { get; }

        // 物品移動控制軸對應的ID

        List<GIID> giid_move { get; }

        // 物品旋轉控制圓對應的ID

        List<GIID> giid_rotate { get; }

        // 獲得key/value的清單

        IDictionary<String, String> getPropertyList();

        // 更改key所對應的value

        void notifyPropertyChange(String key, String value);

        // edititem用來獲得可能需要的資訊

        // 讀取/儲存物品資訊到xml節點中

        bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool load, bool clipboard);

        // 讀取/儲存物品資訊到檔案中

        bool serialize(IFile file, IEditItem edititem, bool load);

        // 儲存物品

        bool serialize(BinaryWriter binWriter);

        // 讀取物品

        bool serialize(BinaryReader binReader, IEditItem edititem);

        // 移動物品

        new void move(Vector3F v);

        // 移動到指定位置

        new void moveTo(Vector3F pos);

        // 旋轉

        new void rotate(Vector3F pos, Vector3F axis, float angle);

        // 縮放

        new void scale(Vector3F scale_var);

        void scaleForPar(Vector3F scale_var);

        // 設定物品位置,并更新物品包圍盒

        void updateLocationAABB();

        // 将物品加入到硬體選擇

        void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将線模型加入到硬體選擇

        void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将移動控制軸加入到硬體選擇

        void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys);

        // 将旋轉控制圓加入到硬體選擇

        void pushHardwareSelect_Rotate(ClientBridge.ClientRenderSys rendersys);

        // 得到物品類别字元串

        string getActorTypestr();

        //父物品層Hide操作回調

        void notifyLayerHide(bool isHide);

        //父物品層Freeze操作回調

        void notifyLayerFreeze(bool isFreeze);

        //擷取物體是否可見

        bool isVisible();

        //得到物品類型

        ACTOR_TYPE GetActorType();

        //删除一個模型時,會從管理器中拿走,在從管理器拿走之前做一些必要的重置操作

        //目前用到該地方的是寶寶和坐騎綁定,在釋放坐騎時要将和寶寶的綁定關系重置

        void DoBeforeDel();

    }

    // 物品的實作輔助基類,用來實作若幹預設物品的接口,友善物品接口的實作

    // 實作IActor的類不是必須要繼承這個類!

    public class ActorBase : IXmlSerial

    {

        protected GIID m_giid = new GIID();

        List<GIID> m_move_giid = new List<GIID>();     // 為物品移動控制軸提供六個ID,以控制移動方向

        List<GIID> m_rotate_giid = new List<GIID>();   // 為物品旋轉控制圓提供3個ID,以控制旋轉方向, fixme:目前繞三個軸旋轉

        Rect<int> m_rect = new Rect<int>(); // 2d矩形位置,界面編輯器用

        bool m_hide = false;                // 是否隐藏

        bool m_freeze = false;              // 是否當機

        protected Dictionary<String, String> m_property_dic = new Dictionary<string, string>();  // 屬性清單

        Matrix4F m_locationmat = Matrix4F.Identity;    // 3d位置矩陣

        protected AxisAlignedBox m_aabb = new AxisAlignedBox();  // 包圍盒

        protected Vector3F m_center = new Vector3F();            // 物品中心(移動、旋轉軸),暫時為包圍盒中心,在更新包圍盒的同時更新物品中心

        IActor m_parent = null;                        // 物品屬于哪個父物品(Group、Prefeb)

        public virtual IActorLayerMng getActorBuffer() { return null; }

        public virtual ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_END;

        }

        public virtual void DoBeforeDel()

        {

        }

        public ActorBase()

        {

        }

        virtual public Rect<int> rect

        {

            get { return m_rect; }

            set { m_rect = value; }

        }

        virtual public int flag

        {

            get { return 0; }

        }

        virtual public bool hide

        {

            get { return m_hide; }

            set

            {

                m_hide = value;

            }

        }

        virtual public bool freeze

        {

            get { return m_freeze; }

            set

            {

                m_freeze = value;

            }

        }

        virtual public IActor parent

        {

            get { return m_parent; }

            set { m_parent = value; }

        }

        /// <summary>

        /// 物品所屬的層

        /// </summary>

        [XmlIgnore]

        virtual public IActorLayerMng parentLayer

        {

            get { return m_parent_layer; }

            set { m_parent_layer = value; }

        }

        IActorLayerMng m_parent_layer = null;

        protected QuaternionF m_quat = QuaternionF.Identity;

        virtual public string name

        {

            get { return ""; }

            set { AssertUtil.confirm(this is PrefebActor); }

        }

        /// <summary>

        /// 是否顯示名稱

        /// </summary>

        virtual public bool canDisplayName

        {

            get { return m_canDisplayName; }

            set { m_canDisplayName = value; }

        }

        bool m_canDisplayName = true;

        virtual public Matrix4F locationmat

        {

            get { return m_locationmat; }

            set

            {

                m_locationmat = value;

                updateLocationAABB();

            }

        }

        virtual public Vector3F Scale

        {

            get

            {

                return m_scale;

            }

        }

        protected Vector3F m_scale = new Vector3F(1, 1, 1);

        // 獲得物品Memento

        virtual public IMemento getMemento(int mode)

        {

            ActorMemento mem = new ActorMemento();

            foreach (KeyValuePair<string, string> kv in m_property_dic)

            {

                mem.m_property_dic.Add(kv.Key, kv.Value);

            }

            return mem;

        }

        // 設定物品Memento

        virtual public void setMemento(IMemento mem)

        {

            ActorMemento actormem = (ActorMemento)mem;

            foreach (KeyValuePair<string, string> kv in actormem.m_property_dic)

            {

                notifyPropertyChange(kv.Key, kv.Value);

            }

        }

        // 移動物品

        virtual public void move(Vector3F v)

        {

            //             // 移動Group中的子物品

            //             IActorLayerMng sublayer = getActorBuffer();

            //             if (sublayer != null)

            //             {

            //                 foreach (IActor actor in sublayer.getOrgBuffer())

            //                 {

            //                     actor.move(v);

            //                 }

            //             }

            //             else  // 非Group物品

            //             {

            //                 Matrix4F matrixmove = TransformationF.Translation(v);

            //                 notifyPropertyChange("LocationMat", (matrixmove * locationmat).ToString());

            //             }

            // 移動Group中的子物品

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

                    actor.move(v);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(v);

            notifyPropertyChange("LocationMat", (matrixmove * locationmat).ToString());

        }

        virtual public void Attach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void Detach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

        }

        // 将物品移動到某位置

        virtual public void moveTo(Vector3F pos)

        {

            //             // 移動Group中的子物品到某位置

            //             IActorLayerMng sublayer = getActorBuffer();

            //             if (sublayer != null)

            //             {

            //                 foreach (IActor actor in sublayer.getOrgBuffer())

            //                 {

            //                     //Vector3F minpos = GActorHelper.getMinPos(sublayer.getOrgBuffer());

            //                     //Vector3F possub = new Vector3F(pos.X + (actor.aabb.Min.X - minpos.X),

            //                     //                               pos.Y + (actor.aabb.Min.Y - minpos.Y),

            //                     //                               pos.Z + (actor.aabb.Min.Z - minpos.Z));

            //

            //                     Vector3F possub = new Vector3F(pos.X + (actor.locationmat.M14 - locationmat.M14),

            //                                                    pos.Y + (actor.locationmat.M24 - locationmat.M24),

            //                                                    pos.Z + (actor.locationmat.M34 - locationmat.M34));

            //                     actor.moveTo(possub);

            //                 }

            //             }

            //             //else  // fixme:

            //             {

            //                 Matrix4F matrixmove = TransformationF.Translation(pos);

            //                 notifyPropertyChange("LocationMat", (matrixmove * Matrix4F.Identity).ToString());

            //             }

            // 移動Group中的子物品到某位置

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

                    //Vector3F minpos = GActorHelper.getMinPos(sublayer.getOrgBuffer());

                    //Vector3F possub = new Vector3F(pos.X + (actor.aabb.Min.X - minpos.X),

                    //                               pos.Y + (actor.aabb.Min.Y - minpos.Y),

                    //                               pos.Z + (actor.aabb.Min.Z - minpos.Z));

                    Vector3F possub = new Vector3F(pos.X + (actor.locationmat.M14 - locationmat.M14),

                                                   pos.Y + (actor.locationmat.M24 - locationmat.M24),

                                                   pos.Z + (actor.locationmat.M34 - locationmat.M34));

                    actor.moveTo(possub);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(pos);

            Matrix4F locatmat = new Matrix4F(locationmat);

            locatmat.M14 = 0;

            locatmat.M24 = 0;

            locatmat.M34 = 0;

            notifyPropertyChange("LocationMat", (matrixmove * locatmat).ToString());

        }

        virtual protected bool CanTransform()

        {

            return true;

        }

        public virtual void UpdateCpuSkin(float t)

        {

        }

        virtual public void align(IActor dst_actor, bool x_axis, bool y_axis, bool z_axis)

        {

            if (CanTransform() && dst_actor != null)

            {

                Vector3F pos = new Vector3F((x_axis ? dst_actor.locationmat.M14 : locationmat.M14), (y_axis ? dst_actor.locationmat.M24 : locationmat.M24), (z_axis ? dst_actor.locationmat.M34 : locationmat.M34));

                moveTo(pos);

            }

        }

        private void set_world_location(Vector3F wloc)

        {

            Matrix4F matrixmove = TransformationF.Translation(wloc);

            Matrix4F locatmat = new Matrix4F(locationmat);

            locatmat.M14 = 0;

            locatmat.M24 = 0;

            locatmat.M34 = 0;

            notifyPropertyChange("LocationMat", (matrixmove * locatmat).ToString());

        }

        // 旋轉物品

        virtual public void rotate(Vector3F pos, Vector3F axis, float angle)

        {

            axis.Normalize();

            QuaternionF quat = QuaternionF.FromAxisAngle(axis, angle);

            m_quat = quat * m_quat;

            m_quat.Normalize();

            // Group

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

                    Vector3F rotatecenter = pos;

                    GroupActor groupactor = actor.parent as GroupActor;

                    if (groupactor != null && groupactor.rotatemode == RotateMode.RM_SELF) // Group内物品繞自身軸旋轉

                    {

                        rotatecenter = actor.center;

                    }

                    actor.rotate(rotatecenter, axis, angle);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(-pos);

            Matrix4F matrixrotate = TransformationF.RotationAxis(axis, angle);

            Matrix4F matrixmoveback = TransformationF.Translation(pos);

            notifyPropertyChange("LocationMat", (matrixmoveback * matrixrotate * matrixmove * locationmat).ToString());

            Vector3F euler = Tool.QuaternionToEulerXYZ(m_quat);

            m_euler.X = Tool.Rad2Deg(euler.X);

            m_euler.Y = Tool.Rad2Deg(euler.Y);

            m_euler.Z = Tool.Rad2Deg(euler.Z);

            notifyPropertyChange("旋轉角度", m_euler.ToString());

            return;

        }

        // 縮放

        private void scale(float x, float y, float z)

        {

            Vector3F center = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

            Matrix4F matrixmove = TransformationF.Translation(-center);

            Matrix4F matrixscale = TransformationF.Scaling(x, y, z);

            Matrix4F matrixmoveback = TransformationF.Translation(center);

            notifyPropertyChange("LocationMat", (matrixmoveback * matrixscale * matrixmove * locationmat).ToString());

        }

        // 縮放

        virtual public void scaleForPar(Vector3F scale_var)

        {

            if (CanTransform())

            {

                Vector3F new_scale = new Vector3F(scale_var.X * m_scale.X, scale_var.Y * m_scale.Y, scale_var.Z * m_scale.Z);

                notifyPropertyChange("縮放比例", new_scale.ToString());

            }

        }

        virtual public void scale(Vector3F scale_var)

        {

            m_scale = new Vector3F(scale_var.X * m_scale.X, scale_var.Y * m_scale.Y, scale_var.Z * m_scale.Z);

            Vector3F center = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

            Matrix4F matrixmove = TransformationF.Translation(-center);

            Matrix4F matrixscale = TransformationF.Scaling(scale_var.X, scale_var.Y, scale_var.Z);

            Matrix4F matrixmoveback = TransformationF.Translation(center);

            notifyPropertyChange("縮放比例", (matrixmoveback * matrixscale * matrixmove * locationmat).ToString());

        }

        private void rotate(Vector3F euler)

        {

            Vector3F r_euler = new Vector3F(Tool.Deg2Rad(euler.X), Tool.Deg2Rad(euler.Y), Tool.Deg2Rad(euler.Z));

            m_quat = Tool.EulerXYZToQuaternion(r_euler);

            m_quat.Normalize();

            Matrix4F matrixscale = TransformationF.Scaling(m_scale);

            Matrix4F matrixrotate = QuaternionF.QuaternionToMatrix(m_quat);

            Matrix4F matrixmoveback = TransformationF.Translation(new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34));

            notifyPropertyChange("LocationMat", (matrixmoveback * matrixscale * matrixrotate).ToString());

        }

        virtual public AxisAlignedBox aabb

        {

            get { return m_aabb; }

            set

            {

                m_aabb = value;

                // 更新物品中心

                //m_center = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

                m_center = new Vector3F((m_aabb.Min.X + m_aabb.Max.X) / 2.0f, (m_aabb.Min.Y + m_aabb.Max.Y) / 2.0f, (m_aabb.Min.Z + m_aabb.Max.Z) / 2.0f);

            }

        }

        virtual public Vector3F center

        {

            get { return m_center; }

            set { m_center = value; }

        }

        virtual public void updateLocationAABB()

        {

            // 所有物品在更新位置時都需要更新其父物品的位置,放到基類

            if (parent != null)

            {

                parent.updateLocationAABB();

            }

        }

        public virtual void update(int t)

        {

        }

        public virtual void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

        }

        // 繪制包圍盒

        public virtual void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            float[] c = { color.r, color.g, color.b, color.a };

            Vector3F[] vetexs = aabb.ComputeVertices();

            float[] points = new float[24];

            for (int i = 0; i < 8; i++)

            {

                points[i * 3] = vetexs[i].X;

                points[i * 3 + 1] = vetexs[i].Y;

                points[i * 3 + 2] = vetexs[i].Z;

            }

            int[] indexs = { 0,1, 1,2, 2,3, 3,0,

                             4,5, 5,6, 6,7, 7,4,

                             0,4, 1,5, 2,6, 3,7

                           };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, c, false);

        }

        // 将移動控制軸加入到硬體選擇

        virtual public void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys)

        {

            GroupActor ga = this as GroupActor;

            if (ga != null && !ga.close)

            {

                ActorBuffer gab = getActorBuffer().getOrgBuffer();

                foreach (IActor gasel in gab)

                {

                    gasel.pushHardwareSelect_Move(rendersys);

                }

            }

            float[] colorr = { 1, 0, 0, 1 };

            float[] colorg = { 0, 1, 0, 1 };

            float[] colorb = { 0, 0, 1, 1 };

            float[] colorw = { 1, 1, 1, 1 };

            float[] points = { center.X, center.Y, center.Z,      // 0 o

                               center.X + 2.0f, center.Y, center.Z,  // 1 x

                               center.X, center.Y + 2.0f, center.Z,  // 2 y

                               center.X, center.Y,center.Z + 2.0f,   // 3 z

                               center.X + 1.0f, center.Y, center.Z,  // 4 x_h

                               center.X, center.Y +1.0f, center.Z,   // 5 y_h

                               center.X, center.Y, center.Z + 1.0f,  // 6 z_h

                               center.X+1.0f, center.Y+1.0f, center.Z,  // 7 x_y

                               center.X+1.0f, center.Y, center.Z + 1.0f,  // 8 x_z

                               center.X, center.Y+1.0f, center.Z + 1.0f   // 9 y_z

                             };

            int[] indexs_x = { 0, 1 };  // x軸索引

            int[] indexs_y = { 0, 2 };  // y軸索引

            int[] indexs_z = { 0, 3 };  // z軸索引

            int[] indexs_xy = { 4, 7, 5 };  // xy夾角索引

            int[] indexs_xz = { 4, 8, 6 };  // xz夾角索引

            int[] indexs_yz = { 5, 9, 6 };  // yz夾角索引

            rendersys.pushSelectID((uint)(m_move_giid[0].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_x, colorr, true);

            rendersys.pushSelectID((uint)(m_move_giid[1].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_y, colorg, true);

            rendersys.pushSelectID((uint)(m_move_giid[2].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_z, colorb, true);

            rendersys.pushSelectID((uint)(m_move_giid[3].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xy, colorw, true);

            rendersys.pushSelectID((uint)(m_move_giid[4].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xz, colorw, true);

            rendersys.pushSelectID((uint)(m_move_giid[5].value));

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_yz, colorw, true);

            return;

        }

        // 繪制移動控制軸

        public virtual void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys)

        {

            float[] colorr = { 1, 0, 0, 1 };

            float[] colorg = { 0, 1, 0, 1 };

            float[] colorb = { 0, 0, 1, 1 };

            float[] colorw = { 1, 1, 1, 1 };

            float[] points = { center.X, center.Y, center.Z,      // 0 o

                               center.X + 2.0f, center.Y, center.Z,  // 1 x

                               center.X, center.Y + 2.0f, center.Z,  // 2 y

                               center.X, center.Y,center.Z + 2.0f,   // 3 z

                               center.X + 1.0f, center.Y, center.Z,  // 4 x_h

                               center.X, center.Y +1.0f, center.Z,   // 5 y_h

                               center.X, center.Y, center.Z + 1.0f,  // 6 z_h

                               center.X+1.0f, center.Y+1.0f, center.Z,  // 7 x_y

                               center.X+1.0f, center.Y, center.Z + 1.0f,  // 8 x_z

                               center.X, center.Y+1.0f, center.Z + 1.0f   // 9 y_z

                             };

            int[] indexs_x = { 0, 1 };  // x軸索引

            int[] indexs_y = { 0, 2 };  // y軸索引

            int[] indexs_z = { 0, 3 };  // z軸索引

            int[] indexs_xy = { 4, 7, 5 };  // xy夾角索引

            int[] indexs_xz = { 4, 8, 6 };  // xz夾角索引

            int[] indexs_yz = { 5, 9, 6 };  // yz夾角索引

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_x, colorr, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_y, colorg, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_z, colorb, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xy, colorw, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xz, colorw, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_yz, colorw, true);

        }

        // 将移動控制軸加入到硬體選擇

        virtual public void pushHardwareSelect_Rotate(ClientBridge.ClientRenderSys rendersys)

        {

            GroupActor ga = this as GroupActor;

            if (ga != null && !ga.close)

            {

                ActorBuffer gab = getActorBuffer().getOrgBuffer();

                foreach (IActor gasel in gab)

                {

                    gasel.pushHardwareSelect_Rotate(rendersys);

                }

            }

            List<uint> idlist = new List<uint>();

            for (int i = 0; i < m_rotate_giid.Count; i++)

            {

                idlist.Add((uint)m_rotate_giid[i].value);

            }

            GActorHelper.drawRotateCircles(idlist, center, rendersys);

            return;

        }

        // 繪制旋轉控制圓

        public virtual void renderCircles(int t, ClientBridge.ClientRenderSys rendersys)

        {

            GActorHelper.drawRotateCircles(null, center, rendersys);

        }

        /// <summary>

        /// Xml序列化使用

        /// </summary>

        public Vector3F Euler

        {

            get { return m_euler; }

        }

        protected Vector3F m_euler = new Vector3F(0, 0, 0);

        public Vector3F Trans

        {

            get { return m_trans; }

        }

        protected Vector3F m_trans = new Vector3F(0, 0, 0);

        /// <summary>

        /// 是否産生實時陰影

        /// </summary>

        virtual public bool castshadow

        {

            get { return m_castshadow; }

            set { m_castshadow = value; }

        }

        bool m_castshadow = true;

        /// <summary>

        /// 是否物體生成陰影

        /// </summary>

        virtual public bool genlightmap

        {

            get { return m_genLightMap; }

            set { m_genLightMap = value; }

        }

        bool m_genLightMap = true;

        public GIID giid

        {

            get { return m_giid; }

            private set { m_giid = value; }

        }

        public List<GIID> giid_move

        {

            get { return m_move_giid; }

        }

        public List<GIID> giid_rotate

        {

            get { return m_rotate_giid; }

        }

        // 得到物品屬性清單

        virtual public IDictionary<String, String> getPropertyList()

        {

            return m_property_dic;

        }

        virtual public void notifyPropertyChange(String key, String value)

        {

            string old_value = m_property_dic.ContainsKey(key) ? m_property_dic[key] : null;

            m_property_dic[key] = value;

            if (key == "LocationMat")

            {

                locationmat = Matrix4F.setMatrix(value);

            }

            else if (key == "Hide")

            {

                hide = bool.Parse(value);

            }

            else if (key == "Freeze")

            {

                freeze = bool.Parse(value);

            }

            else if (key == "産生陰影")

            {

                if (!bool.TryParse(value, out m_genLightMap))

                {

                    return;

                }

            }

            else if (key == "實時陰影")

            {

                if (!bool.TryParse(value, out m_castshadow))

                {

                    return;

                }

            }

            else if (key == "縮放比例")

            {

                Vector3F old_scale, new_scale;

                try

                {

                    old_scale = Vector3F.Parse(old_value);

                    new_scale = Vector3F.Parse(value);

                }

                catch

                {

                    return;

                }

                if (old_scale.X != 0 && old_scale.Y != 0 && old_scale.Z != 0)

                {

                    m_scale = new_scale;

                    scale(new_scale.X / old_scale.X, new_scale.Y / old_scale.Y, new_scale.Z / old_scale.Z);

                }

            }

            else if (key == "世界坐标")

            {

                try

                {

                    m_trans = Vector3F.Parse(value);

                }

                catch (System.Exception)

                {

                    return;

                }

                set_world_location(m_trans);

            }

            else if (key == "旋轉角度")

            {

                Vector3F euler = new Vector3F(0, 0, 0);

                try { euler = Vector3F.Parse(value); }

                catch (System.Exception) { return; }

                if (!Tool.FloatCompare(euler.X, m_euler.X, 0.001f) ||

                    !Tool.FloatCompare(euler.Y, m_euler.Y, 0.001f) ||

                    !Tool.FloatCompare(euler.Z, m_euler.Z, 0.001f))

                {

                    m_euler = euler;

                    rotate(m_euler);

                }

            }

            insertValueToPropertyDic(key, value);

        }

        public virtual void insertValueToPropertyDic(string key, string value)

        {

            m_property_dic[key] = value;

        }

        public ActorBase(GIIDMng giidmng)

        {

            m_giid = giidmng.getGIID();

            for (int i = 0; i < 6; i++)

            {

                m_move_giid.Add(giidmng.getGIID());

            }

            for (int i = 0; i < 3; i++)

            {

                m_rotate_giid.Add(giidmng.getGIID());

            }

            m_property_dic["Hide"] = hide.ToString();

            m_property_dic["Freeze"] = freeze.ToString();

            m_property_dic["産生陰影"] = m_genLightMap.ToString();

            m_property_dic["實時陰影"] = m_castshadow.ToString();

            m_property_dic["縮放比例"] = m_scale.ToString();

            m_property_dic["世界坐标"] = m_trans.ToString();

            m_property_dic["旋轉角度"] = m_euler.ToString();

        }

        public bool serialize(IFile file, IEditItem edititem, bool load)

        {

            return true;

        }

        // 儲存讀取

        public virtual bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool load, bool clipboard)

        {

            if (load)

            {

                foreach (XmlNode childnode in xmlnode.ChildNodes)

                {

                    if (childnode.Name != "Item")

                    {

                        m_property_dic[childnode.Name] = childnode.Value;

                        notifyPropertyChange(childnode.Name, childnode.InnerText);

                    }

                    else

                    { //

                        IActor actor = GActorHelper.generateActorWithoutInfo(childnode.Attributes["type"].Value, edititem);

                        actor.serialize(childnode, edititem, load, clipboard);

                        getActorBuffer().getOrgBuffer().insert(actor);

                    }

                }

            }

            else // save

            {

                foreach (KeyValuePair<string, string> kv in m_property_dic)

                {

                    XmlNode node = xmlnode.OwnerDocument.CreateNode("element", kv.Key, "");

                    node.InnerText = kv.Value;

                    xmlnode.InsertAfter(node, xmlnode.LastChild);

                }

                if (this is GroupActor)

                {

                    foreach (IActor subactor in getActorBuffer().getOrgBuffer())

                    {

                        XmlNode node = xmlnode.OwnerDocument.CreateNode("element", "Item", "");

                        XmlAttribute att = xmlnode.OwnerDocument.CreateAttribute("type");

                        att.Value = GActorHelper.getActorTypestr(subactor);

                        node.Attributes.Append(att);

                        subactor.serialize(node, edititem, load, clipboard);

                        xmlnode.InsertAfter(node, xmlnode.LastChild);

                    }

                }

            }

            return true;

        }

        // 儲存物品

        virtual public bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(hide);

            binWriter.Write(freeze);

            for (int i = 0; i < 16; i++)

            {

                binWriter.Write(locationmat[i]);

            }

            return true;

        }

        // 讀取物品

        virtual public bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            notifyPropertyChange("Hide", binReader.ReadBoolean().ToString());

            notifyPropertyChange("Freeze", binReader.ReadBoolean().ToString());

            float[] locarray = new float[16];

            for (int i = 0; i < 16; i++)

            {

                locarray[i] = binReader.ReadSingle();

            }

            // 恢複儲存到二進制檔案的Prefeb執行個體的位置   

            if (this is PrefebActor)

            {

                Vector3F pos = new Vector3F(locarray[3], locarray[7], locarray[11]);

                Vector3F posold = GActorHelper.getMinPos(getActorBuffer().getOrgBuffer());

                foreach (IActor subactor in getActorBuffer().getOrgBuffer())

                {

                    subactor.move(pos - posold);

                }

            }

            notifyPropertyChange("LocationMat", (new Matrix4F(locarray)).ToString());

            return true;

        }

        virtual public void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            return;

        }

        public virtual void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            return;

        }

        // 擷取物體是否可見

        public virtual bool isVisible()

        {

            return !(hide || BaseCommand.isActorLayerReadOnly(parentLayer, BaseCommand.ACTORLAYER_ITERATE_MODE.HIDE));

        }

        public virtual bool mouseHover(Rect<int> rect, IView view)

        {

            return true;

        }

        public virtual bool mouseSelect(Rect<int> rect, IView view)

        {

            return true;

        }

        // 得到物品類别字元串

        virtual public string getActorTypestr()

        {

            return "Actor";

        }

        //父物品層Hide操作回調

        virtual public void notifyLayerHide(bool isHide)

        {

            if (!hide && getActorBuffer() != null)

                getActorBuffer().notifyLayerHide(isHide);

        }

        //父物品層Freeze操作回調

        virtual public void notifyLayerFreeze(bool isFreeze)

        {

            if (!freeze && getActorBuffer() != null)

                getActorBuffer().notifyLayerFreeze(isFreeze);

        }

        public virtual System.Xml.Schema.XmlSchema GetSchema()

        {

            throw new NotImplementedException();

        }

        public virtual void ReadXmlInner(System.Xml.XmlReader reader)

        {

            this.giid = (GIID)Serializer.ReadXmlObj(reader, "giid");

            this.hide = (bool)Serializer.ReadXmlObj(reader, "hide");

            this.freeze = (bool)Serializer.ReadXmlObj(reader, "freeze");

            SDictionary<string, string> temp

                = (SDictionary<String, String>)Serializer.ReadXmlObj(reader, "m_property_dic");

            this.m_property_dic = SDictionary<string, string>.ToDic(temp);

            this.locationmat = (Matrix4F)Serializer.ReadXmlObj(reader, "locationmat");

            this.aabb = (AxisAlignedBox)Serializer.ReadXmlObj(reader, "aabb");

            this.center = (Vector3F)Serializer.ReadXmlObj(reader, "center");

            this.genlightmap = (bool)Serializer.ReadXmlObj(reader, "genlightmap");

            this.castshadow = (bool)Serializer.ReadXmlObj(reader, "castshadow");

            this.m_scale = (Vector3F)Serializer.ReadXmlObj(reader, "m_scale");

            this.m_trans = (Vector3F)Serializer.ReadXmlObj(reader, "m_trans");

            this.m_euler = (Vector3F)Serializer.ReadXmlObj(reader, "m_euler");

        }

        public virtual void ReadXml(XmlReader reader)

        {

            Serializer.PreReadXmlObj(reader);

            ReadXmlInner(reader);

            Serializer.AfterReadXmlObj(reader);

        }

        public virtual void WriteXml(XmlWriter writer)

        {

            Serializer.WriteXmlObj(writer, this.giid, "giid");

            Serializer.WriteXmlObj(writer, this.hide, "hide");

            Serializer.WriteXmlObj(writer, this.freeze, "freeze");

            SDictionary<string, string> temp = SDictionary<string, string>.ToSDic(m_property_dic);

            Serializer.WriteXmlObj(writer, temp, "m_property_dic");

            Serializer.WriteXmlObj(writer, this.locationmat, "locationmat");

            Serializer.WriteXmlObj(writer, this.aabb, "aabb");

            Serializer.WriteXmlObj(writer, this.center, "center");

            Serializer.WriteXmlObj(writer, this.genlightmap, "genlightmap");

            Serializer.WriteXmlObj(writer, this.castshadow, "castshadow");

            Serializer.WriteXmlObj(writer, this.m_scale, "m_scale");

            Serializer.WriteXmlObj(writer, this.m_trans, "m_trans");

            Serializer.WriteXmlObj(writer, this.m_euler, "m_euler");

        }

    }

    public enum DETAIL_ACTOR_TYPE

    {

        DAT_HUGE_ACTOR,

        DAT_SMALL_ACTOR,

        DAT_DETAIL_VEGETATION,

    }

    // 模型資訊

    public class ModelActorInfo

    {

        public string m_model_name;    // 物品名稱 字首+id

        public string m_resouce_name;  // 資源名成

        public float m_height;         // 距離地面高度

        public bool m_collide;

        public bool m_is_bridge;

        public bool m_visible_ingame;

        public float m_visible_distance; // 可見範圍

        public bool m_far_object; // 遠處的對象

        public bool m_is_tree;

        public bool m_temp_transparent;

        public bool m_reflection;

        public bool m_lightable = false;    //是否接受光斑

        public bool m_use_lightmap = true; //是否應用Lightmap

        //public bool m_selshadow_in_lightmap = false;    //Ligthmap中是否有自陰影

        public string m_lightmap_quality = "普通";  //Lightmap品質

        public DETAIL_ACTOR_TYPE m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR; // 細節物體類型

        public bool m_as_actor; // 是否受角色光

        public ModelActorInfo(Dictionary<string, string> createpropdic, int curindex)

        {

            string nameprefix = "M_" + createpropdic["NamePrefix"];

            m_model_name = nameprefix + "_" + curindex.ToString();

            m_resouce_name = createpropdic["ResName"];

            try

            {

                m_height = float.Parse(createpropdic["Height"]);

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_collide = false;

            m_is_bridge = false;

            m_visible_ingame = true;

            m_far_object = false;

            m_is_tree = false;

            m_temp_transparent = true;

            m_lightable = false;

            m_use_lightmap = true;

            //m_selshadow_in_lightmap = false;

            m_lightmap_quality = "普通";

            m_as_actor = false;

            if (createpropdic.ContainsKey("碰撞物體"))

            {

                m_collide = createpropdic["碰撞物體"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("橋梁物體"))

            {

                m_is_bridge = createpropdic["橋梁物體"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("遊戲中可見"))

            {

                m_visible_ingame = createpropdic["遊戲中可見"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("可視距離"))

            {

                if (!float.TryParse(createpropdic["可視距離"], out m_visible_distance))

                {

                    m_visible_distance = 1000;

                }

            }

            else

            {

                m_visible_distance = 1000;

            }

            if (createpropdic.ContainsKey("遠景"))

            {

                m_far_object = createpropdic["遠景"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("是否是樹"))

            {

                m_is_tree = createpropdic["是否是樹"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("臨時透明"))

            {

                m_temp_transparent = createpropdic["臨時透明"].ToLower() == "true";

            }

            m_reflection = true;

            if (createpropdic.ContainsKey("反射中繪制"))

            {

                bool.TryParse(createpropdic["反射中繪制"], out m_reflection);

            }

            if (createpropdic.ContainsKey("是否接受光斑"))

            {

                m_lightable = createpropdic["是否接受光斑"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("是否應用Lightmap"))

            {

                m_use_lightmap = createpropdic["是否應用Lightmap"].ToLower() == "true";

            }

            //if (createpropdic.ContainsKey("Ligthmap中是否有自陰影"))

            //{

            //    m_selshadow_in_lightmap = createpropdic["Ligthmap中是否有自陰影"].ToLower() == "true";

            //}

            if (createpropdic.ContainsKey("Lightmap品質"))

            {

                m_lightmap_quality = createpropdic["Lightmap品質"];

            }

            if (createpropdic.ContainsKey("細節物體類型"))

            {

                m_dat = (DETAIL_ACTOR_TYPE)Enum.Parse(typeof(DETAIL_ACTOR_TYPE), createpropdic["細節物體類型"], true);

            }

            if (createpropdic.ContainsKey("受角色光"))

            {

                bool.TryParse(createpropdic["受角色光"], out m_as_actor);

            }

        }

        public ModelActorInfo(string modelname, string resname, float height)

        {

            m_model_name = modelname;

            m_resouce_name = resname;

            m_height = height;

        }

        public ModelActorInfo(string modelname, string resname, float height, bool collide, bool is_bridge, bool visible_ingame, float visible_distance, bool far_object, bool is_tree, bool temp_transparent, bool reflection)

        {

            m_model_name = modelname;

            m_resouce_name = resname;

            m_height = height;

            m_collide = collide;

            m_is_bridge = is_bridge;

            m_visible_ingame = visible_ingame;

            m_visible_distance = visible_distance;

            m_far_object = far_object;

            m_is_tree = is_tree;

            m_temp_transparent = temp_transparent;

            m_reflection = reflection;

            m_lightable = false;

            m_use_lightmap = true;

            //m_selshadow_in_lightmap = false;

            m_lightmap_quality = "普通";

            m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR;

            m_as_actor = false;

        }

        // 轉換成屬性清單

        public void toDic(Dictionary<string, string> dic)

        {

            dic["Name"] = m_model_name;

            dic["ResName"] = m_resouce_name;

            dic["Height"] = m_height.ToString();

            dic["碰撞物體"] = m_collide.ToString();

            dic["橋梁物體"] = m_is_bridge.ToString();

            dic["遊戲中可見"] = m_visible_ingame.ToString();

            //dic["可視距離"] = m_visible_distance.ToString();

            dic["遠景"] = m_far_object.ToString();

            dic["是否是樹"] = m_is_tree.ToString();

            dic["臨時透明"] = m_temp_transparent.ToString();

            dic["反射中繪制"] = m_reflection.ToString();

            dic["是否接受光斑"] = m_lightable.ToString();

            dic["是否應用Lightmap"] = m_use_lightmap.ToString();

            //dic["Ligthmap中是否有自陰影"] = m_selshadow_in_lightmap.ToString();

            dic["Lightmap品質"] = m_lightmap_quality;

            dic["受角色光"] = m_as_actor.ToString();

            string dat;

            if (m_dat == DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION)

                dat = "細節植被";

            else if (m_dat == DETAIL_ACTOR_TYPE.DAT_HUGE_ACTOR)

                dat = "大型物體";

            else

                dat = "小型物體";

            dic["細節物體類型"] = dat;

        }

        public ModelActorInfo()

        {

        }

        // 轉換成存儲清單

        public void toDicAll(Dictionary<string, string> dic)

        {

            dic["Name"] = m_model_name;

            dic["ResName"] = m_resouce_name;

            dic["Height"] = m_height.ToString();

            dic["碰撞物體"] = m_collide.ToString();

            dic["橋梁物體"] = m_is_bridge.ToString();

            dic["遊戲中可見"] = m_visible_ingame.ToString();

            dic["可視距離"] = m_visible_distance.ToString();

            dic["遠景"] = m_far_object.ToString();

            dic["是否是樹"] = m_is_tree.ToString();

            dic["臨時透明"] = m_temp_transparent.ToString();

            dic["反射中繪制"] = m_reflection.ToString();

            dic["是否接受光斑"] = m_lightable.ToString();

            dic["是否應用Lightmap"] = m_use_lightmap.ToString();

            //dic["Ligthmap中是否有自陰影"] = m_selshadow_in_lightmap.ToString();

            dic["Lightmap品質"] = m_lightmap_quality;

            dic["細節物體類型"] = m_dat.ToString();

            dic["受角色光"] = m_as_actor.ToString();

        }

        public int getLightmapQualityPower(string value)

        {

            switch (value)

            {

                case "最低":

                    return -2;

                case "低":

                    return -1;

                case "普通":

                    return 0;

                case "高":

                    return 1;

                case "最高":

                    return 2;

                default:

                    return int.MaxValue;

            }

        }

        // 更新屬性值

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_model_name = value;

                    break;

                case "ResName":

                    m_resouce_name = value;

                    break;

                case "Height":

                    try

                    {

                        m_height = float.Parse(value);

                    }

                    catch (Exception)

                    {

                        m_height = 0;

                    }

                    break;

                case "碰撞物體":

                    m_collide = value.ToLower() == "true";

                    break;

                case "橋梁物體":

                    m_is_bridge = value.ToLower() == "true";

                    break;

                case "遊戲中可見":

                    m_visible_ingame = value.ToLower() == "true";

                    break;

                case "可視距離":

                    float.TryParse(value, out m_visible_distance);

                    break;

                case "遠景":

                    m_far_object = value.ToLower() == "true";

                    break;

                case "是否是樹":

                    m_is_tree = value.ToLower() == "true";

                    break;

                case "臨時透明":

                    m_temp_transparent = value.ToLower() == "true";

                    break;

                case "反射中繪制":

                    bool.TryParse(value, out m_reflection);

                    break;

                case "是否接受光斑":

                    m_lightable = value.ToLower() == "true";

                    break;

                case "是否應用Lightmap":

                    m_use_lightmap = value.ToLower() == "true";

                    break;

                //case "Ligthmap中是否有自陰影":

                //    m_selshadow_in_lightmap = value.ToLower() == "true";

                //    break;

                case "Lightmap品質":

                    m_lightmap_quality = value;

                    break;

                case "細節物體類型":

                    if (value == "大型物體" || value == DETAIL_ACTOR_TYPE.DAT_HUGE_ACTOR.ToString())

                        m_dat = DETAIL_ACTOR_TYPE.DAT_HUGE_ACTOR;

                    if (value == "小型物體" || value == DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR.ToString())

                        m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR;

                    if (value == "細節植被" || value == DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION.ToString())

                        m_dat = DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION;

                    break;

                case "受角色光":

                    bool.TryParse(value, out m_as_actor);

                    break;

                default:

                    break;

            }

        }

    }

    // 模型

      public class ModelActor : ResActorBase, IActor

    {

        public ModelActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ClientBridge.ClientRenderSys rendersys, int curindex)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

            m_model = rendersys.createModel(m_actor_info.m_resouce_name);

            if (m_model == null)

            {

                return;

            }

            //m_model.setVisibleDist(visible_distance);

            notifyPropertyChange("實時陰影", "True");

            //notifyPropertyChange("是否是樹", "False");

            //notifyPropertyChange("臨時透明", "True");

            return;

        }

        public ModelActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo();

            if (m_model != null)

                notifyPropertyChange("實時陰影", "True");

            //notifyPropertyChange("是否是樹", "False");

            //notifyPropertyChange("臨時透明", "True");

            //notifyPropertyChange("反射中繪制", "True");

            return;

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_model != null)

            {

                m_model.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_model != null)

            {

                m_model.Detach(scene);

            }

        }

        override public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

            if (m_model != null)

            {

                //m_model.setMaterialLod(lod);

            }

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

                //父層為Hide,隻設定辨別位,否則進行具體Hide操作

                if (m_model != null && !BaseCommand.isActorLayerReadOnly(parentLayer, BaseCommand.ACTORLAYER_ITERATE_MODE.HIDE))

                {

                    //m_model.setVisible(!value);

                }

            }

        }

        public override void notifyLayerFreeze(bool isFreeze)

        {

            //base.notifyLayerFreeze(isFreeze);

        }

        //父物品層設定Hide通知

        public override void notifyLayerHide(bool isHide)

        {

            if (hide)

                return;

            //if(m_model != null)

            //    m_model.setVisible(!isHide);

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_model_name;

            }

            set

            {

                m_actor_info.m_model_name = value;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        public bool collide

        {

            get

            {

                return m_actor_info.m_collide;

            }

        }

        public bool is_bridge

        {

            get

            {

                return m_actor_info.m_is_bridge;

            }

        }

        public bool visible_ingame

        {

            get

            {

                return m_actor_info.m_visible_ingame;

            }

        }

        public float visible_distance

        {

            get

            {

                return m_actor_info.m_visible_distance;

            }

        }

        public bool far_object

        {

            get

            {

                return m_actor_info.m_far_object;

            }

        }

        public bool is_tree

        {

            get

            {

                return m_actor_info.m_is_tree;

            }

        }

        public bool temp_transparent

        {

            get

            {

                return m_actor_info.m_temp_transparent;

            }

        }

        #region about IDisposable

        virtual public void Dispose()

        {

            m_model.release();

        }

        #endregion

        #region about IActor

        // fixme : 各類物品的Clone目前都還沒有實作

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            ModelActor actor = null;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_actor_info.m_model_name);

            binWriter.Write(m_actor_info.m_resouce_name);

            binWriter.Write(m_actor_info.m_height);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            m_actor_info.m_model_name = binReader.ReadString();

            m_actor_info.m_resouce_name = binReader.ReadString();

            m_actor_info.m_height = binReader.ReadSingle();

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

            m_model = root.clientRenderSys.createModel(m_actor_info.m_resouce_name);

            return base.serialize(binReader, edititem);

        }

        public override bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool load, bool clipboard)

        {

            base.serialize(xmlnode, edititem, load, clipboard);

            if (load)

            {

                RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

                m_model = root.clientRenderSys.createModel(m_actor_info.m_resouce_name);

            }

            updateLocationAABB();

            return true;

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

            m_model.render();

        }

        public override void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_model == null)

            {

                return;

            }

            // 設定mat

            List<float> matrix = new List<float>();

            for (int i = 0; i < 16; i++)

            {

                matrix.Add(locationmat[i]);

            }

            m_model.setLocationMatrix(matrix);

            // 修改包圍盒

            List<float> aabblist = new List<float>();

            for (int i = 0; i < 6; i++)

            {

                aabblist.Add(0);

            }

            m_model.getAABB(aabblist);

            aabb = new AxisAlignedBox(new Vector3F(aabblist[0], aabblist[1], aabblist[2]),

                                      new Vector3F(aabblist[3], aabblist[4], aabblist[5]));

            base.updateLocationAABB();

        }

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            rendersys.pushHardwareSelectObject(m_model, (uint)giid.value);

        }

        public override void notifyPropertyChange(String key, String value)

        {

            if (key == "Lightmap品質")

            {

                int cur_p = m_actor_info.getLightmapQualityPower(m_actor_info.m_lightmap_quality);

                int new_p = m_actor_info.getLightmapQualityPower(value);

                if (new_p == int.MaxValue)

                {

                    return;

                }

                //if (!m_model.setLightmapQuality(new_p))

                //{

                //    if (new_p > cur_p)

                //    {

                //        MessageBox.Show("不允許再提升品質");

                //    }

                //    else if (new_p < cur_p)

                //    {

                //        MessageBox.Show("不允許再降低品質");

                //    }

                //    return;

                //}

            }

            if (key != "可視距離")

                base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

            if (m_model != null)

            {

                if (key == "可視距離")

                {

                    //m_model.setVisibleDist(visible_distance);

                }

                else if (key == "實時陰影")

                {

                    //m_model.setCastShadow(base.castshadow);

                }

                else if (key == "反射中繪制")

                {

                    //m_model.setReflection(m_actor_info.m_reflection);

                }

                else if (key == "是否接受光斑")

                {

                    //m_model.setLightable(m_actor_info.m_lightable);

                }

                else if (key == "受角色光")

                {

                    //m_model.asActor(m_actor_info.m_as_actor);

                }

            }

        }

        public override string getActorTypestr()

        {

            return "模型";

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_DML;

        }

        public ModelActorInfo m_actor_info;

        public ClientBridge.Model m_model;

        override public string ResName

        {

            get { return res; }

        }

        override public object getRes()

        {

            return m_model;

        }

        public override void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res)

        {

            if (m_model != null)

            {

                m_model.changeRes(rendersys, new_res);

                m_actor_info.m_resouce_name = new_res;

                updateLocationAABB();

            }

        }

        override public void addRef()

        {

            if (m_model != null)

            {

                m_model.addRef();

            }

        }

        override public int ResRefCount

        {

            get

            {

                if (m_model != null)

                {

                    return m_model.m_ref_count;

                }

                else

                {

                    return 0;

                }

            }

        }

    }

    // 骨骼模型

    public class SkeletonModelActor : ActorBase, IActor

    {

        public SkeletonModelActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ClientBridge.ClientRenderSys rendersys, int curindex)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

            m_model = rendersys.creatSkeletonModel(m_actor_info.m_resouce_name);

            //m_model.setVisibleDist(visible_distance);

            return;

        }

        public SkeletonModelActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo();

            return;

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_CHR;

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_model_name;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        virtual public void Dispose()

        {

            if (m_model != null)

            {

                m_model.release();

            }

        }

        #region about IActor

        // fixme : 各類物品的Clone目前都還沒有實作

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            ModelActor actor = null;

            return actor;

        }

        protected void getSaveProperty(Dictionary<string, string> mPro)

        {

            foreach (KeyValuePair<string, string> kv in base.getPropertyList())

            {

                mPro[kv.Key] = kv.Value;

            }

        }

        public override void update(int t)

        {

            if (hide == false)

            {

                m_model.update(((float)t) / 1.0f);

            }

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            if (!hide)

            {

                m_model.render();

            }

        }

        public override void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public void updateAABB()

        {

            // 修改包圍盒

            List<float> aabblist = new List<float>();

            for (int i = 0; i < 6; i++)

            {

                aabblist.Add(0);

            }

            m_model.getAABB(aabblist);

            aabb = new AxisAlignedBox(new Vector3F(aabblist[0], aabblist[1], aabblist[2]),

                                      new Vector3F(aabblist[3], aabblist[4], aabblist[5]));

        }

        public override void updateLocationAABB()

        {

            if (m_model == null)

            {

                return;

            }

            // 設定mat

            List<float> matrix = new List<float>();

            for (int i = 0; i < 16; i++)

            {

                matrix.Add(locationmat[i]);

            }

            m_model.setLocationMatrix(matrix);

            updateAABB();

        }

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            rendersys.pushHardwareSelectObject(m_model, (uint)giid.value);

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

        }

        public ModelActorInfo m_actor_info;

        public ClientBridge.SkeletonModel m_model;

        public void SetAction(int trackid, string actionname)

        {

            m_model.setAim(trackid, actionname);

        }

        public void SetActionTime(int trackid, float time)

        {

            m_model.SetCurrentActionTime(trackid, time);

        }

        public void PlayAction(int trackid, float time)

        {

            m_model.SetCurrentActionTime(trackid, time);

            //             m_model.update(0);

            //             m_irender.updatePhx((int)(0));//time*1000f

        }

        public void ClearChannelAnim(int id)

        {

            m_model.ClearChannelAnim(0);

        }

        public Vector3F GetPosFromRootBone()

        {

            if (m_model!=null)

            {

                string rootName = m_model.GetRootBoneName();

                int rootID = m_model.GetBoneID(rootName);

                List<float> mat = m_model.GetBoneLocation(rootID);

                return new Vector3F(mat[3],mat[7],mat[11]);

            }

            return new Vector3F(0.0f,0.0f,0.0f);

        }

    }

    // 角色

    public class StageRoleActor : SkeletonModelActor

    {

        public StageRoleActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ClientBridge.ClientRenderSys rendersys, int curindex, bool male)

            : base(giidmng)

        {

            m_crs = rendersys;

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

            m_actor_model = m_crs.creatActorModel("StageRoleActor" + curindex.ToString(), male);

            base.m_model = (ClientBridge.SkeletonModel)m_actor_model;

            notifyPropertyChange("産生陰影", "True");

            notifyPropertyChange("Update", "True");

            return;

        }

        public override void update(int t)

        {

            base.update(t);

            updateAABB();

        }

        public void SetBodyPart(int pos, string bpt_filename)

        {

            m_actor_model.SetBodyPart(pos, bpt_filename);

        }

        public void SetAdornment(ClientBridge.SpecialEffectMng sem, int pos, string lik_filename)

        {

            m_actor_model.SetAdornment(sem, pos, lik_filename);

        }

        public void PostProcessCreating()

        {

            m_actor_model.PostProcessCreating();

        }

        public override int flag

        {

            get { return (int)ActorFlag.UNDELETEABLE | (int)ActorFlag.UNSERIALIZABLE; }

        }

        public override void notifyPropertyChange(string key, string value)

        {

            if (key != "ResName")

            {

                base.notifyPropertyChange(key, value);

            }

        }

        private ClientBridge.ClientRenderSys m_crs;

        private ClientBridge.ActorModel m_actor_model;

    }

    // 特效資訊

    public struct EffectActorInfo

    {

        public string m_effect_name;   // 物品名稱 字首+id

        public string m_resouce_name;

        public float m_visible_distance;

        public float m_height;

        public bool m_reflection;

        public bool m_as_actor;

        public float m_random_offset_min;

        public float m_random_offset_max;

        public EffectActorInfo(Dictionary<string, string> createpropdic, int curindx)

        {

            string nameprefix = "E_" + createpropdic["NamePrefix"];

            m_effect_name = nameprefix + "_" + curindx.ToString();

            m_resouce_name = createpropdic["ResName"];

            if (createpropdic.ContainsKey("可視距離"))

            {

                if (!float.TryParse(createpropdic["可視距離"], out m_visible_distance))

                {

                    m_visible_distance = 1000;

                }

            }

            else

            {

                m_visible_distance = 1000;

            }

            try

            {

                m_height = float.Parse(createpropdic["Height"]);

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_reflection = true;

            if (createpropdic.ContainsKey("反射中繪制"))

            {

                bool.TryParse(createpropdic["反射中繪制"], out m_reflection);

            }

            m_as_actor = false;

            if (createpropdic.ContainsKey("受角色光"))

            {

                bool.TryParse(createpropdic["受角色光"], out m_as_actor);

            }

            try

            {

                m_random_offset_min = float.Parse(createpropdic["随機動畫偏移最小值"]);

                m_random_offset_max = float.Parse(createpropdic["随機動畫偏移最大值"]);

            }

            catch (Exception)

            {

                m_random_offset_min = 0;

                m_random_offset_max = 0;

            }

        }

        public EffectActorInfo(string effectname, string resname, float height)

        {

            m_effect_name = effectname;

            m_resouce_name = resname;

            m_height = height;

            m_visible_distance = 0;

            m_reflection = true;

            m_as_actor = false;

            m_random_offset_min = 0;

            m_random_offset_max = 0;

        }

        public EffectActorInfo(string effectname, string resname, float height, float visible_distance, bool reflection)

        {

            m_effect_name = effectname;

            m_resouce_name = resname;

            m_height = height;

            m_visible_distance = visible_distance;

            m_reflection = reflection;

            m_as_actor = false;

            m_random_offset_min = 0;

            m_random_offset_max = 0;

        }

        public void toDic(Dictionary<string, string> dic)

        {

            dic["Name"] = m_effect_name;

            dic["ResName"] = m_resouce_name;

            dic["Height"] = m_height.ToString();

            dic["反射中繪制"] = m_reflection.ToString();

            dic["受角色光"] = m_as_actor.ToString();

            dic["随機動畫偏移最小值"] = m_random_offset_min.ToString();

            dic["随機動畫偏移最大值"] = m_random_offset_max.ToString();

        }

        public void toDicAll(Dictionary<string, string> dic)

        {

            dic["Name"] = m_effect_name;

            dic["ResName"] = m_resouce_name;

            dic["Height"] = m_height.ToString();

            dic["可視距離"] = m_visible_distance.ToString();

            dic["反射中繪制"] = m_reflection.ToString();

            dic["受角色光"] = m_as_actor.ToString();

            dic["随機動畫偏移最小值"] = m_random_offset_min.ToString();

            dic["随機動畫偏移最大值"] = m_random_offset_max.ToString();

        }

        // 更新屬性值

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_effect_name = value;

                    break;

                case "ResName":

                    m_resouce_name = value;

                    break;

                case "Height":

                    float.TryParse(value, out m_height);

                    break;

                case "可視距離":

                    float.TryParse(value, out m_visible_distance);

                    break;

                case "反射中繪制":

                    bool.TryParse(value, out m_reflection);

                    break;

                case "受角色光":

                    bool.TryParse(value, out m_as_actor);

                    break;

                case "随機動畫偏移最小值":

                    float.TryParse(value, out m_random_offset_min);

                    break;

                case "随機動畫偏移最大值":

                    float.TryParse(value, out m_random_offset_max);

                    break;

                default:

                    break;

            }

        }

    }

    // 特效

    public class EffectActor : ResActorBase, IActor

    {

        public EffectActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ClientBridge.ClientRenderSys rendersys, int curindex)

            : base(giidmng)

        {

            m_actor_info = new EffectActorInfo(createpropdic, curindex);

            m_effect = rendersys.getSpecialEffectMng().loadEffect(m_actor_info.m_resouce_name);

            m_effect.play();

        }

        public EffectActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new EffectActorInfo();

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_effect != null)

            {

                m_effect.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_effect != null)

            {

                m_effect.Detach(scene);

            }

        }

        override public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

            if (m_effect != null)

            {

                //m_effect.setMaterialLod(lod);

            }

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_SPE;

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

                //若父層為Hide,則隻改變辨別位,不進行具體操作

                if (m_effect != null && !BaseCommand.isActorLayerReadOnly(parentLayer, BaseCommand.ACTORLAYER_ITERATE_MODE.HIDE))

                {

                    m_effect.setVisible(!value);

                }

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_effect_name;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        public float visible_distance

        {

            get

            {

                return m_actor_info.m_visible_distance;

            }

        }

        public override AxisAlignedBox aabb

        {

            get { return base.aabb; }

            set

            {

                m_aabb = value;

                if (parentLayer != null && this is IActor)

                {

                    parentLayer.OnActorAABBChanged((IActor)this, m_render_aabb);

                }

                // 更新物品中心

                m_center = new Vector3F((m_aabb.Min.X + m_aabb.Max.X) / 2.0f, (m_aabb.Min.Y + m_aabb.Max.Y) / 2.0f, (m_aabb.Min.Z + m_aabb.Max.Z) / 2.0f);

            }

        }

        #region about IDisposable

        public void Dispose()

        {

            //m_effect.release();  // 有問題?

        }

        #endregion

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            EffectActor actor = null;

            return actor;

        }

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_effect == null)

            {

                return;

            }

            List<float> matrix = new List<float>();

            for (int i = 0; i < 16; i++)

            {

                matrix.Add(locationmat[i]);

            }

            m_effect.setLocationMatrix(matrix);

            //m_model.setLocationMatrix(matrix);

            // 修改包圍盒

            List<float> aabblist = new List<float>();

            for (int i = 0; i < 6; i++)

            {

                aabblist.Add(0);

            }

            m_effect.getAABB(aabblist);

            m_render_aabb = new AxisAlignedBox(new Vector3F(aabblist[0], aabblist[1], aabblist[2]),

                                      new Vector3F(aabblist[3], aabblist[4], aabblist[5]));

            Vector3F trans = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

            aabb = new AxisAlignedBox(s_min + trans, s_max + trans);

            base.updateLocationAABB();

            m_pos = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

            Vector4F nor = new Vector4F(0, 0, -1, 0);

            nor = locationmat * nor;

            m_nor = new Vector3F(nor.X, nor.Y, nor.Z);

        }

        //         public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        //         {

        //

        //         }

        public override void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            rendersys.pushSelectID((uint)giid.value);

            rendersel(0, rendersys);

        }

        public override void notifyPropertyChange(String key, String value)

        {

            float min = m_actor_info.m_random_offset_min;

            float max = m_actor_info.m_random_offset_max;

            bool offsetChanged = false;

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

            if (m_effect != null)

            {

                if (key == "實時陰影")

                {

                    //m_effect.setCastShadow(base.castshadow);

                }

                else if (key == "反射中繪制")

                {

                    //m_effect.setReflection(m_actor_info.m_reflection);

                }

                else if (key == "受角色光")

                {

                    //m_effect.asActor(m_actor_info.m_as_actor);

                }

                else if (key == "随機動畫偏移最小值")

                {

                    if (m_actor_info.m_random_offset_min < 0)

                        m_actor_info.m_random_offset_min = 0;

                    if (m_actor_info.m_random_offset_min > m_actor_info.m_random_offset_max)

                    {

                        m_actor_info.m_random_offset_max = m_actor_info.m_random_offset_min;

                        base.notifyPropertyChange("随機動畫偏移最大值", m_actor_info.m_random_offset_max.ToString());

                    }

                    offsetChanged = min != m_actor_info.m_random_offset_min;

                }

                else if (key == "随機動畫偏移最大值")

                {

                    if (m_actor_info.m_random_offset_max < 0)

                        m_actor_info.m_random_offset_max = 0;

                    if (m_actor_info.m_random_offset_max < m_actor_info.m_random_offset_min)

                    {

                        m_actor_info.m_random_offset_min = m_actor_info.m_random_offset_max;

                        base.notifyPropertyChange("随機動畫偏移最小值", m_actor_info.m_random_offset_min.ToString());

                    }

                    offsetChanged = max != m_actor_info.m_random_offset_max;

                }

                if (offsetChanged)

                    setRandomOffsetPlay();

            }

        }

        //設定随機動畫偏移

        private void setRandomOffsetPlay()

        {

            Random ran = new Random(unchecked((int)DateTime.Now.Ticks));

            float seed = (float)ran.NextDouble();

            float result = (m_actor_info.m_random_offset_max - m_actor_info.m_random_offset_min) * seed + m_actor_info.m_random_offset_min;

            m_effect.update(result, false);

        }

        //通知父層設定了Hide狀态

        public override void notifyLayerHide(bool isHide)

        {

            if (hide)

                return;

            if (m_effect != null)

                m_effect.setVisible(!isHide);

        }

        //通知父層設定了Freeze狀态

        public override void notifyLayerFreeze(bool isFreeze)

        {

            //base.notifyLayerFreeze(isFreeze);

        }

        public override string getActorTypestr()

        {

            return "特效";

        }

        //public IMemento getMemento(int mode)

        //{

        //    return null;

        //}

        //public void setMemento(IMemento mem)

        //{

        //}

        public override void update(int t)

        {

            if (m_effect == null)

            {

                return;

            }

            m_effect.update(t);

            updateLocationAABB();

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_actor_info.m_effect_name);

            binWriter.Write(m_actor_info.m_resouce_name);

            binWriter.Write(m_actor_info.m_height);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            m_actor_info.m_effect_name = binReader.ReadString();

            m_actor_info.m_resouce_name = binReader.ReadString();

            m_actor_info.m_height = binReader.ReadSingle();

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

            m_effect = root.clientRenderSys.getSpecialEffectMng().loadEffect(m_actor_info.m_resouce_name);

            m_effect.play();

            return base.serialize(binReader, edititem); ;

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

            if (m_effect == null)

                return;

            m_effect.render();

        }

        public void drawRenderLine(int t, ClientBridge.ClientRenderSys rendersys)

        {

            float[] cy = { 1, 1, 0, 1 };

            RenderHelper.RenderConic(0, m_pos, m_nor, 45, 10, cy, rendersys);

        }

        public void rendersel(int t, ClientBridge.ClientRenderSys rendersys)

        {

            drawRenderLine(t, rendersys);

        }

        public override void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public ClientBridge.SpecialEffect m_effect;

        EffectActorInfo m_actor_info;

        AxisAlignedBox m_render_aabb;

        static Vector3F s_min = new Vector3F(-25, -25, -25);

        static Vector3F s_max = new Vector3F(25, 25, 25);

        Vector3F m_pos = new Vector3F(0, 0, 0);

        Vector3F m_nor = new Vector3F(0, 0, -1);

        override public string ResName

        {

            get { return res; }

        }

        override public object getRes()

        {

            return m_effect;

        }

        override public void reload()

        {

            m_effect.reload();

        }

        public override void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res)

        {

            if (m_effect != null)

            {

                m_effect.changeRes(rendersys, new_res);

                m_actor_info.m_resouce_name = new_res;

                updateLocationAABB();

            }

        }

        override public void addRef()

        {

            if (m_effect != null)

            {

                m_effect.addRef();

            }

        }

        override public int ResRefCount

        {

            get

            {

                if (m_effect != null)

                {

                    return m_effect.m_ref_count;

                }

                else

                {

                    return 0;

                }

            }

        }

    }

    // 聲音

    public class SoundActor : ActorBase, IActor

    {

        public SoundActor(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        public void Dispose()

        {

            //

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_SOUND;

        }

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            SoundActor actor = new SoundActor(root.giidmng);

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

        }

        #endregion

    }

    // AI節點

    public class AINodeActor : ActorBase, IActor

    {

        public AINodeActor(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_AINODE;

        }

        #region about IDisposable

        public void Dispose()

        {

            //

        }

        #endregion

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            AINodeActor actor = new AINodeActor(root.giidmng);

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

        }

        #endregion

    }

    public enum LightShape

    {

        CIRCLE = 0,

        RECT = 1

    }

    // 燈光資訊

    public struct LightInfo

    {

        LightInfo(string type)

        {

            m_type = type;

            m_spe_color = new Color();

            m_dif_color = new Color();

            m_amb_color = new Color();

        }

        LightInfo(string type, Color difcolor, Color speccolor, Color ambcolor)

        {

            m_type = type;

            m_dif_color = difcolor;

            m_spe_color = speccolor;

            m_amb_color = ambcolor;

        }

        public string m_type;

        public Color m_dif_color;

        public Color m_spe_color;

        public Color m_amb_color;

    }

    // 區域燈光

    public class LightActor : ActorBase, IActor

    {

        public LightActor(GIIDMng giidmng, LightInfo lightinfo, ClientBridge.ClientRenderSys rendersys)

            : base(giidmng)

        {

            m_light_info = lightinfo;

            m_light = rendersys.createLight(lightinfo.m_type);

        }

        public LightActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_light_info = new LightInfo();

        }

        public override  ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_LIGHT;

        }

        public void Dispose()

        {

            //

        }

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            LightActor actor = new LightActor(root.giidmng, m_light_info, root.clientRenderSys);

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_light != null)

            {

                //m_light.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_light != null)

            {

                //m_light.Detach(scene);

            }

        }

        ClientBridge.Light m_light;

        LightInfo m_light_info;

    }

    //操作方式

    public enum ActorActionState

    {

        SELECT,

        MOVE,

        ROTATE,

        DRAG,

        RESIZE,

    }

    // 移動方向

    public enum MoveDirection

    {

        MD_NONE = 0, // 不移動

        MD_X = 0x01 << 0,    // 沿X軸移動

        MD_Y = 0x01 << 1,    // 沿Y軸移動

        MD_Z = 0x01 << 2,    // 沿Z軸移動

        MD_XY = MD_X | MD_Y,   // 在XY平面移動

        MD_XZ = MD_X | MD_Z,   // 在XZ平面移動

        MD_YZ = MD_Y | MD_Z,    // 在YZ平面移動

    }

    // 旋轉軸

    public enum RotateDirection

    {

        RD_NONE, // 不旋轉

        RD_X,    // 沿X軸旋轉

        RD_Y,    // 沿Y軸旋轉

        RD_Z     // 沿Z軸旋轉

    }

    // 旋轉方式

    public enum RotateMode

    {

        RM_WHOLE,  // 繞同一個軸

        RM_SELF,   // 繞自身軸

        RM_BOTH    // fixme:

    }

    public enum ResizeDirection

    {

        RD_NONE = 0, // 不移動

        RD_X = 0x01 << 0,    // 沿X軸移動

        RD_Y = 0x01 << 1,    // 沿Y軸移動

        RD_Z = 0x01 << 2,    // 沿Z軸移動

        RD_XY = RD_X | RD_Y,   // 在XY平面移動

        RD_XZ = RD_X | RD_Z,   // 在XZ平面移動

        RD_YZ = RD_Y | RD_Z,

        RD_XYZ = RD_X | RD_Y | RD_Z

    }

    public class RenderHelper

    {

        public static float stdDist = 50.0f;

        public static float GetFakeLength(Vector3F center, float reallength, float fstdDist, IView view)

        {

            Vector3F ca_pos = view.getCamera().getCameraPosition();

            float dis = ComputeDisBetweenTwoPoint(center, ca_pos);

            reallength *= dis / fstdDist;

            return reallength;

        }

        public static void drawCircle(Vector3F center, Vector3F normal, float radius, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            normal.Normalize();

            // 用360個點的連線模拟圓

            int pointcount = 360;

            float[] points = new float[pointcount * 3];

            //int[] indexs = new int[pointcount*3 + 1];

            int[] indexs = new int[pointcount + 1];

            for (int t = 0; t < pointcount; t++)

            {

                float factor = 0;

                Vector3F u = new Vector3F();

                if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

                Vector3F v = Vector3F.CrossProduct(normal, u);

                v.Normalize();

                points[t * 3] = (float)(center.X + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.X);

                points[t * 3 + 1] = (float)(center.Y + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Y);

                points[t * 3 + 2] = (float)(center.Z + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Z);

                indexs[t] = t;

            }

            indexs[pointcount] = 0;

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs, color, true);

        }

        public static void drawRotateCircles(Vector3F center, IView view, float[] circlexy, float[] circleyz, float[] circlexz, bool hardsel)

        {

            drawRotateCircles(center, view, circlexy, circleyz, circlexz, hardsel, Matrix3F.Identity);

        }

        public static void drawRotateCircles(Vector3F center, IView view, float[] circlexy, float[] circleyz, float[] circlexz, bool hardsel, Matrix3F rotmat)

        {

            drawRotateCircles(center, view, 10.0f, circlexy, circleyz, circlexz, hardsel, rotmat);

        }

         public static void DrawMoustSelectRect(int x1, int y1, int x2, int y2, IView view)

        {

            Vector3F p1 = view.getCamera().GetScreenXYZ(x1, y1, view.getRenderSys());

            Vector3F p2 = view.getCamera().GetScreenXYZ(x2, y2, view.getRenderSys());

            Vector3F p3 = view.getCamera().GetScreenXYZ(x1, y2, view.getRenderSys());

            Vector3F p4 = view.getCamera().GetScreenXYZ(x2, y1, view.getRenderSys());

            Vector3F p_p1 = new Vector3F(p1.X - view.getCamera().position.x, p1.Y - view.getCamera().position.y, p1.Z - view.getCamera().position.z);

            Vector3F p_p2 = new Vector3F(p2.X - view.getCamera().position.x, p2.Y - view.getCamera().position.y, p2.Z - view.getCamera().position.z);

            Vector3F p_p3 = new Vector3F(p3.X - view.getCamera().position.x, p3.Y - view.getCamera().position.y, p3.Z - view.getCamera().position.z);

            Vector3F p_p4 = new Vector3F(p4.X - view.getCamera().position.x, p4.Y - view.getCamera().position.y, p4.Z - view.getCamera().position.z);

            float e = 0.01f;

            float[] color = { 1, 1, 1, 1 };

            p_p1.Normalize();

            p_p2.Normalize();

            p_p3.Normalize();

            p_p4.Normalize();

            p1 += p_p1 * e;

            p2 += p_p2 * e;

            p3 += p_p3 * e;

            p4 += p_p4 * e;

            float[] points = { p1.X, p1.Y, p1.Z, p3.X, p3.Y, p3.Z, p2.X, p2.Y, p2.Z, p4.X, p4.Y, p4.Z, };

            view.getRenderSys().drawMouseSelectRect(points, color);

        }

        public static void drawRotateCircles(Vector3F center, IView view, float coord_length, float[] circlexy, float[] circleyz, float[] circlexz, bool hardsel, Matrix3F rotmat)

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

            length = GetFakeLength(center, length, stdDist, view);

            Vector3F coord_x = Matrix3F.Transform(rotmat, new Vector3F(1, 0, 0));

            Vector3F coord_y = Matrix3F.Transform(rotmat, new Vector3F(0, 1, 0));

            Vector3F coord_z = Matrix3F.Transform(rotmat, new Vector3F(0, 0, 1));

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

            drawCircle(center, coord_x, length, circleyz, rendersys);  // 繪制垂直于x軸的圓

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

            drawCircle(center, coord_y, length, circlexz, rendersys);  // 繪制垂直于y軸的圓

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

            drawCircle(center, coord_z, length, circlexy, rendersys);  // 繪制垂直于z軸的圓

            coord_x = length * coord_x + center;

            coord_y = length * coord_y + center;

            coord_z = length * coord_z + center;

            float[] points = { center.X, center.Y, center.Z,      // 0 o

                               coord_x.X,  coord_x.Y, coord_x.Z,  // 1 x

                               coord_y.X,  coord_y.Y, coord_y.Z,  // 2 y

                               coord_z.X,  coord_z.Y, coord_z.Z,   // 3 z

                             };

            int[] indexsx = { 0, 1 };

            int[] indexsy = { 0, 2 };

            int[] indexsz = { 0, 3 };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsx, circleyz, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsy, circlexz, true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsz, circlexy, true);

        }

        public static void renderCoordinate(Vector3F center, IView view, float[] colorx, float[] colory, float[] colorz, float[] colorxy, float[] coloryz, float[] colorxz, bool hardsel)

        {

            renderCoordinate(center, view, colorx, colory, colorz, colorxy, coloryz, colorxz, hardsel, Matrix3F.Identity);

        }

        public static void renderCoordinate(Vector3F center, IView view, float[] colorx, float[] colory, float[] colorz, float[] colorxy, float[] coloryz, float[] colorxz, bool hardsel, Matrix3F rotmat)

        {

            renderCoordinate(center, view, 10.0f, colorx, colory, colorz, colorxy, coloryz, colorxz, hardsel, rotmat);

        }

        public static void renderCoordinate(Vector3F center, IView view, float coord_length, float[] colorx, float[] colory, float[] colorz, float[] colorxy, float[] coloryz, float[] colorxz, bool hardsel, Matrix3F rotmat)

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

            length = GetFakeLength(center, length, stdDist, view);

            float length1 = length / 2.0f;

            Vector3F coord_x = center + Matrix3F.Transform(rotmat, new Vector3F(length, 0, 0));

            Vector3F coord_y = center + Matrix3F.Transform(rotmat, new Vector3F(0, length, 0));

            Vector3F coord_z = center + Matrix3F.Transform(rotmat, new Vector3F(0, 0, length));

            Vector3F coord_xh = center + Matrix3F.Transform(rotmat, new Vector3F(length1, 0, 0));

            Vector3F coord_yh = center + Matrix3F.Transform(rotmat, new Vector3F(0, length1, 0));

            Vector3F coord_zh = center + Matrix3F.Transform(rotmat, new Vector3F(0, 0, length1));

            Vector3F coord_xy = center + Matrix3F.Transform(rotmat, new Vector3F(length1, length1, 0));

            Vector3F coord_xz = center + Matrix3F.Transform(rotmat, new Vector3F(length1, 0, length1));

            Vector3F coord_yz = center + Matrix3F.Transform(rotmat, new Vector3F(0, length1, length1));

            float[] points = { center.X  , center.Y  , center.Z  ,  // 0 o

                               coord_x.X , coord_x.Y , coord_x.Z ,  // 1 x

                               coord_y.X , coord_y.Y , coord_y.Z ,  // 2 y

                               coord_z.X , coord_z.Y , coord_z.Z ,  // 3 z

                               coord_xh.X, coord_xh.Y, coord_xh.Z,  // 4 x_h

                               coord_yh.X, coord_yh.Y, coord_yh.Z,  // 5 y_h

                               coord_zh.X, coord_zh.Y, coord_zh.Z,  // 6 z_h

                               coord_xy.X, coord_xy.Y, coord_xy.Z,  // 7 x_y

                               coord_xz.X, coord_xz.Y, coord_xz.Z,  // 8 x_z

                               coord_yz.X, coord_yz.Y, coord_yz.Z   // 9 y_z

                             };

            int[] indexs_x = { 0, 1 };  // x軸索引

            int[] indexs_y = { 0, 2 };  // y軸索引

            int[] indexs_z = { 0, 3 };  // z軸索引

            int[] indexs_xy = { 4, 7, 5 };  // xy夾角索引

            int[] indexs_xz = { 4, 8, 6 };  // xz夾角索引

            int[] indexs_yz = { 5, 9, 6 };  // yz夾角索引

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_x, colorx, true);

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_y, colory, true);

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_z, colorz, true);

            if (hardsel)

            {

                rendersys.pushSelectID(3);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xy, colorxy, true);

            if (hardsel)

            {

                rendersys.pushSelectID(4);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_xz, colorxz, true);

            if (hardsel)

            {

                rendersys.pushSelectID(5);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_yz, coloryz, true);

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

            RenderPyramid(coord_x, coord_x - center, length / 3, colorx, rendersys);

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

            RenderPyramid(coord_y, coord_y - center, length / 3, colory, rendersys);

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

            RenderPyramid(coord_z, coord_z - center, length / 3, colorz, rendersys);

        }

        public static void renderResizeCoordinate(ResizeDirection rd, Vector3F center, IView view, float[] colorx, float[] colory, float[] colorz, float[] colorxy, float[] coloryz, float[] colorxz, float[] colorxyz, bool hardsel)

        {

            renderResizeCoordinate(rd, center, 10.0f, view, colorx, colory, colorz, colorxy, coloryz, colorxz, colorxyz, hardsel);

        }

        public static void renderResizeCoordinate(ResizeDirection rd, Vector3F center, float coord_length, IView view, float[] colorx, float[] colory, float[] colorz, float[] colorxy, float[] coloryz, float[] colorxz, float[] colorxyz, bool hardsel)

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

            length = GetFakeLength(center, length, stdDist, view);

            Vector3F coordx = center + new Vector3F(length, 0, 0);

            Vector3F coordy = center + new Vector3F(0, length, 0);

            Vector3F coordz = center + new Vector3F(0, 0, length);

            float length1 = length * 2 / 3;

            float length2 = length / 2;

            float[] points = { center.X, center.Y, center.Z,      // 0 o

                               center.X + length, center.Y, center.Z,  // 1 x

                               center.X, center.Y + length, center.Z,  // 2 y

                               center.X, center.Y,center.Z + length,   // 3 z

                               center.X + length1, center.Y, center.Z,  // 4 x_h

                               center.X, center.Y + length1, center.Z,   // 5 y_h

                               center.X, center.Y, center.Z + length1,  // 6 z_h

                               center.X + length2, center.Y, center.Z, //7

                               center.X, center.Y + length2, center.Z, //8

                               center.X, center.Y, center.Z + length2, //9

                             };

            int[] indexs_x = { 0, 1 };  // x軸索引

            int[] indexs_y = { 0, 2 };  // y軸索引

            int[] indexs_z = { 0, 3 };  // z軸索引

            int[] indexs_xyl = { 4, 5, 7, 8 };

            int[] indexs_xzl = { 4, 6, 7, 9 };

            int[] indexs_yzl = { 5, 6, 8, 9 };

            int[] indexs_xz = { 4, 6, 7, 7, 6, 9 };  // xy夾角索引

            int[] indexs_xy = { 4, 7, 5, 7, 8, 5 };  // xz夾角索引

            int[] indexs_yz = { 9, 6, 8, 8, 6, 5 };  // yz夾角索引

            int[] indexs_xyz = { 7, 9, 8 };

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_x, colorx, true);

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_y, colory, true);

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs_z, colorz, true);

            if (hardsel)

            {

                rendersys.pushSelectID(3);

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xy, colorxy, true);

            }

            else

            {

                if (rd == ResizeDirection.RD_XY)

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xy, colorxy, true);

                }

                else

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs_xyl, colorxy, true);

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(4);

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xz, colorxz, true);

            }

            else

            {

                if (rd == ResizeDirection.RD_XZ)

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xz, colorxz, true);

                }

                else

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs_xzl, colorxz, true);

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(5);

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_yz, coloryz, true);

            }

            else

            {

                if (rd == ResizeDirection.RD_YZ)

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_yz, coloryz, true);

                }

                else

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs_yzl, coloryz, true);

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(6);

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xyz, colorxyz, true);

            }

            else

            {

                if (rd == ResizeDirection.RD_XYZ)

                {

                    rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs_xyz, colorxyz, true);

                }

            }

            RenderPyramid(coordx, coordx - center, length / 3, colorx, rendersys);

            RenderPyramid(coordy, coordy - center, length / 3, colory, rendersys);

            RenderPyramid(coordz, coordz - center, length / 3, colorz, rendersys);

        }

        public static MoveDirection SelectMoveLines(Vector3F center, System.Drawing.Point point, IView view)

        {

            return SelectMoveLines(center, point, view, Matrix3F.Identity);

        }

        public static MoveDirection SelectMoveLines(Vector3F center, System.Drawing.Point point, IView view, Matrix3F rotmat)

        {

            return SelectMoveLines(center, point, view, 10.0f, rotmat);

        }

        public static MoveDirection SelectMoveLines(Vector3F center, System.Drawing.Point point, IView view, float length, Matrix3F rotmat)

        {

            view.setCamera();

            view.getRenderSys().beginHardwareSelect(new int[] { point.X - Tool.SelLine_EdgeWidth, point.Y - Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth }, true);

            renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Blue, Tool.White, Tool.White, Tool.White, true, rotmat);

            uint[] res = view.getRenderSys().endHardwareSelect();

            if (res != null && res.GetLength(0) > 0)

            {

                switch (res[0])

                {

                    case 0:

                        return MoveDirection.MD_X;

                    case 1:

                        return MoveDirection.MD_Y;

                    case 2:

                        return MoveDirection.MD_Z;

                    case 3:

                        return MoveDirection.MD_XY;

                    case 4:

                        return MoveDirection.MD_XZ;

                    case 5:

                        return MoveDirection.MD_YZ;

                    default:

                        return MoveDirection.MD_NONE;

                }

            }

            else

            {

                return MoveDirection.MD_NONE;

            }

        }

        public static RotateDirection SelectRotateCircles(Vector3F center, System.Drawing.Point point, IView view)

        {

            return SelectRotateCircles(center, point, view, Matrix3F.Identity);

        }

        public static RotateDirection SelectRotateCircles(Vector3F center, System.Drawing.Point point, IView view, Matrix3F rotmat)

        {

            return SelectRotateCircles(center, point, 10.0f, view, rotmat);

        }

        public static RotateDirection SelectRotateCircles(Vector3F center, System.Drawing.Point point, float length, IView view, Matrix3F rotmat)

        {

            view.setCamera();

            view.getRenderSys().beginHardwareSelect(new int[] { point.X - Tool.SelLine_EdgeWidth, point.Y - Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth }, true);

            drawRotateCircles(center, view, length, Tool.Red, Tool.Green, Tool.Blue, true, rotmat);

            uint[] res = view.getRenderSys().endHardwareSelect();

            if (res != null && res.GetLength(0) > 0)

            {

                switch (res[0])

                {

                    case 0:

                        return RotateDirection.RD_X;

                    case 1:

                        return RotateDirection.RD_Y;

                    case 2:

                        return RotateDirection.RD_Z;

                    default:

                        return RotateDirection.RD_NONE;

                }

            }

            else

            {

                return RotateDirection.RD_NONE;

            }

        }

        public static ResizeDirection SelectResizeDirection(Vector3F center, System.Drawing.Point point, IView view)

        {

            return SelectResizeDirection(center, point, 10.0f, view);

        }

        public static ResizeDirection SelectResizeDirection(Vector3F center, System.Drawing.Point point, float length, IView view)

        {

            view.setCamera();

            view.getRenderSys().beginHardwareSelect(new int[] { point.X - Tool.SelLine_EdgeWidth, point.Y - Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth, 2 * Tool.SelLine_EdgeWidth }, true);

            renderResizeCoordinate(ResizeDirection.RD_NONE, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.White, Tool.White, Tool.White, Tool.White, true);

            uint[] res = view.getRenderSys().endHardwareSelect();

            if (res != null && res.GetLength(0) > 0)

            {

                switch (res[0])

                {

                    case 0:

                        return ResizeDirection.RD_X;

                    case 1:

                        return ResizeDirection.RD_Y;

                    case 2:

                        return ResizeDirection.RD_Z;

                    case 3:

                        return ResizeDirection.RD_XY;

                    case 4:

                        return ResizeDirection.RD_XZ;

                    case 5:

                        return ResizeDirection.RD_YZ;

                    case 6:

                        return ResizeDirection.RD_XYZ;

                    default:

                        return ResizeDirection.RD_NONE;

                }

            }

            else

            {

                return ResizeDirection.RD_NONE;

            }

        }

        //兩個點相減求向量 并歸一化

        public static Vector3F ComputeVectorAndNormalize(Vector3F start, Vector3F end)

        {

            Vector3F res = Vector3F.Subtract(end, start);

            float length = (float)Math.Sqrt(res.X * res.X + res.Y * res.Y + res.Z * res.Z);

            res.X /= length;

            res.Y /= length;

            res.Z /= length;

            return res;

        }

        //求兩個點之間的距離

        public static float ComputeDisBetweenTwoPoint(Vector3F start, Vector3F end)

        {

            Vector3F res = Vector3F.Subtract(end, start);

            return (float)Math.Sqrt(res.X * res.X + res.Y * res.Y + res.Z * res.Z);

        }

        //給定球心和半徑,求頂點

        private static void ComputePointVertex(Vector3F center, float radius, float[] points)

        {

            float da = (float)Math.PI / 5;

            float cos_da = (float)Math.Cos(da);

            float sin_da = (float)Math.Sin(da);

            float dx1 = radius * (float)Math.Sin(Math.PI / 3);

            float dy1 = 0;

            float dx2 = radius;

            float dy2 = 0;

            float z1 = center.Z + radius / 2;

            float z2 = center.Z - radius / 2;

            points[0] = center.X;

            points[1] = center.Y;

            points[2] = center.Z + radius;

            points[93] = center.X;

            points[94] = center.Y;

            points[95] = center.Z - radius;

            for (int i = 0; i < 10; ++i)

            {

                int index = 3 * i;

                // 點

                points[index + 3] = dx1 * cos_da - dy1 * sin_da;

                points[index + 4] = dx1 * sin_da + dy1 * cos_da;

                dx1 = points[index + 3];

                dy1 = points[index + 4];

                points[index + 3] += center.X;

                points[index + 4] += center.Y;

                points[index + 5] = z1;

                points[index + 33] = dx2 * cos_da - dy2 * sin_da;

                points[index + 34] = dx2 * sin_da + dy2 * cos_da;

                dx2 = points[index + 33];

                dy2 = points[index + 34];

                points[index + 33] += center.X;

                points[index + 34] += center.Y;

                points[index + 35] = center.Z;

                points[index + 63] = points[index + 3];

                points[index + 64] = points[index + 4];

                points[index + 65] = z2;

            }

        }

        public static void RenderMoveCoordinate(MoveDirection md, Vector3F center, IView view)

        {

            RenderMoveCoordinate(md, center, view, Matrix3F.Identity);

        }

        public static void RenderMoveCoordinate(MoveDirection md, Vector3F center, IView view, Matrix3F rotmat)

        {

            RenderMoveCoordinate(md, center, view, 10.0f, rotmat);

        }

        public static void RenderMoveCoordinate(MoveDirection md, Vector3F center, IView view, float length, Matrix3F rotmat)

        {

            switch (md)

            {

                case MoveDirection.MD_X:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Yellow, Tool.Green, Tool.Blue, Tool.White, Tool.White, Tool.White, false, rotmat);

                    break;

                case MoveDirection.MD_Y:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Yellow, Tool.Blue, Tool.White, Tool.White, Tool.White, false, rotmat);

                    break;

                case MoveDirection.MD_Z:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Yellow, Tool.White, Tool.White, Tool.White, false, rotmat);

                    break;

                case MoveDirection.MD_XY:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Blue, Tool.Yellow, Tool.White, Tool.White, false, rotmat);

                    break;

                case MoveDirection.MD_XZ:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Blue, Tool.White, Tool.White, Tool.Yellow, false, rotmat);

                    break;

                case MoveDirection.MD_YZ:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Blue, Tool.White, Tool.Yellow, Tool.White, false, rotmat);

                    break;

                case MoveDirection.MD_NONE:

                    RenderHelper.renderCoordinate(center, view, length, Tool.Red, Tool.Green, Tool.Blue, Tool.White, Tool.White, Tool.White, false, rotmat);

                    break;

                default:

                    break;

            }

        }

        public static void RenderRotateCircles(RotateDirection rd, Vector3F center, IView view)

        {

            RenderRotateCircles(rd, center, view, Matrix3F.Identity);

        }

        public static void RenderRotateCircles(RotateDirection rd, Vector3F center, IView view, Matrix3F rotmat)

        {

            RenderRotateCircles(rd, 10.0f, center, view, rotmat);

        }

        public static void RenderRotateCircles(RotateDirection rd, float length, Vector3F center, IView view, Matrix3F rotmat)

        {

            switch (rd)

            {

                case RotateDirection.RD_X:

                    RenderHelper.drawRotateCircles(center, view, length, Tool.Blue, Tool.Yellow, Tool.Green, false, rotmat);

                    break;

                case RotateDirection.RD_Y:

                    RenderHelper.drawRotateCircles(center, view, length, Tool.Blue, Tool.Red, Tool.Yellow, false, rotmat);

                    break;

                case RotateDirection.RD_Z:

                    RenderHelper.drawRotateCircles(center, view, length, Tool.Yellow, Tool.Red, Tool.Green, false, rotmat);

                    break;

                case RotateDirection.RD_NONE:

                    RenderHelper.drawRotateCircles(center, view, length, Tool.Blue, Tool.Red, Tool.Green, false, rotmat);

                    break;

                default:

                    RenderHelper.drawRotateCircles(center, view, length, Tool.Blue, Tool.Red, Tool.Green, false, rotmat);

                    break;

            }

        }

        public static void RenderResizeCoordinate(ResizeDirection rd, Vector3F center, IView view)

        {

            RenderResizeCoordinate(rd, center, 10.0f, view);

        }

        public static void RenderResizeCoordinate(ResizeDirection rd, Vector3F center, float length, IView view)

        {

            switch (rd)

            {

                case ResizeDirection.RD_X:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Yellow, Tool.Green, Tool.Blue, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_Y:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Yellow, Tool.Blue, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_Z:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_XY:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.Purple, Tool.Yellow, Tool.Yellow, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_XZ:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.Yellow, Tool.Yellow, Tool.Purple, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_YZ:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.Yellow, Tool.Purple, Tool.Yellow, Tool.Yellow, false);

                    break;

                case ResizeDirection.RD_XYZ:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Purple, false);

                    break;

                case ResizeDirection.RD_NONE:

                    RenderHelper.renderResizeCoordinate(rd, center, length, view, Tool.Red, Tool.Green, Tool.Blue, Tool.Yellow, Tool.Yellow, Tool.Yellow, Tool.Yellow, false);

                    break;

                default:

                    break;

            }

        }

        public static void Draw2DViewRect(int x1, int y1, int x2, int y2, IView view)

        {

            Vector3F p1 = view.getCamera().GetScreenXYZ(x1, y1, view.getRenderSys());

            Vector3F p2 = view.getCamera().GetScreenXYZ(x2, y2, view.getRenderSys());

            Vector3F p3 = view.getCamera().GetScreenXYZ(x1, y2, view.getRenderSys());

            Vector3F p4 = view.getCamera().GetScreenXYZ(x2, y1, view.getRenderSys());

            Vector3F p_p1 = new Vector3F(p1.X - view.getCamera().position.x, p1.Y - view.getCamera().position.y, p1.Z - view.getCamera().position.z);

            Vector3F p_p2 = new Vector3F(p2.X - view.getCamera().position.x, p2.Y - view.getCamera().position.y, p2.Z - view.getCamera().position.z);

            Vector3F p_p3 = new Vector3F(p3.X - view.getCamera().position.x, p3.Y - view.getCamera().position.y, p3.Z - view.getCamera().position.z);

            Vector3F p_p4 = new Vector3F(p4.X - view.getCamera().position.x, p4.Y - view.getCamera().position.y, p4.Z - view.getCamera().position.z);

            float e = 0.01f;

            float[] color = { 1, 1, 1, 1 };

            p_p1.Normalize();

            p_p2.Normalize();

            p_p3.Normalize();

            p_p4.Normalize();

            p1 += p_p1 * e;

            p2 += p_p2 * e;

            p3 += p_p3 * e;

            p4 += p_p4 * e;

            view.getRenderSys().drawLine(p1.X, p1.Y, p1.Z, p3.X, p3.Y, p3.Z, color);

            view.getRenderSys().drawLine(p1.X, p1.Y, p1.Z, p4.X, p4.Y, p4.Z, color);

            view.getRenderSys().drawLine(p2.X, p2.Y, p2.Z, p3.X, p3.Y, p3.Z, color);

            view.getRenderSys().drawLine(p2.X, p2.Y, p2.Z, p4.X, p4.Y, p4.Z, color);

        }

        public static void DrawDirectionArrow(Vector3F start, Matrix4F locationmat, IView view)

        {

            Vector3F dir = new Vector3F(0, -1, 0);

            Matrix4F tmp = TransformationF.Translation(dir);

            Matrix4F res = locationmat * tmp;

            Vector3F end = new Vector3F(res.M14, res.M24, res.M34);

            dir = new Vector3F(locationmat.M14, locationmat.M24, locationmat.M34);

            DrawDirectionArrow(start, end - dir, view);

        }

        public static void DrawDirectionArrow(Vector3F start, Vector3F dir, IView view)

        {

            float length1 = 6;

            float length2 = 1;

            length1 = RenderHelper.GetFakeLength(start, length1, RenderHelper.stdDist, view);

            Vector3F end = RenderHelper.GetPointDisNToPoint(start, dir, length1);

            RenderHelper.DrawLinkLine(start, end, Tool.Yellow, view.getRenderSys());

            length2 = RenderHelper.GetFakeLength(end, length2, RenderHelper.stdDist, view);

            RenderHelper.RenderConic((int)LightShape.CIRCLE, end, -dir, 45, length2, Tool.Yellow, view.getRenderSys());

        }

        //畫一個球體

        public static void DrawPoint(Vector3F center, float radius, float[] color, IView view)

        {

            ClientBridge.ClientRenderSys crs = view.getRenderSys();

            float[] points = new float[96]; // 32個點

            int[] indexs = new int[180]; // 60個三角形

            radius = GetFakeLength(center, radius, stdDist, view);

            ComputePointVertex(center, radius, points);

            for (int i = 0; i < 10; ++i)

            {

                int index = 3 * i;

                // 三角形索引

                indexs[index] = 0;

                indexs[index + 1] = (i + 1) % 10 + 1;

                indexs[index + 2] = i + 1;

                indexs[index + 30] = indexs[index + 2];

                indexs[index + 31] = indexs[index + 1];

                indexs[index + 32] = indexs[index + 31] + 10;

                indexs[index + 60] = indexs[index + 30];

                indexs[index + 61] = indexs[index + 32];

                indexs[index + 62] = indexs[index + 30] + 10;

                indexs[index + 90] = indexs[index + 62];

                indexs[index + 91] = indexs[index + 61];

                indexs[index + 92] = indexs[index + 91] + 10;

                indexs[index + 120] = indexs[index + 90];

                indexs[index + 121] = indexs[index + 92];

                indexs[index + 122] = indexs[index + 90] + 10;

                indexs[index + 150] = indexs[index + 122];

                indexs[index + 151] = indexs[index + 121];

                indexs[index + 152] = 31;

            }

            crs.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs, color, false);

        }

        //畫一個球的網格

        public static void DrawPointGrid(Vector3F center, float radius, float[] color, ClientBridge.ClientRenderSys crs)

        {

            float[] points = new float[96]; // 32個點

            int[] indexs = new int[180]; // 90條邊

            ComputePointVertex(center, radius, points);

            for (int i = 0; i < 10; i++)

            {

                int index = 2 * i;

                indexs[index] = 0;

                indexs[index + 1] = i + 1;

            }

            for (int i = 0; i < 10; i++)

            {

                int index = 2 * i;

                indexs[index + 20] = indexs[index + 1];

                indexs[index + 21] = indexs[index + 3 > 19 ? 1 : index + 3];

                indexs[index + 80] = indexs[index + 20] + 10;

                indexs[index + 81] = indexs[index + 21] + 10;

                indexs[index + 40] = indexs[index + 20];

                indexs[index + 41] = indexs[index + 80];

                indexs[index + 60] = indexs[index + 20];

                indexs[index + 61] = indexs[index + 81 > 99 ? index + 80 : index + 81];

                indexs[index + 140] = indexs[index + 80] + 10;

                indexs[index + 141] = indexs[index + 81] + 10;

                indexs[index + 100] = indexs[index + 80];

                indexs[index + 101] = indexs[index + 140];

                indexs[index + 120] = indexs[index + 80];

                indexs[index + 121] = indexs[index + 141 > 159 ? index + 140 : index + 141];

                indexs[index + 160] = indexs[index + 140];

                indexs[index + 161] = 31;

            }

            crs.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, color, false);

        }

        //畫非點光源的起點和終點之間的連接配接線

        public static void DrawLinkLine(Vector3F start, Vector3F end, float[] color, ClientBridge.ClientRenderSys crs)

        {

            float[] points = {start.X, start.Y, start.Z,

                              end.X, end.Y, end.Z};

            crs.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, new int[] { 0, 1 }, color, false);

        }

        public static Vector3F GetPointDisNToPoint(Vector3F start, Vector3F dir, float dis)

        {

            float x = 0, y = 0, z = 0;

            int index = 0;

            float m = 0, n = 0;

            float tmp = 0;

            if (dis == 0)

            {

                return new Vector3F(start);

            }

            else if (dis < 0)

            {

                dis = -dis;

                dir = Vector3F.Negate(dir);

            }

            if (dir.Z != 0)

            {

                m = dir.Z;

                n = start.Z;

                index = 1;

            }

            else if (dir.X != 0)

            {

                m = dir.X;

                n = start.X;

                index = 2;

            }

            else if (dir.Y != 0)

            {

                m = dir.Y;

                n = start.Y;

                index = 3;

            }

            else

            {

                return new Vector3F();

            }

            tmp = dis * dis * m * m;

            tmp /= (dir.X * dir.X + dir.Y * dir.Y + dir.Z * dir.Z);

            tmp = (float)Math.Sqrt(tmp);

            if (tmp * m < 0)

            {

                tmp = -tmp;

            }

            tmp += n;

            if (index == 1)

            {

                z = tmp;

                if (dir.X != 0)

                {

                    x = dir.X * (z - start.Z) / dir.Z + start.X;

                }

                else

                {

                    x = start.X;

                }

                if (dir.Y != 0)

                {

                    y = dir.Y * (z - start.Z) / dir.Z + start.Y;

                }

                else

                {

                    y = start.Y;

                }

            }

            if (index == 2)

            {

                x = tmp;

                if (dir.Y != 0)

                {

                    y = dir.Y * (x - start.X) / dir.X + start.Y;

                }

                else

                {

                    y = start.Y;

                }

                if (dir.Z != 0)

                {

                    z = dir.Z * (x - start.X) / dir.X + start.Z;

                }

                else

                {

                    z = start.Z;

                }

            }

            if (index == 3)

            {

                y = tmp;

                if (dir.X != 0)

                {

                    x = dir.X * (y - start.Y) / dir.Y + start.X;

                }

                else

                {

                    x = start.X;

                }

                if (dir.Z != 0)

                {

                    z = dir.Z * (y - start.Y) / dir.Y + start.Z;

                }

                else

                {

                    z = start.Z;

                }

            }

            return new Vector3F(x, y, z);

        }

        //求線段上距起點一定距離的點

        public static Vector3F GetPointDisNToPointOnLine(Vector3F start, Vector3F end, float dis)

        {

            Vector3F direct = Vector3F.Subtract(start, end);

            return GetPointDisNToPoint(start, direct, dis);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            RenderCube(center, normal, radis, length, color, rendersys, false);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys, bool hardsel)

        {

            RenderCube(center, normal, radis, length, color, rendersys, hardsel, false);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys, bool hardsel, bool hidesee)

        {

            float[] points = new float[24];

            float radius = radis * ((float)Math.Sqrt(2));

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            if (normal.GetLength() != 0)

            {

                normal.Normalize();

            }

            for (int t = 0; t < 4; t++)

            {

                float factor = 0;

                Vector3F u = new Vector3F();

                if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

                Vector3F v = Vector3F.CrossProduct(normal, u);

                v.Normalize();

                points[t * 3] = (float)(center.X + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.X);

                points[t * 3 + 1] = (float)(center.Y + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Y);

                points[t * 3 + 2] = (float)(center.Z + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Z);

                points[12 + t * 3] = (float)(center2.X + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.X);

                points[12 + t * 3 + 1] = (float)(center2.Y + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Y);

                points[12 + t * 3 + 2] = (float)(center2.Z + (radius * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Z);

            }

            if (hardsel)

            {

                int[] indexs = new int[36] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 0, 1, 5, 0, 5, 4, 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 0, 4, 3, 4, 7 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs, color, hidesee);

            }

            else

            {

                int[] indexs = new int[24] { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, color, hidesee);

            }

        }

        public static void RenderCloumn(Vector3F center, Vector3F normal, float radius, float length, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            normal.Normalize();

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            int pointcount = 360;

            float[] points1 = new float[pointcount * 3];

            int[] indexs1 = new int[pointcount + 1];

            float[] points2 = new float[pointcount * 3];

            int[] indexs2 = new int[pointcount + 1];

            float[] points3 = new float[24];

            int i = 0;

            for (int t = 0; t < pointcount; t++)

            {

                float factor = 0;

                Vector3F u = new Vector3F();

                if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

                Vector3F v = Vector3F.CrossProduct(normal, u);

                v.Normalize();

                points1[t * 3] = (float)(center.X + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.X);

                points1[t * 3 + 1] = (float)(center.Y + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Y);

                points1[t * 3 + 2] = (float)(center.Z + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Z);

                points2[t * 3] = (float)(center2.X + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.X);

                points2[t * 3 + 1] = (float)(center2.Y + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Y);

                points2[t * 3 + 2] = (float)(center2.Z + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Z);

                indexs1[t] = t;

                indexs2[t] = t;

                if (t % 90 == 0)

                {

                    points3[i * 3] = points1[t * 3];

                    points3[i * 3 + 1] = points1[t * 3 + 1];

                    points3[i * 3 + 2] = points1[t * 3 + 2];

                    points3[12 + i * 3] = points2[t * 3];

                    points3[12 + i * 3 + 1] = points2[t * 3 + 1];

                    points3[12 + i * 3 + 2] = points2[t * 3 + 2];

                    i++;

                }

            }

            indexs1[pointcount] = 0;

            indexs2[pointcount] = 0;

            int[] indexs3 = new int[8] { 0, 4, 1, 5, 2, 6, 3, 7 };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points1, indexs1, color, false);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points2, indexs2, color, false);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points3, indexs3, color, false);

        }

        //畫一個四棱錐

        public static void RenderPyramid(Vector3F center, Vector3F normal, float height, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            if (normal.GetLength() != 0)

                normal.Normalize();

            else

                return;

            Vector3F top = GetPointDisNToPoint(center, normal, height);

            Vector3F up = Tool.FloatCompare(normal.X, 0, float.Epsilon) && Tool.FloatCompare(normal.Y, 0, float.Epsilon) ? Vector3F.YAxis : Vector3F.ZAxis;

            Vector3F right = Vector3F.CrossProduct(up, normal);

            right.Normalize();

            up = Vector3F.CrossProduct(right, normal);

            up.Normalize();

            float half_l = height / 5;

            Vector3F[] verts = new Vector3F[6];

            verts[0] = top;

            verts[1] = center - half_l * right;

            verts[2] = center - half_l * up;

            verts[3] = center + half_l * right;

            verts[4] = center + half_l * up;

            verts[5] = center;

            float[] points = new float[18];

            for (int i = 0; i < 6; i++)

            {

                points[i * 3 + 0] = verts[i].X;

                points[i * 3 + 1] = verts[i].Y;

                points[i * 3 + 2] = verts[i].Z;

            }

            int[] indexs = new int[24] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 1, 5, 2, 2, 5, 3, 3, 5, 4, 4, 5, 1 };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs, color, true);

        }

        public static void RenderConic(int shape, Vector3F center, Vector3F normal, float angle, float length, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            if (normal.GetLength() != 0)

            {

                normal.Normalize();

            }

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            float radius = (float)Math.Tan(Math.PI * angle / (180 * 2)) * length;

            if (shape == (int)LightShape.CIRCLE)

            {

                int pointcount = 360;

                float[] points = new float[pointcount * 3];

                int[] indexs = new int[pointcount + 1];

                float[] points1 = new float[15];

                int i = 0;

                for (int t = 0; t < pointcount; t++)

                {

                    float factor = 0;

                    Vector3F u = new Vector3F();

                    if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                    {

                        factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                        u.X = -normal.Z * factor;

                        u.Y = 0;

                        u.Z = normal.X * factor;

                    }

                    else

                    {

                        factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                        u.X = 0;

                        u.Y = normal.Z * factor;

                        u.Z = -normal.Y * factor;

                    }

                    u.Normalize();

                    Vector3F v = Vector3F.CrossProduct(normal, u);

                    v.Normalize();

                    points[t * 3] = (float)(center2.X + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.X);

                    points[t * 3 + 1] = (float)(center2.Y + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Y);

                    points[t * 3 + 2] = (float)(center2.Z + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Z);

                    indexs[t] = t;

                    if (t % 90 == 0)

                    {

                        points1[i * 3] = points[t * 3];

                        points1[i * 3 + 1] = points[t * 3 + 1];

                        points1[i * 3 + 2] = points[t * 3 + 2];

                        i++;

                    }

                }

                indexs[pointcount] = 0;

                points1[12] = center.X;

                points1[13] = center.Y;

                points1[14] = center.Z;

                int[] indexs1 = new int[8] { 4, 0, 4, 1, 4, 2, 4, 3 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs, color, false);

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points1, indexs1, color, false);

            }

            else

            {

                float radius1 = radius * ((float)Math.Sqrt(2));

                float[] points = new float[27];

                for (int t = 0; t < 4; t++)

                {

                    float factor = 0;

                    Vector3F u = new Vector3F();

                    if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                    {

                        factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                        u.X = -normal.Z * factor;

                        u.Y = 0;

                        u.Z = normal.X * factor;

                    }

                    else

                    {

                        factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                        u.X = 0;

                        u.Y = normal.Z * factor;

                        u.Z = -normal.Y * factor;

                    }

                    u.Normalize();

                    Vector3F v = Vector3F.CrossProduct(normal, u);

                    v.Normalize();

                    points[t * 3] = (float)(center2.X + (radius1 * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.X + (radius1 * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.X);

                    points[t * 3 + 1] = (float)(center2.Y + (radius1 * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Y + (radius1 * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Y);

                    points[t * 3 + 2] = (float)(center2.Z + (radius1 * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.Z + (radius1 * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.Z);

                    points[12 + t * 3] = (float)(center2.X + (radius * Math.Cos(Math.PI * (t * 90) / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * (t * 90) / 180.0f)) * v.X);

                    points[12 + t * 3 + 1] = (float)(center2.Y + (radius * Math.Cos(Math.PI * (t * 90) / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * (t * 90) / 180.0f)) * v.Y);

                    points[12 + t * 3 + 2] = (float)(center2.Z + (radius * Math.Cos(Math.PI * (t * 90) / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * (t * 90) / 180.0f)) * v.Z);

                }

                points[24] = center.X;

                points[25] = center.Y;

                points[26] = center.Z;

                int[] indexs = new int[24] { 0, 1, 1, 2, 2, 3, 3, 0, 8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, color, false);

            }

        }

        public static void RenderDirStartPoint(Vector3F start, Vector3F end, float radius, float[] color, IView view)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

            radius = GetFakeLength(start, radius, stdDist, view);

            RenderCloumn(start, dir, radius, 2 * radius, color, view.getRenderSys());

        }

        public static void RenderPrmStartPoint(int shape, Vector3F start, Vector3F end, float angle, float[] color, IView view)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

            float length = GetFakeLength(start, 2, stdDist, view);

            length = (float)(length * Math.Cos(Math.PI * angle / 360.0f));

            RenderConic(shape, start, dir, angle, length, color, view.getRenderSys());

        }

        public static void RenderLightEndPoint(Vector3F start, Vector3F end, float radius, float[] color, IView view, bool hardsel)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

            radius = GetFakeLength(end, radius, stdDist, view);

            RenderCube(end, Vector3F.Negate(dir), radius, 2 * radius, color, view.getRenderSys(), hardsel);

        }

    }

    // Group資訊

    public struct GroupActorInfo

    {

        public string m_group_name;   // 物品名稱 字首+id

        public float m_height;

        public bool m_bClose;

        public RotateMode m_eRotateMode;

        public GroupActorInfo(Dictionary<string, string> createpropdic, int curindex)

        {

            string nameprefix = createpropdic["NamePrefix"];

            m_group_name = nameprefix + "_" + curindex.ToString();

            try

            {

                m_height = float.Parse(createpropdic["Height"]);

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_bClose = true;

            m_eRotateMode = RotateMode.RM_WHOLE;

        }

        // 轉換成屬性清單

        public void toDic(Dictionary<string, string> dic)

        {

            dic["Name"] = m_group_name;

            dic["Height"] = m_height.ToString();

            dic["Close"] = m_bClose.ToString();

            dic["RotateMode"] = m_eRotateMode.ToString();

        }

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_group_name = value;

                    break;

                case "Height":

                    try

                    {

                        m_height = float.Parse(value);

                    }

                    catch (Exception)

                    {

                        m_height = 0;

                    }

                    break;

                case "Close":

                    m_bClose = value.ToLower() == "true" ? true : false;

                    break;

                case "RotateMode":

                    // fixme :

                    if (value == "RM_WHOLE")

                        m_eRotateMode = RotateMode.RM_WHOLE;

                    else if (value == "RM_SELF")

                        m_eRotateMode = RotateMode.RM_SELF;

                    else

                        m_eRotateMode = RotateMode.RM_BOTH;

                    break;

                default:

                    break;

            }

        }

    }

    // Group

    public class GroupActor : ActorBase, IActor

    {

        IActorLayerMng m_actor_layer = null;

        GroupActorInfo m_actor_info;

        // 包圍盒12條線段對應的GIID,在Group生成時就記錄下來。為解決打開Group時的選擇問題

        GIID m_aabb_giid;

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, int curindex)

            : this(giidmng, createpropdic, curindex, null)

        {

        }

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, int curindex, IActorLayerMng parentLayer)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo(createpropdic, curindex);

            // 将m_actor_layer置為parentLayer類型

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            this.parentLayer = parentLayer;

            //insertActors(ab);

            //m_actor_layer.getOrgBuffer().add(ab);

            // 位置

            Vector3F max = GActorHelper.getMaxPos(m_actor_layer.getOrgBuffer());

            Vector3F pos = GActorHelper.getMinPos(m_actor_layer.getOrgBuffer());

            pos = new Vector3F((max.X + pos.X) / 2.0f, (max.Y + pos.Y) / 2.0f, 0);

            locationmat = TransformationF.Translation(pos) * Matrix4F.Identity;

            m_aabb_giid = giidmng.getGIID();

        }

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ActorBuffer ab, int curindex)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo(createpropdic, curindex);

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            m_actor_layer.getOrgBuffer().add(ab);

            // 位置

            Vector3F pos = GActorHelper.getMinPos(m_actor_layer.getOrgBuffer());

            locationmat = TransformationF.Translation(pos) * Matrix4F.Identity;

            m_aabb_giid = giidmng.getGIID();

        }

        public GroupActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo();

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            m_aabb_giid = giidmng.getGIID();

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_GROUP;

        }

        public void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id, IActorLayerMng sellayer)

        {

            if (m_aabb_giid.value == id)

            {

                // 得到應該被選中的Actor

                IActor selactor = this;

                if (!selactors.ContainsKey(sellayer))

                {

                    selactors[sellayer] = new ActorBuffer(null, new DummyActorFun());

                }

                if (!selactors[sellayer].Contains<IActor>(selactor))

                {

                    selactors[sellayer].insert(selactor);

                }

            }

            foreach (IActor actor in getActorBuffer().getOrgBuffer())

            {

                if (actor is GroupActor)

                {

                    ((GroupActor)actor).getSelectByID(selactors, id, sellayer);

                }

                else if (actor.giid.value == id)

                {

                    // 得到應該被選中的Actor

                    IActor selactor = actor;

                    while (selactor.parent != null && ((GroupActor)(selactor.parent)).close)

                    {

                        selactor = selactor.parent;

                    }

                    if (!selactors.ContainsKey(sellayer))

                    {

                        selactors[sellayer] = new ActorBuffer(null, new DummyActorFun());

                    }

                    if (!selactors[sellayer].Contains<IActor>(selactor))

                    {

                        selactors[sellayer].insert(selactor);

                    }

                    return;

                }

            }

        }

        //public void getSelectMoveLineID(int id, IActorLayerMng sellayer)

        //{

        //}

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            // 使所有子物品參與硬體選擇

            getActorBuffer().pushHardwareSelect(rendersys);

            if (!close)

            { // Group打開狀态下,包圍盒參與選擇

                rendersys.pushSelectID((uint)(m_aabb_giid.value));

                float[] c = { 1, 0, 0, 1 };

                Vector3F[] vetexs = aabb.ComputeVertices();

                float[] points = new float[24];

                for (int i = 0; i < 8; i++)

                {

                    points[i * 3] = vetexs[i].X;

                    points[i * 3 + 1] = vetexs[i].Y;

                    points[i * 3 + 2] = vetexs[i].Z;

                }

                int[] indexs = { 0,1, 1,2, 2,3, 3,0,

                                 4,5, 5,6, 6,7, 7,4,

                                 0,4, 1,5, 2,6, 3,7

                               };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, c, false);

                // fixme : 線的硬體選擇engine還有問題。。。

                rendersys.pushSelectID(100);

                rendersys.drawLine(vetexs[7].X, vetexs[7].Y, vetexs[7].Z, vetexs[0].X, vetexs[0].Y, vetexs[0].Z, c);

            }

        }

        public override bool hide

        {

            get

            {

                return base.hide;

            }

            set

            {

                base.hide = value;

                foreach (IActor actor in getActorBuffer().getOrgBuffer())

                {

                    actor.hide = value;

                }

            }

        }

        public override bool freeze

        {

            get

            {

                return base.freeze;

            }

            set

            {

                base.freeze = value;

                foreach (IActor actor in getActorBuffer().getOrgBuffer())

                {

                    actor.freeze = value;

                }

            }

        }

        // Group關閉狀态

        public bool close

        {

            get

            {

                return m_actor_info.m_bClose;

            }

            set

            {

                if (this is PrefebActor)

                {

                    MessageBox.Show("fixme : can not open prefeb!");

                    return;

                }

                m_actor_info.m_bClose = value;

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_group_name;

            }

            set

            {

                AssertUtil.confirm(this is PrefebActor);

                m_actor_info.m_group_name = value;

            }

        }

        public RotateMode rotatemode

        {

            get

            {

                return m_actor_info.m_eRotateMode;

            }

            set

            {

                m_actor_info.m_eRotateMode = value;

            }

        }

        public void Dispose()

        {

            m_actor_layer.Dispose();

        }

        #region about IActor

        public override IActorLayerMng getActorBuffer()

        {

            return m_actor_layer;

        }

        public List<T> getActors<T>() where T : IActor

        {

            List<T> l = new List<T>();

            IEnumerator<T> it = m_actor_layer.getOrgBuffer().GetEnumerator<T>();

            while (it.MoveNext())

            {

                l.Add(it.Current);

            }

            IEnumerator<GroupActor> it_group = m_actor_layer.getOrgBuffer().GetEnumerator<GroupActor>();

            while (it_group.MoveNext())

            {

                l.AddRange(it_group.Current.getActors<T>());

            }

            return l;

        }

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            GroupActor actor = null;

            return actor;

        }

        //public IMemento getMemento(int mode)

        //{

        //    return null;

        //}

        //public void setMemento(IMemento mem)

        //{

        //}

        public override bool serialize(BinaryWriter binWriter)

        {

            if (!(this is PrefebActor))

            {

                binWriter.Write(m_actor_info.m_group_name);

                binWriter.Write(m_actor_info.m_height);

                binWriter.Write(m_actor_info.m_bClose);

                getActorBuffer().serialize(binWriter);

            }

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            if (!(this is PrefebActor))

            {

                m_actor_info.m_group_name = binReader.ReadString();

                m_actor_info.m_height = binReader.ReadSingle();

                m_actor_info.m_bClose = binReader.ReadBoolean();

                m_actor_layer.serialize(binReader, edititem);

            }

            foreach (IActor actor in m_actor_layer.getOrgBuffer())

            {

                actor.parent = this;

            }

            return base.serialize(binReader, edititem);

        }

        #endregion

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 調用自己的繪制函數

            m_actor_layer.render(t, rendersys);

        }

        public override void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            base.renderAABB(t, rendersys, color);

        }

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_actor_layer.getOrgBuffer().Count<IActor>() == 0)

            {

                return;

            }

            // 修改包圍盒

            IActor actor0 = m_actor_layer.getOrgBuffer().ElementAt<IActor>(0);

            aabb = actor0.aabb;

            foreach (IActor actor in m_actor_layer.getOrgBuffer())

            {

                Vector3F aabbmin = aabb.Min;

                Vector3F aabbmax = aabb.Max;

                if (actor.aabb.Min.X < aabbmin.X)

                {

                    aabbmin.X = actor.aabb.Min.X;

                }

                if (actor.aabb.Min.Y < aabbmin.Y)

                {

                    aabbmin.Y = actor.aabb.Min.Y;

                }

                if (actor.aabb.Min.Z < aabbmin.Z)

                {

                    aabbmin.Z = actor.aabb.Min.Z;

                }

                if (actor.aabb.Max.X > aabbmax.X)

                {

                    aabbmax.X = actor.aabb.Max.X;

                }

                if (actor.aabb.Max.Y > aabbmax.Y)

                {

                    aabbmax.Y = actor.aabb.Max.Y;

                }

                if (actor.aabb.Max.Z > aabbmax.Z)

                {

                    aabbmax.Z = actor.aabb.Max.Z;

                }

                aabb = new AxisAlignedBox(aabbmin, aabbmax);

            }

            base.updateLocationAABB();

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

        }

    }

    public struct PrefebActorInfo

    {

        public string m_group_name;

        public string m_prefeb_name;

        public PrefebActorInfo(string group, string name)

        {

            m_group_name = group;

            m_prefeb_name = name;

        }

    }

    // 包裹

    public class PrefebActor : GroupActor

    {

        public PrefebActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ActorBuffer ab, int curindex, string group, string name)

            : base(giidmng, createpropdic, ab, curindex)

        {

            m_prefeb_info = new PrefebActorInfo(group, name);

        }

        public PrefebActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_prefeb_info = new PrefebActorInfo();

        }

        public override IDictionary<string, string> getPropertyList()

        {

            return base.getPropertyList();

        }

        // 判斷包裹執行個體是否由某個包裹模闆建立

        public bool isCreateFrom(string groupname, string prefebname)

        {

            return ((m_prefeb_info.m_group_name == groupname) && (m_prefeb_info.m_prefeb_name == prefebname));

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_prefeb_info.m_group_name);

            binWriter.Write(m_prefeb_info.m_prefeb_name);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            return base.serialize(binReader, edititem);

        }

        PrefebActorInfo m_prefeb_info;

    }

    // 包裹管理器

    public class PrefebManager

    {

        public static void allrotateandmove(GroupActor actor, Matrix4F rotatemat)

        {

            actor.moveTo(new Vector3F(0, 0, 0));

            IActorLayerMng sublayer = actor.getActorBuffer();

            foreach (IActor subactor in sublayer.getOrgBuffer())

            {

                if (subactor is GroupActor)

                    allrotateandmove((GroupActor)subactor, rotatemat * new Matrix4F(subactor.locationmat));

                else

                    subactor.notifyPropertyChange("LocationMat", (rotatemat * subactor.locationmat).ToString());

            }

            actor.notifyPropertyChange("LocationMat", (rotatemat * actor.locationmat).ToString());

        }

        // 将指定物品生成Prefeb模闆檔案。groupname:組名; name:包裹名稱

        public static void generatePrefebFile(IActorLayerMng layer, ActorBuffer ab, string groupname, string prefebname)

        {

            bool prefebmodifyflag = false;

            string path = s_xml_path_prefix + "/" + groupname;

            if (!Directory.Exists(path))

            {

                Directory.CreateDirectory(path);

            }

            string fullfilename = path + "/" + prefebname + ".xml";

            if (File.Exists(fullfilename))

            {

                DialogResult dr = MessageBox.Show("名為[" + prefebname + "]的包裹已存在,是否覆寫?覆寫将更新所有對應的包裹執行個體!", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (dr == DialogResult.Yes)

                {

                    prefebmodifyflag = true;

                }

                else if (dr == DialogResult.No)

                {

                    generatePrefebFile(layer, ab, groupname, prefebname + " new");

                    return;

                }

            }

            XmlDocument xml = new XmlDocument();

            XmlDeclaration xmldecl;

            xmldecl = xml.CreateXmlDeclaration("1.0", "GBK", "yes");

            xml.AppendChild(xmldecl);

            XmlNode rootElem = xml.CreateNode("element", "PrefebActor", "");

            xml.AppendChild(rootElem);

            XmlNode propertynode;

            // fixme : 包裹資訊,暫時在程式中寫死

            propertynode = xml.CreateNode("element", "NamePrefix", "");

            propertynode.InnerText = prefebname;

            rootElem.InsertAfter(propertynode, rootElem.LastChild);

            propertynode = xml.CreateNode("element", "Height", "");

            propertynode.InnerText = "0";

            rootElem.InsertAfter(propertynode, rootElem.LastChild);

            // 儲存包裹中物品的資訊,,,

            XmlNode actornode;

            XmlAttribute actoratt;

            foreach (IActor actor in ab)

            {

                actornode = xml.CreateNode("element", "Item", "");

                actoratt = xml.CreateAttribute("type");

                actoratt.Value = GActorHelper.getActorTypestr(actor);

                actornode.Attributes.Append(actoratt);

                actor.serialize(actornode, null, false, false);

                rootElem.InsertAfter(actornode, rootElem.LastChild);

            }

            xml.Save(fullfilename);

            if (prefebmodifyflag)

            {

                GActorHelper.updatePrefebActors(layer, groupname, prefebname);

            }

            return;

        }

        // 包裹内容的擷取

        public static PrefebActor getActorBufferFromPrefebFile(string groupname, string name, IEditItem edititem)

        {

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            Dictionary<string, string> createpropdic = new Dictionary<string, string>();

            //

            XmlDocument prefebxml = new XmlDocument();

            string filename = s_xml_path_prefix + "/" + groupname + "/" + name + ".xml";

            prefebxml.Load(filename);

            foreach (XmlNode childnode in prefebxml.SelectSingleNode("PrefebActor").ChildNodes)

            {

                if (childnode.Name != "Item")

                {

                    // to get the prefeb properties

                    createpropdic[childnode.Name] = childnode.InnerText;

                }

                else

                {

                    // to get the properties of the child actors

                    XmlAttribute typeatt = childnode.Attributes["type"];

                    IActor actor = GActorHelper.generateActorWithoutInfo(typeatt.Value, edititem);

                    actor.serialize(childnode, edititem, true, false);

                    ab.insert(actor);

                }

            }

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

            IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", (IEditItem)SceneGraph.getEditItemCommon("RootItem", edititem));

            IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

            string prefix = createpropdic["NamePrefix"];

            PrefebActor prefebactor = new PrefebActor(root.giidmng, createpropdic, ab, doc.getMaxActorIndex(prefix), groupname, name);

            foreach (IActor actor in ab)

            {

                actor.parent = prefebactor;

            }

            return prefebactor;

        }

        // Prefeb模闆xml所在路徑

        private static string s_xml_path_prefix = @"../resources/editor/Prefebs";

    }

    // 物品memento,用物品屬性清單建構

    public class DancerMemento : IMemento

    {

        public Dictionary<String, String> m_property_dic = new Dictionary<string, string>();

        public int m_index;

        public float m_angle;

        public bool m_ismale;

        public List<string> m_bodyparts = new List<string>();

        public string m_act = "";

    }

    // 人物 fixme:僅做了一個給美術臨時用的測試版本,不能儲存讀取

    public class DancerActor : ActorBase, IActor

    {

        public int m_index;

        public float m_angle;

        public bool m_ismale;

        public List<string> m_bodyparts = new List<string>();

        public string m_act = "";

        public string m_name;

        public DancerActor(GIIDMng giidmng, ClientBridge.ClientRenderSys rendersys)

            : base(giidmng)

        {

        }

        public DancerActor(GIIDMng giidmng, string name, bool ismale, int index, ClientBridge.ClientRenderSys rendersys)

            : base(giidmng)

        {

            m_name = name;

            m_index = index;

            m_ismale = ismale;

            // 設定預設值

            m_angle = 90;

            m_bodyparts.Add("100000004.bp3");

            m_bodyparts.Add("101001004.bp3");

            m_bodyparts.Add("102004001.bp3");

            m_bodyparts.Add("103021002.bp3");

            m_bodyparts.Add("104025001.bp3");

            m_bodyparts.Add("105000000.bp3");

            m_bodyparts.Add("106008001.bp3");

            m_bodyparts.Add("107000000.bp3");

            m_bodyparts.Add("108010001.bp3");

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_ACTOR;

        }

        public void Dispose()

        {

            m_bodyparts.Clear();

        }

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)SceneGraph.getEditItemCommon("RootItem", edititem);

            DancerActor actor = null;

            return actor;

        }

        public override void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

        }

        public override void renderAABB(int t, ClientBridge.ClientRenderSys rendersys, Color color)

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            return base.getPropertyList();

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

        }

        // 獲得物品Memento

        public override IMemento getMemento(int mode)

        {

            DancerMemento mem = new DancerMemento();

            foreach (KeyValuePair<string, string> kv in m_property_dic)

            {

                mem.m_property_dic.Add(kv.Key, kv.Value);

            }

            mem.m_act = m_act;

            mem.m_angle = m_angle;

            foreach (string str in m_bodyparts)

            {

                mem.m_bodyparts.Add(str);

            }

            mem.m_index = m_index;

            mem.m_ismale = m_ismale;

            return mem;

        }

        // 設定物品Memento

        public override void setMemento(IMemento mem)

        {

            DancerMemento actormem = (DancerMemento)mem;

            m_act = actormem.m_act;

            m_angle = actormem.m_angle;

            m_bodyparts.Clear();

            foreach (string str in actormem.m_bodyparts)

            {

                m_bodyparts.Add(str);

            }

            m_index = actormem.m_index;

            m_ismale = actormem.m_ismale;

            foreach (KeyValuePair<string, string> kv in actormem.m_property_dic)

            {

                notifyPropertyChange(kv.Key, kv.Value);

            }

            updateLocationAABB();

        }

    }

    // -------------

    // 在物品加入容器或從容器中移出時,會調用相應的函數

    public interface IActorFun

    {

        void insert(IActor actor, IActorLayerMng layer);

        void remove(IActor actor, IActorLayerMng layer);

    }

    // 在物品加入容器或從容器中移出時,不做任何事情

    public class DummyActorFun : IActorFun

    {

        #region IActorFun 成員

        public void insert(IActor actor, IActorLayerMng layer)

        {

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

        }

        #endregion

    }

    // 在删除以及插入actor時,将actor的層次管理器(如果有的話)删除或添加到對應的層次管理器中

    public class ActorAsLayerActorFun : IActorFun

    {

        public void insert(IActor actor, IActorLayerMng layer)

        {

            if (actor.getActorBuffer() != null)

            {

                layer.getList().Add(actor.getActorBuffer());

                actor.getActorBuffer().parent = layer;

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            if (actor.getActorBuffer() != null)

            {

                actor.getActorBuffer().parent = null;

                layer.getList().Remove(actor.getActorBuffer());

            }

        }

    }

    // 物品容器,用來記錄相同類型和不同類型的物品,可以輪訓

    // 不負責所記錄actor的銷毀

    //     public class ActorBuffer : IEnumerable<IActor>

    //     {

    //         // 所在的物品層

    //         IActorLayerMng m_layer;

    //         // 物品移入移出時所調用的函數

    //         IActorFun m_actor_fun;

    //

    //         public ActorBuffer(IActorLayerMng layer, IActorFun fun)

    //         {

    //             m_layer = layer;

    //             m_actor_fun = fun;

    //         }

    //         // 物品容器用來記錄所有的物品,不同類型還沒有用不同的容器來儲存

    //         Dictionary<Type, Dictionary<IActor, IActor>> m_dic = new Dictionary<Type, Dictionary<IActor, IActor>>();

    //

    //         // 疊代器供疊代使用,将Dictionary的疊代器轉化為IEnumerator<IActor>類型的疊代器

    //         // fixme: 可以為了針對指定類型的疊代,這個類還需要記錄所剩物品類型所對應的物品容器

    //         public class ActorBufferEnumerator<T> : IEnumerator<T> where T: IActor

    //         {

    //             public ActorBufferEnumerator(IEnumerator<KeyValuePair<Type, Dictionary<IActor, IActor>>> base_enumerator)

    //             {

    //                 AssertUtil.confirm(base_enumerator != null);

    //                 m_base_enumerator = base_enumerator;

    //                 Reset();

    //             }

    //             public ActorBufferEnumerator(IEnumerator<KeyValuePair<IActor, IActor>> cur_enumerator)

    //             {

    //                 m_cur_enumerator = cur_enumerator;

    //                 m_single_type = true;

    //             }

    //

    //             IEnumerator<KeyValuePair<Type, Dictionary<IActor, IActor>>> m_base_enumerator;

    //             IEnumerator<KeyValuePair<IActor, IActor>> m_cur_enumerator;

    //             bool m_single_type = false;

    //             

    //             public T Current

    //             {

    //                 get { return (T)m_cur_enumerator.Current.Key; }

    //             }

    //

    //             public void Dispose()

    //             {

    //                 if (m_base_enumerator != null)

    //                 {

    //                     m_base_enumerator.Dispose();

    //                 }

    //                 if (m_cur_enumerator != null)

    //                 {

    //                     m_cur_enumerator.Dispose();

    //                 }

    //             }

    //

    //             object System.Collections.IEnumerator.Current

    //             {

    //                 get { return m_cur_enumerator.Current.Key; }

    //             }

    //

    //             public bool MoveNext()

    //             {

    //                 if (m_cur_enumerator == null)

    //                 {

    //                     return false;

    //                 }

    //                 if (m_cur_enumerator.MoveNext())

    //                 {

    //                     return true;

    //                 }

    //                 else

    //                 {

    //                     if (!m_single_type && m_base_enumerator.MoveNext())

    //                     {

    //                         m_cur_enumerator = m_base_enumerator.Current.Value.GetEnumerator();

    //

    //                         return MoveNext();

    //                     }

    //                     else

    //                     {

    //                         return false;

    //                     }

    //                 }

    //             }

    //             

    //             public void Reset()

    //             {

    //                 if (m_single_type && m_cur_enumerator != null)

    //                 {

    //                     m_cur_enumerator.Reset();

    //                 }

    //                 else

    //                 {

    //                     m_base_enumerator.Reset();

    //                     if (m_base_enumerator.MoveNext())

    //                     {

    //                         m_cur_enumerator = m_base_enumerator.Current.Value.GetEnumerator();

    //                     }

    //                     else

    //                     {

    //                         m_cur_enumerator = null;

    //                     }

    //                 }

    //             }

    //         }

    //

    //         // 是否沒有内容

    //         public bool empty()

    //         {

    //             return m_dic.Count == 0;

    //         }

    //         //

    //         public void insert(IActor a)

    //         {

    //             if (!m_dic.ContainsKey(a.GetType()))

    //             {

    //                 m_dic.Add(a.GetType(), new Dictionary<IActor, IActor>());

    //             }

    //             m_dic[a.GetType()].Add(a, a);

    //             m_actor_fun.insert(a, m_layer);

    //         }

    //         //

    //         public void remove(IActor a)

    //         {

    //             if (m_dic.ContainsKey(a.GetType()))

    //             {

    //                 m_dic[a.GetType()].Remove(a);

    //                 m_actor_fun.remove(a, m_layer);

    //                 if (m_dic[a.GetType()].Count == 0)

    //                 {

    //                     m_dic.Remove(a.GetType());

    //                 }

    //             }

    //         }

    //         // 清除所有内容

    //         // 本類不負責所記錄actor的銷毀

    //         public void clear()

    //         {

    //             m_dic.Clear();

    //         }

    //         // 集合減操作,修改自身内容

    //         public void substract(ActorBuffer buf)

    //         {

    //             foreach (KeyValuePair<Type, Dictionary<IActor, IActor>> tvp in buf.m_dic)

    //             {

    //                 if (m_dic.ContainsKey(tvp.Key))

    //                 {

    //                     foreach (KeyValuePair<IActor, IActor> kvp in tvp.Value)

    //                     {

    //                         if (m_dic[tvp.Key].ContainsKey(kvp.Key))

    //                         {

    //                             m_dic[tvp.Key].Remove(kvp.Key);

    //                             m_actor_fun.remove(kvp.Key, m_layer);

    //                         }

    //                     }

    //                     if (m_dic[tvp.Key].Count == 0)

    //                     {

    //                         m_dic.Remove(tvp.Key);

    //                     }

    //                 }

    //             }

    //         }

    //         // 集合并操作,修改自身内容

    //         public void add(ActorBuffer buf)

    //         {

    //             foreach (KeyValuePair<Type, Dictionary<IActor, IActor>> tvp in buf.m_dic)

    //             {

    //                 if (!m_dic.ContainsKey(tvp.Key))

    //                 {

    //                     m_dic.Add(tvp.Key, new Dictionary<IActor, IActor>());

    //                 }

    //                 foreach (KeyValuePair<IActor, IActor> kvp in tvp.Value)

    //                 {

    //                     if (!m_dic[tvp.Key].ContainsKey(kvp.Key))

    //                     {

    //                         m_dic[tvp.Key].Add(kvp.Key, kvp.Value);

    //                         m_actor_fun.insert(kvp.Key, m_layer);

    //                     }

    //                 }

    //                 if (m_dic[tvp.Key].Count == 0)

    //                 {

    //                     m_dic.Remove(tvp.Key);

    //                 }

    //             }

    //         }

    //         // 複制自身内容,注意不複制對應的IActorFun

    //         public ActorBuffer clone()

    //         {

    //             ActorBuffer actorbuf = new ActorBuffer(null, new DummyActorFun());

    //

    //             actorbuf.add(this);

    //

    //             return actorbuf;

    //         }

    // //         // 針對不同類型的疊代器

    // //         public IEnumerator<T> GetEnumerator<T>() where T : IActor

    // //         {

    // //             if (m_dic.ContainsKey(typeof(T)))

    // //             {

    // //                 return new ActorBufferEnumerator<T>(m_dic[typeof(T)].GetEnumerator());

    // //             }

    // //             else

    // //             {

    // //                 return new ActorBufferEnumerator<T>((IEnumerator<KeyValuePair<IActor, IActor>>)null);

    // //             }

    // //         }

    // //         //

    // //         public IEnumerator<IActor> GetEnumerator()

    // //         {

    // //             return new ActorBufferEnumerator<IActor>(m_dic.GetEnumerator());

    // //         }

    // //         //

    // //         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    // //         {

    // //             return new ActorBufferEnumerator<IActor>(m_dic.GetEnumerator());

    // //         }

    //

    //         // 針對不同類型的疊代器

    //         public IEnumerator<T> GetEnumerator<T>() where T : IActor

    //         {

    //             return GetEnumerator<T>(false);

    //         }

    //         public IEnumerator<T> GetEnumerator<T>(bool recurse) where T : IActor

    //         {

    //             return new ActorBufferEnumerator<T>(recurse, false, m_actor_dic, m_type_dic);

    //         }

    //         public IEnumerator<T> GetReverseEnumerator<T>() where T : IActor

    //         {

    //             return GetReverseEnumerator<T>(false);

    //         }

    //         public IEnumerator<T> GetReverseEnumerator<T>(bool recurse) where T : IActor

    //         {

    //             return new ActorBufferEnumerator<T>(recurse, true, m_actor_dic, m_type_dic);

    //         }

    //         //

    //         public IEnumerator<IActor> GetEnumerator()

    //         {

    //             return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

    //         }

    //         //

    //         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    //         {

    //             return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

    //         }

    //

    //         // 是否包含指定的物品

    //         public bool contain(IActor actor)

    //         {

    //             if (actor != null)

    //             {

    //                 if (m_dic.ContainsKey(actor.GetType()))

    //                 {

    //                     return m_dic[actor.GetType()].ContainsKey(actor);

    //                 }

    //             }

    //             return false;

    //         }

    //     }

    // 物品容器,用來記錄相同類型和不同類型的物品,可以輪訓

    // 不負責所記錄actor的銷毀

    public class ActorBuffer : IEnumerable<IActor>

    {

        /// <summary>

        /// 所在的物品層

        /// </summary>

        [XmlIgnore]

        public IActorLayerMng LayerMng

        {

            get { return m_layer; }

            set { m_layer = value; }

        }

        /// <summary>

        /// 物品移入移出時所調用的函數

        /// 序列化使用

        /// </summary>

        [XmlElement]

        public IActorFun ActorFun

        {

            get { return m_actor_fun; }

            set { m_actor_fun = value; }

        }

        //判斷内部類型是否是傳入類型或者是否是傳入類型的子類型

        public ActorBuffer getTypeActors(Type _t)

        {

            ActorBuffer buffer = new ActorBuffer(m_layer, m_actor_fun);

            foreach (Type type in m_actor_dic.Keys)

            {

                bool b = false; Type t = type;

                while (t != null && !b)

                    if (t.Equals(_t))

                        b = true;

                    else

                        t = t.BaseType;

                if (b)

                    foreach (IActor actor in m_actor_dic[type].Values)

                        buffer.insert(actor);

            }

            return buffer;

        }

        public ActorBuffer(IActorLayerMng layer, IActorFun fun)

        {

            m_layer = layer;

            m_actor_fun = fun;

        }

        // 是否沒有内容

        public bool empty()

        {

            return m_actor_dic.Count == 0;

        }

        //

        public void insert(IActor a)

        {

            if (!m_actor_dic.ContainsKey(a.GetType()))

            {

                m_actor_dic.Add(a.GetType(), new Dictionary<GIID, IActor>());

                addType(a.GetType());

            }

            if (!m_actor_dic[a.GetType()].ContainsKey(a.giid))

            {

                m_actor_dic[a.GetType()].Add(a.giid, a);

                if (a.getActorBuffer() != null)

                    addChildren(a);

                m_actor_fun.insert(a, m_layer);

                //if (m_layer != null)

                //    a.parentLayer = m_layer;

            }

        }

        //

        public void remove(IActor a)

        {

            if (m_actor_dic.ContainsKey(a.GetType()))

            {

                m_actor_dic[a.GetType()].Remove(a.giid);

                if (m_actor_dic[a.GetType()].Count == 0)

                {

                    m_actor_dic.Remove(a.GetType());

                    removeType(a.GetType());

                }

                if (a.getActorBuffer() != null)

                    substractChildren(a);

                m_actor_fun.remove(a, m_layer);

            }

        }

        public IActor find(GIID giid)

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> pair in m_actor_dic)

            {

                if (pair.Value.ContainsKey(giid))

                {

                    return pair.Value[giid];

                }

            }

            return null;

        }

        // 清除所有内容

        // 本類不負責所記錄actor的銷毀

        public void clear()

        {

            List<IActor> romove_list = new List<IActor>();

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in m_actor_dic)

            {

                foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                {

                    romove_list.Add(kvp.Value);

                }

            }

            m_actor_dic.Clear();

            m_type_dic.Clear();

            foreach (IActor actor in romove_list)

            {

                m_actor_fun.remove(actor, m_layer);

            }

        }

        // 集合減操作,修改自身内容

        public void substract(ActorBuffer buf)

        {

            List<IActor> romove_list = new List<IActor>();

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in buf.m_actor_dic)

            {

                if (m_actor_dic.ContainsKey(tvp.Key))

                {

                    Dictionary<GIID, IActor> actors = m_actor_dic[tvp.Key];

                    foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                    {

                        if (actors.ContainsKey(kvp.Key))

                        {

                            actors.Remove(kvp.Key);

                            romove_list.Add(kvp.Value);

                        }

                    }

                    if (actors.Count == 0)

                    {

                        m_actor_dic.Remove(tvp.Key);

                        removeType(tvp.Key);

                    }

                }

            }

            foreach (IActor actor in romove_list)

            {

                if (actor.getActorBuffer() != null)

                    substractChildren(actor);

                //actor.DoBeforeDel();

                m_actor_fun.remove(actor, m_layer);

            }

        }

        private void substractChildren(IActor actor)

        {

            foreach (IActor childActor in actor.getActorBuffer().getOrgBuffer())

            {

                if (childActor.getActorBuffer() != null)

                    substractChildren(childActor);

                m_actor_fun.remove(childActor, m_layer);

            }

        }

        // 集合并操作,修改自身内容

        public void add(ActorBuffer buf)

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in buf.m_actor_dic)

            {

                if (!m_actor_dic.ContainsKey(tvp.Key))

                {

                    m_actor_dic.Add(tvp.Key, new Dictionary<GIID, IActor>());

                    addType(tvp.Key);

                }

                Dictionary<GIID, IActor> actors = m_actor_dic[tvp.Key];

                foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                {

                    if (!actors.ContainsKey(kvp.Key))

                    {

                        actors.Add(kvp.Key, kvp.Value);

                        if (kvp.Value.getActorBuffer() != null)

                            addChildren(kvp.Value);

                        m_actor_fun.insert(kvp.Value, m_layer);

                        //if (m_layer != null)

                        //    kvp.Value.parentLayer = m_layer;

                    }

                }

            }

        }

        private void addChildren(IActor actor)

        {

            foreach (IActor childActor in actor.getActorBuffer().getOrgBuffer())

            {

                if (childActor.getActorBuffer() != null)

                    addChildren(childActor);

                m_actor_fun.insert(childActor, m_layer);

                childActor.parentLayer = actor.getActorBuffer();

            }

        }

        // 複制自身内容,注意不複制對應的IActorFun

        public ActorBuffer clone()

        {

            ActorBuffer actorbuf = new ActorBuffer(null, new DummyActorFun());

            actorbuf.add(this);

            return actorbuf;

        }

        // 針對不同類型的疊代器

        public IEnumerator<T> GetEnumerator<T>() where T : IActor

        {

            return GetEnumerator<T>(false);

        }

        public IEnumerator<T> GetEnumerator<T>(bool recurse) where T : IActor

        {

            return new ActorBufferEnumerator<T>(recurse, false, m_actor_dic, m_type_dic);

        }

        public IEnumerator<T> GetReverseEnumerator<T>() where T : IActor

        {

            return GetReverseEnumerator<T>(false);

        }

        public IEnumerator<T> GetReverseEnumerator<T>(bool recurse) where T : IActor

        {

            return new ActorBufferEnumerator<T>(recurse, true, m_actor_dic, m_type_dic);

        }

        //

        public IEnumerator<IActor> GetEnumerator()

        {

            return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

        }

        //

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

        {

            return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

        }

        // 是否包含指定的物品

        public bool contain(IActor actor)

        {

            if (actor != null)

            {

                if (m_actor_dic.ContainsKey(actor.GetType()))

                {

                    return m_actor_dic[actor.GetType()].ContainsKey(actor.giid);

                }

            }

            return false;

        }

        private void addType(Type type)

        {

            Type base_type = type.BaseType;

            Type iactor_type = typeof(IActor);

            if (iactor_type.IsAssignableFrom(base_type))

            {

                addType(base_type);

            }

            else

            {

                base_type = iactor_type;

            }

            if (!m_type_dic.ContainsKey(base_type))

            {

                m_type_dic.Add(base_type, new Dictionary<Type, Type>());

            }

            if (!m_type_dic[base_type].ContainsKey(type))

            {

                m_type_dic[base_type].Add(type, type);

            }

        }

        private void removeType(Type type)

        {

            if (!m_type_dic.ContainsKey(type))

            {

                Type base_type = type.BaseType;

                Type iactor_type = typeof(IActor);

                if (!iactor_type.IsAssignableFrom(base_type))

                {

                    base_type = iactor_type;

                }

                if (!m_type_dic.ContainsKey(type) && m_type_dic.ContainsKey(base_type))

                {

                    m_type_dic[base_type].Remove(type);

                    if (m_type_dic[base_type].Count == 0)

                    {

                        m_type_dic.Remove(base_type);

                    }

                }

            }

        }

        /// <summary>

        /// 擷取一個Actor,當隻有一個Actor存在時,這個Actor一般是根Actor

        /// </summary>

        /// <returns></returns>

        public IActor getFirstActor()

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> pair in m_actor_dic)

            {

                foreach (KeyValuePair<GIID, IActor> p in pair.Value)

                {

                    return p.Value;

                }

            }

            return null;

        }

        // 疊代器供疊代使用,将Dictionary的疊代器轉化為IEnumerator<IActor>類型的疊代器

        // fixme: 可以為了針對指定類型的疊代,這個類還需要記錄所剩物品類型所對應的物品容器

        private class ActorBufferEnumerator<T> : IEnumerator<T> where T : IActor

        {

            public ActorBufferEnumerator(bool recurse, bool reverse, Dictionary<Type, Dictionary<GIID, IActor>> actor_dic, Dictionary<Type, Dictionary<Type, Type>> type_dic)

            {

                m_recurse = recurse;

                m_reverse = reverse;

                m_actor_dic = actor_dic;

                m_type_dic = type_dic;

                Reset();

            }

            public T Current

            {

                get { return (T)m_cur_enumerator.Current.Value; }

            }

            public void Dispose()

            {

                if (m_cur_enumerator != null)

                {

                    m_cur_enumerator.Dispose();

                }

            }

            object System.Collections.IEnumerator.Current

            {

                get { return m_cur_enumerator.Current.Key; }

            }

            public bool MoveNext()

            {

                if (m_cur_enumerator != null && m_cur_enumerator.MoveNext())

                {

                    return true;

                }

                else

                {

                    if (m_type_stack.Count > 0)

                    {

                        Type cur_type = m_type_stack[0];

                        m_type_stack.RemoveAt(0);

                        if (m_recurse && m_type_dic.ContainsKey(cur_type))

                        {

                            foreach (KeyValuePair<Type, Type> kvp in (m_reverse ? Enumerable.Reverse(m_type_dic[cur_type]) : m_type_dic[cur_type]))

                            {

                                m_type_stack.Add(kvp.Key);

                            }

                        }

                        if (m_actor_dic.ContainsKey(cur_type))

                        {

                            m_cur_enumerator = (m_reverse ? Enumerable.Reverse(m_actor_dic[cur_type]) : m_actor_dic[cur_type]).GetEnumerator();

                        }

                        return MoveNext();

                    }

                    else

                    {

                        return false;

                    }

                }

            }

            public void Reset()

            {

                m_type_stack.Clear();

                m_type_stack.Add(m_base_type);

                m_cur_enumerator = null;

            }

            List<Type> m_type_stack = new List<Type>();

            IEnumerator<KeyValuePair<GIID, IActor>> m_cur_enumerator;

            Type m_base_type = typeof(T);

            bool m_recurse = false;

            bool m_reverse = false;

            Dictionary<Type, Dictionary<GIID, IActor>> m_actor_dic;

            Dictionary<Type, Dictionary<Type, Type>> m_type_dic;

        }

        // 所在的物品層

        IActorLayerMng m_layer;

        // 物品移入移出時所調用的函數

        IActorFun m_actor_fun;

        // 物品容器用來記錄所有的物品

        Dictionary<Type, Dictionary<GIID, IActor>> m_actor_dic = new Dictionary<Type, Dictionary<GIID, IActor>>();

        Dictionary<Type, Dictionary<Type, Type>> m_type_dic = new Dictionary<Type, Dictionary<Type, Type>>();

    }

    // Actor輔助類

    public class GActorHelper

    {

        // 根據生成屬性生成指定類别物品

        public static IActor generateActor(string type, Dictionary<string, string> createpropdic, IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

            IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", (IEditItem)SceneGraph.getEditItemCommon("RootItem", edititem));

            IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

            string prefix = (type != "DancerActor" && createpropdic.ContainsKey("NamePrefix")) ? createpropdic["NamePrefix"] : "dancer";

            int actorindex = doc.getMaxActorIndex(prefix);

            switch (type)

            {

                case "ModelActor":

                    return new ModelActor(root.giidmng, createpropdic, root.clientRenderSys, actorindex);

                case "EffectActor":

                    return new EffectActor(root.giidmng, createpropdic, root.clientRenderSys, actorindex);

                case "LightActor":

                    return new LightActor(root.giidmng, new LightInfo(), root.clientRenderSys);

                case "AINodeActor":

                    return new AINodeActor(root.giidmng);                        // fixme :

                case "SoundActor":

                    return new SoundActor(root.giidmng);

                case "GroupActor":

                    return new GroupActor(root.giidmng);

                case "PrefebActor":

                    return PrefebManager.getActorBufferFromPrefebFile(createpropdic["group"], createpropdic["name"], edititem);

                case "DancerActor":

                    return new DancerActor(root.giidmng, "nametest", true, actorindex - 1, root.clientRenderSys);

                default:

                    return null;

            }

        }

        // 生成不含物品具體資訊的物品

        public static IActor generateActorWithoutInfo(string type, IEditItem edititem)

        {

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", edititem));

            switch (type)

            {

                case "ModelActor":

                    return new ModelActor(root.giidmng);

                case "EffectActor":

                    return new EffectActor(root.giidmng);

                case "LightActor":

                    return new LightActor(root.giidmng);

                case "AINodeActor":

                    return new AINodeActor(root.giidmng);

                case "SoundActor":

                    return new SoundActor(root.giidmng);

                case "GroupActor":

                    return new GroupActor(root.giidmng);

                case "PrefebActor":

                    return new PrefebActor(root.giidmng);

                default:

                    return null;

            }

        }

        public static void getTypeActors(Dictionary<IActorLayerMng, ActorBuffer> resultactors, IActorLayerMng layer, string type, bool select, bool substract)

        {

            ActorBuffer allab = select ? (layer.getSelBuffer()) : (layer.getOrgBuffer());

            foreach (IActor actor in allab)

            {

                if (getActorTypestr(actor) == type)

                {

                    if (!resultactors.ContainsKey(layer))

                    {

                        resultactors[layer] = new ActorBuffer(null, new DummyActorFun());

                    }

                    resultactors[layer].insert(actor);

                    //ab.insert(actor);

                }

            }

            if (substract)

            {

                foreach (IActor actor in allab)

                {

                    if (getActorTypestr(actor) == type)

                    {

                        layer.getOrgBuffer().remove(actor);

                    }

                }

            }

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                getTypeActors(resultactors, sublayer, type, select, substract);

            }

        }

        //得到指定層及其子層中的物品 unfreeze:為true則不擷取當機物體 DTK198 liaowenfang

        public static void getActors(ActorBuffer ab, IActorLayerMng layer, bool select, bool substract, bool unfreeze)

        {

            ActorBuffer allab = select ? (layer.getSelBuffer()) : (layer.getOrgBuffer());

            ab.add(allab);

            if (substract)

            {

                layer.getOrgBuffer().substract(allab);

            }

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                getActors(ab, sublayer, select, substract);

            }

            if (unfreeze)

            {

                ActorBuffer ufab = new ActorBuffer(ab.LayerMng, ab.ActorFun);

                foreach (IActor actor in ab)

                    if (!actor.freeze && !actor.hide && !BaseCommand.isActorLayerReadOnly(actor.parentLayer, BaseCommand.ACTORLAYER_ITERATE_MODE.FREEZE | BaseCommand.ACTORLAYER_ITERATE_MODE.HIDE))

                        ufab.insert(actor);

                ab.clear();

                ab.add(ufab);

            }

        }

        // 得到指定層及其子層中的物品,參數含義同getTypeActors

        public static void getActors(ActorBuffer ab, IActorLayerMng layer, bool select, bool substract)

        {

            getActors(ab, layer, select, substract, false);

        }

        public static void updatePrefebActors(IActorLayerMng layer, string groupname, string prefebname)

        {

            ActorBuffer abold = new ActorBuffer(null, new DummyActorFun());

            ActorBuffer abnew = new ActorBuffer(null, new DummyActorFun());

            foreach (IActor actor in layer.getOrgBuffer())

            {

                if (actor is PrefebActor)

                {

                    PrefebActor pactor = actor as PrefebActor;

                    if (pactor.isCreateFrom(groupname, prefebname))

                    {

                        abold.insert(actor);

                        IActor newactor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, layer);

                        // 位置更新

                        Vector3F posold = GActorHelper.getMinPos(actor.getActorBuffer().getOrgBuffer());

                        Vector3F posnew = GActorHelper.getMinPos(newactor.getActorBuffer().getOrgBuffer());

                        Vector3F posmove = posold - posnew;

                        foreach (IActor subactor in newactor.getActorBuffer().getOrgBuffer())

                        {

                            subactor.move(posmove);

                        }

                        abnew.insert(newactor);

                    }

                }

            }

            layer.getOrgBuffer().substract(abold);

            layer.getOrgBuffer().add(abnew);

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                updatePrefebActors(sublayer, groupname, prefebname);

            }

        }

        // 得到物品類别字元串

        public static string getActorTypestr(IActor actor)

        {

            if (actor is ModelActor)

            {

                return "ModelActor";

            }

            else if (actor is EffectActor)

            {

                return "EffectActor";

            }

            else if (actor is SoundActor)

            {

                return "SoundActor";

            }

            else if (actor is AINodeActor)

            {

                return "AINodeActor";

            }

            else if (actor is LightActor)

            {

                return "LightActor";

            }

            else if (actor is GroupActor)

            {

                if (actor is PrefebActor)

                {

                    return "PrefebActor";

                }

                return "GroupActor";

            }

            else if (actor is DancerActor)

            {

                return "DancerActor";

            }

            AssertUtil.confirm(false);

            return "";

        }

        // 得到多個物品的最小位置

        public static Vector3F getMinPos(ActorBuffer ab)

        {

            if (ab.Count<IActor>() == 0)

            {

                return Vector3F.Zero;

            }

            IActor actor0 = ab.ElementAt<IActor>(0);

            Vector3F pos = actor0.aabb.Min;

            foreach (IActor actor in ab)

            {

                if (actor.aabb.Min.X < pos.X)

                {

                    pos.X = actor.aabb.Min.X;

                }

                if (actor.aabb.Min.Y < pos.Y)

                {

                    pos.Y = actor.aabb.Min.Y;

                }

                if (actor.aabb.Min.Z < pos.Z)

                {

                    pos.Z = actor.aabb.Min.Z;

                }

            }

            return pos;

        }

        得到多個物品的最小位置

        //public static Vector3F getMinPos(ActorBuffer ab)

        //{

        //    if (ab.Count<IActor>() == 0)

        //    {

        //        return Vector3F.Zero;

        //    }

        //    IActor actor0 = ab.ElementAt<IActor>(0);

        //    Vector3F pos = new Vector3F(actor0.locationmat.M14, actor0.locationmat.M24, actor0.locationmat.M34);

        //    foreach (IActor actor in ab)

        //    {

        //        if (actor.locationmat.M14 < pos.X)

        //        {

        //            pos.X = actor.locationmat.M14;

        //        }

        //        if (actor.locationmat.M24 < pos.Y)

        //        {

        //            pos.Y = actor.locationmat.M24;

        //        }

        //        if (actor.locationmat.M34 < pos.Z)

        //        {

        //            pos.Z = actor.locationmat.M34;

        //        }

        //    }

        //    return pos;

        //}

        // 得到多個物品的最大位置

        public static Vector3F getMaxPos(ActorBuffer ab)

        {

            if (ab.Count<IActor>() == 0)

            {

                return Vector3F.Zero;

            }

            IActor actor0 = ab.ElementAt<IActor>(0);

            Vector3F pos = actor0.aabb.Max;

            foreach (IActor actor in ab)

            {

                if (actor.aabb.Max.X > pos.X)

                {

                    pos.X = actor.aabb.Max.X;

                }

                if (actor.aabb.Max.Y > pos.Y)

                {

                    pos.Y = actor.aabb.Max.Y;

                }

                if (actor.aabb.Max.Z > pos.Z)

                {

                    pos.Z = actor.aabb.Max.Z;

                }

            }

            return pos;

        }

        public static Vector3F ComputeCenter(ActorBuffer ab)

        {

            if (ab == null || ab.empty())

            {

                return new Vector3F();

            }

            if (ab.Count<IActor>() == 1)

            {

                return ab.ElementAt(0).center;

            }

            Vector3F max = getMaxPos(ab);

            Vector3F min = getMinPos(ab);

            Vector3F res = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

            return res;

        }

        public static void drawCircle(Vector3F center, Vector3F normal, float radius, Color color, ClientBridge.ClientRenderSys rendersys)

        {

            normal.Normalize();

            // 用360個點的連線模拟圓

            int pointcount = 360;

            float[] points = new float[pointcount * 3];

            int[] indexs = new int[pointcount * 3 + 1];

            for (int t = 0; t < pointcount; t++)

            {

                float factor = 0;

                Vector3F u = new Vector3F();

                if (Math.Abs(normal.X) > Math.Abs(normal.Y))

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.X * normal.X + normal.Z * normal.Z);

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

                    factor = 1.0f / (float)Math.Sqrt(normal.Y * normal.Y + normal.Z * normal.Z);

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

                Vector3F v = Vector3F.CrossProduct(normal, u);

                v.Normalize();

                points[t * 3] = (float)(center.X + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.X + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.X);

                points[t * 3 + 1] = (float)(center.Y + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Y + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Y);

                points[t * 3 + 2] = (float)(center.Z + (radius * Math.Cos(Math.PI * t / 180.0f)) * u.Z + (radius * Math.Sin(Math.PI * t / 180.0f)) * v.Z);

                indexs[t * 3] = t * 3;

                indexs[t * 3 + 1] = t * 3 + 1;

                indexs[t * 3 + 2] = t * 3 + 2;

            }

            indexs[pointcount * 3] = 0;

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points, indexs, color.toArray(), true);

        }

        public static void drawRotateCircles(List<uint> idlist, Vector3F center, ClientBridge.ClientRenderSys rendersys)

        {

            Color cr = new Color(1, 0, 0, 1);

            Color cg = new Color(0, 1, 0, 1);

            Color cb = new Color(0, 0, 1, 1);

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[0]);

            }

            GActorHelper.drawCircle(center, new Vector3F(1, 0, 0), 1, cr, rendersys);  // 繪制垂直于x軸的圓

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[1]);

            }

            GActorHelper.drawCircle(center, new Vector3F(0, 1, 0), 1, cg, rendersys);  // 繪制垂直于y軸的圓

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[2]);

            }

            GActorHelper.drawCircle(center, new Vector3F(0, 0, 1), 1, cb, rendersys);  // 繪制垂直于z軸的圓

            //List<float> viewmat = new List<float>();

            //for (int i = 0; i < 16; i++)

            //{

            //    viewmat.Add(0);

            //}

            //rendersys.getPerspective(viewmat);

            //Vector3F dir = new Vector3F(viewmat[0], viewmat[4], viewmat[8]);

            //GActorHelper.drawCircle(center, dir, 2, cr, rendersys);

            float[] points = { center.X, center.Y, center.Z,      // 0 o

                               center.X + 1, center.Y, center.Z,  // 1 x

                               center.X, center.Y + 1, center.Z,  // 2 y

                               center.X, center.Y,center.Z + 1,   // 3 z

                             };

            int[] indexsx = { 0, 1 };

            int[] indexsy = { 0, 2 };

            int[] indexsz = { 0, 3 };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsx, cr.toArray(), true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsy, cg.toArray(), true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsz, cb.toArray(), true);

        }

    }

    // 物品管理層借口類,可以有子層

    // fixme: 子層沒有記錄在scenegraph裡面

    public interface IActorLayerMng : IEditItem

    {

        // 獲得原始物品容器

        ActorBuffer getOrgBuffer();

        // 獲得選中物品容器

        ActorBuffer getSelBuffer();

        // 獲得屬性清單

        IDictionary<String, String> getPropertyList();

        // 物品包圍盒變化

        void OnActorAABBChanged(IActor actor, AxisAlignedBox aabb);

        // 修改key對應的value

        void notifyPropertyChange(String key, String value);

        // 獲得目前的物品管理層

        IActorLayerMng currentLayerMng { get; set; }

        // 設定最具體的目前的編輯層,如果layer不在目前層會繼續到下一層設定

        void setCurrentLayerMng(IActorLayerMng layer);

        // 獲得目前的編輯層,與currentLayerMng不同的是:這個函數可以獲得最具體的目前編輯層

        IActorLayerMng getCurrentLayerMng();

        // 獲得根物品管理器

        IActorLayerMng getRootActorLayer();

        // 看給定的layer,在那個子物品管理器中

        IActorLayerMng getSubRootActorLayer(IActorLayerMng layer);

        // 獲得所有的子物品管理層

        IList<IActorLayerMng> getList();

        // 清空所有内容

        void clean();

        // 獲得父親類

        IActorLayerMng parent

        {

            get;

            set;

        }

        string name

        {

            get;

            set;

        }

        // 獲得目前layer的位置偏移量

        // fixme: 幫助函數,接口類中不應該定義

        void getOffset(ref float delx, ref float dely);

        //建立子層

        IActorLayerMng createSubActorLayer();

        // 更新

        void update(int t);

        void UpdateCpuSkin(float t);

        // 繪制

        void render(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制包圍盒

        void renderAABB(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制移動控制軸

        void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制移動控制軸

        void renderSingleCircle(int t, ClientBridge.ClientRenderSys rendersys);

        // 繪制旋轉控制圈

        void renderCircles(int t, ClientBridge.ClientRenderSys rendersys);

        // 儲存層中的物品

        bool serialize(BinaryWriter binWriter);

        // 讀取物品

        bool serialize(BinaryReader binReader, IEditItem edititem);

        // save

        bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool clipboard);

        // load

        bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, IMacroCommand cmd, bool clipboard);

        void customHardwareSelect(Dictionary<IActorLayerMng, ActorBuffer> selactors, IView view, Rect<int> rect, bool selectfirst);

        // 将物品添加到硬體選擇

        void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将物品移動控制軸添加到硬體選擇

        void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys);

        // 将物品旋轉控制圓添加到硬體選擇

        void pushHardwareSelect_Rotate(RotateMode rm, ClientBridge.ClientRenderSys rendersys);

        // 将指定ID對應的物品添加到dictionary中

        void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id);

        // 傳回指定ID對應的移動控制軸的編号

        int getSelectMoveLineID(int id);

        // 傳回指定ID對應的旋轉控制圓的編号

        int getSelectRotateCircleID(int id);

        // 是否可以複制、剪切

        bool canCopyCut();

        // 是否可以粘貼

        bool canPaste();

        //判斷是否可執行group操作

        bool canCreateGroup();

        bool canDestroyGroup();

        bool canOpenGroup();

        bool canCloseGroup();

        bool canDettachGroup();

        bool canAttachGroup();

        //建立物品組 不同的物品層可能會建立不同類型的GruopActor

        GroupActor createLayerActorGroup(string name, out ActorBuffer ab);

        //設定所有actor的lod級别

        void setActorMaterialLod(ClientBridge.LOD_LEVEL lod);

        //父層的Hide狀态改變,回調通知子層及子Actor

        void notifyLayerHide(bool isHide);

        //父層的Freeze狀态改變,回調通知子層及子Actor

        void notifyLayerFreeze(bool isFreeze);

        //傳回用于層管理器中的層清單

        IList<IActorLayerMng> getLayersToManage();

    }

    // 物品管理層實作類

    public class ActorLayerMngImp : BaseEditItem, IActorLayerMng

    {

        // fixme: 應該通過子容器的屬性設定,而不是用這個值來表示

        IActorLayerMng m_cur_actor_layer = null;

        List<IActorLayerMng> m_actor_layer_list = new List<IActorLayerMng>();

        String m_name;

        ActorBuffer m_org_buffer;

        ActorBuffer m_sel_buffer;

        // 屬性清單,用來記錄若幹物品資訊

        IDictionary<String, String> m_property_list = new Dictionary<String, String>();

        IActorLayerMng m_parent = null;

        // 獲得父親類

        public IActorLayerMng parent

        {

            get { return m_parent; }

            set { m_parent = value; }

        }

        public string name

        {

            get { return m_name; }

            set { m_name = value; }

        }

        // orgfun表示将物品從原始物品清單中移入移出需要調用的函數

        // selfun表示将物品從選擇物品清單中移入移出需要調用的函數

        public ActorLayerMngImp(IEditItem parent, IActorFun orgfun, IActorFun selfun)

        {

            m_org_buffer = new ActorBuffer(this, orgfun);

            m_sel_buffer = new ActorBuffer(this, selfun);

            m_parent = (IActorLayerMng)parent;

            name = "物品簇";

        }

        public ActorLayerMngImp(IEditItem parent, IActorFun orgfun, IActorFun selfun, string name_string)

        {

            m_org_buffer = new ActorBuffer(this, orgfun);

            m_sel_buffer = new ActorBuffer(this, selfun);

            m_parent = (IActorLayerMng)parent;

            name = name_string;

        }

        /// <summary>

        /// 用于序列化

        /// </summary>

        public ActorLayerMngImp()

        {

        }

        // 儲存

        public bool serialize(BinaryWriter binWriter)

        {

            // 儲存ActorLayer自身資訊

            binWriter.Write(name);  // string

            binWriter.Write(getOrgBuffer().Count<IActor>());    // 物品個數

            binWriter.Write(getList().Count<IActorLayerMng>()); // 子層個數

            // 儲存各子物品

            foreach (IActor actor in getOrgBuffer())

            {

                binWriter.Write(GActorHelper.getActorTypestr(actor));

                actor.serialize(binWriter);

            }

            // 儲存各子層

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.serialize(binWriter);

            }

            return true;

        }

        // 讀取

        public bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            name = binReader.ReadString();

            int actornum = binReader.ReadInt32();

            int sublayernum = binReader.ReadInt32();

            for (int i = 0; i < actornum; i++)

            {

                string type = binReader.ReadString();

                IActor actor = null;

                if (type == "PrefebActor")

                {

                    string groupname = binReader.ReadString();

                    string prefebname = binReader.ReadString();

                    actor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, edititem);

                }

                else

                {

                    actor = GActorHelper.generateActorWithoutInfo(type, edititem);

                }

                if (actor != null)

                {

                    actor.serialize(binReader, edititem);

                    getOrgBuffer().insert(actor);

                }

            }

            for (int i = 0; i < sublayernum; i++)

            {

                IActorLayerMng sublayer = new ActorLayerMngImp(this, new DummyActorFun(), new DummyActorFun());

                BaseCommand.getDocLogic(edititem).addCommand(new AddActorLayerCmd(this, sublayer));

                sublayer.serialize(binReader, edititem);

            }

            return true;

        }

        // save

        public virtual bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool clipboard)

        {

            System.Xml.XmlNode subnode;

            XmlAttribute att;

            // 儲存ActorLayer自身資訊

            att = xmlnode.OwnerDocument.CreateAttribute("Name");

            att.Value = name;

            xmlnode.Attributes.Append(att);

            att = xmlnode.OwnerDocument.CreateAttribute("Hide");

            att.Value = BaseCommand.isValueTrue(getPropertyList(), "hide").ToString();

            xmlnode.Attributes.Append(att);

            att = xmlnode.OwnerDocument.CreateAttribute("Freeze");

            att.Value = BaseCommand.isValueTrue(getPropertyList(), "freeze").ToString();

            xmlnode.Attributes.Append(att);

            // 儲存各子物品

            foreach (IActor actor in (clipboard ? getSelBuffer() : getOrgBuffer()))

            {

                if ((actor.flag & (int)ActorFlag.UNSERIALIZABLE) == 0)

                {

                    subnode = xmlnode.OwnerDocument.CreateNode("element", "Actor", "");

                    att = xmlnode.OwnerDocument.CreateAttribute("Type");

                    att.Value = GActorHelper.getActorTypestr(actor);

                    subnode.Attributes.Append(att);

                    actor.serialize(subnode, edititem, false, clipboard);

                    xmlnode.InsertAfter(subnode, xmlnode.LastChild);

                }

            }

            // 儲存各子層

            foreach (IActorLayerMng sublayer in getList())

            {

                subnode = xmlnode.OwnerDocument.CreateNode("element", "Layer", "");

                sublayer.serialize(subnode, edititem, clipboard);

                xmlnode.InsertAfter(subnode, xmlnode.LastChild);

            }

            return true;

        }

        // load

        public virtual bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, IMacroCommand cmd, bool clipboard)

        {

            //ClientBridge.Profile.Begin(129);

            ActorBuffer actor_buffer = new ActorBuffer(null, new DummyActorFun());

            foreach (System.Xml.XmlNode subnode in xmlnode.SelectNodes("Actor"))

            {

                XmlElement ele = (XmlElement)subnode;

                string type = ele.GetAttribute("Type");

                IActor actor = null;

                if (type == "PrefebActor")

                {

                    string groupname = ele.GetAttribute("GroupName");

                    string prefebname = ele.GetAttribute("PrefebName");

                    actor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, edititem);

                    foreach (XmlNode childnode in subnode.ChildNodes)

                    {

                        if (childnode.Name != "Item" && childnode.Name != "LocationMat")

                        {

                            actor.notifyPropertyChange(childnode.Name, childnode.InnerText);

                        }

                    }

                    XmlNode node = subnode.SelectSingleNode("LocationMat");

                    if (node != null)

                    {

                        Matrix4F locationmat = Matrix4F.setMatrix(node.InnerText);

                        PrefebManager.allrotateandmove((PrefebActor)actor, new Matrix4F(locationmat));

                    }

                    actor_buffer.insert(actor);

                }

                else

                {

                    actor = GActorHelper.generateActorWithoutInfo(type, edititem);

                    if (actor != null)

                    {

                        actor.serialize(subnode, edititem, true, clipboard);

                        actor_buffer.insert(actor);

                    }

                }

            }

            if (clipboard)

            {

                cmd.addCmd(new InsertCmd(this, actor_buffer));

            }

            else

            {

                getOrgBuffer().add(actor_buffer);

            }

            foreach (System.Xml.XmlNode subnode in xmlnode.SelectNodes("Layer"))

            {

                string layer_name = ((XmlElement)subnode).GetAttribute("Name");

                IActorLayerMng sublayer = GetLayerByName(layer_name);

                if (sublayer == null)

                {

                    sublayer = this.createSubActorLayer();

                    sublayer.name = layer_name;

                    this.getList().Add(sublayer);

                }

                sublayer.serialize(subnode, edititem, cmd, clipboard);

                if (((XmlElement)subnode).HasAttribute("Hide") && ((XmlElement)subnode).HasAttribute("Freeze"))

                {

                    sublayer.notifyPropertyChange("hide", ((XmlElement)subnode).GetAttribute("Hide").ToLower());

                    sublayer.notifyPropertyChange("freeze", ((XmlElement)subnode).GetAttribute("Freeze").ToLower());

                }

                SceneGraph.notify((IEditItem)SceneGraph.getEditItemCommon("RootItem", this.getRootActorLayer()), NotifyType.ACTOR, "LayerInsert/Remove", "");

            }

            //ClientBridge.Profile.End(129);

            return true;

        }

        protected IActorLayerMng GetLayerByName(string layer_name)

        {

            foreach (IActorLayerMng layer in m_actor_layer_list)

            {

                if (layer_name == layer.name)

                {

                    return layer;

                }

            }

            return null;

        }

        public virtual void setActorMaterialLod(ClientBridge.LOD_LEVEL lod)

        {

            IEnumerator<IActor> it_actor = Tool.GetActorsFromLayerManager<IActor>(this, true, true, true).GetEnumerator();

            while (it_actor.MoveNext())

            {

                if (it_actor.Current is ResActorBase)

                {

                    ((ResActorBase)it_actor.Current).SetLod(lod);

                }

            }

        }

        // 原始物品清單

        public ActorBuffer getOrgBuffer()

        {

            return m_org_buffer;

        }

        // 選中物品清單

        public ActorBuffer getSelBuffer()

        {

            return m_sel_buffer;

        }

        public IDictionary<string, string> getPropertyList()

        {

            return m_property_list;

        }

        public virtual void OnActorAABBChanged(IActor actor, AxisAlignedBox aabb)

        {

        }

        public void notifyPropertyChange(string key, string value)

        {

            m_property_list[key] = value;

        }

        //建立子層預設操作

        public virtual IActorLayerMng createSubActorLayer()

        {

            return new ActorLayerMngImp(this, new DummyActorFun(), new DummyActorFun());

        }

        // 需要根據類型進行設定和擷取

        public IActorLayerMng currentLayerMng

        {

            get

            {

                return m_cur_actor_layer;

            }

            set

            {

                m_cur_actor_layer = value;

            }

        }

        public void setCurrentLayerMng(IActorLayerMng layer)

        {

            if (layer == this)

            {

                currentLayerMng = null;

                return;

            }

            else

            {

                IActorLayerMng sublayer = getSubRootActorLayer(layer);

                AssertUtil.confirm(sublayer != null);

                currentLayerMng = sublayer;

                sublayer.setCurrentLayerMng(layer);

            }

        }

        public IActorLayerMng getCurrentLayerMng()

        {

            if (currentLayerMng == null)

                return this;

            else

                return currentLayerMng.getCurrentLayerMng();

        }

        public IActorLayerMng getRootActorLayer()

        {

            if (parent != null)

                return parent.getRootActorLayer();

            else

                return this;

        }

        public IActorLayerMng getSubRootActorLayer(IActorLayerMng layer)

        {

            foreach (IActorLayerMng subactorlayer in m_actor_layer_list)

            {

                if (subactorlayer == layer)

                    return subactorlayer;

                else if (subactorlayer.getSubRootActorLayer(layer) != null)

                    return subactorlayer;

            }

            return null;

        }

        public void getOffset(ref float delx, ref float dely)

        {

            if (currentLayerMng == null)

            {

                return;

            }

            else

            {

                // 找到current layer所對應的物品,然後累計偏移量

                foreach (IActor actor in getOrgBuffer())

                {

                    if (actor.getActorBuffer() == currentLayerMng)

                    {

                        delx += actor.rect.x;

                        dely += actor.rect.y;

                        currentLayerMng.getOffset(ref delx, ref dely);

                        return;

                    }

                }

            }

        }

        public IList<IActorLayerMng> getList()

        {

            return m_actor_layer_list;

        }

        override public void Dispose()

        {

            clean();

            base.Dispose();

        }

        public virtual void clean()

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.Dispose();

            }

            m_org_buffer.clear();

            m_sel_buffer.clear();

            foreach (IActorLayerMng al in m_actor_layer_list)

            {

                al.Dispose();

            }

            m_actor_layer_list.Clear();

            m_cur_actor_layer = null;

        }

        public static IActorLayerMng getCurrentLayerMng(IActorLayerMng layermng)

        {

            while (true)

            {

                if (layermng.currentLayerMng != null)

                    layermng = layermng.currentLayerMng; // go deeper

                else

                    return layermng;

            }

        }

        public virtual void customHardwareSelect(Dictionary<IActorLayerMng, ActorBuffer> selactors, IView view, Rect<int> rect, bool selectfirst)

        {

        }

        public void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.pushHardwareSelect(rendersys);

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushHardwareSelect(rendersys);

            }

        }

        public virtual void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                if (!actor.hide && !actor.freeze)

                {

                    actor.pushLineHardwareSelect(rendersys);

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushLineHardwareSelect(rendersys);

            }

        }

        public void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.pushHardwareSelect_Move(rendersys);

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushHardwareSelect_Move(rendersys);

            }

        }

        public void pushHardwareSelect_Rotate(RotateMode rm, ClientBridge.ClientRenderSys rendersys)

        {

            switch (rm)

            {

                case RotateMode.RM_SELF:

                    foreach (IActor actor in m_org_buffer)

                    {

                        actor.pushHardwareSelect_Rotate(rendersys);

                    }

                    foreach (IActorLayerMng sublayer in getList())

                    {

                        sublayer.pushHardwareSelect_Rotate(rm, rendersys);

                    }

                    break;

                case RotateMode.RM_WHOLE:

                    List<uint> idlist = new List<uint>();

                    idlist.Add(0);

                    idlist.Add(1);

                    idlist.Add(2);

                    ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

                    GActorHelper.getActors(ab, this, true, false);

                    Vector3F max = GActorHelper.getMaxPos(ab);

                    Vector3F min = GActorHelper.getMinPos(ab);

                    Vector3F center = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

                    GActorHelper.drawRotateCircles(idlist, center, rendersys);

                    break;

                default:

                    break;

            }

        }

        public int getSelectMoveLineID(int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                for (int i = 0; i < actor.giid_move.Count; i++)

                {

                    if (actor.giid_move[i].value == id)

                    {

                        return i;

                    }

                }

                //對Group的處理

                if (actor is GroupActor)

                {

                    GroupActor ga = actor as GroupActor;

                    int reid = ga.getActorBuffer().getSelectMoveLineID(id);

                    if (reid != -1)

                    {

                        return reid;

                    }

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                int reid = sublayer.getSelectMoveLineID(id);

                if (reid != -1)

                {

                    return reid;

                }

            }

            return -1;

        }

        public int getSelectRotateCircleID(int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                for (int i = 0; i < actor.giid_rotate.Count; i++)

                {

                    if (actor.giid_rotate[i].value == id)

                    {

                        return i;

                    }

                }

                // 對Group的處理

                if (actor is GroupActor)

                {

                    GroupActor ga = actor as GroupActor;

                    int reid = ga.getActorBuffer().getSelectRotateCircleID(id);

                    if (reid != -1)

                    {

                        return reid;

                    }

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                int reid = sublayer.getSelectRotateCircleID(id);

                if (reid != -1)

                {

                    return reid;

                }

            }

            return -1;

        }

        public void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                if (actor.giid.value == id)

                {

                    if (!selactors.ContainsKey(this))

                    {

                        selactors[this] = new ActorBuffer(null, new DummyActorFun());

                    }

                    if (!selactors[this].Contains<IActor>(actor))

                    {

                        selactors[this].insert(actor);

                    }

                    return;

                }

                // 對Group的特殊處理

                if (actor is GroupActor)

                {

                    ((GroupActor)actor).getSelectByID(selactors, id, this);

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.getSelectByID(selactors, id);

            }

        }

        public virtual void update(int t)

        {

            //ClientBridge.Profile.Begin(89);

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                actor.update(t);

            }

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.update(t);

            }

            // ClientBridge.Profile.End(89);

        }

        public virtual void UpdateCpuSkin(float t)

        {

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                actor.UpdateCpuSkin(t);

            }

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.UpdateCpuSkin(t);

            }

        }

        virtual public void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 繪制目前層所有物品

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                if (!actor.hide)

                {

                    actor.render(t, rendersys);

                }

            }

            // 繪制子層

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.render(t, rendersys);

            }

        }

        public void renderAABB(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 繪制選中物品包圍盒

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    Color color = (sactor is PrefebActor) ? (new Color(1, 1, 0, 1)) : (new Color(1, 1, 1, 1));

                    sactor.renderAABB(t, rendersys, color);

                    if (sactor.parent is GroupActor)

                    {

                        sactor.parent.renderAABB(t, rendersys, new Color(0, 1, 1, 1));

                    }

                }

            }

            //某些chr即使沒有 被選中也需要繪制aabb

            ActorBuffer orgbuffer = getOrgBuffer();

            foreach (IActor actor in orgbuffer)

            {

                if (!actor.hide && actor.GetActorType()==ACTOR_TYPE.AT_CHR)

                {

                    Color color = (actor is PrefebActor) ? (new Color(1, 1, 0, 1)) : (new Color(1, 1, 1, 1));

                  //  actor.renderAABB(t, rendersys, color);

                }

            }

            // 繪制子層

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderAABB(t, rendersys);

            }

        }

        public void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 繪制選中物品Coordinate

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    sactor.renderCoordinate(t, rendersys);

                }

            }

            // 繪制子層

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderCoordinate(t, rendersys);

            }

        }

        public void renderCircles(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 繪制選中物品Coordinate

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    sactor.renderCircles(t, rendersys);

                }

            }

            // 繪制子層

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderCircles(t, rendersys);

            }

        }

        public void renderSingleCircle(int t, ClientBridge.ClientRenderSys rendersys)

        {

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(ab, this, true, false);

            if (ab.Count<IActor>() == 0)

            {

                return;

            }

            Vector3F max = GActorHelper.getMaxPos(ab);

            Vector3F min = GActorHelper.getMinPos(ab);

            Vector3F center = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

            GActorHelper.drawRotateCircles(null, center, rendersys);

        }

        // 是否可以複制、剪切

        public virtual bool canCopyCut()

        {

            return !getSelBuffer().empty();

        }

        // 是否可以粘貼

        public virtual bool canPaste()

        {

            return Clipboard.ContainsData(DataFormats.Text) && !BaseCommand.isActorLayerReadOnly(this);

        }

        public virtual bool canCreateGroup()

        {

            int actorCount = 0;

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            foreach (IActor actor in sel_ab)

            {

                if (actor.parent == null)

                    actorCount++;

            }

            return actorCount > 0;

        }

        private void getSelectedGroupActors(IActorLayerMng layer, List<ActorBuffer> buffers)

        {

            ActorBuffer b1 = layer.getSelBuffer().getTypeActors(typeof(GroupActor));

            if (!b1.empty())

                buffers.Add(b1);

            foreach (IActorLayerMng sub_layer in layer.getList())

            {

                getSelectedGroupActors(sub_layer, buffers);

            }

        }

        private List<ActorBuffer> getSelectedGroupActors(IActorLayerMng layer)

        {

            List<ActorBuffer> buffers = new List<ActorBuffer>();

            getSelectedGroupActors(layer, buffers);

            return buffers;

        }

        public virtual bool canDestroyGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            return buffers.Count > 0;

        }

        public virtual bool canOpenGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            int actorCount = 0;

            foreach (ActorBuffer ab in buffers)

            {

                foreach (GroupActor ga in ab)

                {

                    if (ga.close)

                        actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canCloseGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            int actorCount = 0;

            foreach (ActorBuffer ab in buffers)

            {

                foreach (GroupActor ga in ab)

                {

                    if (!ga.close)

                        actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canDettachGroup()

        {

            int actorCount = 0;

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            foreach (IActor actor in sel_ab)

            {

                GroupActor ga = actor.parent as GroupActor;

                if (ga != null)

                {

                    actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canAttachGroup()

        {

            return true;

        }

        public virtual GroupActor createLayerActorGroup(string name, out ActorBuffer outAb)

        {

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", getRootActorLayer()));

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            foreach (IActor actor in sel_ab)

            {

                if (actor.parent == null)

                    ab.insert(actor);

            }

            if (ab.empty())

            {

                outAb = null;

                return null;

            }

            outAb = ab;

            int group_index = 0;

            if (name == null || name.Length == 0)

            {

                IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", root);

                IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

                group_index = doc.getMaxActorIndex("Group");

            }

            Dictionary<string, string> createpropdic = new Dictionary<string, string>();

            createpropdic["NamePrefix"] = "Group";

            createpropdic["Height"] = "0";

            GroupActor ga = new GroupActor(root.giidmng, createpropdic, group_index, this);

            if (name != null && name.Length > 0)

                ga.name = name;

            return ga;

        }

        //傳回用于層管理器中的層清單

        public virtual IList<IActorLayerMng> getLayersToManage()

        {

            return getList();

        }

        //父層的Hide狀态改變,回調通知子層及子Actor

        virtual public void notifyLayerHide(bool isHide)

        {

            if (BaseCommand.isValueTrue(getPropertyList(), "hide"))

                return;

            foreach (IActorLayerMng layer in m_actor_layer_list)

                layer.notifyLayerHide(isHide);

            foreach (IActor actor in m_org_buffer)

                actor.notifyLayerHide(isHide);

        }

        //父層的Freeze狀态改變,回調通知子層及子Actor

        virtual public void notifyLayerFreeze(bool isFreeze)

        {

            if (BaseCommand.isValueTrue(getPropertyList(), "freeze"))

                return;

            foreach (IActorLayerMng layer in m_actor_layer_list)

                layer.notifyLayerFreeze(isFreeze);

            foreach (IActor actor in m_org_buffer)

                actor.notifyLayerFreeze(isFreeze);

        }

    }

    public interface IResHandle

    {

        string ResName { get; }

        object getRes();

        void reload();

        void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res);

        void addRef();

        int ResRefCount { get; }

        List<IResHandle> getSubResHandleList();

    }

    public class ResActorBase : ActorBase, IResHandle

    {

        public ResActorBase(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        virtual public string ResName

        {

            get { return ""; }

        }

        virtual public object getRes()

        {

            return null;

        }

        virtual public void reload()

        {

        }

        virtual public void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res)

        {

        }

        new virtual public void Attach(ClientBridge.SceneBase scene)

        {

        }

        new virtual public void Detach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void addRef()

        {

        }

        virtual public int ResRefCount

        {

            get { return 1; }

        }

        virtual public List<IResHandle> getSubResHandleList()

        {

            return new List<IResHandle>();

        }

        new protected bool CanTransform()

        {

            return ResRefCount == 1;

        }

    }

    [Serializable]

    public class MultiActorFun : IActorFun

    {

        public void AddFun(IActorFun actorfun)

        {

            if (m_actorfun_list.GetIndex(actorfun) == -1)

            {

                m_actorfun_list.Add(actorfun);

            }

        }

        public void insert(IActor actor, IActorLayerMng layer)

        {

            foreach (IActorFun actorfun in m_actorfun_list)

            {

                actorfun.insert(actor, layer);

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            foreach (IActorFun actorfun in m_actorfun_list)

            {

                actorfun.remove(actor, layer);

            }

        }

        ListEx<IActorFun> m_actorfun_list = new ListEx<IActorFun>();

    }

    public class SceneActorFun : IActorFun

    {

        public SceneActorFun(ClientBridge.SceneBase scene)

        {

            m_scene = scene;

        }

        public void SetScene(ClientBridge.SceneBase scene)

        {

            m_scene = scene;

        }

        public void insert(IActor actor, IActorLayerMng layer)

        {

            if (m_scene != null && actor is ResActorBase)

            {

                ((ResActorBase)actor).Attach(m_scene);

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            if (m_scene != null && actor is ResActorBase)

            {

                ((ResActorBase)actor).Detach(m_scene);

            }

        }

        ClientBridge.SceneBase m_scene;

    }

}

繼續閱讀