From 81ad9255b5f44d988bf37cfaf6dc59b05fd744b7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 6 Jun 2013 03:03:05 +0100 Subject: Hook up Keyframe motion to almost everything. Failing to cross a sim border may yield unexpected results in some cases. No database persistence yet, --- .../EntityTransfer/EntityTransferModule.cs | 3 + .../InventoryAccess/InventoryAccessModule.cs | 3 + OpenSim/Region/Framework/Scenes/Scene.cs | 9 ++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 11 ++ .../Region/Framework/Scenes/SceneObjectGroup.cs | 13 ++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 15 +++ .../Scenes/Serialization/SceneObjectSerializer.cs | 16 +++ .../Shared/Api/Implementation/LSL_Api.cs | 140 +++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 1 + .../Shared/Api/Runtime/LSL_Constants.cs | 13 ++ .../ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 5 + 11 files changed, 229 insertions(+) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index f58a24f..85d26f3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -2247,6 +2247,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // move out of the region creating an infinite loop of failed attempts to cross grp.UpdatePrimFlags(grp.RootPart.LocalId,false,grp.IsTemporary,grp.IsPhantom,false); + if (grp.RootPart.KeyframeMotion != null) + grp.RootPart.KeyframeMotion.CrossingFailure(); + grp.ScheduleGroupForFullUpdate(); } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index e6d6cbf..880205a 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -357,6 +357,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectGroup objectGroup in objlist) { + if (objectGroup.RootPart.KeyframeMotion != null) + objectGroup.RootPart.KeyframeMotion.Stop(); + objectGroup.RootPart.KeyframeMotion = null; // Vector3 inventoryStoredPosition = new Vector3 // (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) // ? 250 diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0743ce7..a9f8a85 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2364,6 +2364,12 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Delete(); + part.KeyframeMotion = null; + } + if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) { PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? @@ -2705,6 +2711,9 @@ namespace OpenSim.Region.Framework.Scenes // before we restart the scripts, or else some functions won't work. newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); newObject.ResumeScripts(); + + if (newObject.RootPart.KeyframeMotion != null) + newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject); } // Do this as late as possible so that listeners have full access to the incoming object diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a84f6d3..bb7ae7f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1645,6 +1645,12 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void LinkObjects(SceneObjectPart root, List children) { + if (root.KeyframeMotion != null) + { + root.KeyframeMotion.Stop(); + root.KeyframeMotion = null; + } + SceneObjectGroup parentGroup = root.ParentGroup; if (parentGroup == null) return; @@ -1722,6 +1728,11 @@ namespace OpenSim.Region.Framework.Scenes { if (part != null) { + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Stop(); + part.KeyframeMotion = null; + } if (part.ParentGroup.PrimCount != 1) // Skip single { if (part.LinkNum < 2) // Root diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index df23cc5..da80e4f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -455,6 +455,9 @@ namespace OpenSim.Region.Framework.Scenes || Scene.TestBorderCross(val, Cardinals.S)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) { + if (m_rootPart.KeyframeMotion != null) + m_rootPart.KeyframeMotion.StartCrossingCheck(); + m_scene.CrossPrimGroupIntoNewRegion(val, this, true); } } @@ -578,6 +581,8 @@ namespace OpenSim.Region.Framework.Scenes childPa.Selected = value; } } + if (RootPart.KeyframeMotion != null) + RootPart.KeyframeMotion.Selected = value; } } @@ -1551,6 +1556,8 @@ namespace OpenSim.Region.Framework.Scenes newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); } + if (part.KeyframeMotion != null) + newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); } if (userExposed) @@ -1578,6 +1585,12 @@ namespace OpenSim.Region.Framework.Scenes public void ScriptSetPhysicsStatus(bool usePhysics) { + if (usePhysics) + { + if (RootPart.KeyframeMotion != null) + RootPart.KeyframeMotion.Stop(); + RootPart.KeyframeMotion = null; + } UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ea8c3c5..ff3f738 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -354,6 +354,13 @@ namespace OpenSim.Region.Framework.Scenes private UUID m_collisionSound; private float m_collisionSoundVolume; + private KeyframeMotion m_keyframeMotion = null; + + public KeyframeMotion KeyframeMotion + { + get; set; + } + #endregion Fields // ~SceneObjectPart() @@ -1799,6 +1806,8 @@ namespace OpenSim.Region.Framework.Scenes Array.Copy(Shape.ExtraParams, extraP, extraP.Length); dupe.Shape.ExtraParams = extraP; + // safeguard actual copy is done in sog.copy + dupe.KeyframeMotion = null; dupe.PayPrice = (int[])PayPrice.Clone(); dupe.DynAttrs.CopyFrom(DynAttrs); @@ -2001,6 +2010,9 @@ namespace OpenSim.Region.Framework.Scenes { if (UsePhysics) { + if (ParentGroup.RootPart.KeyframeMotion != null) + ParentGroup.RootPart.KeyframeMotion.Stop(); + ParentGroup.RootPart.KeyframeMotion = null; ParentGroup.Scene.AddPhysicalPrim(1); pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; @@ -4327,6 +4339,9 @@ namespace OpenSim.Region.Framework.Scenes if (isPhysical) { + if (ParentGroup.RootPart.KeyframeMotion != null) + ParentGroup.RootPart.KeyframeMotion.Stop(); + ParentGroup.RootPart.KeyframeMotion = null; ParentGroup.Scene.AddPhysicalPrim(1); pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 39420a6..3882b45 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -262,6 +262,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sr.Close(); } + XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion"); + if (keymotion.Count > 0) + sceneObject.RootPart.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText)); + else + sceneObject.RootPart.KeyframeMotion = null; + // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(doc); @@ -1182,6 +1188,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization }); writer.WriteEndElement(); + + if (sog.RootPart.KeyframeMotion != null) + { + Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); + + writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); + writer.WriteBase64(data, 0, data.Length); + writer.WriteEndElement(); + } + writer.WriteEndElement(); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0b4b043..cd6092d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7296,6 +7296,146 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public void llSetKeyframedMotion(LSL_List frames, LSL_List options) + { + SceneObjectGroup group = m_host.ParentGroup; + + if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) + return; + if (group.IsAttachment) + return; + + if (frames.Data.Length > 0) // We are getting a new motion + { + if (group.RootPart.KeyframeMotion != null) + group.RootPart.KeyframeMotion.Delete(); + group.RootPart.KeyframeMotion = null; + + int idx = 0; + + KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; + KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; + + while (idx < options.Data.Length) + { + int option = (int)options.GetLSLIntegerItem(idx++); + int remain = options.Data.Length - idx; + + switch (option) + { + case ScriptBaseClass.KFM_MODE: + if (remain < 1) + break; + int modeval = (int)options.GetLSLIntegerItem(idx++); + switch(modeval) + { + case ScriptBaseClass.KFM_FORWARD: + mode = KeyframeMotion.PlayMode.Forward; + break; + case ScriptBaseClass.KFM_REVERSE: + mode = KeyframeMotion.PlayMode.Reverse; + break; + case ScriptBaseClass.KFM_LOOP: + mode = KeyframeMotion.PlayMode.Loop; + break; + case ScriptBaseClass.KFM_PING_PONG: + mode = KeyframeMotion.PlayMode.PingPong; + break; + } + break; + case ScriptBaseClass.KFM_DATA: + if (remain < 1) + break; + int dataval = (int)options.GetLSLIntegerItem(idx++); + data = (KeyframeMotion.DataFormat)dataval; + break; + } + } + + group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); + + idx = 0; + + int elemLength = 2; + if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) + elemLength = 3; + + List keyframes = new List(); + while (idx < frames.Data.Length) + { + int remain = frames.Data.Length - idx; + + if (remain < elemLength) + break; + + KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); + frame.Position = null; + frame.Rotation = null; + + if ((data & KeyframeMotion.DataFormat.Translation) != 0) + { + LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); + frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); + } + if ((data & KeyframeMotion.DataFormat.Rotation) != 0) + { + LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); + Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); + q.Normalize(); + frame.Rotation = q; + } + + float tempf = (float)frames.GetLSLFloatItem(idx++); + frame.TimeMS = (int)(tempf * 1000.0f); + + keyframes.Add(frame); + } + + group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); + group.RootPart.KeyframeMotion.Start(); + } + else + { + if (group.RootPart.KeyframeMotion == null) + return; + + if (options.Data.Length == 0) + { + group.RootPart.KeyframeMotion.Stop(); + return; + } + + int code = (int)options.GetLSLIntegerItem(0); + + int idx = 0; + + while (idx < options.Data.Length) + { + int option = (int)options.GetLSLIntegerItem(idx++); + int remain = options.Data.Length - idx; + + switch (option) + { + case ScriptBaseClass.KFM_COMMAND: + int cmd = (int)options.GetLSLIntegerItem(idx++); + switch (cmd) + { + case ScriptBaseClass.KFM_CMD_PLAY: + group.RootPart.KeyframeMotion.Start(); + break; + case ScriptBaseClass.KFM_CMD_STOP: + group.RootPart.KeyframeMotion.Stop(); + break; + case ScriptBaseClass.KFM_CMD_PAUSE: + group.RootPart.KeyframeMotion.Pause(); + break; + } + break; + } + } + } + } + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) { int idx = 0; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 4ac179a..a6ea88c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -427,6 +427,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void print(string str); void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); + void llSetKeyframedMotion(LSL_List frames, LSL_List options); LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index dc5ef13..559068d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -748,6 +748,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public static readonly LSLInteger RCERR_SIM_PERF_LOW = -2; public static readonly LSLInteger RCERR_CAST_TIME_EXCEEDED = 3; + public const int KFM_MODE = 1; + public const int KFM_LOOP = 1; + public const int KFM_REVERSE = 3; + public const int KFM_FORWARD = 0; + public const int KFM_PING_PONG = 2; + public const int KFM_DATA = 2; + public const int KFM_TRANSLATION = 2; + public const int KFM_ROTATION = 1; + public const int KFM_COMMAND = 0; + public const int KFM_CMD_PLAY = 0; + public const int KFM_CMD_STOP = 1; + public const int KFM_CMD_PAUSE = 2; + /// /// process name parameter as regex /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index c7a7cf6..398c125 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -554,6 +554,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetLinkNumberOfSides(link); } + public void llSetKeyframedMotion(LSL_List frames, LSL_List options) + { + m_LSL_Functions.llSetKeyframedMotion(frames, options); + } + public LSL_Integer llGetListEntryType(LSL_List src, int index) { return m_LSL_Functions.llGetListEntryType(src, index); -- cgit v1.1 From a3210d1cf812554b53afb407fd76dbb67ce2ac28 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 6 Jun 2013 03:17:38 +0100 Subject: Database persistence for keyframes. Contains a Migration. --- OpenSim/Data/MySQL/MySQLSimulationData.cs | 29 +++++++++++++++++++--- .../Data/MySQL/Resources/RegionStore.migrations | 7 ++++++ 2 files changed, 32 insertions(+), 4 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 2d20eaf..448962a 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -173,9 +173,9 @@ namespace OpenSim.Data.MySQL "ParticleSystem, ClickAction, Material, " + "CollisionSound, CollisionSoundVolume, " + "PassTouches, " + - "LinkNumber, MediaURL, DynAttrs, " + + "LinkNumber, MediaURL, KeyframeMotion, " + "PhysicsShapeType, Density, GravityModifier, " + - "Friction, Restitution " + + "Friction, Restitution, DynAttrs " + ") values (" + "?UUID, " + "?CreationDate, ?Name, ?Text, " + "?Description, ?SitName, ?TouchName, " + @@ -208,9 +208,9 @@ namespace OpenSim.Data.MySQL "?ColorB, ?ColorA, ?ParticleSystem, " + "?ClickAction, ?Material, ?CollisionSound, " + "?CollisionSoundVolume, ?PassTouches, " + - "?LinkNumber, ?MediaURL, ?DynAttrs, " + + "?LinkNumber, ?MediaURL, ?KeyframeMotion, " + "?PhysicsShapeType, ?Density, ?GravityModifier, " + - "?Friction, ?Restitution)"; + "?Friction, ?Restitution, ?DynAttrs)"; FillPrimCommand(cmd, prim, obj.UUID, regionUUID); @@ -455,7 +455,11 @@ namespace OpenSim.Data.MySQL foreach (SceneObjectPart prim in prims.Values) { if (prim.ParentUUID == UUID.Zero) + { objects[prim.UUID] = new SceneObjectGroup(prim); + if (prim.KeyframeMotion != null) + prim.KeyframeMotion.UpdateSceneObject(objects[prim.UUID]); + } } // Add all of the children objects to the SOGs @@ -1307,6 +1311,19 @@ namespace OpenSim.Data.MySQL else prim.DynAttrs = new DAMap(); + if (!(row["KeyframeMotion"] is DBNull)) + { + Byte[] data = (byte[])row["KeyframeMotion"]; + if (data.Length > 0) + prim.KeyframeMotion = KeyframeMotion.FromData(null, data); + else + prim.KeyframeMotion = null; + } + else + { + prim.KeyframeMotion = null; + } + prim.PhysicsShapeType = (byte)Convert.ToInt32(row["PhysicsShapeType"].ToString()); prim.Density = (float)(double)row["Density"]; prim.GravityModifier = (float)(double)row["GravityModifier"]; @@ -1659,6 +1676,10 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); + if (prim.KeyframeMotion != null) + cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize()); + else + cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]); if (prim.DynAttrs.Count > 0) cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml()); diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index 513c784..70b9558 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -923,3 +923,10 @@ ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5'; COMMIT; +:VERSION 48 #---------------- Keyframes + +BEGIN; + +ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob; + +COMMIT; -- cgit v1.1