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)
        {
            /*base.notifyPropertyChange(key, value);
            m_actor_info.valueChanged(key, 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;
        }

        /**绘制圆
         * center : 圆心
         * normal : 法向量
         * radius : 半径
         * color  : 绘制颜色
         **/
        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);
        }

        /**绘制旋转控制圆
          * center : 圆心
          * circlexy:xy平面圆的颜色
          * circleyz:yz平面圆的颜色
          * circlexz:xz平面圆的颜色
          **/
        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);
        }

        /**绘制坐标轴
       * center: 圆心
       * colorx:  x轴颜色
       * colory:  y轴颜色
       * colorz:  z轴颜色
       * colorxy: xy平面两条直线的颜色
       * coloryz: yz平面两条直线的颜色
       * colorxz: xz平面两条直线的颜色
       **/

        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;
            }
        }

        /**得到所有指定类型的Actor
         * ab : 返回的物品Buffer
         * layer : 处理的物品层
         * substract : 是否减去
         * select:true表示取所有选中的type类型物品,否则取所有type类型物品
         **/
        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);
        }

        /**更新已经创建的包裹
         * layer : 物品层,更新该层及其所有子层中满足条件的包裹
         * groupname : 包裹所在组
         * prefebname : 包裹名称
         **/
        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;
        }

        /**绘制圆
         * center : 圆心
         * normal : 法向量
         * radius : 半径
         * color  : 绘制颜色
         **/
        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);
        }


        /**绘制旋转控制圆
          * center : 圆心
          **/
        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;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值