天天看点

Actor.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using Sharp3D.Math.Core;

using Sharp3D.Math.Geometry3D;

using System.IO;

using System.Xml;

using System.Xml.Serialization;

using HelpTools;

namespace Editor

{

    public class IFile

    {

    }

    // 全局唯一值,用来记录其他物品

    public struct GIID

    {

        public GIID(int id, GIIDMng giidmng)

        {

            m_id = id;

            m_giid_mng = giidmng;

        }

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

        // 获得唯一值

        public int value { get { return m_id; } }

        // 所记录的唯一值

        int m_id;

        public override int GetHashCode()

        {

            return base.GetHashCode();

        }

        public override bool Equals(object obj)

        {

            if (obj is GIID)

            {

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

            }

            return false;

        }

        // 所记录的唯一值

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

        {

            return giid1.m_id == giid2.m_id;

        }

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

        {

            return !(giid1 == giid2);

        }

        public override string ToString()

        {

            return m_giid_mng.getIDString(this);

        }

        public void Parse(string id_string)

        {

            m_giid_mng.setIDString(this, id_string);

        }

        GIIDMng m_giid_mng;

    }

    // 全局唯一值管理器

    // 没有完成

    public class GIIDMng

    {

        public GIIDMng()

        {

        }

        // 生成一个全局唯一值

        public GIID getGIID()

        {

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

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

            return giid;

        }

        public bool getGIID(string id_string, out GIID giid)

        {

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

            {

                if (pair.Value == id_string)

                {

                    giid = pair.Key;

                    return true;

                }

            }

            giid = new GIID();

            return false;

        }

        public void setIDString(GIID id, string id_string)

        {

            m_map[id] = id_string;

        }

        public string getIDString(GIID id)

        {

            return m_map[id];

        }

        // 删除一个全局唯一值

        public void removeGIID(GIID id)

        {

            if (m_map.ContainsKey(id))

            {

                m_map.Remove(id);

            }

        }

        public void Clear()

        {

            m_map.Clear();

            //m_id_acc = 0;

        }

        int m_id_acc = 0;

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

        // 地图编辑器社区使用,其他慎用!

        public void SetNextGiid(int next)

        {

            if (next <= m_id_acc)

                return;

            else

                m_id_acc = next;

        }

    }

    // 物品memento,用物品属性列表构建

    public class ActorMemento : IMemento

    {

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

    }

    public enum ActorFlag

    {

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

        UNEDITABLE = 0x02,    //是否可以编辑

        UNSELECTABLE = 0x04,  //是否可以选择

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

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

        UNCOPYPASTABLE = 0x20,//是否可以复制粘贴

    }

    public interface ISelectableObject

    {

        // 鼠标悬浮

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

        // 鼠标选择

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

    }

    public interface ITransformableObject

    {

        // 移动物品

        void move(Vector3F v);

        // 移动到指定位置

        void moveTo(Vector3F pos);

        // 旋转

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

        // 缩放

        void scale(Vector3F scale_var);

        // 对齐

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

    }

    //物品类型枚举,炫舞1编辑器从炫舞2修改而来,遗留了很多无用或者不合适的定义和数据结构,这里重新定义一个枚举是为了减少之前的杂乱和引进的错误

    public enum ACTOR_TYPE

    {

        AT_DML,

        AT_CHR,

        AT_ACTOR,

        AT_NEWACTOR,

        AT_SPE,

        AT_SOUND,

        AT_AINODE,

        AT_LIGHT,

        AT_GROUP,

        AT_END

    }

    // 物品接口类

    public interface IActor : ISelectableObject, ITransformableObject, IDisposable

    {

        // 复制

        IActor clone(IEditItem edititem);

        // 获得子物品容器,如果没有子物品容器返回null  

        IActorLayerMng getActorBuffer();

        // 2D的矩形位置

        Rect<int> rect { get; set; }

        //scale

        Vector3F Scale { get; }

        // 3D位置矩阵

        Matrix4F locationmat { get; set; }

        // 包围盒

        AxisAlignedBox aabb { get; set; }

        // 中心

        Vector3F center { get; set; }

        // 是否隐藏

        bool hide { get; set; }

        // 是否冻结

        bool freeze { get; set; }

        // 是否显示名称

        bool canDisplayName { get; set; }

        // 所属物品层

        IActorLayerMng parentLayer { get; set; }

        // 父物品

        IActor parent { get; set; }

        // 物品名称

        string name { get; set; }

        //是否生成阴影

        bool genlightmap { get; set; }

        //是否投射(实时)阴影

        bool castshadow { get; set; }

        //获得标志

        int flag { get; }

        // 获得设置memento

        IMemento getMemento(int mode);

        void setMemento(IMemento mem);

        // 更新

        void update(int t);

        void UpdateCpuSkin(float t);

        // 绘制

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

        // 绘制包围盒

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

        // 绘制坐标轴

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

        // 绘制圆

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

        // 全局唯一ID,主要用来保存链接的内容

        GIID giid { get; }

        // 物品移动控制轴对应的ID

        List<GIID> giid_move { get; }

        // 物品旋转控制圆对应的ID

        List<GIID> giid_rotate { get; }

        // 获得key/value的列表

        IDictionary<String, String> getPropertyList();

        // 更改key所对应的value

        void notifyPropertyChange(String key, String value);

        // edititem用来获得可能需要的信息

        // 读取/保存物品信息到xml节点中

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

        // 读取/保存物品信息到文件中

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

        // 保存物品

        bool serialize(BinaryWriter binWriter);

        // 读取物品

        bool serialize(BinaryReader binReader, IEditItem edititem);

        // 移动物品

        new void move(Vector3F v);

        // 移动到指定位置

        new void moveTo(Vector3F pos);

        // 旋转

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

        // 缩放

        new void scale(Vector3F scale_var);

        void scaleForPar(Vector3F scale_var);

        // 设置物品位置,并更新物品包围盒

        void updateLocationAABB();

        // 将物品加入到硬件选择

        void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将线模型加入到硬件选择

        void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将移动控制轴加入到硬件选择

        void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys);

        // 将旋转控制圆加入到硬件选择

        void pushHardwareSelect_Rotate(ClientBridge.ClientRenderSys rendersys);

        // 得到物品类别字符串

        string getActorTypestr();

        //父物品层Hide操作回调

        void notifyLayerHide(bool isHide);

        //父物品层Freeze操作回调

        void notifyLayerFreeze(bool isFreeze);

        //获取物体是否可见

        bool isVisible();

        //得到物品类型

        ACTOR_TYPE GetActorType();

        //删除一个模型时,会从管理器中拿走,在从管理器拿走之前做一些必要的重置操作

        //目前用到该地方的是宝宝和坐骑绑定,在释放坐骑时要将和宝宝的绑定关系重置

        void DoBeforeDel();

    }

    // 物品的实现辅助基类,用来实现若干默认物品的接口,方便物品接口的实现

    // 实现IActor的类不是必须要继承这个类!

    public class ActorBase : IXmlSerial

    {

        protected GIID m_giid = new GIID();

        List<GIID> m_move_giid = new List<GIID>();     // 为物品移动控制轴提供六个ID,以控制移动方向

        List<GIID> m_rotate_giid = new List<GIID>();   // 为物品旋转控制圆提供3个ID,以控制旋转方向, fixme:目前绕三个轴旋转

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

        bool m_hide = false;                // 是否隐藏

        bool m_freeze = false;              // 是否冻结

        protected Dictionary<String, String> m_property_dic = new Dictionary<string, string>();  // 属性列表

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

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

        protected Vector3F m_center = new Vector3F();            // 物品中心(移动、旋转轴),暂时为包围盒中心,在更新包围盒的同时更新物品中心

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

        public virtual IActorLayerMng getActorBuffer() { return null; }

        public virtual ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_END;

        }

        public virtual void DoBeforeDel()

        {

        }

        public ActorBase()

        {

        }

        virtual public Rect<int> rect

        {

            get { return m_rect; }

            set { m_rect = value; }

        }

        virtual public int flag

        {

            get { return 0; }

        }

        virtual public bool hide

        {

            get { return m_hide; }

            set

            {

                m_hide = value;

            }

        }

        virtual public bool freeze

        {

            get { return m_freeze; }

            set

            {

                m_freeze = value;

            }

        }

        virtual public IActor parent

        {

            get { return m_parent; }

            set { m_parent = value; }

        }

        /// <summary>

        /// 物品所属的层

        /// </summary>

        [XmlIgnore]

        virtual public IActorLayerMng parentLayer

        {

            get { return m_parent_layer; }

            set { m_parent_layer = value; }

        }

        IActorLayerMng m_parent_layer = null;

        protected QuaternionF m_quat = QuaternionF.Identity;

        virtual public string name

        {

            get { return ""; }

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

        }

        /// <summary>

        /// 是否显示名称

        /// </summary>

        virtual public bool canDisplayName

        {

            get { return m_canDisplayName; }

            set { m_canDisplayName = value; }

        }

        bool m_canDisplayName = true;

        virtual public Matrix4F locationmat

        {

            get { return m_locationmat; }

            set

            {

                m_locationmat = value;

                updateLocationAABB();

            }

        }

        virtual public Vector3F Scale

        {

            get

            {

                return m_scale;

            }

        }

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

        // 获得物品Memento

        virtual public IMemento getMemento(int mode)

        {

            ActorMemento mem = new ActorMemento();

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

            {

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

            }

            return mem;

        }

        // 设置物品Memento

        virtual public void setMemento(IMemento mem)

        {

            ActorMemento actormem = (ActorMemento)mem;

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

            {

                notifyPropertyChange(kv.Key, kv.Value);

            }

        }

        // 移动物品

        virtual public void move(Vector3F v)

        {

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

            //             IActorLayerMng sublayer = getActorBuffer();

            //             if (sublayer != null)

            //             {

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

            //                 {

            //                     actor.move(v);

            //                 }

            //             }

            //             else  // 非Group物品

            //             {

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

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

            //             }

            // 移动Group中的子物品

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

                    actor.move(v);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(v);

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

        }

        virtual public void Attach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void Detach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

        }

        // 将物品移动到某位置

        virtual public void moveTo(Vector3F pos)

        {

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

            //             IActorLayerMng sublayer = getActorBuffer();

            //             if (sublayer != null)

            //             {

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

            //                 {

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

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

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

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

            //

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

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

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

            //                     actor.moveTo(possub);

            //                 }

            //             }

            //             //else  // fixme:

            //             {

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

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

            //             }

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

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

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

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

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

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

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

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

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

                    actor.moveTo(possub);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(pos);

            Matrix4F locatmat = new Matrix4F(locationmat);

            locatmat.M14 = 0;

            locatmat.M24 = 0;

            locatmat.M34 = 0;

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

        }

        virtual protected bool CanTransform()

        {

            return true;

        }

        public virtual void UpdateCpuSkin(float t)

        {

        }

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

        {

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

            {

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

                moveTo(pos);

            }

        }

        private void set_world_location(Vector3F wloc)

        {

            Matrix4F matrixmove = TransformationF.Translation(wloc);

            Matrix4F locatmat = new Matrix4F(locationmat);

            locatmat.M14 = 0;

            locatmat.M24 = 0;

            locatmat.M34 = 0;

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

        }

        // 旋转物品

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

        {

            axis.Normalize();

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

            m_quat = quat * m_quat;

            m_quat.Normalize();

            // Group

            IActorLayerMng sublayer = getActorBuffer();

            if (sublayer != null)

            {

                foreach (IActor actor in sublayer.getOrgBuffer())

                {

                    Vector3F rotatecenter = pos;

                    GroupActor groupactor = actor.parent as GroupActor;

                    if (groupactor != null && groupactor.rotatemode == RotateMode.RM_SELF) // Group内物品绕自身轴旋转

                    {

                        rotatecenter = actor.center;

                    }

                    actor.rotate(rotatecenter, axis, angle);

                }

            }

            Matrix4F matrixmove = TransformationF.Translation(-pos);

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

            Matrix4F matrixmoveback = TransformationF.Translation(pos);

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

            Vector3F euler = Tool.QuaternionToEulerXYZ(m_quat);

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

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

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

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

            return;

        }

        // 缩放

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

        {

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

            Matrix4F matrixmove = TransformationF.Translation(-center);

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

            Matrix4F matrixmoveback = TransformationF.Translation(center);

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

        }

        // 缩放

        virtual public void scaleForPar(Vector3F scale_var)

        {

            if (CanTransform())

            {

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

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

            }

        }

        virtual public void scale(Vector3F scale_var)

        {

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

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

            Matrix4F matrixmove = TransformationF.Translation(-center);

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

            Matrix4F matrixmoveback = TransformationF.Translation(center);

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

        }

        private void rotate(Vector3F euler)

        {

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

            m_quat = Tool.EulerXYZToQuaternion(r_euler);

            m_quat.Normalize();

            Matrix4F matrixscale = TransformationF.Scaling(m_scale);

            Matrix4F matrixrotate = QuaternionF.QuaternionToMatrix(m_quat);

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

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

        }

        virtual public AxisAlignedBox aabb

        {

            get { return m_aabb; }

            set

            {

                m_aabb = value;

                // 更新物品中心

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

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

            }

        }

        virtual public Vector3F center

        {

            get { return m_center; }

            set { m_center = value; }

        }

        virtual public void updateLocationAABB()

        {

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

            if (parent != null)

            {

                parent.updateLocationAABB();

            }

        }

        public virtual void update(int t)

        {

        }

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

        {

        }

        // 绘制包围盒

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

        {

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

            Vector3F[] vetexs = aabb.ComputeVertices();

            float[] points = new float[24];

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

            {

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

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

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

            }

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

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

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

                           };

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

        }

        // 将移动控制轴加入到硬件选择

        virtual public void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys)

        {

            GroupActor ga = this as GroupActor;

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

            {

                ActorBuffer gab = getActorBuffer().getOrgBuffer();

                foreach (IActor gasel in gab)

                {

                    gasel.pushHardwareSelect_Move(rendersys);

                }

            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                             };

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return;

        }

        // 绘制移动控制轴

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

        {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                             };

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

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

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

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

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

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

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

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

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

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

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

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

        }

        // 将移动控制轴加入到硬件选择

        virtual public void pushHardwareSelect_Rotate(ClientBridge.ClientRenderSys rendersys)

        {

            GroupActor ga = this as GroupActor;

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

            {

                ActorBuffer gab = getActorBuffer().getOrgBuffer();

                foreach (IActor gasel in gab)

                {

                    gasel.pushHardwareSelect_Rotate(rendersys);

                }

            }

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

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

            {

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

            }

            GActorHelper.drawRotateCircles(idlist, center, rendersys);

            return;

        }

        // 绘制旋转控制圆

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

        {

            GActorHelper.drawRotateCircles(null, center, rendersys);

        }

        /// <summary>

        /// Xml序列化使用

        /// </summary>

        public Vector3F Euler

        {

            get { return m_euler; }

        }

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

        public Vector3F Trans

        {

            get { return m_trans; }

        }

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

        /// <summary>

        /// 是否产生实时阴影

        /// </summary>

        virtual public bool castshadow

        {

            get { return m_castshadow; }

            set { m_castshadow = value; }

        }

        bool m_castshadow = true;

        /// <summary>

        /// 是否物体生成阴影

        /// </summary>

        virtual public bool genlightmap

        {

            get { return m_genLightMap; }

            set { m_genLightMap = value; }

        }

        bool m_genLightMap = true;

        public GIID giid

        {

            get { return m_giid; }

            private set { m_giid = value; }

        }

        public List<GIID> giid_move

        {

            get { return m_move_giid; }

        }

        public List<GIID> giid_rotate

        {

            get { return m_rotate_giid; }

        }

        // 得到物品属性列表

        virtual public IDictionary<String, String> getPropertyList()

        {

            return m_property_dic;

        }

        virtual public void notifyPropertyChange(String key, String value)

        {

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

            m_property_dic[key] = value;

            if (key == "LocationMat")

            {

                locationmat = Matrix4F.setMatrix(value);

            }

            else if (key == "Hide")

            {

                hide = bool.Parse(value);

            }

            else if (key == "Freeze")

            {

                freeze = bool.Parse(value);

            }

            else if (key == "产生阴影")

            {

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

                {

                    return;

                }

            }

            else if (key == "实时阴影")

            {

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

                {

                    return;

                }

            }

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

            {

                Vector3F old_scale, new_scale;

                try

                {

                    old_scale = Vector3F.Parse(old_value);

                    new_scale = Vector3F.Parse(value);

                }

                catch

                {

                    return;

                }

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

                {

                    m_scale = new_scale;

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

                }

            }

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

            {

                try

                {

                    m_trans = Vector3F.Parse(value);

                }

                catch (System.Exception)

                {

                    return;

                }

                set_world_location(m_trans);

            }

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

            {

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

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

                catch (System.Exception) { return; }

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

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

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

                {

                    m_euler = euler;

                    rotate(m_euler);

                }

            }

            insertValueToPropertyDic(key, value);

        }

        public virtual void insertValueToPropertyDic(string key, string value)

        {

            m_property_dic[key] = value;

        }

        public ActorBase(GIIDMng giidmng)

        {

            m_giid = giidmng.getGIID();

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

            {

                m_move_giid.Add(giidmng.getGIID());

            }

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

            {

                m_rotate_giid.Add(giidmng.getGIID());

            }

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

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

            m_property_dic["产生阴影"] = m_genLightMap.ToString();

            m_property_dic["实时阴影"] = m_castshadow.ToString();

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

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

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

        }

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

        {

            return true;

        }

        // 保存读取

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

        {

            if (load)

            {

                foreach (XmlNode childnode in xmlnode.ChildNodes)

                {

                    if (childnode.Name != "Item")

                    {

                        m_property_dic[childnode.Name] = childnode.Value;

                        notifyPropertyChange(childnode.Name, childnode.InnerText);

                    }

                    else

                    { //

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

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

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

                    }

                }

            }

            else // save

            {

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

                {

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

                    node.InnerText = kv.Value;

                    xmlnode.InsertAfter(node, xmlnode.LastChild);

                }

                if (this is GroupActor)

                {

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

                    {

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

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

                        att.Value = GActorHelper.getActorTypestr(subactor);

                        node.Attributes.Append(att);

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

                        xmlnode.InsertAfter(node, xmlnode.LastChild);

                    }

                }

            }

            return true;

        }

        // 保存物品

        virtual public bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(hide);

            binWriter.Write(freeze);

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

            {

                binWriter.Write(locationmat[i]);

            }

            return true;

        }

        // 读取物品

        virtual public bool serialize(BinaryReader binReader, IEditItem edititem)

        {

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

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

            float[] locarray = new float[16];

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

            {

                locarray[i] = binReader.ReadSingle();

            }

            // 恢复保存到二进制文件的Prefeb实例的位置   

            if (this is PrefebActor)

            {

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

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

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

                {

                    subactor.move(pos - posold);

                }

            }

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

            return true;

        }

        virtual public void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            return;

        }

        public virtual void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            return;

        }

        // 获取物体是否可见

        public virtual bool isVisible()

        {

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

        }

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

        {

            return true;

        }

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

        {

            return true;

        }

        // 得到物品类别字符串

        virtual public string getActorTypestr()

        {

            return "Actor";

        }

        //父物品层Hide操作回调

        virtual public void notifyLayerHide(bool isHide)

        {

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

                getActorBuffer().notifyLayerHide(isHide);

        }

        //父物品层Freeze操作回调

        virtual public void notifyLayerFreeze(bool isFreeze)

        {

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

                getActorBuffer().notifyLayerFreeze(isFreeze);

        }

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

        {

            throw new NotImplementedException();

        }

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

        {

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

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

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

            SDictionary<string, string> temp

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

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

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

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

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

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

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

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

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

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

        }

        public virtual void ReadXml(XmlReader reader)

        {

            Serializer.PreReadXmlObj(reader);

            ReadXmlInner(reader);

            Serializer.AfterReadXmlObj(reader);

        }

        public virtual void WriteXml(XmlWriter writer)

        {

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

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

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

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

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

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

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

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

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

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

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

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

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

        }

    }

    public enum DETAIL_ACTOR_TYPE

    {

        DAT_HUGE_ACTOR,

        DAT_SMALL_ACTOR,

        DAT_DETAIL_VEGETATION,

    }

    // 模型信息

    public class ModelActorInfo

    {

        public string m_model_name;    // 物品名称 前缀+id

        public string m_resouce_name;  // 资源名成

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

        public bool m_collide;

        public bool m_is_bridge;

        public bool m_visible_ingame;

        public float m_visible_distance; // 可见范围

        public bool m_far_object; // 远处的对象

        public bool m_is_tree;

        public bool m_temp_transparent;

        public bool m_reflection;

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

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

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

        public string m_lightmap_quality = "普通";  //Lightmap质量

        public DETAIL_ACTOR_TYPE m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR; // 细节物体类型

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

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

        {

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

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

            m_resouce_name = createpropdic["ResName"];

            try

            {

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

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_collide = false;

            m_is_bridge = false;

            m_visible_ingame = true;

            m_far_object = false;

            m_is_tree = false;

            m_temp_transparent = true;

            m_lightable = false;

            m_use_lightmap = true;

            //m_selshadow_in_lightmap = false;

            m_lightmap_quality = "普通";

            m_as_actor = false;

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

            {

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

            }

            if (createpropdic.ContainsKey("桥梁物体"))

            {

                m_is_bridge = createpropdic["桥梁物体"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("游戏中可见"))

            {

                m_visible_ingame = createpropdic["游戏中可见"].ToLower() == "true";

            }

            if (createpropdic.ContainsKey("可视距离"))

            {

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

                {

                    m_visible_distance = 1000;

                }

            }

            else

            {

                m_visible_distance = 1000;

            }

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

            {

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

            }

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

            {

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

            }

            if (createpropdic.ContainsKey("临时透明"))

            {

                m_temp_transparent = createpropdic["临时透明"].ToLower() == "true";

            }

            m_reflection = true;

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

            {

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

            }

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

            {

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

            }

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

            {

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

            }

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

            //{

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

            //}

            if (createpropdic.ContainsKey("Lightmap质量"))

            {

                m_lightmap_quality = createpropdic["Lightmap质量"];

            }

            if (createpropdic.ContainsKey("细节物体类型"))

            {

                m_dat = (DETAIL_ACTOR_TYPE)Enum.Parse(typeof(DETAIL_ACTOR_TYPE), createpropdic["细节物体类型"], true);

            }

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

            {

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

            }

        }

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

        {

            m_model_name = modelname;

            m_resouce_name = resname;

            m_height = height;

        }

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

        {

            m_model_name = modelname;

            m_resouce_name = resname;

            m_height = height;

            m_collide = collide;

            m_is_bridge = is_bridge;

            m_visible_ingame = visible_ingame;

            m_visible_distance = visible_distance;

            m_far_object = far_object;

            m_is_tree = is_tree;

            m_temp_transparent = temp_transparent;

            m_reflection = reflection;

            m_lightable = false;

            m_use_lightmap = true;

            //m_selshadow_in_lightmap = false;

            m_lightmap_quality = "普通";

            m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR;

            m_as_actor = false;

        }

        // 转换成属性列表

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

        {

            dic["Name"] = m_model_name;

            dic["ResName"] = m_resouce_name;

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

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

            dic["桥梁物体"] = m_is_bridge.ToString();

            dic["游戏中可见"] = m_visible_ingame.ToString();

            //dic["可视距离"] = m_visible_distance.ToString();

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

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

            dic["临时透明"] = m_temp_transparent.ToString();

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

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

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

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

            dic["Lightmap质量"] = m_lightmap_quality;

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

            string dat;

            if (m_dat == DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION)

                dat = "细节植被";

            else if (m_dat == DETAIL_ACTOR_TYPE.DAT_HUGE_ACTOR)

                dat = "大型物体";

            else

                dat = "小型物体";

            dic["细节物体类型"] = dat;

        }

        public ModelActorInfo()

        {

        }

        // 转换成存储列表

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

        {

            dic["Name"] = m_model_name;

            dic["ResName"] = m_resouce_name;

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

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

            dic["桥梁物体"] = m_is_bridge.ToString();

            dic["游戏中可见"] = m_visible_ingame.ToString();

            dic["可视距离"] = m_visible_distance.ToString();

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

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

            dic["临时透明"] = m_temp_transparent.ToString();

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

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

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

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

            dic["Lightmap质量"] = m_lightmap_quality;

            dic["细节物体类型"] = m_dat.ToString();

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

        }

        public int getLightmapQualityPower(string value)

        {

            switch (value)

            {

                case "最低":

                    return -2;

                case "低":

                    return -1;

                case "普通":

                    return 0;

                case "高":

                    return 1;

                case "最高":

                    return 2;

                default:

                    return int.MaxValue;

            }

        }

        // 更新属性值

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_model_name = value;

                    break;

                case "ResName":

                    m_resouce_name = value;

                    break;

                case "Height":

                    try

                    {

                        m_height = float.Parse(value);

                    }

                    catch (Exception)

                    {

                        m_height = 0;

                    }

                    break;

                case "碰撞物体":

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

                    break;

                case "桥梁物体":

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

                    break;

                case "游戏中可见":

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

                    break;

                case "可视距离":

                    float.TryParse(value, out m_visible_distance);

                    break;

                case "远景":

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

                    break;

                case "是否是树":

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

                    break;

                case "临时透明":

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

                    break;

                case "反射中绘制":

                    bool.TryParse(value, out m_reflection);

                    break;

                case "是否接受光斑":

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

                    break;

                case "是否应用Lightmap":

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

                    break;

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

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

                //    break;

                case "Lightmap质量":

                    m_lightmap_quality = value;

                    break;

                case "细节物体类型":

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

                        m_dat = DETAIL_ACTOR_TYPE.DAT_HUGE_ACTOR;

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

                        m_dat = DETAIL_ACTOR_TYPE.DAT_SMALL_ACTOR;

                    if (value == "细节植被" || value == DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION.ToString())

                        m_dat = DETAIL_ACTOR_TYPE.DAT_DETAIL_VEGETATION;

                    break;

                case "受角色光":

                    bool.TryParse(value, out m_as_actor);

                    break;

                default:

                    break;

            }

        }

    }

    // 模型

      public class ModelActor : ResActorBase, IActor

    {

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

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

            m_model = rendersys.createModel(m_actor_info.m_resouce_name);

            if (m_model == null)

            {

                return;

            }

            //m_model.setVisibleDist(visible_distance);

            notifyPropertyChange("实时阴影", "True");

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

            //notifyPropertyChange("临时透明", "True");

            return;

        }

        public ModelActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo();

            if (m_model != null)

                notifyPropertyChange("实时阴影", "True");

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

            //notifyPropertyChange("临时透明", "True");

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

            return;

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_model != null)

            {

                m_model.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_model != null)

            {

                m_model.Detach(scene);

            }

        }

        override public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

            if (m_model != null)

            {

                //m_model.setMaterialLod(lod);

            }

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

                //父层为Hide,只设置标识位,否则进行具体Hide操作

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

                {

                    //m_model.setVisible(!value);

                }

            }

        }

        public override void notifyLayerFreeze(bool isFreeze)

        {

            //base.notifyLayerFreeze(isFreeze);

        }

        //父物品层设置Hide通知

        public override void notifyLayerHide(bool isHide)

        {

            if (hide)

                return;

            //if(m_model != null)

            //    m_model.setVisible(!isHide);

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_model_name;

            }

            set

            {

                m_actor_info.m_model_name = value;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        public bool collide

        {

            get

            {

                return m_actor_info.m_collide;

            }

        }

        public bool is_bridge

        {

            get

            {

                return m_actor_info.m_is_bridge;

            }

        }

        public bool visible_ingame

        {

            get

            {

                return m_actor_info.m_visible_ingame;

            }

        }

        public float visible_distance

        {

            get

            {

                return m_actor_info.m_visible_distance;

            }

        }

        public bool far_object

        {

            get

            {

                return m_actor_info.m_far_object;

            }

        }

        public bool is_tree

        {

            get

            {

                return m_actor_info.m_is_tree;

            }

        }

        public bool temp_transparent

        {

            get

            {

                return m_actor_info.m_temp_transparent;

            }

        }

        #region about IDisposable

        virtual public void Dispose()

        {

            m_model.release();

        }

        #endregion

        #region about IActor

        // fixme : 各类物品的Clone目前都还没有实现

        public IActor clone(IEditItem edititem)

        {

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

            ModelActor actor = null;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_actor_info.m_model_name);

            binWriter.Write(m_actor_info.m_resouce_name);

            binWriter.Write(m_actor_info.m_height);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            m_actor_info.m_model_name = binReader.ReadString();

            m_actor_info.m_resouce_name = binReader.ReadString();

            m_actor_info.m_height = binReader.ReadSingle();

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

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

            return base.serialize(binReader, edititem);

        }

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

        {

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

            if (load)

            {

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

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

            }

            updateLocationAABB();

            return true;

        }

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

        {

            // 调用自己的绘制函数

            m_model.render();

        }

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

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_model == null)

            {

                return;

            }

            // 设置mat

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

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

            {

                matrix.Add(locationmat[i]);

            }

            m_model.setLocationMatrix(matrix);

            // 修改包围盒

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

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

            {

                aabblist.Add(0);

            }

            m_model.getAABB(aabblist);

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

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

            base.updateLocationAABB();

        }

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

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

        }

        public override void notifyPropertyChange(String key, String value)

        {

            if (key == "Lightmap质量")

            {

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

                int new_p = m_actor_info.getLightmapQualityPower(value);

                if (new_p == int.MaxValue)

                {

                    return;

                }

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

                //{

                //    if (new_p > cur_p)

                //    {

                //        MessageBox.Show("不允许再提升质量");

                //    }

                //    else if (new_p < cur_p)

                //    {

                //        MessageBox.Show("不允许再降低质量");

                //    }

                //    return;

                //}

            }

            if (key != "可视距离")

                base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

            if (m_model != null)

            {

                if (key == "可视距离")

                {

                    //m_model.setVisibleDist(visible_distance);

                }

                else if (key == "实时阴影")

                {

                    //m_model.setCastShadow(base.castshadow);

                }

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

                {

                    //m_model.setReflection(m_actor_info.m_reflection);

                }

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

                {

                    //m_model.setLightable(m_actor_info.m_lightable);

                }

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

                {

                    //m_model.asActor(m_actor_info.m_as_actor);

                }

            }

        }

        public override string getActorTypestr()

        {

            return "模型";

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_DML;

        }

        public ModelActorInfo m_actor_info;

        public ClientBridge.Model m_model;

        override public string ResName

        {

            get { return res; }

        }

        override public object getRes()

        {

            return m_model;

        }

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

        {

            if (m_model != null)

            {

                m_model.changeRes(rendersys, new_res);

                m_actor_info.m_resouce_name = new_res;

                updateLocationAABB();

            }

        }

        override public void addRef()

        {

            if (m_model != null)

            {

                m_model.addRef();

            }

        }

        override public int ResRefCount

        {

            get

            {

                if (m_model != null)

                {

                    return m_model.m_ref_count;

                }

                else

                {

                    return 0;

                }

            }

        }

    }

    // 骨骼模型

    public class SkeletonModelActor : ActorBase, IActor

    {

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

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

            m_model = rendersys.creatSkeletonModel(m_actor_info.m_resouce_name);

            //m_model.setVisibleDist(visible_distance);

            return;

        }

        public SkeletonModelActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new ModelActorInfo();

            return;

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_CHR;

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_model_name;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        virtual public void Dispose()

        {

            if (m_model != null)

            {

                m_model.release();

            }

        }

        #region about IActor

        // fixme : 各类物品的Clone目前都还没有实现

        public IActor clone(IEditItem edititem)

        {

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

            ModelActor actor = null;

            return actor;

        }

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

        {

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

            {

                mPro[kv.Key] = kv.Value;

            }

        }

        public override void update(int t)

        {

            if (hide == false)

            {

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

            }

        }

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

        {

            if (!hide)

            {

                m_model.render();

            }

        }

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

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public void updateAABB()

        {

            // 修改包围盒

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

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

            {

                aabblist.Add(0);

            }

            m_model.getAABB(aabblist);

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

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

        }

        public override void updateLocationAABB()

        {

            if (m_model == null)

            {

                return;

            }

            // 设置mat

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

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

            {

                matrix.Add(locationmat[i]);

            }

            m_model.setLocationMatrix(matrix);

            updateAABB();

        }

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

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

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

        }

        public ModelActorInfo m_actor_info;

        public ClientBridge.SkeletonModel m_model;

        public void SetAction(int trackid, string actionname)

        {

            m_model.setAim(trackid, actionname);

        }

        public void SetActionTime(int trackid, float time)

        {

            m_model.SetCurrentActionTime(trackid, time);

        }

        public void PlayAction(int trackid, float time)

        {

            m_model.SetCurrentActionTime(trackid, time);

            //             m_model.update(0);

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

        }

        public void ClearChannelAnim(int id)

        {

            m_model.ClearChannelAnim(0);

        }

        public Vector3F GetPosFromRootBone()

        {

            if (m_model!=null)

            {

                string rootName = m_model.GetRootBoneName();

                int rootID = m_model.GetBoneID(rootName);

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

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

            }

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

        }

    }

    // 角色

    public class StageRoleActor : SkeletonModelActor

    {

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

            : base(giidmng)

        {

            m_crs = rendersys;

            m_actor_info = new ModelActorInfo(createpropdic, curindex);

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

            base.m_model = (ClientBridge.SkeletonModel)m_actor_model;

            notifyPropertyChange("产生阴影", "True");

            notifyPropertyChange("Update", "True");

            return;

        }

        public override void update(int t)

        {

            base.update(t);

            updateAABB();

        }

        public void SetBodyPart(int pos, string bpt_filename)

        {

            m_actor_model.SetBodyPart(pos, bpt_filename);

        }

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

        {

            m_actor_model.SetAdornment(sem, pos, lik_filename);

        }

        public void PostProcessCreating()

        {

            m_actor_model.PostProcessCreating();

        }

        public override int flag

        {

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

        }

        public override void notifyPropertyChange(string key, string value)

        {

            if (key != "ResName")

            {

                base.notifyPropertyChange(key, value);

            }

        }

        private ClientBridge.ClientRenderSys m_crs;

        private ClientBridge.ActorModel m_actor_model;

    }

    // 特效信息

    public struct EffectActorInfo

    {

        public string m_effect_name;   // 物品名称 前缀+id

        public string m_resouce_name;

        public float m_visible_distance;

        public float m_height;

        public bool m_reflection;

        public bool m_as_actor;

        public float m_random_offset_min;

        public float m_random_offset_max;

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

        {

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

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

            m_resouce_name = createpropdic["ResName"];

            if (createpropdic.ContainsKey("可视距离"))

            {

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

                {

                    m_visible_distance = 1000;

                }

            }

            else

            {

                m_visible_distance = 1000;

            }

            try

            {

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

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_reflection = true;

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

            {

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

            }

            m_as_actor = false;

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

            {

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

            }

            try

            {

                m_random_offset_min = float.Parse(createpropdic["随机动画偏移最小值"]);

                m_random_offset_max = float.Parse(createpropdic["随机动画偏移最大值"]);

            }

            catch (Exception)

            {

                m_random_offset_min = 0;

                m_random_offset_max = 0;

            }

        }

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

        {

            m_effect_name = effectname;

            m_resouce_name = resname;

            m_height = height;

            m_visible_distance = 0;

            m_reflection = true;

            m_as_actor = false;

            m_random_offset_min = 0;

            m_random_offset_max = 0;

        }

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

        {

            m_effect_name = effectname;

            m_resouce_name = resname;

            m_height = height;

            m_visible_distance = visible_distance;

            m_reflection = reflection;

            m_as_actor = false;

            m_random_offset_min = 0;

            m_random_offset_max = 0;

        }

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

        {

            dic["Name"] = m_effect_name;

            dic["ResName"] = m_resouce_name;

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

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

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

            dic["随机动画偏移最小值"] = m_random_offset_min.ToString();

            dic["随机动画偏移最大值"] = m_random_offset_max.ToString();

        }

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

        {

            dic["Name"] = m_effect_name;

            dic["ResName"] = m_resouce_name;

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

            dic["可视距离"] = m_visible_distance.ToString();

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

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

            dic["随机动画偏移最小值"] = m_random_offset_min.ToString();

            dic["随机动画偏移最大值"] = m_random_offset_max.ToString();

        }

        // 更新属性值

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_effect_name = value;

                    break;

                case "ResName":

                    m_resouce_name = value;

                    break;

                case "Height":

                    float.TryParse(value, out m_height);

                    break;

                case "可视距离":

                    float.TryParse(value, out m_visible_distance);

                    break;

                case "反射中绘制":

                    bool.TryParse(value, out m_reflection);

                    break;

                case "受角色光":

                    bool.TryParse(value, out m_as_actor);

                    break;

                case "随机动画偏移最小值":

                    float.TryParse(value, out m_random_offset_min);

                    break;

                case "随机动画偏移最大值":

                    float.TryParse(value, out m_random_offset_max);

                    break;

                default:

                    break;

            }

        }

    }

    // 特效

    public class EffectActor : ResActorBase, IActor

    {

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

            : base(giidmng)

        {

            m_actor_info = new EffectActorInfo(createpropdic, curindex);

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

            m_effect.play();

        }

        public EffectActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new EffectActorInfo();

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_effect != null)

            {

                m_effect.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_effect != null)

            {

                m_effect.Detach(scene);

            }

        }

        override public void SetLod(ClientBridge.LOD_LEVEL lod)

        {

            if (m_effect != null)

            {

                //m_effect.setMaterialLod(lod);

            }

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_SPE;

        }

        override public bool hide

        {

            get { return base.hide; }

            set

            {

                base.hide = value;

                //若父层为Hide,则只改变标识位,不进行具体操作

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

                {

                    m_effect.setVisible(!value);

                }

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_effect_name;

            }

        }

        public string res

        {

            get

            {

                return m_actor_info.m_resouce_name;

            }

        }

        public float visible_distance

        {

            get

            {

                return m_actor_info.m_visible_distance;

            }

        }

        public override AxisAlignedBox aabb

        {

            get { return base.aabb; }

            set

            {

                m_aabb = value;

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

                {

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

                }

                // 更新物品中心

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

            }

        }

        #region about IDisposable

        public void Dispose()

        {

            //m_effect.release();  // 有问题?

        }

        #endregion

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

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

            EffectActor actor = null;

            return actor;

        }

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_effect == null)

            {

                return;

            }

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

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

            {

                matrix.Add(locationmat[i]);

            }

            m_effect.setLocationMatrix(matrix);

            //m_model.setLocationMatrix(matrix);

            // 修改包围盒

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

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

            {

                aabblist.Add(0);

            }

            m_effect.getAABB(aabblist);

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

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

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

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

            base.updateLocationAABB();

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

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

            nor = locationmat * nor;

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

        }

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

        //         {

        //

        //         }

        public override void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

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

            rendersel(0, rendersys);

        }

        public override void notifyPropertyChange(String key, String value)

        {

            float min = m_actor_info.m_random_offset_min;

            float max = m_actor_info.m_random_offset_max;

            bool offsetChanged = false;

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

            if (m_effect != null)

            {

                if (key == "实时阴影")

                {

                    //m_effect.setCastShadow(base.castshadow);

                }

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

                {

                    //m_effect.setReflection(m_actor_info.m_reflection);

                }

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

                {

                    //m_effect.asActor(m_actor_info.m_as_actor);

                }

                else if (key == "随机动画偏移最小值")

                {

                    if (m_actor_info.m_random_offset_min < 0)

                        m_actor_info.m_random_offset_min = 0;

                    if (m_actor_info.m_random_offset_min > m_actor_info.m_random_offset_max)

                    {

                        m_actor_info.m_random_offset_max = m_actor_info.m_random_offset_min;

                        base.notifyPropertyChange("随机动画偏移最大值", m_actor_info.m_random_offset_max.ToString());

                    }

                    offsetChanged = min != m_actor_info.m_random_offset_min;

                }

                else if (key == "随机动画偏移最大值")

                {

                    if (m_actor_info.m_random_offset_max < 0)

                        m_actor_info.m_random_offset_max = 0;

                    if (m_actor_info.m_random_offset_max < m_actor_info.m_random_offset_min)

                    {

                        m_actor_info.m_random_offset_min = m_actor_info.m_random_offset_max;

                        base.notifyPropertyChange("随机动画偏移最小值", m_actor_info.m_random_offset_min.ToString());

                    }

                    offsetChanged = max != m_actor_info.m_random_offset_max;

                }

                if (offsetChanged)

                    setRandomOffsetPlay();

            }

        }

        //设置随机动画偏移

        private void setRandomOffsetPlay()

        {

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

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

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

            m_effect.update(result, false);

        }

        //通知父层设置了Hide状态

        public override void notifyLayerHide(bool isHide)

        {

            if (hide)

                return;

            if (m_effect != null)

                m_effect.setVisible(!isHide);

        }

        //通知父层设置了Freeze状态

        public override void notifyLayerFreeze(bool isFreeze)

        {

            //base.notifyLayerFreeze(isFreeze);

        }

        public override string getActorTypestr()

        {

            return "特效";

        }

        //public IMemento getMemento(int mode)

        //{

        //    return null;

        //}

        //public void setMemento(IMemento mem)

        //{

        //}

        public override void update(int t)

        {

            if (m_effect == null)

            {

                return;

            }

            m_effect.update(t);

            updateLocationAABB();

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_actor_info.m_effect_name);

            binWriter.Write(m_actor_info.m_resouce_name);

            binWriter.Write(m_actor_info.m_height);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            m_actor_info.m_effect_name = binReader.ReadString();

            m_actor_info.m_resouce_name = binReader.ReadString();

            m_actor_info.m_height = binReader.ReadSingle();

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

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

            m_effect.play();

            return base.serialize(binReader, edititem); ;

        }

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

        {

            // 调用自己的绘制函数

            if (m_effect == null)

                return;

            m_effect.render();

        }

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

        {

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

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

        }

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

        {

            drawRenderLine(t, rendersys);

        }

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

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public ClientBridge.SpecialEffect m_effect;

        EffectActorInfo m_actor_info;

        AxisAlignedBox m_render_aabb;

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

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

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

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

        override public string ResName

        {

            get { return res; }

        }

        override public object getRes()

        {

            return m_effect;

        }

        override public void reload()

        {

            m_effect.reload();

        }

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

        {

            if (m_effect != null)

            {

                m_effect.changeRes(rendersys, new_res);

                m_actor_info.m_resouce_name = new_res;

                updateLocationAABB();

            }

        }

        override public void addRef()

        {

            if (m_effect != null)

            {

                m_effect.addRef();

            }

        }

        override public int ResRefCount

        {

            get

            {

                if (m_effect != null)

                {

                    return m_effect.m_ref_count;

                }

                else

                {

                    return 0;

                }

            }

        }

    }

    // 声音

    public class SoundActor : ActorBase, IActor

    {

        public SoundActor(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        public void Dispose()

        {

            //

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_SOUND;

        }

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

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

            SoundActor actor = new SoundActor(root.giidmng);

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

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

        {

            // 调用自己的绘制函数

        }

        #endregion

    }

    // AI节点

    public class AINodeActor : ActorBase, IActor

    {

        public AINodeActor(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_AINODE;

        }

        #region about IDisposable

        public void Dispose()

        {

            //

        }

        #endregion

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

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

            AINodeActor actor = new AINodeActor(root.giidmng);

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

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

        {

            // 调用自己的绘制函数

        }

        #endregion

    }

    public enum LightShape

    {

        CIRCLE = 0,

        RECT = 1

    }

    // 灯光信息

    public struct LightInfo

    {

        LightInfo(string type)

        {

            m_type = type;

            m_spe_color = new Color();

            m_dif_color = new Color();

            m_amb_color = new Color();

        }

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

        {

            m_type = type;

            m_dif_color = difcolor;

            m_spe_color = speccolor;

            m_amb_color = ambcolor;

        }

        public string m_type;

        public Color m_dif_color;

        public Color m_spe_color;

        public Color m_amb_color;

    }

    // 区域灯光

    public class LightActor : ActorBase, IActor

    {

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

            : base(giidmng)

        {

            m_light_info = lightinfo;

            m_light = rendersys.createLight(lightinfo.m_type);

        }

        public LightActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_light_info = new LightInfo();

        }

        public override  ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_LIGHT;

        }

        public void Dispose()

        {

            //

        }

        public IActor clone(IEditItem edititem)

        {

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

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

            actor.hide = hide;

            actor.freeze = freeze;

            return actor;

        }

        new public IMemento getMemento(int mode)

        {

            return null;

        }

        new public void setMemento(IMemento mem)

        {

        }

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

        {

            // 调用自己的绘制函数

        }

        override public void Attach(ClientBridge.SceneBase scene)

        {

            if (m_light != null)

            {

                //m_light.Attach(scene);

            }

        }

        override public void Detach(ClientBridge.SceneBase scene)

        {

            if (m_light != null)

            {

                //m_light.Detach(scene);

            }

        }

        ClientBridge.Light m_light;

        LightInfo m_light_info;

    }

    //操作方式

    public enum ActorActionState

    {

        SELECT,

        MOVE,

        ROTATE,

        DRAG,

        RESIZE,

    }

    // 移动方向

    public enum MoveDirection

    {

        MD_NONE = 0, // 不移动

        MD_X = 0x01 << 0,    // 沿X轴移动

        MD_Y = 0x01 << 1,    // 沿Y轴移动

        MD_Z = 0x01 << 2,    // 沿Z轴移动

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

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

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

    }

    // 旋转轴

    public enum RotateDirection

    {

        RD_NONE, // 不旋转

        RD_X,    // 沿X轴旋转

        RD_Y,    // 沿Y轴旋转

        RD_Z     // 沿Z轴旋转

    }

    // 旋转方式

    public enum RotateMode

    {

        RM_WHOLE,  // 绕同一个轴

        RM_SELF,   // 绕自身轴

        RM_BOTH    // fixme:

    }

    public enum ResizeDirection

    {

        RD_NONE = 0, // 不移动

        RD_X = 0x01 << 0,    // 沿X轴移动

        RD_Y = 0x01 << 1,    // 沿Y轴移动

        RD_Z = 0x01 << 2,    // 沿Z轴移动

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

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

        RD_YZ = RD_Y | RD_Z,

        RD_XYZ = RD_X | RD_Y | RD_Z

    }

    public class RenderHelper

    {

        public static float stdDist = 50.0f;

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

        {

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

            float dis = ComputeDisBetweenTwoPoint(center, ca_pos);

            reallength *= dis / fstdDist;

            return reallength;

        }

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

        {

            normal.Normalize();

            // 用360个点的连线模拟圆

            int pointcount = 360;

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

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

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

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

            {

                float factor = 0;

                Vector3F u = new Vector3F();

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

                {

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

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

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

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

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

                v.Normalize();

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

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

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

                indexs[t] = t;

            }

            indexs[pointcount] = 0;

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

        }

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

        {

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

        }

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

        {

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

        }

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

        {

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

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

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

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

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

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

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

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

            float e = 0.01f;

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

            p_p1.Normalize();

            p_p2.Normalize();

            p_p3.Normalize();

            p_p4.Normalize();

            p1 += p_p1 * e;

            p2 += p_p2 * e;

            p3 += p_p3 * e;

            p4 += p_p4 * e;

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

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

        }

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

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

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

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

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

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

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

            drawCircle(center, coord_x, length, circleyz, rendersys);  // 绘制垂直于x轴的圆

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

            drawCircle(center, coord_y, length, circlexz, rendersys);  // 绘制垂直于y轴的圆

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

            drawCircle(center, coord_z, length, circlexy, rendersys);  // 绘制垂直于z轴的圆

            coord_x = length * coord_x + center;

            coord_y = length * coord_y + center;

            coord_z = length * coord_z + center;

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

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

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

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

                             };

            int[] indexsx = { 0, 1 };

            int[] indexsy = { 0, 2 };

            int[] indexsz = { 0, 3 };

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

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

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

        }

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

        {

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

        }

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

        {

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

        }

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

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

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

            float length1 = length / 2.0f;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                             };

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

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

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

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

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

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

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(3);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(4);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(5);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

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

        }

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

        {

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

        }

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

        {

            ClientBridge.ClientRenderSys rendersys = view.getRenderSys();

            float length = coord_length;

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

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

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

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

            float length1 = length * 2 / 3;

            float length2 = length / 2;

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

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

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

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

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

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

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

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

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

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

                             };

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

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

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

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

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

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

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

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

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

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

            if (hardsel)

            {

                rendersys.pushSelectID(0);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(1);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(2);

            }

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

            if (hardsel)

            {

                rendersys.pushSelectID(3);

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

            }

            else

            {

                if (rd == ResizeDirection.RD_XY)

                {

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

                }

                else

                {

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

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(4);

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

            }

            else

            {

                if (rd == ResizeDirection.RD_XZ)

                {

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

                }

                else

                {

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

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(5);

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

            }

            else

            {

                if (rd == ResizeDirection.RD_YZ)

                {

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

                }

                else

                {

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

                }

            }

            if (hardsel)

            {

                rendersys.pushSelectID(6);

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

            }

            else

            {

                if (rd == ResizeDirection.RD_XYZ)

                {

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

                }

            }

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

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

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

        }

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

        {

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

        }

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

        {

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

        }

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

        {

            view.setCamera();

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

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

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

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

            {

                switch (res[0])

                {

                    case 0:

                        return MoveDirection.MD_X;

                    case 1:

                        return MoveDirection.MD_Y;

                    case 2:

                        return MoveDirection.MD_Z;

                    case 3:

                        return MoveDirection.MD_XY;

                    case 4:

                        return MoveDirection.MD_XZ;

                    case 5:

                        return MoveDirection.MD_YZ;

                    default:

                        return MoveDirection.MD_NONE;

                }

            }

            else

            {

                return MoveDirection.MD_NONE;

            }

        }

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

        {

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

        }

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

        {

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

        }

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

        {

            view.setCamera();

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

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

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

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

            {

                switch (res[0])

                {

                    case 0:

                        return RotateDirection.RD_X;

                    case 1:

                        return RotateDirection.RD_Y;

                    case 2:

                        return RotateDirection.RD_Z;

                    default:

                        return RotateDirection.RD_NONE;

                }

            }

            else

            {

                return RotateDirection.RD_NONE;

            }

        }

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

        {

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

        }

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

        {

            view.setCamera();

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

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

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

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

            {

                switch (res[0])

                {

                    case 0:

                        return ResizeDirection.RD_X;

                    case 1:

                        return ResizeDirection.RD_Y;

                    case 2:

                        return ResizeDirection.RD_Z;

                    case 3:

                        return ResizeDirection.RD_XY;

                    case 4:

                        return ResizeDirection.RD_XZ;

                    case 5:

                        return ResizeDirection.RD_YZ;

                    case 6:

                        return ResizeDirection.RD_XYZ;

                    default:

                        return ResizeDirection.RD_NONE;

                }

            }

            else

            {

                return ResizeDirection.RD_NONE;

            }

        }

        //两个点相减求向量 并归一化

        public static Vector3F ComputeVectorAndNormalize(Vector3F start, Vector3F end)

        {

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

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

            res.X /= length;

            res.Y /= length;

            res.Z /= length;

            return res;

        }

        //求两个点之间的距离

        public static float ComputeDisBetweenTwoPoint(Vector3F start, Vector3F end)

        {

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

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

        }

        //给定球心和半径,求顶点

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

        {

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

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

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

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

            float dy1 = 0;

            float dx2 = radius;

            float dy2 = 0;

            float z1 = center.Z + radius / 2;

            float z2 = center.Z - radius / 2;

            points[0] = center.X;

            points[1] = center.Y;

            points[2] = center.Z + radius;

            points[93] = center.X;

            points[94] = center.Y;

            points[95] = center.Z - radius;

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

            {

                int index = 3 * i;

                // 点

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

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

                dx1 = points[index + 3];

                dy1 = points[index + 4];

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

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

                points[index + 5] = z1;

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

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

                dx2 = points[index + 33];

                dy2 = points[index + 34];

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

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

                points[index + 35] = center.Z;

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

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

                points[index + 65] = z2;

            }

        }

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

        {

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

        }

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

        {

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

        }

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

        {

            switch (md)

            {

                case MoveDirection.MD_X:

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

                    break;

                case MoveDirection.MD_Y:

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

                    break;

                case MoveDirection.MD_Z:

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

                    break;

                case MoveDirection.MD_XY:

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

                    break;

                case MoveDirection.MD_XZ:

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

                    break;

                case MoveDirection.MD_YZ:

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

                    break;

                case MoveDirection.MD_NONE:

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

                    break;

                default:

                    break;

            }

        }

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

        {

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

        }

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

        {

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

        }

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

        {

            switch (rd)

            {

                case RotateDirection.RD_X:

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

                    break;

                case RotateDirection.RD_Y:

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

                    break;

                case RotateDirection.RD_Z:

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

                    break;

                case RotateDirection.RD_NONE:

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

                    break;

                default:

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

                    break;

            }

        }

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

        {

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

        }

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

        {

            switch (rd)

            {

                case ResizeDirection.RD_X:

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

                    break;

                case ResizeDirection.RD_Y:

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

                    break;

                case ResizeDirection.RD_Z:

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

                    break;

                case ResizeDirection.RD_XY:

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

                    break;

                case ResizeDirection.RD_XZ:

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

                    break;

                case ResizeDirection.RD_YZ:

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

                    break;

                case ResizeDirection.RD_XYZ:

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

                    break;

                case ResizeDirection.RD_NONE:

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

                    break;

                default:

                    break;

            }

        }

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

        {

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

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

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

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

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

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

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

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

            float e = 0.01f;

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

            p_p1.Normalize();

            p_p2.Normalize();

            p_p3.Normalize();

            p_p4.Normalize();

            p1 += p_p1 * e;

            p2 += p_p2 * e;

            p3 += p_p3 * e;

            p4 += p_p4 * e;

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

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

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

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

        }

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

        {

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

            Matrix4F tmp = TransformationF.Translation(dir);

            Matrix4F res = locationmat * tmp;

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

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

            DrawDirectionArrow(start, end - dir, view);

        }

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

        {

            float length1 = 6;

            float length2 = 1;

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

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

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

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

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

        }

        //画一个球体

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

        {

            ClientBridge.ClientRenderSys crs = view.getRenderSys();

            float[] points = new float[96]; // 32个点

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

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

            ComputePointVertex(center, radius, points);

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

            {

                int index = 3 * i;

                // 三角形索引

                indexs[index] = 0;

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

                indexs[index + 2] = i + 1;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                indexs[index + 152] = 31;

            }

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

        }

        //画一个球的网格

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

        {

            float[] points = new float[96]; // 32个点

            int[] indexs = new int[180]; // 90条边

            ComputePointVertex(center, radius, points);

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

            {

                int index = 2 * i;

                indexs[index] = 0;

                indexs[index + 1] = i + 1;

            }

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

            {

                int index = 2 * i;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                indexs[index + 161] = 31;

            }

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

        }

        //画非点光源的起点和终点之间的连接线

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

        {

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

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

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

        }

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

        {

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

            int index = 0;

            float m = 0, n = 0;

            float tmp = 0;

            if (dis == 0)

            {

                return new Vector3F(start);

            }

            else if (dis < 0)

            {

                dis = -dis;

                dir = Vector3F.Negate(dir);

            }

            if (dir.Z != 0)

            {

                m = dir.Z;

                n = start.Z;

                index = 1;

            }

            else if (dir.X != 0)

            {

                m = dir.X;

                n = start.X;

                index = 2;

            }

            else if (dir.Y != 0)

            {

                m = dir.Y;

                n = start.Y;

                index = 3;

            }

            else

            {

                return new Vector3F();

            }

            tmp = dis * dis * m * m;

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

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

            if (tmp * m < 0)

            {

                tmp = -tmp;

            }

            tmp += n;

            if (index == 1)

            {

                z = tmp;

                if (dir.X != 0)

                {

                    x = dir.X * (z - start.Z) / dir.Z + start.X;

                }

                else

                {

                    x = start.X;

                }

                if (dir.Y != 0)

                {

                    y = dir.Y * (z - start.Z) / dir.Z + start.Y;

                }

                else

                {

                    y = start.Y;

                }

            }

            if (index == 2)

            {

                x = tmp;

                if (dir.Y != 0)

                {

                    y = dir.Y * (x - start.X) / dir.X + start.Y;

                }

                else

                {

                    y = start.Y;

                }

                if (dir.Z != 0)

                {

                    z = dir.Z * (x - start.X) / dir.X + start.Z;

                }

                else

                {

                    z = start.Z;

                }

            }

            if (index == 3)

            {

                y = tmp;

                if (dir.X != 0)

                {

                    x = dir.X * (y - start.Y) / dir.Y + start.X;

                }

                else

                {

                    x = start.X;

                }

                if (dir.Z != 0)

                {

                    z = dir.Z * (y - start.Y) / dir.Y + start.Z;

                }

                else

                {

                    z = start.Z;

                }

            }

            return new Vector3F(x, y, z);

        }

        //求线段上距起点一定距离的点

        public static Vector3F GetPointDisNToPointOnLine(Vector3F start, Vector3F end, float dis)

        {

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

            return GetPointDisNToPoint(start, direct, dis);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            RenderCube(center, normal, radis, length, color, rendersys, false);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys, bool hardsel)

        {

            RenderCube(center, normal, radis, length, color, rendersys, hardsel, false);

        }

        public static void RenderCube(Vector3F center, Vector3F normal, float radis, float length, float[] color, ClientBridge.ClientRenderSys rendersys, bool hardsel, bool hidesee)

        {

            float[] points = new float[24];

            float radius = radis * ((float)Math.Sqrt(2));

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            if (normal.GetLength() != 0)

            {

                normal.Normalize();

            }

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

            {

                float factor = 0;

                Vector3F u = new Vector3F();

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

                {

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

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

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

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

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

                v.Normalize();

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

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

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

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

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

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

            }

            if (hardsel)

            {

                int[] indexs = new int[36] { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 0, 1, 5, 0, 5, 4, 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 0, 4, 3, 4, 7 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_TRIANGLE_LIST, points, indexs, color, hidesee);

            }

            else

            {

                int[] indexs = new int[24] { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 };

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexs, color, hidesee);

            }

        }

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

        {

            normal.Normalize();

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            int pointcount = 360;

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

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

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

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

            float[] points3 = new float[24];

            int i = 0;

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

            {

                float factor = 0;

                Vector3F u = new Vector3F();

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

                {

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

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

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

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

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

                v.Normalize();

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

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

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

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

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

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

                indexs1[t] = t;

                indexs2[t] = t;

                if (t % 90 == 0)

                {

                    points3[i * 3] = points1[t * 3];

                    points3[i * 3 + 1] = points1[t * 3 + 1];

                    points3[i * 3 + 2] = points1[t * 3 + 2];

                    points3[12 + i * 3] = points2[t * 3];

                    points3[12 + i * 3 + 1] = points2[t * 3 + 1];

                    points3[12 + i * 3 + 2] = points2[t * 3 + 2];

                    i++;

                }

            }

            indexs1[pointcount] = 0;

            indexs2[pointcount] = 0;

            int[] indexs3 = new int[8] { 0, 4, 1, 5, 2, 6, 3, 7 };

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points1, indexs1, color, false);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_STRIP, points2, indexs2, color, false);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points3, indexs3, color, false);

        }

        //画一个四棱锥

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

        {

            if (normal.GetLength() != 0)

                normal.Normalize();

            else

                return;

            Vector3F top = GetPointDisNToPoint(center, normal, height);

            Vector3F up = Tool.FloatCompare(normal.X, 0, float.Epsilon) && Tool.FloatCompare(normal.Y, 0, float.Epsilon) ? Vector3F.YAxis : Vector3F.ZAxis;

            Vector3F right = Vector3F.CrossProduct(up, normal);

            right.Normalize();

            up = Vector3F.CrossProduct(right, normal);

            up.Normalize();

            float half_l = height / 5;

            Vector3F[] verts = new Vector3F[6];

            verts[0] = top;

            verts[1] = center - half_l * right;

            verts[2] = center - half_l * up;

            verts[3] = center + half_l * right;

            verts[4] = center + half_l * up;

            verts[5] = center;

            float[] points = new float[18];

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

            {

                points[i * 3 + 0] = verts[i].X;

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

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

            }

            int[] indexs = new int[24] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 1, 5, 2, 2, 5, 3, 3, 5, 4, 4, 5, 1 };

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

        }

        public static void RenderConic(int shape, Vector3F center, Vector3F normal, float angle, float length, float[] color, ClientBridge.ClientRenderSys rendersys)

        {

            if (normal.GetLength() != 0)

            {

                normal.Normalize();

            }

            Vector3F center2 = GetPointDisNToPoint(center, normal, length);

            float radius = (float)Math.Tan(Math.PI * angle / (180 * 2)) * length;

            if (shape == (int)LightShape.CIRCLE)

            {

                int pointcount = 360;

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

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

                float[] points1 = new float[15];

                int i = 0;

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

                {

                    float factor = 0;

                    Vector3F u = new Vector3F();

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

                    {

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

                        u.X = -normal.Z * factor;

                        u.Y = 0;

                        u.Z = normal.X * factor;

                    }

                    else

                    {

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

                        u.X = 0;

                        u.Y = normal.Z * factor;

                        u.Z = -normal.Y * factor;

                    }

                    u.Normalize();

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

                    v.Normalize();

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

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

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

                    indexs[t] = t;

                    if (t % 90 == 0)

                    {

                        points1[i * 3] = points[t * 3];

                        points1[i * 3 + 1] = points[t * 3 + 1];

                        points1[i * 3 + 2] = points[t * 3 + 2];

                        i++;

                    }

                }

                indexs[pointcount] = 0;

                points1[12] = center.X;

                points1[13] = center.Y;

                points1[14] = center.Z;

                int[] indexs1 = new int[8] { 4, 0, 4, 1, 4, 2, 4, 3 };

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

                rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points1, indexs1, color, false);

            }

            else

            {

                float radius1 = radius * ((float)Math.Sqrt(2));

                float[] points = new float[27];

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

                {

                    float factor = 0;

                    Vector3F u = new Vector3F();

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

                    {

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

                        u.X = -normal.Z * factor;

                        u.Y = 0;

                        u.Z = normal.X * factor;

                    }

                    else

                    {

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

                        u.X = 0;

                        u.Y = normal.Z * factor;

                        u.Z = -normal.Y * factor;

                    }

                    u.Normalize();

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

                    v.Normalize();

                    points[t * 3] = (float)(center2.X + (radius1 * Math.Cos(Math.PI * (t * 90 + 45) / 180.0f)) * u.X + (radius1 * Math.Sin(Math.PI * (t * 90 + 45) / 180.0f)) * v.X);

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

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

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

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

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

                }

                points[24] = center.X;

                points[25] = center.Y;

                points[26] = center.Z;

                int[] indexs = new int[24] { 0, 1, 1, 2, 2, 3, 3, 0, 8, 0, 8, 1, 8, 2, 8, 3, 8, 4, 8, 5, 8, 6, 8, 7 };

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

            }

        }

        public static void RenderDirStartPoint(Vector3F start, Vector3F end, float radius, float[] color, IView view)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

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

            RenderCloumn(start, dir, radius, 2 * radius, color, view.getRenderSys());

        }

        public static void RenderPrmStartPoint(int shape, Vector3F start, Vector3F end, float angle, float[] color, IView view)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

            float length = GetFakeLength(start, 2, stdDist, view);

            length = (float)(length * Math.Cos(Math.PI * angle / 360.0f));

            RenderConic(shape, start, dir, angle, length, color, view.getRenderSys());

        }

        public static void RenderLightEndPoint(Vector3F start, Vector3F end, float radius, float[] color, IView view, bool hardsel)

        {

            Vector3F dir = ComputeVectorAndNormalize(start, end);

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

            RenderCube(end, Vector3F.Negate(dir), radius, 2 * radius, color, view.getRenderSys(), hardsel);

        }

    }

    // Group信息

    public struct GroupActorInfo

    {

        public string m_group_name;   // 物品名称 前缀+id

        public float m_height;

        public bool m_bClose;

        public RotateMode m_eRotateMode;

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

        {

            string nameprefix = createpropdic["NamePrefix"];

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

            try

            {

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

            }

            catch (Exception)

            {

                m_height = 0;

            }

            m_bClose = true;

            m_eRotateMode = RotateMode.RM_WHOLE;

        }

        // 转换成属性列表

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

        {

            dic["Name"] = m_group_name;

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

            dic["Close"] = m_bClose.ToString();

            dic["RotateMode"] = m_eRotateMode.ToString();

        }

        public void valueChanged(string key, string value)

        {

            switch (key)

            {

                case "Name":

                    m_group_name = value;

                    break;

                case "Height":

                    try

                    {

                        m_height = float.Parse(value);

                    }

                    catch (Exception)

                    {

                        m_height = 0;

                    }

                    break;

                case "Close":

                    m_bClose = value.ToLower() == "true" ? true : false;

                    break;

                case "RotateMode":

                    // fixme :

                    if (value == "RM_WHOLE")

                        m_eRotateMode = RotateMode.RM_WHOLE;

                    else if (value == "RM_SELF")

                        m_eRotateMode = RotateMode.RM_SELF;

                    else

                        m_eRotateMode = RotateMode.RM_BOTH;

                    break;

                default:

                    break;

            }

        }

    }

    // Group

    public class GroupActor : ActorBase, IActor

    {

        IActorLayerMng m_actor_layer = null;

        GroupActorInfo m_actor_info;

        // 包围盒12条线段对应的GIID,在Group生成时就记录下来。为解决打开Group时的选择问题

        GIID m_aabb_giid;

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, int curindex)

            : this(giidmng, createpropdic, curindex, null)

        {

        }

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, int curindex, IActorLayerMng parentLayer)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo(createpropdic, curindex);

            // 将m_actor_layer置为parentLayer类型

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            this.parentLayer = parentLayer;

            //insertActors(ab);

            //m_actor_layer.getOrgBuffer().add(ab);

            // 位置

            Vector3F max = GActorHelper.getMaxPos(m_actor_layer.getOrgBuffer());

            Vector3F pos = GActorHelper.getMinPos(m_actor_layer.getOrgBuffer());

            pos = new Vector3F((max.X + pos.X) / 2.0f, (max.Y + pos.Y) / 2.0f, 0);

            locationmat = TransformationF.Translation(pos) * Matrix4F.Identity;

            m_aabb_giid = giidmng.getGIID();

        }

        public GroupActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ActorBuffer ab, int curindex)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo(createpropdic, curindex);

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            m_actor_layer.getOrgBuffer().add(ab);

            // 位置

            Vector3F pos = GActorHelper.getMinPos(m_actor_layer.getOrgBuffer());

            locationmat = TransformationF.Translation(pos) * Matrix4F.Identity;

            m_aabb_giid = giidmng.getGIID();

        }

        public GroupActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_actor_info = new GroupActorInfo();

            m_actor_layer = new ActorLayerMngImp(null, new DummyActorFun(), new DummyActorFun());

            m_aabb_giid = giidmng.getGIID();

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_GROUP;

        }

        public void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id, IActorLayerMng sellayer)

        {

            if (m_aabb_giid.value == id)

            {

                // 得到应该被选中的Actor

                IActor selactor = this;

                if (!selactors.ContainsKey(sellayer))

                {

                    selactors[sellayer] = new ActorBuffer(null, new DummyActorFun());

                }

                if (!selactors[sellayer].Contains<IActor>(selactor))

                {

                    selactors[sellayer].insert(selactor);

                }

            }

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

            {

                if (actor is GroupActor)

                {

                    ((GroupActor)actor).getSelectByID(selactors, id, sellayer);

                }

                else if (actor.giid.value == id)

                {

                    // 得到应该被选中的Actor

                    IActor selactor = actor;

                    while (selactor.parent != null && ((GroupActor)(selactor.parent)).close)

                    {

                        selactor = selactor.parent;

                    }

                    if (!selactors.ContainsKey(sellayer))

                    {

                        selactors[sellayer] = new ActorBuffer(null, new DummyActorFun());

                    }

                    if (!selactors[sellayer].Contains<IActor>(selactor))

                    {

                        selactors[sellayer].insert(selactor);

                    }

                    return;

                }

            }

        }

        //public void getSelectMoveLineID(int id, IActorLayerMng sellayer)

        //{

        //}

        public override void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            // 使所有子物品参与硬件选择

            getActorBuffer().pushHardwareSelect(rendersys);

            if (!close)

            { // Group打开状态下,包围盒参与选择

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

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

                Vector3F[] vetexs = aabb.ComputeVertices();

                float[] points = new float[24];

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

                {

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

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

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

                }

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

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

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

                               };

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

                // fixme : 线的硬件选择engine还有问题。。。

                rendersys.pushSelectID(100);

                rendersys.drawLine(vetexs[7].X, vetexs[7].Y, vetexs[7].Z, vetexs[0].X, vetexs[0].Y, vetexs[0].Z, c);

            }

        }

        public override bool hide

        {

            get

            {

                return base.hide;

            }

            set

            {

                base.hide = value;

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

                {

                    actor.hide = value;

                }

            }

        }

        public override bool freeze

        {

            get

            {

                return base.freeze;

            }

            set

            {

                base.freeze = value;

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

                {

                    actor.freeze = value;

                }

            }

        }

        // Group关闭状态

        public bool close

        {

            get

            {

                return m_actor_info.m_bClose;

            }

            set

            {

                if (this is PrefebActor)

                {

                    MessageBox.Show("fixme : can not open prefeb!");

                    return;

                }

                m_actor_info.m_bClose = value;

            }

        }

        public override string name

        {

            get

            {

                return m_actor_info.m_group_name;

            }

            set

            {

                AssertUtil.confirm(this is PrefebActor);

                m_actor_info.m_group_name = value;

            }

        }

        public RotateMode rotatemode

        {

            get

            {

                return m_actor_info.m_eRotateMode;

            }

            set

            {

                m_actor_info.m_eRotateMode = value;

            }

        }

        public void Dispose()

        {

            m_actor_layer.Dispose();

        }

        #region about IActor

        public override IActorLayerMng getActorBuffer()

        {

            return m_actor_layer;

        }

        public List<T> getActors<T>() where T : IActor

        {

            List<T> l = new List<T>();

            IEnumerator<T> it = m_actor_layer.getOrgBuffer().GetEnumerator<T>();

            while (it.MoveNext())

            {

                l.Add(it.Current);

            }

            IEnumerator<GroupActor> it_group = m_actor_layer.getOrgBuffer().GetEnumerator<GroupActor>();

            while (it_group.MoveNext())

            {

                l.AddRange(it_group.Current.getActors<T>());

            }

            return l;

        }

        public IActor clone(IEditItem edititem)

        {

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

            GroupActor actor = null;

            return actor;

        }

        //public IMemento getMemento(int mode)

        //{

        //    return null;

        //}

        //public void setMemento(IMemento mem)

        //{

        //}

        public override bool serialize(BinaryWriter binWriter)

        {

            if (!(this is PrefebActor))

            {

                binWriter.Write(m_actor_info.m_group_name);

                binWriter.Write(m_actor_info.m_height);

                binWriter.Write(m_actor_info.m_bClose);

                getActorBuffer().serialize(binWriter);

            }

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            if (!(this is PrefebActor))

            {

                m_actor_info.m_group_name = binReader.ReadString();

                m_actor_info.m_height = binReader.ReadSingle();

                m_actor_info.m_bClose = binReader.ReadBoolean();

                m_actor_layer.serialize(binReader, edititem);

            }

            foreach (IActor actor in m_actor_layer.getOrgBuffer())

            {

                actor.parent = this;

            }

            return base.serialize(binReader, edititem);

        }

        #endregion

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

        {

            // 调用自己的绘制函数

            m_actor_layer.render(t, rendersys);

        }

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

        {

            base.renderAABB(t, rendersys, color);

        }

        public override IDictionary<string, string> getPropertyList()

        {

            m_actor_info.toDic(m_property_dic);

            return base.getPropertyList();

        }

        public override void updateLocationAABB()

        {

            if (m_actor_layer.getOrgBuffer().Count<IActor>() == 0)

            {

                return;

            }

            // 修改包围盒

            IActor actor0 = m_actor_layer.getOrgBuffer().ElementAt<IActor>(0);

            aabb = actor0.aabb;

            foreach (IActor actor in m_actor_layer.getOrgBuffer())

            {

                Vector3F aabbmin = aabb.Min;

                Vector3F aabbmax = aabb.Max;

                if (actor.aabb.Min.X < aabbmin.X)

                {

                    aabbmin.X = actor.aabb.Min.X;

                }

                if (actor.aabb.Min.Y < aabbmin.Y)

                {

                    aabbmin.Y = actor.aabb.Min.Y;

                }

                if (actor.aabb.Min.Z < aabbmin.Z)

                {

                    aabbmin.Z = actor.aabb.Min.Z;

                }

                if (actor.aabb.Max.X > aabbmax.X)

                {

                    aabbmax.X = actor.aabb.Max.X;

                }

                if (actor.aabb.Max.Y > aabbmax.Y)

                {

                    aabbmax.Y = actor.aabb.Max.Y;

                }

                if (actor.aabb.Max.Z > aabbmax.Z)

                {

                    aabbmax.Z = actor.aabb.Max.Z;

                }

                aabb = new AxisAlignedBox(aabbmin, aabbmax);

            }

            base.updateLocationAABB();

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

            m_actor_info.valueChanged(key, value);

        }

    }

    public struct PrefebActorInfo

    {

        public string m_group_name;

        public string m_prefeb_name;

        public PrefebActorInfo(string group, string name)

        {

            m_group_name = group;

            m_prefeb_name = name;

        }

    }

    // 包裹

    public class PrefebActor : GroupActor

    {

        public PrefebActor(GIIDMng giidmng, Dictionary<string, string> createpropdic, ActorBuffer ab, int curindex, string group, string name)

            : base(giidmng, createpropdic, ab, curindex)

        {

            m_prefeb_info = new PrefebActorInfo(group, name);

        }

        public PrefebActor(GIIDMng giidmng)

            : base(giidmng)

        {

            m_prefeb_info = new PrefebActorInfo();

        }

        public override IDictionary<string, string> getPropertyList()

        {

            return base.getPropertyList();

        }

        // 判断包裹实例是否由某个包裹模板创建

        public bool isCreateFrom(string groupname, string prefebname)

        {

            return ((m_prefeb_info.m_group_name == groupname) && (m_prefeb_info.m_prefeb_name == prefebname));

        }

        public override bool serialize(BinaryWriter binWriter)

        {

            binWriter.Write(m_prefeb_info.m_group_name);

            binWriter.Write(m_prefeb_info.m_prefeb_name);

            return base.serialize(binWriter);

        }

        public override bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            return base.serialize(binReader, edititem);

        }

        PrefebActorInfo m_prefeb_info;

    }

    // 包裹管理器

    public class PrefebManager

    {

        public static void allrotateandmove(GroupActor actor, Matrix4F rotatemat)

        {

            actor.moveTo(new Vector3F(0, 0, 0));

            IActorLayerMng sublayer = actor.getActorBuffer();

            foreach (IActor subactor in sublayer.getOrgBuffer())

            {

                if (subactor is GroupActor)

                    allrotateandmove((GroupActor)subactor, rotatemat * new Matrix4F(subactor.locationmat));

                else

                    subactor.notifyPropertyChange("LocationMat", (rotatemat * subactor.locationmat).ToString());

            }

            actor.notifyPropertyChange("LocationMat", (rotatemat * actor.locationmat).ToString());

        }

        // 将指定物品生成Prefeb模板文件。groupname:组名; name:包裹名称

        public static void generatePrefebFile(IActorLayerMng layer, ActorBuffer ab, string groupname, string prefebname)

        {

            bool prefebmodifyflag = false;

            string path = s_xml_path_prefix + "/" + groupname;

            if (!Directory.Exists(path))

            {

                Directory.CreateDirectory(path);

            }

            string fullfilename = path + "/" + prefebname + ".xml";

            if (File.Exists(fullfilename))

            {

                DialogResult dr = MessageBox.Show("名为[" + prefebname + "]的包裹已存在,是否覆盖?覆盖将更新所有对应的包裹实例!", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (dr == DialogResult.Yes)

                {

                    prefebmodifyflag = true;

                }

                else if (dr == DialogResult.No)

                {

                    generatePrefebFile(layer, ab, groupname, prefebname + " new");

                    return;

                }

            }

            XmlDocument xml = new XmlDocument();

            XmlDeclaration xmldecl;

            xmldecl = xml.CreateXmlDeclaration("1.0", "GBK", "yes");

            xml.AppendChild(xmldecl);

            XmlNode rootElem = xml.CreateNode("element", "PrefebActor", "");

            xml.AppendChild(rootElem);

            XmlNode propertynode;

            // fixme : 包裹信息,暂时在程序中写死

            propertynode = xml.CreateNode("element", "NamePrefix", "");

            propertynode.InnerText = prefebname;

            rootElem.InsertAfter(propertynode, rootElem.LastChild);

            propertynode = xml.CreateNode("element", "Height", "");

            propertynode.InnerText = "0";

            rootElem.InsertAfter(propertynode, rootElem.LastChild);

            // 保存包裹中物品的信息,,,

            XmlNode actornode;

            XmlAttribute actoratt;

            foreach (IActor actor in ab)

            {

                actornode = xml.CreateNode("element", "Item", "");

                actoratt = xml.CreateAttribute("type");

                actoratt.Value = GActorHelper.getActorTypestr(actor);

                actornode.Attributes.Append(actoratt);

                actor.serialize(actornode, null, false, false);

                rootElem.InsertAfter(actornode, rootElem.LastChild);

            }

            xml.Save(fullfilename);

            if (prefebmodifyflag)

            {

                GActorHelper.updatePrefebActors(layer, groupname, prefebname);

            }

            return;

        }

        // 包裹内容的获取

        public static PrefebActor getActorBufferFromPrefebFile(string groupname, string name, IEditItem edititem)

        {

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            Dictionary<string, string> createpropdic = new Dictionary<string, string>();

            //

            XmlDocument prefebxml = new XmlDocument();

            string filename = s_xml_path_prefix + "/" + groupname + "/" + name + ".xml";

            prefebxml.Load(filename);

            foreach (XmlNode childnode in prefebxml.SelectSingleNode("PrefebActor").ChildNodes)

            {

                if (childnode.Name != "Item")

                {

                    // to get the prefeb properties

                    createpropdic[childnode.Name] = childnode.InnerText;

                }

                else

                {

                    // to get the properties of the child actors

                    XmlAttribute typeatt = childnode.Attributes["type"];

                    IActor actor = GActorHelper.generateActorWithoutInfo(typeatt.Value, edititem);

                    actor.serialize(childnode, edititem, true, false);

                    ab.insert(actor);

                }

            }

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

            IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", (IEditItem)SceneGraph.getEditItemCommon("RootItem", edititem));

            IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

            string prefix = createpropdic["NamePrefix"];

            PrefebActor prefebactor = new PrefebActor(root.giidmng, createpropdic, ab, doc.getMaxActorIndex(prefix), groupname, name);

            foreach (IActor actor in ab)

            {

                actor.parent = prefebactor;

            }

            return prefebactor;

        }

        // Prefeb模板xml所在路径

        private static string s_xml_path_prefix = @"../resources/editor/Prefebs";

    }

    // 物品memento,用物品属性列表构建

    public class DancerMemento : IMemento

    {

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

        public int m_index;

        public float m_angle;

        public bool m_ismale;

        public List<string> m_bodyparts = new List<string>();

        public string m_act = "";

    }

    // 人物 fixme:仅做了一个给美术临时用的测试版本,不能保存读取

    public class DancerActor : ActorBase, IActor

    {

        public int m_index;

        public float m_angle;

        public bool m_ismale;

        public List<string> m_bodyparts = new List<string>();

        public string m_act = "";

        public string m_name;

        public DancerActor(GIIDMng giidmng, ClientBridge.ClientRenderSys rendersys)

            : base(giidmng)

        {

        }

        public DancerActor(GIIDMng giidmng, string name, bool ismale, int index, ClientBridge.ClientRenderSys rendersys)

            : base(giidmng)

        {

            m_name = name;

            m_index = index;

            m_ismale = ismale;

            // 设置默认值

            m_angle = 90;

            m_bodyparts.Add("100000004.bp3");

            m_bodyparts.Add("101001004.bp3");

            m_bodyparts.Add("102004001.bp3");

            m_bodyparts.Add("103021002.bp3");

            m_bodyparts.Add("104025001.bp3");

            m_bodyparts.Add("105000000.bp3");

            m_bodyparts.Add("106008001.bp3");

            m_bodyparts.Add("107000000.bp3");

            m_bodyparts.Add("108010001.bp3");

        }

        public override ACTOR_TYPE GetActorType()

        {

            return ACTOR_TYPE.AT_ACTOR;

        }

        public void Dispose()

        {

            m_bodyparts.Clear();

        }

        #region about IActor

        public IActor clone(IEditItem edititem)

        {

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

            DancerActor actor = null;

            return actor;

        }

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

        {

        }

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

        {

            base.renderAABB(t, rendersys, color);

        }

        #endregion

        public override IDictionary<string, string> getPropertyList()

        {

            return base.getPropertyList();

        }

        public override void notifyPropertyChange(String key, String value)

        {

            base.notifyPropertyChange(key, value);

        }

        // 获得物品Memento

        public override IMemento getMemento(int mode)

        {

            DancerMemento mem = new DancerMemento();

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

            {

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

            }

            mem.m_act = m_act;

            mem.m_angle = m_angle;

            foreach (string str in m_bodyparts)

            {

                mem.m_bodyparts.Add(str);

            }

            mem.m_index = m_index;

            mem.m_ismale = m_ismale;

            return mem;

        }

        // 设置物品Memento

        public override void setMemento(IMemento mem)

        {

            DancerMemento actormem = (DancerMemento)mem;

            m_act = actormem.m_act;

            m_angle = actormem.m_angle;

            m_bodyparts.Clear();

            foreach (string str in actormem.m_bodyparts)

            {

                m_bodyparts.Add(str);

            }

            m_index = actormem.m_index;

            m_ismale = actormem.m_ismale;

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

            {

                notifyPropertyChange(kv.Key, kv.Value);

            }

            updateLocationAABB();

        }

    }

    // -------------

    // 在物品加入容器或从容器中移出时,会调用相应的函数

    public interface IActorFun

    {

        void insert(IActor actor, IActorLayerMng layer);

        void remove(IActor actor, IActorLayerMng layer);

    }

    // 在物品加入容器或从容器中移出时,不做任何事情

    public class DummyActorFun : IActorFun

    {

        #region IActorFun 成员

        public void insert(IActor actor, IActorLayerMng layer)

        {

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

        }

        #endregion

    }

    // 在删除以及插入actor时,将actor的层次管理器(如果有的话)删除或添加到对应的层次管理器中

    public class ActorAsLayerActorFun : IActorFun

    {

        public void insert(IActor actor, IActorLayerMng layer)

        {

            if (actor.getActorBuffer() != null)

            {

                layer.getList().Add(actor.getActorBuffer());

                actor.getActorBuffer().parent = layer;

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            if (actor.getActorBuffer() != null)

            {

                actor.getActorBuffer().parent = null;

                layer.getList().Remove(actor.getActorBuffer());

            }

        }

    }

    // 物品容器,用来记录相同类型和不同类型的物品,可以轮训

    // 不负责所记录actor的销毁

    //     public class ActorBuffer : IEnumerable<IActor>

    //     {

    //         // 所在的物品层

    //         IActorLayerMng m_layer;

    //         // 物品移入移出时所调用的函数

    //         IActorFun m_actor_fun;

    //

    //         public ActorBuffer(IActorLayerMng layer, IActorFun fun)

    //         {

    //             m_layer = layer;

    //             m_actor_fun = fun;

    //         }

    //         // 物品容器用来记录所有的物品,不同类型还没有用不同的容器来保存

    //         Dictionary<Type, Dictionary<IActor, IActor>> m_dic = new Dictionary<Type, Dictionary<IActor, IActor>>();

    //

    //         // 迭代器供迭代使用,将Dictionary的迭代器转化为IEnumerator<IActor>类型的迭代器

    //         // fixme: 可以为了针对指定类型的迭代,这个类还需要记录所剩物品类型所对应的物品容器

    //         public class ActorBufferEnumerator<T> : IEnumerator<T> where T: IActor

    //         {

    //             public ActorBufferEnumerator(IEnumerator<KeyValuePair<Type, Dictionary<IActor, IActor>>> base_enumerator)

    //             {

    //                 AssertUtil.confirm(base_enumerator != null);

    //                 m_base_enumerator = base_enumerator;

    //                 Reset();

    //             }

    //             public ActorBufferEnumerator(IEnumerator<KeyValuePair<IActor, IActor>> cur_enumerator)

    //             {

    //                 m_cur_enumerator = cur_enumerator;

    //                 m_single_type = true;

    //             }

    //

    //             IEnumerator<KeyValuePair<Type, Dictionary<IActor, IActor>>> m_base_enumerator;

    //             IEnumerator<KeyValuePair<IActor, IActor>> m_cur_enumerator;

    //             bool m_single_type = false;

    //             

    //             public T Current

    //             {

    //                 get { return (T)m_cur_enumerator.Current.Key; }

    //             }

    //

    //             public void Dispose()

    //             {

    //                 if (m_base_enumerator != null)

    //                 {

    //                     m_base_enumerator.Dispose();

    //                 }

    //                 if (m_cur_enumerator != null)

    //                 {

    //                     m_cur_enumerator.Dispose();

    //                 }

    //             }

    //

    //             object System.Collections.IEnumerator.Current

    //             {

    //                 get { return m_cur_enumerator.Current.Key; }

    //             }

    //

    //             public bool MoveNext()

    //             {

    //                 if (m_cur_enumerator == null)

    //                 {

    //                     return false;

    //                 }

    //                 if (m_cur_enumerator.MoveNext())

    //                 {

    //                     return true;

    //                 }

    //                 else

    //                 {

    //                     if (!m_single_type && m_base_enumerator.MoveNext())

    //                     {

    //                         m_cur_enumerator = m_base_enumerator.Current.Value.GetEnumerator();

    //

    //                         return MoveNext();

    //                     }

    //                     else

    //                     {

    //                         return false;

    //                     }

    //                 }

    //             }

    //             

    //             public void Reset()

    //             {

    //                 if (m_single_type && m_cur_enumerator != null)

    //                 {

    //                     m_cur_enumerator.Reset();

    //                 }

    //                 else

    //                 {

    //                     m_base_enumerator.Reset();

    //                     if (m_base_enumerator.MoveNext())

    //                     {

    //                         m_cur_enumerator = m_base_enumerator.Current.Value.GetEnumerator();

    //                     }

    //                     else

    //                     {

    //                         m_cur_enumerator = null;

    //                     }

    //                 }

    //             }

    //         }

    //

    //         // 是否没有内容

    //         public bool empty()

    //         {

    //             return m_dic.Count == 0;

    //         }

    //         //

    //         public void insert(IActor a)

    //         {

    //             if (!m_dic.ContainsKey(a.GetType()))

    //             {

    //                 m_dic.Add(a.GetType(), new Dictionary<IActor, IActor>());

    //             }

    //             m_dic[a.GetType()].Add(a, a);

    //             m_actor_fun.insert(a, m_layer);

    //         }

    //         //

    //         public void remove(IActor a)

    //         {

    //             if (m_dic.ContainsKey(a.GetType()))

    //             {

    //                 m_dic[a.GetType()].Remove(a);

    //                 m_actor_fun.remove(a, m_layer);

    //                 if (m_dic[a.GetType()].Count == 0)

    //                 {

    //                     m_dic.Remove(a.GetType());

    //                 }

    //             }

    //         }

    //         // 清除所有内容

    //         // 本类不负责所记录actor的销毁

    //         public void clear()

    //         {

    //             m_dic.Clear();

    //         }

    //         // 集合减操作,修改自身内容

    //         public void substract(ActorBuffer buf)

    //         {

    //             foreach (KeyValuePair<Type, Dictionary<IActor, IActor>> tvp in buf.m_dic)

    //             {

    //                 if (m_dic.ContainsKey(tvp.Key))

    //                 {

    //                     foreach (KeyValuePair<IActor, IActor> kvp in tvp.Value)

    //                     {

    //                         if (m_dic[tvp.Key].ContainsKey(kvp.Key))

    //                         {

    //                             m_dic[tvp.Key].Remove(kvp.Key);

    //                             m_actor_fun.remove(kvp.Key, m_layer);

    //                         }

    //                     }

    //                     if (m_dic[tvp.Key].Count == 0)

    //                     {

    //                         m_dic.Remove(tvp.Key);

    //                     }

    //                 }

    //             }

    //         }

    //         // 集合并操作,修改自身内容

    //         public void add(ActorBuffer buf)

    //         {

    //             foreach (KeyValuePair<Type, Dictionary<IActor, IActor>> tvp in buf.m_dic)

    //             {

    //                 if (!m_dic.ContainsKey(tvp.Key))

    //                 {

    //                     m_dic.Add(tvp.Key, new Dictionary<IActor, IActor>());

    //                 }

    //                 foreach (KeyValuePair<IActor, IActor> kvp in tvp.Value)

    //                 {

    //                     if (!m_dic[tvp.Key].ContainsKey(kvp.Key))

    //                     {

    //                         m_dic[tvp.Key].Add(kvp.Key, kvp.Value);

    //                         m_actor_fun.insert(kvp.Key, m_layer);

    //                     }

    //                 }

    //                 if (m_dic[tvp.Key].Count == 0)

    //                 {

    //                     m_dic.Remove(tvp.Key);

    //                 }

    //             }

    //         }

    //         // 复制自身内容,注意不复制对应的IActorFun

    //         public ActorBuffer clone()

    //         {

    //             ActorBuffer actorbuf = new ActorBuffer(null, new DummyActorFun());

    //

    //             actorbuf.add(this);

    //

    //             return actorbuf;

    //         }

    // //         // 针对不同类型的迭代器

    // //         public IEnumerator<T> GetEnumerator<T>() where T : IActor

    // //         {

    // //             if (m_dic.ContainsKey(typeof(T)))

    // //             {

    // //                 return new ActorBufferEnumerator<T>(m_dic[typeof(T)].GetEnumerator());

    // //             }

    // //             else

    // //             {

    // //                 return new ActorBufferEnumerator<T>((IEnumerator<KeyValuePair<IActor, IActor>>)null);

    // //             }

    // //         }

    // //         //

    // //         public IEnumerator<IActor> GetEnumerator()

    // //         {

    // //             return new ActorBufferEnumerator<IActor>(m_dic.GetEnumerator());

    // //         }

    // //         //

    // //         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    // //         {

    // //             return new ActorBufferEnumerator<IActor>(m_dic.GetEnumerator());

    // //         }

    //

    //         // 针对不同类型的迭代器

    //         public IEnumerator<T> GetEnumerator<T>() where T : IActor

    //         {

    //             return GetEnumerator<T>(false);

    //         }

    //         public IEnumerator<T> GetEnumerator<T>(bool recurse) where T : IActor

    //         {

    //             return new ActorBufferEnumerator<T>(recurse, false, m_actor_dic, m_type_dic);

    //         }

    //         public IEnumerator<T> GetReverseEnumerator<T>() where T : IActor

    //         {

    //             return GetReverseEnumerator<T>(false);

    //         }

    //         public IEnumerator<T> GetReverseEnumerator<T>(bool recurse) where T : IActor

    //         {

    //             return new ActorBufferEnumerator<T>(recurse, true, m_actor_dic, m_type_dic);

    //         }

    //         //

    //         public IEnumerator<IActor> GetEnumerator()

    //         {

    //             return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

    //         }

    //         //

    //         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

    //         {

    //             return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

    //         }

    //

    //         // 是否包含指定的物品

    //         public bool contain(IActor actor)

    //         {

    //             if (actor != null)

    //             {

    //                 if (m_dic.ContainsKey(actor.GetType()))

    //                 {

    //                     return m_dic[actor.GetType()].ContainsKey(actor);

    //                 }

    //             }

    //             return false;

    //         }

    //     }

    // 物品容器,用来记录相同类型和不同类型的物品,可以轮训

    // 不负责所记录actor的销毁

    public class ActorBuffer : IEnumerable<IActor>

    {

        /// <summary>

        /// 所在的物品层

        /// </summary>

        [XmlIgnore]

        public IActorLayerMng LayerMng

        {

            get { return m_layer; }

            set { m_layer = value; }

        }

        /// <summary>

        /// 物品移入移出时所调用的函数

        /// 序列化使用

        /// </summary>

        [XmlElement]

        public IActorFun ActorFun

        {

            get { return m_actor_fun; }

            set { m_actor_fun = value; }

        }

        //判断内部类型是否是传入类型或者是否是传入类型的子类型

        public ActorBuffer getTypeActors(Type _t)

        {

            ActorBuffer buffer = new ActorBuffer(m_layer, m_actor_fun);

            foreach (Type type in m_actor_dic.Keys)

            {

                bool b = false; Type t = type;

                while (t != null && !b)

                    if (t.Equals(_t))

                        b = true;

                    else

                        t = t.BaseType;

                if (b)

                    foreach (IActor actor in m_actor_dic[type].Values)

                        buffer.insert(actor);

            }

            return buffer;

        }

        public ActorBuffer(IActorLayerMng layer, IActorFun fun)

        {

            m_layer = layer;

            m_actor_fun = fun;

        }

        // 是否没有内容

        public bool empty()

        {

            return m_actor_dic.Count == 0;

        }

        //

        public void insert(IActor a)

        {

            if (!m_actor_dic.ContainsKey(a.GetType()))

            {

                m_actor_dic.Add(a.GetType(), new Dictionary<GIID, IActor>());

                addType(a.GetType());

            }

            if (!m_actor_dic[a.GetType()].ContainsKey(a.giid))

            {

                m_actor_dic[a.GetType()].Add(a.giid, a);

                if (a.getActorBuffer() != null)

                    addChildren(a);

                m_actor_fun.insert(a, m_layer);

                //if (m_layer != null)

                //    a.parentLayer = m_layer;

            }

        }

        //

        public void remove(IActor a)

        {

            if (m_actor_dic.ContainsKey(a.GetType()))

            {

                m_actor_dic[a.GetType()].Remove(a.giid);

                if (m_actor_dic[a.GetType()].Count == 0)

                {

                    m_actor_dic.Remove(a.GetType());

                    removeType(a.GetType());

                }

                if (a.getActorBuffer() != null)

                    substractChildren(a);

                m_actor_fun.remove(a, m_layer);

            }

        }

        public IActor find(GIID giid)

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> pair in m_actor_dic)

            {

                if (pair.Value.ContainsKey(giid))

                {

                    return pair.Value[giid];

                }

            }

            return null;

        }

        // 清除所有内容

        // 本类不负责所记录actor的销毁

        public void clear()

        {

            List<IActor> romove_list = new List<IActor>();

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in m_actor_dic)

            {

                foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                {

                    romove_list.Add(kvp.Value);

                }

            }

            m_actor_dic.Clear();

            m_type_dic.Clear();

            foreach (IActor actor in romove_list)

            {

                m_actor_fun.remove(actor, m_layer);

            }

        }

        // 集合减操作,修改自身内容

        public void substract(ActorBuffer buf)

        {

            List<IActor> romove_list = new List<IActor>();

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in buf.m_actor_dic)

            {

                if (m_actor_dic.ContainsKey(tvp.Key))

                {

                    Dictionary<GIID, IActor> actors = m_actor_dic[tvp.Key];

                    foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                    {

                        if (actors.ContainsKey(kvp.Key))

                        {

                            actors.Remove(kvp.Key);

                            romove_list.Add(kvp.Value);

                        }

                    }

                    if (actors.Count == 0)

                    {

                        m_actor_dic.Remove(tvp.Key);

                        removeType(tvp.Key);

                    }

                }

            }

            foreach (IActor actor in romove_list)

            {

                if (actor.getActorBuffer() != null)

                    substractChildren(actor);

                //actor.DoBeforeDel();

                m_actor_fun.remove(actor, m_layer);

            }

        }

        private void substractChildren(IActor actor)

        {

            foreach (IActor childActor in actor.getActorBuffer().getOrgBuffer())

            {

                if (childActor.getActorBuffer() != null)

                    substractChildren(childActor);

                m_actor_fun.remove(childActor, m_layer);

            }

        }

        // 集合并操作,修改自身内容

        public void add(ActorBuffer buf)

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> tvp in buf.m_actor_dic)

            {

                if (!m_actor_dic.ContainsKey(tvp.Key))

                {

                    m_actor_dic.Add(tvp.Key, new Dictionary<GIID, IActor>());

                    addType(tvp.Key);

                }

                Dictionary<GIID, IActor> actors = m_actor_dic[tvp.Key];

                foreach (KeyValuePair<GIID, IActor> kvp in tvp.Value)

                {

                    if (!actors.ContainsKey(kvp.Key))

                    {

                        actors.Add(kvp.Key, kvp.Value);

                        if (kvp.Value.getActorBuffer() != null)

                            addChildren(kvp.Value);

                        m_actor_fun.insert(kvp.Value, m_layer);

                        //if (m_layer != null)

                        //    kvp.Value.parentLayer = m_layer;

                    }

                }

            }

        }

        private void addChildren(IActor actor)

        {

            foreach (IActor childActor in actor.getActorBuffer().getOrgBuffer())

            {

                if (childActor.getActorBuffer() != null)

                    addChildren(childActor);

                m_actor_fun.insert(childActor, m_layer);

                childActor.parentLayer = actor.getActorBuffer();

            }

        }

        // 复制自身内容,注意不复制对应的IActorFun

        public ActorBuffer clone()

        {

            ActorBuffer actorbuf = new ActorBuffer(null, new DummyActorFun());

            actorbuf.add(this);

            return actorbuf;

        }

        // 针对不同类型的迭代器

        public IEnumerator<T> GetEnumerator<T>() where T : IActor

        {

            return GetEnumerator<T>(false);

        }

        public IEnumerator<T> GetEnumerator<T>(bool recurse) where T : IActor

        {

            return new ActorBufferEnumerator<T>(recurse, false, m_actor_dic, m_type_dic);

        }

        public IEnumerator<T> GetReverseEnumerator<T>() where T : IActor

        {

            return GetReverseEnumerator<T>(false);

        }

        public IEnumerator<T> GetReverseEnumerator<T>(bool recurse) where T : IActor

        {

            return new ActorBufferEnumerator<T>(recurse, true, m_actor_dic, m_type_dic);

        }

        //

        public IEnumerator<IActor> GetEnumerator()

        {

            return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

        }

        //

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()

        {

            return new ActorBufferEnumerator<IActor>(true, false, m_actor_dic, m_type_dic);

        }

        // 是否包含指定的物品

        public bool contain(IActor actor)

        {

            if (actor != null)

            {

                if (m_actor_dic.ContainsKey(actor.GetType()))

                {

                    return m_actor_dic[actor.GetType()].ContainsKey(actor.giid);

                }

            }

            return false;

        }

        private void addType(Type type)

        {

            Type base_type = type.BaseType;

            Type iactor_type = typeof(IActor);

            if (iactor_type.IsAssignableFrom(base_type))

            {

                addType(base_type);

            }

            else

            {

                base_type = iactor_type;

            }

            if (!m_type_dic.ContainsKey(base_type))

            {

                m_type_dic.Add(base_type, new Dictionary<Type, Type>());

            }

            if (!m_type_dic[base_type].ContainsKey(type))

            {

                m_type_dic[base_type].Add(type, type);

            }

        }

        private void removeType(Type type)

        {

            if (!m_type_dic.ContainsKey(type))

            {

                Type base_type = type.BaseType;

                Type iactor_type = typeof(IActor);

                if (!iactor_type.IsAssignableFrom(base_type))

                {

                    base_type = iactor_type;

                }

                if (!m_type_dic.ContainsKey(type) && m_type_dic.ContainsKey(base_type))

                {

                    m_type_dic[base_type].Remove(type);

                    if (m_type_dic[base_type].Count == 0)

                    {

                        m_type_dic.Remove(base_type);

                    }

                }

            }

        }

        /// <summary>

        /// 获取一个Actor,当只有一个Actor存在时,这个Actor一般是根Actor

        /// </summary>

        /// <returns></returns>

        public IActor getFirstActor()

        {

            foreach (KeyValuePair<Type, Dictionary<GIID, IActor>> pair in m_actor_dic)

            {

                foreach (KeyValuePair<GIID, IActor> p in pair.Value)

                {

                    return p.Value;

                }

            }

            return null;

        }

        // 迭代器供迭代使用,将Dictionary的迭代器转化为IEnumerator<IActor>类型的迭代器

        // fixme: 可以为了针对指定类型的迭代,这个类还需要记录所剩物品类型所对应的物品容器

        private class ActorBufferEnumerator<T> : IEnumerator<T> where T : IActor

        {

            public ActorBufferEnumerator(bool recurse, bool reverse, Dictionary<Type, Dictionary<GIID, IActor>> actor_dic, Dictionary<Type, Dictionary<Type, Type>> type_dic)

            {

                m_recurse = recurse;

                m_reverse = reverse;

                m_actor_dic = actor_dic;

                m_type_dic = type_dic;

                Reset();

            }

            public T Current

            {

                get { return (T)m_cur_enumerator.Current.Value; }

            }

            public void Dispose()

            {

                if (m_cur_enumerator != null)

                {

                    m_cur_enumerator.Dispose();

                }

            }

            object System.Collections.IEnumerator.Current

            {

                get { return m_cur_enumerator.Current.Key; }

            }

            public bool MoveNext()

            {

                if (m_cur_enumerator != null && m_cur_enumerator.MoveNext())

                {

                    return true;

                }

                else

                {

                    if (m_type_stack.Count > 0)

                    {

                        Type cur_type = m_type_stack[0];

                        m_type_stack.RemoveAt(0);

                        if (m_recurse && m_type_dic.ContainsKey(cur_type))

                        {

                            foreach (KeyValuePair<Type, Type> kvp in (m_reverse ? Enumerable.Reverse(m_type_dic[cur_type]) : m_type_dic[cur_type]))

                            {

                                m_type_stack.Add(kvp.Key);

                            }

                        }

                        if (m_actor_dic.ContainsKey(cur_type))

                        {

                            m_cur_enumerator = (m_reverse ? Enumerable.Reverse(m_actor_dic[cur_type]) : m_actor_dic[cur_type]).GetEnumerator();

                        }

                        return MoveNext();

                    }

                    else

                    {

                        return false;

                    }

                }

            }

            public void Reset()

            {

                m_type_stack.Clear();

                m_type_stack.Add(m_base_type);

                m_cur_enumerator = null;

            }

            List<Type> m_type_stack = new List<Type>();

            IEnumerator<KeyValuePair<GIID, IActor>> m_cur_enumerator;

            Type m_base_type = typeof(T);

            bool m_recurse = false;

            bool m_reverse = false;

            Dictionary<Type, Dictionary<GIID, IActor>> m_actor_dic;

            Dictionary<Type, Dictionary<Type, Type>> m_type_dic;

        }

        // 所在的物品层

        IActorLayerMng m_layer;

        // 物品移入移出时所调用的函数

        IActorFun m_actor_fun;

        // 物品容器用来记录所有的物品

        Dictionary<Type, Dictionary<GIID, IActor>> m_actor_dic = new Dictionary<Type, Dictionary<GIID, IActor>>();

        Dictionary<Type, Dictionary<Type, Type>> m_type_dic = new Dictionary<Type, Dictionary<Type, Type>>();

    }

    // Actor辅助类

    public class GActorHelper

    {

        // 根据生成属性生成指定类别物品

        public static IActor generateActor(string type, Dictionary<string, string> createpropdic, IEditItem edititem)

        {

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

            IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", (IEditItem)SceneGraph.getEditItemCommon("RootItem", edititem));

            IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

            string prefix = (type != "DancerActor" && createpropdic.ContainsKey("NamePrefix")) ? createpropdic["NamePrefix"] : "dancer";

            int actorindex = doc.getMaxActorIndex(prefix);

            switch (type)

            {

                case "ModelActor":

                    return new ModelActor(root.giidmng, createpropdic, root.clientRenderSys, actorindex);

                case "EffectActor":

                    return new EffectActor(root.giidmng, createpropdic, root.clientRenderSys, actorindex);

                case "LightActor":

                    return new LightActor(root.giidmng, new LightInfo(), root.clientRenderSys);

                case "AINodeActor":

                    return new AINodeActor(root.giidmng);                        // fixme :

                case "SoundActor":

                    return new SoundActor(root.giidmng);

                case "GroupActor":

                    return new GroupActor(root.giidmng);

                case "PrefebActor":

                    return PrefebManager.getActorBufferFromPrefebFile(createpropdic["group"], createpropdic["name"], edititem);

                case "DancerActor":

                    return new DancerActor(root.giidmng, "nametest", true, actorindex - 1, root.clientRenderSys);

                default:

                    return null;

            }

        }

        // 生成不含物品具体信息的物品

        public static IActor generateActorWithoutInfo(string type, IEditItem edititem)

        {

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

            switch (type)

            {

                case "ModelActor":

                    return new ModelActor(root.giidmng);

                case "EffectActor":

                    return new EffectActor(root.giidmng);

                case "LightActor":

                    return new LightActor(root.giidmng);

                case "AINodeActor":

                    return new AINodeActor(root.giidmng);

                case "SoundActor":

                    return new SoundActor(root.giidmng);

                case "GroupActor":

                    return new GroupActor(root.giidmng);

                case "PrefebActor":

                    return new PrefebActor(root.giidmng);

                default:

                    return null;

            }

        }

        public static void getTypeActors(Dictionary<IActorLayerMng, ActorBuffer> resultactors, IActorLayerMng layer, string type, bool select, bool substract)

        {

            ActorBuffer allab = select ? (layer.getSelBuffer()) : (layer.getOrgBuffer());

            foreach (IActor actor in allab)

            {

                if (getActorTypestr(actor) == type)

                {

                    if (!resultactors.ContainsKey(layer))

                    {

                        resultactors[layer] = new ActorBuffer(null, new DummyActorFun());

                    }

                    resultactors[layer].insert(actor);

                    //ab.insert(actor);

                }

            }

            if (substract)

            {

                foreach (IActor actor in allab)

                {

                    if (getActorTypestr(actor) == type)

                    {

                        layer.getOrgBuffer().remove(actor);

                    }

                }

            }

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                getTypeActors(resultactors, sublayer, type, select, substract);

            }

        }

        //得到指定层及其子层中的物品 unfreeze:为true则不获取冻结物体 DTK198 liaowenfang

        public static void getActors(ActorBuffer ab, IActorLayerMng layer, bool select, bool substract, bool unfreeze)

        {

            ActorBuffer allab = select ? (layer.getSelBuffer()) : (layer.getOrgBuffer());

            ab.add(allab);

            if (substract)

            {

                layer.getOrgBuffer().substract(allab);

            }

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                getActors(ab, sublayer, select, substract);

            }

            if (unfreeze)

            {

                ActorBuffer ufab = new ActorBuffer(ab.LayerMng, ab.ActorFun);

                foreach (IActor actor in ab)

                    if (!actor.freeze && !actor.hide && !BaseCommand.isActorLayerReadOnly(actor.parentLayer, BaseCommand.ACTORLAYER_ITERATE_MODE.FREEZE | BaseCommand.ACTORLAYER_ITERATE_MODE.HIDE))

                        ufab.insert(actor);

                ab.clear();

                ab.add(ufab);

            }

        }

        // 得到指定层及其子层中的物品,参数含义同getTypeActors

        public static void getActors(ActorBuffer ab, IActorLayerMng layer, bool select, bool substract)

        {

            getActors(ab, layer, select, substract, false);

        }

        public static void updatePrefebActors(IActorLayerMng layer, string groupname, string prefebname)

        {

            ActorBuffer abold = new ActorBuffer(null, new DummyActorFun());

            ActorBuffer abnew = new ActorBuffer(null, new DummyActorFun());

            foreach (IActor actor in layer.getOrgBuffer())

            {

                if (actor is PrefebActor)

                {

                    PrefebActor pactor = actor as PrefebActor;

                    if (pactor.isCreateFrom(groupname, prefebname))

                    {

                        abold.insert(actor);

                        IActor newactor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, layer);

                        // 位置更新

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

                        Vector3F posnew = GActorHelper.getMinPos(newactor.getActorBuffer().getOrgBuffer());

                        Vector3F posmove = posold - posnew;

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

                        {

                            subactor.move(posmove);

                        }

                        abnew.insert(newactor);

                    }

                }

            }

            layer.getOrgBuffer().substract(abold);

            layer.getOrgBuffer().add(abnew);

            foreach (IActorLayerMng sublayer in layer.getList())

            {

                updatePrefebActors(sublayer, groupname, prefebname);

            }

        }

        // 得到物品类别字符串

        public static string getActorTypestr(IActor actor)

        {

            if (actor is ModelActor)

            {

                return "ModelActor";

            }

            else if (actor is EffectActor)

            {

                return "EffectActor";

            }

            else if (actor is SoundActor)

            {

                return "SoundActor";

            }

            else if (actor is AINodeActor)

            {

                return "AINodeActor";

            }

            else if (actor is LightActor)

            {

                return "LightActor";

            }

            else if (actor is GroupActor)

            {

                if (actor is PrefebActor)

                {

                    return "PrefebActor";

                }

                return "GroupActor";

            }

            else if (actor is DancerActor)

            {

                return "DancerActor";

            }

            AssertUtil.confirm(false);

            return "";

        }

        // 得到多个物品的最小位置

        public static Vector3F getMinPos(ActorBuffer ab)

        {

            if (ab.Count<IActor>() == 0)

            {

                return Vector3F.Zero;

            }

            IActor actor0 = ab.ElementAt<IActor>(0);

            Vector3F pos = actor0.aabb.Min;

            foreach (IActor actor in ab)

            {

                if (actor.aabb.Min.X < pos.X)

                {

                    pos.X = actor.aabb.Min.X;

                }

                if (actor.aabb.Min.Y < pos.Y)

                {

                    pos.Y = actor.aabb.Min.Y;

                }

                if (actor.aabb.Min.Z < pos.Z)

                {

                    pos.Z = actor.aabb.Min.Z;

                }

            }

            return pos;

        }

        得到多个物品的最小位置

        //public static Vector3F getMinPos(ActorBuffer ab)

        //{

        //    if (ab.Count<IActor>() == 0)

        //    {

        //        return Vector3F.Zero;

        //    }

        //    IActor actor0 = ab.ElementAt<IActor>(0);

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

        //    foreach (IActor actor in ab)

        //    {

        //        if (actor.locationmat.M14 < pos.X)

        //        {

        //            pos.X = actor.locationmat.M14;

        //        }

        //        if (actor.locationmat.M24 < pos.Y)

        //        {

        //            pos.Y = actor.locationmat.M24;

        //        }

        //        if (actor.locationmat.M34 < pos.Z)

        //        {

        //            pos.Z = actor.locationmat.M34;

        //        }

        //    }

        //    return pos;

        //}

        // 得到多个物品的最大位置

        public static Vector3F getMaxPos(ActorBuffer ab)

        {

            if (ab.Count<IActor>() == 0)

            {

                return Vector3F.Zero;

            }

            IActor actor0 = ab.ElementAt<IActor>(0);

            Vector3F pos = actor0.aabb.Max;

            foreach (IActor actor in ab)

            {

                if (actor.aabb.Max.X > pos.X)

                {

                    pos.X = actor.aabb.Max.X;

                }

                if (actor.aabb.Max.Y > pos.Y)

                {

                    pos.Y = actor.aabb.Max.Y;

                }

                if (actor.aabb.Max.Z > pos.Z)

                {

                    pos.Z = actor.aabb.Max.Z;

                }

            }

            return pos;

        }

        public static Vector3F ComputeCenter(ActorBuffer ab)

        {

            if (ab == null || ab.empty())

            {

                return new Vector3F();

            }

            if (ab.Count<IActor>() == 1)

            {

                return ab.ElementAt(0).center;

            }

            Vector3F max = getMaxPos(ab);

            Vector3F min = getMinPos(ab);

            Vector3F res = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

            return res;

        }

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

        {

            normal.Normalize();

            // 用360个点的连线模拟圆

            int pointcount = 360;

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

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

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

            {

                float factor = 0;

                Vector3F u = new Vector3F();

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

                {

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

                    u.X = -normal.Z * factor;

                    u.Y = 0;

                    u.Z = normal.X * factor;

                }

                else

                {

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

                    u.X = 0;

                    u.Y = normal.Z * factor;

                    u.Z = -normal.Y * factor;

                }

                u.Normalize();

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

                v.Normalize();

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

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

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

                indexs[t * 3] = t * 3;

                indexs[t * 3 + 1] = t * 3 + 1;

                indexs[t * 3 + 2] = t * 3 + 2;

            }

            indexs[pointcount * 3] = 0;

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

        }

        public static void drawRotateCircles(List<uint> idlist, Vector3F center, ClientBridge.ClientRenderSys rendersys)

        {

            Color cr = new Color(1, 0, 0, 1);

            Color cg = new Color(0, 1, 0, 1);

            Color cb = new Color(0, 0, 1, 1);

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[0]);

            }

            GActorHelper.drawCircle(center, new Vector3F(1, 0, 0), 1, cr, rendersys);  // 绘制垂直于x轴的圆

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[1]);

            }

            GActorHelper.drawCircle(center, new Vector3F(0, 1, 0), 1, cg, rendersys);  // 绘制垂直于y轴的圆

            if (idlist != null && idlist.Count >= 3)

            {

                rendersys.pushSelectID(idlist[2]);

            }

            GActorHelper.drawCircle(center, new Vector3F(0, 0, 1), 1, cb, rendersys);  // 绘制垂直于z轴的圆

            //List<float> viewmat = new List<float>();

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

            //{

            //    viewmat.Add(0);

            //}

            //rendersys.getPerspective(viewmat);

            //Vector3F dir = new Vector3F(viewmat[0], viewmat[4], viewmat[8]);

            //GActorHelper.drawCircle(center, dir, 2, cr, rendersys);

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

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

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

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

                             };

            int[] indexsx = { 0, 1 };

            int[] indexsy = { 0, 2 };

            int[] indexsz = { 0, 3 };

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

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsy, cg.toArray(), true);

            rendersys.drawIndex(ClientBridge.IndexDrawType.LDT_LINE_LIST, points, indexsz, cb.toArray(), true);

        }

    }

    // 物品管理层借口类,可以有子层

    // fixme: 子层没有记录在scenegraph里面

    public interface IActorLayerMng : IEditItem

    {

        // 获得原始物品容器

        ActorBuffer getOrgBuffer();

        // 获得选中物品容器

        ActorBuffer getSelBuffer();

        // 获得属性列表

        IDictionary<String, String> getPropertyList();

        // 物品包围盒变化

        void OnActorAABBChanged(IActor actor, AxisAlignedBox aabb);

        // 修改key对应的value

        void notifyPropertyChange(String key, String value);

        // 获得当前的物品管理层

        IActorLayerMng currentLayerMng { get; set; }

        // 设置最具体的当前的编辑层,如果layer不在当前层会继续到下一层设置

        void setCurrentLayerMng(IActorLayerMng layer);

        // 获得当前的编辑层,与currentLayerMng不同的是:这个函数可以获得最具体的当前编辑层

        IActorLayerMng getCurrentLayerMng();

        // 获得根物品管理器

        IActorLayerMng getRootActorLayer();

        // 看给定的layer,在那个子物品管理器中

        IActorLayerMng getSubRootActorLayer(IActorLayerMng layer);

        // 获得所有的子物品管理层

        IList<IActorLayerMng> getList();

        // 清空所有内容

        void clean();

        // 获得父亲类

        IActorLayerMng parent

        {

            get;

            set;

        }

        string name

        {

            get;

            set;

        }

        // 获得当前layer的位置偏移量

        // fixme: 帮助函数,接口类中不应该定义

        void getOffset(ref float delx, ref float dely);

        //创建子层

        IActorLayerMng createSubActorLayer();

        // 更新

        void update(int t);

        void UpdateCpuSkin(float t);

        // 绘制

        void render(int t, ClientBridge.ClientRenderSys rendersys);

        // 绘制包围盒

        void renderAABB(int t, ClientBridge.ClientRenderSys rendersys);

        // 绘制移动控制轴

        void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys);

        // 绘制移动控制轴

        void renderSingleCircle(int t, ClientBridge.ClientRenderSys rendersys);

        // 绘制旋转控制圈

        void renderCircles(int t, ClientBridge.ClientRenderSys rendersys);

        // 保存层中的物品

        bool serialize(BinaryWriter binWriter);

        // 读取物品

        bool serialize(BinaryReader binReader, IEditItem edititem);

        // save

        bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool clipboard);

        // load

        bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, IMacroCommand cmd, bool clipboard);

        void customHardwareSelect(Dictionary<IActorLayerMng, ActorBuffer> selactors, IView view, Rect<int> rect, bool selectfirst);

        // 将物品添加到硬件选择

        void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys);

        // 将物品移动控制轴添加到硬件选择

        void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys);

        // 将物品旋转控制圆添加到硬件选择

        void pushHardwareSelect_Rotate(RotateMode rm, ClientBridge.ClientRenderSys rendersys);

        // 将指定ID对应的物品添加到dictionary中

        void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id);

        // 返回指定ID对应的移动控制轴的编号

        int getSelectMoveLineID(int id);

        // 返回指定ID对应的旋转控制圆的编号

        int getSelectRotateCircleID(int id);

        // 是否可以复制、剪切

        bool canCopyCut();

        // 是否可以粘贴

        bool canPaste();

        //判断是否可执行group操作

        bool canCreateGroup();

        bool canDestroyGroup();

        bool canOpenGroup();

        bool canCloseGroup();

        bool canDettachGroup();

        bool canAttachGroup();

        //创建物品组 不同的物品层可能会创建不同类型的GruopActor

        GroupActor createLayerActorGroup(string name, out ActorBuffer ab);

        //设置所有actor的lod级别

        void setActorMaterialLod(ClientBridge.LOD_LEVEL lod);

        //父层的Hide状态改变,回调通知子层及子Actor

        void notifyLayerHide(bool isHide);

        //父层的Freeze状态改变,回调通知子层及子Actor

        void notifyLayerFreeze(bool isFreeze);

        //返回用于层管理器中的层列表

        IList<IActorLayerMng> getLayersToManage();

    }

    // 物品管理层实现类

    public class ActorLayerMngImp : BaseEditItem, IActorLayerMng

    {

        // fixme: 应该通过子容器的属性设置,而不是用这个值来表示

        IActorLayerMng m_cur_actor_layer = null;

        List<IActorLayerMng> m_actor_layer_list = new List<IActorLayerMng>();

        String m_name;

        ActorBuffer m_org_buffer;

        ActorBuffer m_sel_buffer;

        // 属性列表,用来记录若干物品信息

        IDictionary<String, String> m_property_list = new Dictionary<String, String>();

        IActorLayerMng m_parent = null;

        // 获得父亲类

        public IActorLayerMng parent

        {

            get { return m_parent; }

            set { m_parent = value; }

        }

        public string name

        {

            get { return m_name; }

            set { m_name = value; }

        }

        // orgfun表示将物品从原始物品列表中移入移出需要调用的函数

        // selfun表示将物品从选择物品列表中移入移出需要调用的函数

        public ActorLayerMngImp(IEditItem parent, IActorFun orgfun, IActorFun selfun)

        {

            m_org_buffer = new ActorBuffer(this, orgfun);

            m_sel_buffer = new ActorBuffer(this, selfun);

            m_parent = (IActorLayerMng)parent;

            name = "物品簇";

        }

        public ActorLayerMngImp(IEditItem parent, IActorFun orgfun, IActorFun selfun, string name_string)

        {

            m_org_buffer = new ActorBuffer(this, orgfun);

            m_sel_buffer = new ActorBuffer(this, selfun);

            m_parent = (IActorLayerMng)parent;

            name = name_string;

        }

        /// <summary>

        /// 用于序列化

        /// </summary>

        public ActorLayerMngImp()

        {

        }

        // 保存

        public bool serialize(BinaryWriter binWriter)

        {

            // 保存ActorLayer自身信息

            binWriter.Write(name);  // string

            binWriter.Write(getOrgBuffer().Count<IActor>());    // 物品个数

            binWriter.Write(getList().Count<IActorLayerMng>()); // 子层个数

            // 保存各子物品

            foreach (IActor actor in getOrgBuffer())

            {

                binWriter.Write(GActorHelper.getActorTypestr(actor));

                actor.serialize(binWriter);

            }

            // 保存各子层

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.serialize(binWriter);

            }

            return true;

        }

        // 读取

        public bool serialize(BinaryReader binReader, IEditItem edititem)

        {

            name = binReader.ReadString();

            int actornum = binReader.ReadInt32();

            int sublayernum = binReader.ReadInt32();

            for (int i = 0; i < actornum; i++)

            {

                string type = binReader.ReadString();

                IActor actor = null;

                if (type == "PrefebActor")

                {

                    string groupname = binReader.ReadString();

                    string prefebname = binReader.ReadString();

                    actor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, edititem);

                }

                else

                {

                    actor = GActorHelper.generateActorWithoutInfo(type, edititem);

                }

                if (actor != null)

                {

                    actor.serialize(binReader, edititem);

                    getOrgBuffer().insert(actor);

                }

            }

            for (int i = 0; i < sublayernum; i++)

            {

                IActorLayerMng sublayer = new ActorLayerMngImp(this, new DummyActorFun(), new DummyActorFun());

                BaseCommand.getDocLogic(edititem).addCommand(new AddActorLayerCmd(this, sublayer));

                sublayer.serialize(binReader, edititem);

            }

            return true;

        }

        // save

        public virtual bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, bool clipboard)

        {

            System.Xml.XmlNode subnode;

            XmlAttribute att;

            // 保存ActorLayer自身信息

            att = xmlnode.OwnerDocument.CreateAttribute("Name");

            att.Value = name;

            xmlnode.Attributes.Append(att);

            att = xmlnode.OwnerDocument.CreateAttribute("Hide");

            att.Value = BaseCommand.isValueTrue(getPropertyList(), "hide").ToString();

            xmlnode.Attributes.Append(att);

            att = xmlnode.OwnerDocument.CreateAttribute("Freeze");

            att.Value = BaseCommand.isValueTrue(getPropertyList(), "freeze").ToString();

            xmlnode.Attributes.Append(att);

            // 保存各子物品

            foreach (IActor actor in (clipboard ? getSelBuffer() : getOrgBuffer()))

            {

                if ((actor.flag & (int)ActorFlag.UNSERIALIZABLE) == 0)

                {

                    subnode = xmlnode.OwnerDocument.CreateNode("element", "Actor", "");

                    att = xmlnode.OwnerDocument.CreateAttribute("Type");

                    att.Value = GActorHelper.getActorTypestr(actor);

                    subnode.Attributes.Append(att);

                    actor.serialize(subnode, edititem, false, clipboard);

                    xmlnode.InsertAfter(subnode, xmlnode.LastChild);

                }

            }

            // 保存各子层

            foreach (IActorLayerMng sublayer in getList())

            {

                subnode = xmlnode.OwnerDocument.CreateNode("element", "Layer", "");

                sublayer.serialize(subnode, edititem, clipboard);

                xmlnode.InsertAfter(subnode, xmlnode.LastChild);

            }

            return true;

        }

        // load

        public virtual bool serialize(System.Xml.XmlNode xmlnode, IEditItem edititem, IMacroCommand cmd, bool clipboard)

        {

            //ClientBridge.Profile.Begin(129);

            ActorBuffer actor_buffer = new ActorBuffer(null, new DummyActorFun());

            foreach (System.Xml.XmlNode subnode in xmlnode.SelectNodes("Actor"))

            {

                XmlElement ele = (XmlElement)subnode;

                string type = ele.GetAttribute("Type");

                IActor actor = null;

                if (type == "PrefebActor")

                {

                    string groupname = ele.GetAttribute("GroupName");

                    string prefebname = ele.GetAttribute("PrefebName");

                    actor = PrefebManager.getActorBufferFromPrefebFile(groupname, prefebname, edititem);

                    foreach (XmlNode childnode in subnode.ChildNodes)

                    {

                        if (childnode.Name != "Item" && childnode.Name != "LocationMat")

                        {

                            actor.notifyPropertyChange(childnode.Name, childnode.InnerText);

                        }

                    }

                    XmlNode node = subnode.SelectSingleNode("LocationMat");

                    if (node != null)

                    {

                        Matrix4F locationmat = Matrix4F.setMatrix(node.InnerText);

                        PrefebManager.allrotateandmove((PrefebActor)actor, new Matrix4F(locationmat));

                    }

                    actor_buffer.insert(actor);

                }

                else

                {

                    actor = GActorHelper.generateActorWithoutInfo(type, edititem);

                    if (actor != null)

                    {

                        actor.serialize(subnode, edititem, true, clipboard);

                        actor_buffer.insert(actor);

                    }

                }

            }

            if (clipboard)

            {

                cmd.addCmd(new InsertCmd(this, actor_buffer));

            }

            else

            {

                getOrgBuffer().add(actor_buffer);

            }

            foreach (System.Xml.XmlNode subnode in xmlnode.SelectNodes("Layer"))

            {

                string layer_name = ((XmlElement)subnode).GetAttribute("Name");

                IActorLayerMng sublayer = GetLayerByName(layer_name);

                if (sublayer == null)

                {

                    sublayer = this.createSubActorLayer();

                    sublayer.name = layer_name;

                    this.getList().Add(sublayer);

                }

                sublayer.serialize(subnode, edititem, cmd, clipboard);

                if (((XmlElement)subnode).HasAttribute("Hide") && ((XmlElement)subnode).HasAttribute("Freeze"))

                {

                    sublayer.notifyPropertyChange("hide", ((XmlElement)subnode).GetAttribute("Hide").ToLower());

                    sublayer.notifyPropertyChange("freeze", ((XmlElement)subnode).GetAttribute("Freeze").ToLower());

                }

                SceneGraph.notify((IEditItem)SceneGraph.getEditItemCommon("RootItem", this.getRootActorLayer()), NotifyType.ACTOR, "LayerInsert/Remove", "");

            }

            //ClientBridge.Profile.End(129);

            return true;

        }

        protected IActorLayerMng GetLayerByName(string layer_name)

        {

            foreach (IActorLayerMng layer in m_actor_layer_list)

            {

                if (layer_name == layer.name)

                {

                    return layer;

                }

            }

            return null;

        }

        public virtual void setActorMaterialLod(ClientBridge.LOD_LEVEL lod)

        {

            IEnumerator<IActor> it_actor = Tool.GetActorsFromLayerManager<IActor>(this, true, true, true).GetEnumerator();

            while (it_actor.MoveNext())

            {

                if (it_actor.Current is ResActorBase)

                {

                    ((ResActorBase)it_actor.Current).SetLod(lod);

                }

            }

        }

        // 原始物品列表

        public ActorBuffer getOrgBuffer()

        {

            return m_org_buffer;

        }

        // 选中物品列表

        public ActorBuffer getSelBuffer()

        {

            return m_sel_buffer;

        }

        public IDictionary<string, string> getPropertyList()

        {

            return m_property_list;

        }

        public virtual void OnActorAABBChanged(IActor actor, AxisAlignedBox aabb)

        {

        }

        public void notifyPropertyChange(string key, string value)

        {

            m_property_list[key] = value;

        }

        //创建子层默认操作

        public virtual IActorLayerMng createSubActorLayer()

        {

            return new ActorLayerMngImp(this, new DummyActorFun(), new DummyActorFun());

        }

        // 需要根据类型进行设置和获取

        public IActorLayerMng currentLayerMng

        {

            get

            {

                return m_cur_actor_layer;

            }

            set

            {

                m_cur_actor_layer = value;

            }

        }

        public void setCurrentLayerMng(IActorLayerMng layer)

        {

            if (layer == this)

            {

                currentLayerMng = null;

                return;

            }

            else

            {

                IActorLayerMng sublayer = getSubRootActorLayer(layer);

                AssertUtil.confirm(sublayer != null);

                currentLayerMng = sublayer;

                sublayer.setCurrentLayerMng(layer);

            }

        }

        public IActorLayerMng getCurrentLayerMng()

        {

            if (currentLayerMng == null)

                return this;

            else

                return currentLayerMng.getCurrentLayerMng();

        }

        public IActorLayerMng getRootActorLayer()

        {

            if (parent != null)

                return parent.getRootActorLayer();

            else

                return this;

        }

        public IActorLayerMng getSubRootActorLayer(IActorLayerMng layer)

        {

            foreach (IActorLayerMng subactorlayer in m_actor_layer_list)

            {

                if (subactorlayer == layer)

                    return subactorlayer;

                else if (subactorlayer.getSubRootActorLayer(layer) != null)

                    return subactorlayer;

            }

            return null;

        }

        public void getOffset(ref float delx, ref float dely)

        {

            if (currentLayerMng == null)

            {

                return;

            }

            else

            {

                // 找到current layer所对应的物品,然后累计偏移量

                foreach (IActor actor in getOrgBuffer())

                {

                    if (actor.getActorBuffer() == currentLayerMng)

                    {

                        delx += actor.rect.x;

                        dely += actor.rect.y;

                        currentLayerMng.getOffset(ref delx, ref dely);

                        return;

                    }

                }

            }

        }

        public IList<IActorLayerMng> getList()

        {

            return m_actor_layer_list;

        }

        override public void Dispose()

        {

            clean();

            base.Dispose();

        }

        public virtual void clean()

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.Dispose();

            }

            m_org_buffer.clear();

            m_sel_buffer.clear();

            foreach (IActorLayerMng al in m_actor_layer_list)

            {

                al.Dispose();

            }

            m_actor_layer_list.Clear();

            m_cur_actor_layer = null;

        }

        public static IActorLayerMng getCurrentLayerMng(IActorLayerMng layermng)

        {

            while (true)

            {

                if (layermng.currentLayerMng != null)

                    layermng = layermng.currentLayerMng; // go deeper

                else

                    return layermng;

            }

        }

        public virtual void customHardwareSelect(Dictionary<IActorLayerMng, ActorBuffer> selactors, IView view, Rect<int> rect, bool selectfirst)

        {

        }

        public void pushHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.pushHardwareSelect(rendersys);

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushHardwareSelect(rendersys);

            }

        }

        public virtual void pushLineHardwareSelect(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                if (!actor.hide && !actor.freeze)

                {

                    actor.pushLineHardwareSelect(rendersys);

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushLineHardwareSelect(rendersys);

            }

        }

        public void pushHardwareSelect_Move(ClientBridge.ClientRenderSys rendersys)

        {

            foreach (IActor actor in m_org_buffer)

            {

                actor.pushHardwareSelect_Move(rendersys);

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.pushHardwareSelect_Move(rendersys);

            }

        }

        public void pushHardwareSelect_Rotate(RotateMode rm, ClientBridge.ClientRenderSys rendersys)

        {

            switch (rm)

            {

                case RotateMode.RM_SELF:

                    foreach (IActor actor in m_org_buffer)

                    {

                        actor.pushHardwareSelect_Rotate(rendersys);

                    }

                    foreach (IActorLayerMng sublayer in getList())

                    {

                        sublayer.pushHardwareSelect_Rotate(rm, rendersys);

                    }

                    break;

                case RotateMode.RM_WHOLE:

                    List<uint> idlist = new List<uint>();

                    idlist.Add(0);

                    idlist.Add(1);

                    idlist.Add(2);

                    ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

                    GActorHelper.getActors(ab, this, true, false);

                    Vector3F max = GActorHelper.getMaxPos(ab);

                    Vector3F min = GActorHelper.getMinPos(ab);

                    Vector3F center = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

                    GActorHelper.drawRotateCircles(idlist, center, rendersys);

                    break;

                default:

                    break;

            }

        }

        public int getSelectMoveLineID(int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                for (int i = 0; i < actor.giid_move.Count; i++)

                {

                    if (actor.giid_move[i].value == id)

                    {

                        return i;

                    }

                }

                //对Group的处理

                if (actor is GroupActor)

                {

                    GroupActor ga = actor as GroupActor;

                    int reid = ga.getActorBuffer().getSelectMoveLineID(id);

                    if (reid != -1)

                    {

                        return reid;

                    }

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                int reid = sublayer.getSelectMoveLineID(id);

                if (reid != -1)

                {

                    return reid;

                }

            }

            return -1;

        }

        public int getSelectRotateCircleID(int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                for (int i = 0; i < actor.giid_rotate.Count; i++)

                {

                    if (actor.giid_rotate[i].value == id)

                    {

                        return i;

                    }

                }

                // 对Group的处理

                if (actor is GroupActor)

                {

                    GroupActor ga = actor as GroupActor;

                    int reid = ga.getActorBuffer().getSelectRotateCircleID(id);

                    if (reid != -1)

                    {

                        return reid;

                    }

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                int reid = sublayer.getSelectRotateCircleID(id);

                if (reid != -1)

                {

                    return reid;

                }

            }

            return -1;

        }

        public void getSelectByID(Dictionary<IActorLayerMng, ActorBuffer> selactors, int id)

        {

            foreach (IActor actor in m_org_buffer)

            {

                if (actor.giid.value == id)

                {

                    if (!selactors.ContainsKey(this))

                    {

                        selactors[this] = new ActorBuffer(null, new DummyActorFun());

                    }

                    if (!selactors[this].Contains<IActor>(actor))

                    {

                        selactors[this].insert(actor);

                    }

                    return;

                }

                // 对Group的特殊处理

                if (actor is GroupActor)

                {

                    ((GroupActor)actor).getSelectByID(selactors, id, this);

                }

            }

            foreach (IActorLayerMng sublayer in getList())

            {

                sublayer.getSelectByID(selactors, id);

            }

        }

        public virtual void update(int t)

        {

            //ClientBridge.Profile.Begin(89);

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                actor.update(t);

            }

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.update(t);

            }

            // ClientBridge.Profile.End(89);

        }

        public virtual void UpdateCpuSkin(float t)

        {

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                actor.UpdateCpuSkin(t);

            }

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.UpdateCpuSkin(t);

            }

        }

        virtual public void render(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 绘制当前层所有物品

            ActorBuffer ab = getOrgBuffer();

            foreach (IActor actor in ab)

            {

                if (!actor.hide)

                {

                    actor.render(t, rendersys);

                }

            }

            // 绘制子层

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.render(t, rendersys);

            }

        }

        public void renderAABB(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 绘制选中物品包围盒

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    Color color = (sactor is PrefebActor) ? (new Color(1, 1, 0, 1)) : (new Color(1, 1, 1, 1));

                    sactor.renderAABB(t, rendersys, color);

                    if (sactor.parent is GroupActor)

                    {

                        sactor.parent.renderAABB(t, rendersys, new Color(0, 1, 1, 1));

                    }

                }

            }

            //某些chr即使没有 被选中也需要绘制aabb

            ActorBuffer orgbuffer = getOrgBuffer();

            foreach (IActor actor in orgbuffer)

            {

                if (!actor.hide && actor.GetActorType()==ACTOR_TYPE.AT_CHR)

                {

                    Color color = (actor is PrefebActor) ? (new Color(1, 1, 0, 1)) : (new Color(1, 1, 1, 1));

                  //  actor.renderAABB(t, rendersys, color);

                }

            }

            // 绘制子层

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderAABB(t, rendersys);

            }

        }

        public void renderCoordinate(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 绘制选中物品Coordinate

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    sactor.renderCoordinate(t, rendersys);

                }

            }

            // 绘制子层

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderCoordinate(t, rendersys);

            }

        }

        public void renderCircles(int t, ClientBridge.ClientRenderSys rendersys)

        {

            // 绘制选中物品Coordinate

            ActorBuffer sab = getSelBuffer();

            foreach (IActor sactor in sab)

            {

                if (!sactor.hide)

                {

                    sactor.renderCircles(t, rendersys);

                }

            }

            // 绘制子层

            IList<IActorLayerMng> sublist = getList();

            foreach (IActorLayerMng alm in sublist)

            {

                alm.renderCircles(t, rendersys);

            }

        }

        public void renderSingleCircle(int t, ClientBridge.ClientRenderSys rendersys)

        {

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(ab, this, true, false);

            if (ab.Count<IActor>() == 0)

            {

                return;

            }

            Vector3F max = GActorHelper.getMaxPos(ab);

            Vector3F min = GActorHelper.getMinPos(ab);

            Vector3F center = new Vector3F((max.X + min.X) / 2.0f, (max.Y + min.Y) / 2.0f, (max.Z + min.Z) / 2.0f);

            GActorHelper.drawRotateCircles(null, center, rendersys);

        }

        // 是否可以复制、剪切

        public virtual bool canCopyCut()

        {

            return !getSelBuffer().empty();

        }

        // 是否可以粘贴

        public virtual bool canPaste()

        {

            return Clipboard.ContainsData(DataFormats.Text) && !BaseCommand.isActorLayerReadOnly(this);

        }

        public virtual bool canCreateGroup()

        {

            int actorCount = 0;

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            foreach (IActor actor in sel_ab)

            {

                if (actor.parent == null)

                    actorCount++;

            }

            return actorCount > 0;

        }

        private void getSelectedGroupActors(IActorLayerMng layer, List<ActorBuffer> buffers)

        {

            ActorBuffer b1 = layer.getSelBuffer().getTypeActors(typeof(GroupActor));

            if (!b1.empty())

                buffers.Add(b1);

            foreach (IActorLayerMng sub_layer in layer.getList())

            {

                getSelectedGroupActors(sub_layer, buffers);

            }

        }

        private List<ActorBuffer> getSelectedGroupActors(IActorLayerMng layer)

        {

            List<ActorBuffer> buffers = new List<ActorBuffer>();

            getSelectedGroupActors(layer, buffers);

            return buffers;

        }

        public virtual bool canDestroyGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            return buffers.Count > 0;

        }

        public virtual bool canOpenGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            int actorCount = 0;

            foreach (ActorBuffer ab in buffers)

            {

                foreach (GroupActor ga in ab)

                {

                    if (ga.close)

                        actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canCloseGroup()

        {

            List<ActorBuffer> buffers = getSelectedGroupActors(getRootActorLayer());

            int actorCount = 0;

            foreach (ActorBuffer ab in buffers)

            {

                foreach (GroupActor ga in ab)

                {

                    if (!ga.close)

                        actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canDettachGroup()

        {

            int actorCount = 0;

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            foreach (IActor actor in sel_ab)

            {

                GroupActor ga = actor.parent as GroupActor;

                if (ga != null)

                {

                    actorCount++;

                }

            }

            return actorCount > 0;

        }

        public virtual bool canAttachGroup()

        {

            return true;

        }

        public virtual GroupActor createLayerActorGroup(string name, out ActorBuffer outAb)

        {

            ActorBuffer sel_ab = new ActorBuffer(null, new DummyActorFun());

            GActorHelper.getActors(sel_ab, getRootActorLayer(), true, false, true);

            RootEditItem root = (RootEditItem)(SceneGraph.getEditItemCommon("RootItem", getRootActorLayer()));

            ActorBuffer ab = new ActorBuffer(null, new DummyActorFun());

            foreach (IActor actor in sel_ab)

            {

                if (actor.parent == null)

                    ab.insert(actor);

            }

            if (ab.empty())

            {

                outAb = null;

                return null;

            }

            outAb = ab;

            int group_index = 0;

            if (name == null || name.Length == 0)

            {

                IDocFactory df = (IDocFactory)SceneGraph.getEditItemCommon("DocFactory", root);

                IDoc doc = (IDoc)SceneGraph.getEditItemCommon("doc", df);

                group_index = doc.getMaxActorIndex("Group");

            }

            Dictionary<string, string> createpropdic = new Dictionary<string, string>();

            createpropdic["NamePrefix"] = "Group";

            createpropdic["Height"] = "0";

            GroupActor ga = new GroupActor(root.giidmng, createpropdic, group_index, this);

            if (name != null && name.Length > 0)

                ga.name = name;

            return ga;

        }

        //返回用于层管理器中的层列表

        public virtual IList<IActorLayerMng> getLayersToManage()

        {

            return getList();

        }

        //父层的Hide状态改变,回调通知子层及子Actor

        virtual public void notifyLayerHide(bool isHide)

        {

            if (BaseCommand.isValueTrue(getPropertyList(), "hide"))

                return;

            foreach (IActorLayerMng layer in m_actor_layer_list)

                layer.notifyLayerHide(isHide);

            foreach (IActor actor in m_org_buffer)

                actor.notifyLayerHide(isHide);

        }

        //父层的Freeze状态改变,回调通知子层及子Actor

        virtual public void notifyLayerFreeze(bool isFreeze)

        {

            if (BaseCommand.isValueTrue(getPropertyList(), "freeze"))

                return;

            foreach (IActorLayerMng layer in m_actor_layer_list)

                layer.notifyLayerFreeze(isFreeze);

            foreach (IActor actor in m_org_buffer)

                actor.notifyLayerFreeze(isFreeze);

        }

    }

    public interface IResHandle

    {

        string ResName { get; }

        object getRes();

        void reload();

        void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res);

        void addRef();

        int ResRefCount { get; }

        List<IResHandle> getSubResHandleList();

    }

    public class ResActorBase : ActorBase, IResHandle

    {

        public ResActorBase(GIIDMng giidmng)

            : base(giidmng)

        {

        }

        virtual public string ResName

        {

            get { return ""; }

        }

        virtual public object getRes()

        {

            return null;

        }

        virtual public void reload()

        {

        }

        virtual public void changeRes(ClientBridge.ClientRenderSys rendersys, string new_res)

        {

        }

        new virtual public void Attach(ClientBridge.SceneBase scene)

        {

        }

        new virtual public void Detach(ClientBridge.SceneBase scene)

        {

        }

        virtual public void addRef()

        {

        }

        virtual public int ResRefCount

        {

            get { return 1; }

        }

        virtual public List<IResHandle> getSubResHandleList()

        {

            return new List<IResHandle>();

        }

        new protected bool CanTransform()

        {

            return ResRefCount == 1;

        }

    }

    [Serializable]

    public class MultiActorFun : IActorFun

    {

        public void AddFun(IActorFun actorfun)

        {

            if (m_actorfun_list.GetIndex(actorfun) == -1)

            {

                m_actorfun_list.Add(actorfun);

            }

        }

        public void insert(IActor actor, IActorLayerMng layer)

        {

            foreach (IActorFun actorfun in m_actorfun_list)

            {

                actorfun.insert(actor, layer);

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            foreach (IActorFun actorfun in m_actorfun_list)

            {

                actorfun.remove(actor, layer);

            }

        }

        ListEx<IActorFun> m_actorfun_list = new ListEx<IActorFun>();

    }

    public class SceneActorFun : IActorFun

    {

        public SceneActorFun(ClientBridge.SceneBase scene)

        {

            m_scene = scene;

        }

        public void SetScene(ClientBridge.SceneBase scene)

        {

            m_scene = scene;

        }

        public void insert(IActor actor, IActorLayerMng layer)

        {

            if (m_scene != null && actor is ResActorBase)

            {

                ((ResActorBase)actor).Attach(m_scene);

            }

        }

        public void remove(IActor actor, IActorLayerMng layer)

        {

            if (m_scene != null && actor is ResActorBase)

            {

                ((ResActorBase)actor).Detach(m_scene);

            }

        }

        ClientBridge.SceneBase m_scene;

    }

}

继续阅读