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