--- trunk/ModularRex/RexParts/ModrexObjects.cs 2009/02/04 07:41:03 54 +++ trunk/ModularRex/RexParts/ModrexObjects.cs 2009/12/07 13:42:34 291 @@ -7,32 +7,39 @@ using ModularRex.RexNetwork; using Nini.Config; using OpenMetaverse; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; -using OpenSim.Data.NHibernate; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; using OpenSim.Framework; +using ModularRex.NHibernate; +using OpenSim.Framework.Communications.Cache; namespace ModularRex.RexParts { - public class ModrexObjects : IRegionModule + public class ModrexObjects : IRegionModule, IRexObjectPropertiesEventManager, IModrexObjectsProvider { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - //private Dictionary m_objs = new Dictionary(); + private RexObjectPropertiesManager RexObjectPropertiesCache = new RexObjectPropertiesManager(); private List m_scenes = new List(); private NHibernateRexObjectData m_db; private string m_db_connectionstring; + public delegate void OnChangePythonClassDelegate(UUID id); public event OnChangePythonClassDelegate OnPythonClassChange; public void Initialise(Scene scene, IConfigSource source) { m_scenes.Add(scene); + scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); scene.EventManager.OnClientConnect += EventManager_OnClientConnect; + scene.SceneContents.OnObjectDuplicate += SceneGraph_OnObjectDuplicate; + scene.SceneContents.OnObjectRemove += SceneGraph_OnObjectRemove; + scene.AddCommand(this, "modreximport", "load 0.4 rex database ", "conn string example: SQLiteDialect;SQLite20Driver;Data Source=beneath_the_waves.db;Version=3", HandleLoadRexLegacyData); if (m_db == null) { @@ -60,17 +67,77 @@ void EventManager_OnClientConnect(OpenSim.Framework.Client.IClientCore client) { - RexClientView rcv; + RexClientViewBase rcv; if (client.TryGet(out rcv)) { rcv.OnRexObjectProperties += rcv_OnRexObjectProperties; + rcv.OnPrimFreeData += rcv_OnPrimFreeData; //rcv.OnChatFromClient += rcv_OnChatFromClient; // Send them the current Scene. SendAllPropertiesToUser(rcv); + } + } + + private void rcv_OnPrimFreeData(IClientAPI sender, List parameters) + { + m_log.Info("[REXOBJS] Received Prim free data"); + if (parameters.Count >= 2) + { + UUID primID = new UUID(parameters[0]); + string data = String.Empty; + if(parameters.Count == 2) + { + data = parameters[1]; + }else + { + for (int i = 1; i < parameters.Count; i++) + { + data += parameters[i]; + } + } + + RexObjectProperties props = GetObject(primID); + props.RexData = data; + + SendPrimFreeDataToAllUsers(primID, data); + } + else + { + m_log.Warn("[REXOBJS] unexpected number of parameters"); + } + } + + void SendPrimFreeDataToAllUsers(UUID id, string data) + { + foreach (Scene scene in m_scenes) + { + scene.ForEachScenePresence( + delegate(ScenePresence avatar) + { + RexClientViewBase rex; + if (avatar.ClientView.TryGet(out rex)) + { + rex.SendRexPrimFreeData(id, data); + } + }); } } + void SceneGraph_OnObjectDuplicate(EntityBase original, EntityBase clone) + { + RexObjectProperties origprops = GetObject(original.UUID); + RexObjectProperties cloneprops = GetObject(clone.UUID); + + cloneprops.SetRexPrimDataFromObject(origprops); + } + + void SceneGraph_OnObjectRemove(EntityBase obj) + { + DeleteObject(obj.UUID); + } + + //void rcv_OnChatFromClient(object sender, OpenSim.Framework.OSChatMessage e) //{ // if (e.Message.StartsWith("/rexobj ")) @@ -93,7 +160,7 @@ scene.ForEachScenePresence( delegate(ScenePresence avatar) { - RexClientView rex; + RexClientViewBase rex; if (avatar.ClientView.TryGet(out rex)) { rex.SendRexObjectProperties(id,props); @@ -102,59 +169,59 @@ } } - void SendAllPropertiesToUser(RexClientView user) + private void SendPreloadAssetsToUser(RexClientViewBase user) { - if (m_db.Inizialized) + try { + Scene ourScene = null; foreach (Scene s in m_scenes) { - foreach (EntityBase e in s.Entities) + if (user.Scene.RegionInfo.RegionHandle == s.RegionInfo.RegionHandle) + ourScene = s; + } + + if (ourScene != null) + { + if (ourScene.Modules.ContainsKey("RexAssetPreload")) { - RexObjectProperties p = m_db.LoadObject(e.UUID); - if (p != null) + RexAssetPreload module = (RexAssetPreload)ourScene.Modules["RexAssetPreload"]; + if (module.PreloadAssetDictionary.Count > 0) { - user.SendRexObjectProperties(e.UUID, p); - //p.OnPythonClassChange += PythonClassNameChanged; - if (p.RexClassName.Length > 0) - { - s.GetSceneObjectPart(e.UUID).SetScriptEvents(e.UUID, (int)scriptEvents.touch_start); - } + user.SendRexPreloadAssets(module.PreloadAssetDictionary); } } } } + catch (Exception e) + { + m_log.Error("[MODREXOBJECTS]: Sending preload assets failed.", e); + } } - private void PythonClassNameChanged(UUID id) + void SendAllPropertiesToUser(RexClientViewBase user) { - if (OnPythonClassChange != null) + SendPreloadAssetsToUser(user); + + foreach (RexObjectProperties p in GetObjects()) { - OnPythonClassChange(id); + user.SendRexObjectProperties(p.ParentObjectID, p); + if (p.RexData.Length > 0) //send rex data also if exists + { + user.SendRexPrimFreeData(p.ParentObjectID, p.RexData); + } } } - void rcv_OnRexObjectProperties(RexClientView sender, UUID id, RexObjectProperties props) + void rcv_OnRexObjectProperties(IClientAPI sender, UUID id, RexObjectProperties props) { m_log.Info("[REXOBJS] Received RexObjData for " + id); if (props.ParentObjectID == UUID.Zero) props.ParentObjectID = id; - props.PrintRexPrimdata(); // fixme, debugdata - - // Before saving to db, check if values have changed from the previous values. - RexObjectProperties oldprops = Load(id); - - m_db.StoreObject(props); - - // Compare values - if (oldprops.RexClassName != props.RexClassName) - PythonClassNameChanged(props.ParentObjectID); - if (oldprops.RexScaleToPrim != props.RexScaleToPrim) - ScaleToPrimChanged(id); - if (oldprops.RexCollisionMeshUUID != props.RexCollisionMeshUUID) - CollisionMeshChanged(id); - - SendPropertiesToAllUsers(id, props); + // debugdata props.PrintRexPrimdata(); + + RexObjectProperties currentprops = GetObject(id); + currentprops.SetRexPrimDataFromObject(props); } public void PostInitialise() @@ -166,6 +233,7 @@ m_db.Initialise(m_db_connectionstring); } } + LoadRexObjectPropertiesToCache(); } public void Close() @@ -183,113 +251,231 @@ get { return true; } } - public RexObjectProperties Load(UUID id) - { - RexObjectProperties robject = m_db.LoadObject(id); - if (robject == null) - { - robject = new RexObjectProperties(); - robject.ParentObjectID = id; - } - return robject; - } - public void Save(RexObjectProperties obj) + + #region Trigger/handle rexobjectproperties events + public void TriggerOnChangePythonClass(UUID id) { - m_db.StoreObject(obj); + if (OnPythonClassChange != null) + OnPythonClassChange(id); } - - private void CollisionMeshChanged(UUID id) + + public void TriggerOnChangeCollisionMesh(UUID id) { // tucofixme, add //if (!GlobalSettings.Instance.m_3d_collision_models) // return; - RexObjectProperties p = m_db.LoadObject(id); - if (p == null) - { - m_log.Error("[REXOBJS] CollisionMeshChanged, no RexObjectProperties for id:" + id.ToString()); - return; - } - + RexObjectProperties p = GetObject(id); SceneObjectPart sop = m_scenes[0].GetSceneObjectPart(id); if (sop == null) { - m_log.Error("[REXOBJS] CollisionMeshChanged, no SceneObjectPart for id:" + id.ToString()); + m_log.Error("[REXOBJS] TriggerOnChangeCollisionMesh, no SceneObjectPart for id:" + id.ToString()); return; } - - if (sop.ParentGroup != null) + + if (sop.ParentGroup != null && sop.PhysActor is IRexPhysicsActor) { - if (sop.PhysActor != null) - { - if (p.RexCollisionMeshUUID != UUID.Zero) - RexUpdateCollisionMesh(id); - else - sop.PhysActor.SetCollisionMesh(null, "", false); - } - } + if (p.RexCollisionMeshUUID != UUID.Zero) + RexUpdateCollisionMesh(id); + else + ((IRexPhysicsActor)sop.PhysActor).SetCollisionMesh(null, "", false); + } } - private void ScaleToPrimChanged(UUID id) + public void TriggerOnChangeScaleToPrim(UUID id) { // tucofixme, add //if (!GlobalSettings.Instance.m_3d_collision_models) // return; - - RexObjectProperties p = m_db.LoadObject(id); - if(p == null) - { - m_log.Error("[REXOBJS] ScaleToPrimChanged, no RexObjectProperties for id:" + id.ToString()); - return; - } - + + RexObjectProperties p = GetObject(id); SceneObjectPart sop = m_scenes[0].GetSceneObjectPart(id); if (sop == null) { - m_log.Error("[REXOBJS] ScaleToPrimChanged, no SceneObjectPart for id:" + id.ToString()); - return; + m_log.Error("[REXOBJS] TriggerOnChangeScaleToPrim, no SceneObjectPart for id:" + id.ToString()); + return; } - if (sop.ParentGroup != null) + if (sop.ParentGroup != null && sop.PhysActor is IRexPhysicsActor) { - if (sop.PhysActor != null) - { - sop.PhysActor.SetBoundsScaling(p.RexScaleToPrim); - sop.ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(sop.PhysActor); - } + ((IRexPhysicsActor)sop.PhysActor).SetBoundsScaling(p.RexScaleToPrim); + sop.ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(sop.PhysActor); } - } + public void TriggerOnChangeRexObjectProperties(UUID id) + { + RexObjectProperties props = GetObject(id); + + //instead of saving right away, set timer to save after a sec. + //m_db.StoreObject(props); + SendPropertiesToAllUsers(id,props); + props.ScheduleSave(); + } + + public void TriggerOnChangeRexObjectMetaData(UUID id) + { + RexObjectProperties props = GetObject(id); + + m_db.StoreObject(props); + // tucofixme, send metadata to all users + } + + + public void RexUpdateCollisionMesh(UUID id) { - // tucofixme + // tucofixme, add //if (!GlobalSettings.Instance.m_3d_collision_models) // return; - RexObjectProperties p = m_db.LoadObject(id); - if (p == null) + RexObjectProperties p = GetObject(id); + SceneObjectPart sop = m_scenes[0].GetSceneObjectPart(id); + if (sop == null) { - m_log.Error("[REXOBJS] RexUpdateCollisionMesh, no RexObjectProperties for id:" + id.ToString()); + m_log.Error("[REXOBJS] RexUpdateCollisionMesh, no SceneObjectPart for id:" + id.ToString()); return; } - SceneObjectPart sop = m_scenes[0].GetSceneObjectPart(id); - if (sop == null) + if (p.RexCollisionMeshUUID != UUID.Zero && sop.PhysActor is IRexPhysicsActor) { - m_log.Error("[REXOBJS] RexUpdateCollisionMesh, no SceneObjectPart for id:" + id.ToString()); + AssetBase tempmodel = sop.ParentGroup.Scene.AssetService.Get(p.RexCollisionMeshUUID.ToString()); + if (tempmodel != null) + ((IRexPhysicsActor)sop.PhysActor).SetCollisionMesh(tempmodel.Data, tempmodel.Name, p.RexScaleToPrim); + } + } + + public byte GetAssetType(UUID assetid) + { + AssetBase tempmodel = m_scenes[0].AssetService.Get(assetid.ToString()); + if (tempmodel == null) + m_scenes[0].AssetService.Get(assetid.ToString()); + + if (tempmodel != null) + return(byte)(tempmodel.Type); + else + return 0; + } + + + public void TriggerOnSaveObject(UUID id) + { + RexObjectProperties props = GetObject(id); + m_db.StoreObject(props); + } + #endregion + + + #region RexObjectProperties Cache + + private void LoadRexObjectPropertiesToCache() + { + if (!m_db.Inizialized) + { + m_log.ErrorFormat("LoadRexObjectPropertiesToCache failed, db not initialized"); return; - } + } - if (p.RexCollisionMeshUUID != UUID.Zero && sop.PhysActor != null) + foreach (Scene s in m_scenes) { - AssetBase tempmodel = sop.ParentGroup.Scene.AssetCache.GetAsset(p.RexCollisionMeshUUID,false); - if (tempmodel != null) - sop.PhysActor.SetCollisionMesh(tempmodel.Data, tempmodel.Metadata.Name, p.RexScaleToPrim); + foreach (EntityBase e in s.Entities) + { + RexObjectProperties p = LoadObject(e.UUID); + p.ParentObjectID = e.UUID; + p.SetRexEventManager(this); + RexObjectPropertiesCache.Add(e.UUID,p); + + // Since loaded objects have their properties already set, any initialization that needs to be done should be here. + if(p.RexCollisionMeshUUID != UUID.Zero) + TriggerOnChangeCollisionMesh(e.UUID); + + if (p.RexClassName.Length > 0) + { + SceneObjectPart sop = m_scenes[0].GetSceneObjectPart(p.ParentObjectID); + if (sop != null) + sop.SetScriptEvents(p.ParentObjectID, (int)scriptEvents.touch_start); + } + } + } + } + + private RexObjectProperties LoadObject(UUID id) + { + RexObjectProperties robject = m_db.LoadObject(id); + if (robject == null) + { + robject = new RexObjectProperties(); + robject.ParentObjectID = id; } + return robject; } - + public RexObjectProperties GetObject(UUID id) + { + RexObjectProperties props = RexObjectPropertiesCache[id]; + if (props == null) + { + //Objects that are not in the scene can't be found from cache. + //So before we create new properties, we try to find them from db + props = m_db.LoadObject(id); + if (props == null) + { + props = new RexObjectProperties(id, this); + } + RexObjectPropertiesCache.Add(id, props); + } + return props; + } + + public List GetObjects() + { + return RexObjectPropertiesCache.GetAllRexObjectProperties(); + } + + public bool DeleteObject(UUID id) + { + if (RexObjectPropertiesCache.ContainsKey(id)) + { + RexObjectPropertiesCache.Remove(id); + m_db.RemoveObject(id); + return true; + } + return false; + } + + #endregion + + + public void HandleLoadRexLegacyData(string module, string[] args) + { + NHibernateRexLegacyData legacydata = new NHibernateRexLegacyData(); + + legacydata.Initialise(args[1]); + if(!legacydata.Inizialized) + { + m_log.Info("[MODREXOBJECTS]: Legacy database failed to initialize."); + return; + } + + List rexprimdata = legacydata.LoadAllRexPrimData(); + m_log.Info("[MODREXOBJECTS]: Legacy rexprimdata objects loaded:" + rexprimdata.Count.ToString()); + + List rexprimmaterialdata = legacydata.LoadAllRexPrimMaterialData(); + m_log.Info("[MODREXOBJECTS]: Legacy rexprimmaterialdata objects loaded:" + rexprimmaterialdata.Count.ToString()); + + foreach (RexLegacyPrimData prim in rexprimdata) + { + RexObjectProperties p = GetObject(prim.UUID); + p.SetRexPrimDataFromLegacyData(prim); + } + + foreach (RexLegacyPrimMaterialData primmat in rexprimmaterialdata) + { + RexObjectProperties p = GetObject(primmat.UUID); + p.RexMaterials.AddMaterial((uint)primmat.MaterialIndex,primmat.MaterialUUID); + } + } + } }