Merge branch 'master' into careminster
Conflicts: OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs OpenSim/Region/ScriptEngine/XEngine/XEngine.csavinationmerge
commit
3a495ccd56
|
@ -110,10 +110,11 @@ namespace OpenSim.Framework.Console
|
|||
// Remove initial help keyword
|
||||
helpParts.RemoveAt(0);
|
||||
|
||||
help.Add(""); // Will become a newline.
|
||||
|
||||
// General help
|
||||
if (helpParts.Count == 0)
|
||||
{
|
||||
help.Add(""); // Will become a newline.
|
||||
help.Add(GeneralHelpText);
|
||||
help.AddRange(CollectAllCommandsHelp());
|
||||
}
|
||||
|
@ -129,6 +130,8 @@ namespace OpenSim.Framework.Console
|
|||
help.AddRange(CollectHelp(helpParts));
|
||||
}
|
||||
|
||||
help.Add(""); // Will become a newline.
|
||||
|
||||
return help;
|
||||
}
|
||||
|
||||
|
@ -199,14 +202,11 @@ namespace OpenSim.Framework.Console
|
|||
|
||||
string descriptiveHelp = commandInfo.descriptive_help;
|
||||
|
||||
// If we do have some descriptive help then insert a spacing line before and after for readability.
|
||||
// If we do have some descriptive help then insert a spacing line before for readability.
|
||||
if (descriptiveHelp != string.Empty)
|
||||
help.Add(string.Empty);
|
||||
|
||||
help.Add(commandInfo.descriptive_help);
|
||||
|
||||
if (descriptiveHelp != string.Empty)
|
||||
help.Add(string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -105,7 +105,6 @@ namespace OpenSim.Region.ClientStack.Linden
|
|||
private static readonly string m_ResourceCostSelectedPath = "0103/";
|
||||
private static readonly string m_UpdateAgentInformationPath = "0500/";
|
||||
|
||||
|
||||
// These are callbacks which will be setup by the scene so that we can update scene data when we
|
||||
// receive capability calls
|
||||
public NewInventoryItem AddNewInventoryItem = null;
|
||||
|
|
|
@ -322,6 +322,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
|||
|
||||
if (asset != null)
|
||||
{
|
||||
// Replace an HG ID with the simple asset ID so that we can persist textures for foreign HG avatars
|
||||
asset.ID = asset.FullID.ToString();
|
||||
|
||||
asset.Temporary = false;
|
||||
asset.Local = false;
|
||||
m_scene.AssetService.Store(asset);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyrightD
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
|
|
|
@ -58,8 +58,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
private bool _flying;
|
||||
private bool _setAlwaysRun;
|
||||
private bool _throttleUpdates;
|
||||
private bool _isColliding;
|
||||
private bool _collidingObj;
|
||||
private bool _floatOnWater;
|
||||
private OMV.Vector3 _rotationalVelocity;
|
||||
private bool _kinematic;
|
||||
|
@ -186,10 +184,6 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// standing as well as moving. Destruction of the avatar will destroy the pre-step action.
|
||||
private void SetupMovementMotor()
|
||||
{
|
||||
|
||||
// Someday, use a PID motor for asymmetric speed up and slow down
|
||||
// _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
|
||||
|
||||
// Infinite decay and timescale values so motor only changes current to target values.
|
||||
_velocityMotor = new BSVMotor("BSCharacter.Velocity",
|
||||
0.2f, // time scale
|
||||
|
@ -216,25 +210,68 @@ public sealed class BSCharacter : BSPhysObject
|
|||
// 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
|
||||
OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
|
||||
|
||||
/*
|
||||
// If moveForce is very small, zero things so we don't keep sending microscopic updates to the user
|
||||
float moveForceMagnitudeSquared = moveForce.LengthSquared();
|
||||
if (moveForceMagnitudeSquared < 0.0001)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.MoveMotor,zeroMovement,stepVel={1},vel={2},mass={3},magSq={4},moveForce={5}",
|
||||
LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce);
|
||||
ForceVelocity = OMV.Vector3.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddForce(moveForce, false, true);
|
||||
}
|
||||
*/
|
||||
// DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
|
||||
// Should we check for move force being small and forcing velocity to zero?
|
||||
|
||||
// Add special movement force to allow avatars to walk up stepped surfaces.
|
||||
moveForce += WalkUpStairs();
|
||||
|
||||
DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
|
||||
PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
|
||||
});
|
||||
}
|
||||
|
||||
// Decide of the character is colliding with a low object and compute a force to pop the
|
||||
// avatar up so it has a chance of walking up and over the low object.
|
||||
private OMV.Vector3 WalkUpStairs()
|
||||
{
|
||||
OMV.Vector3 ret = OMV.Vector3.Zero;
|
||||
|
||||
// This test is done if moving forward, not flying and is colliding with something.
|
||||
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
||||
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
||||
if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
||||
{
|
||||
// The range near the character's feet where we will consider stairs
|
||||
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
|
||||
float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
|
||||
|
||||
// Look for a collision point that is near the character's feet and is oriented the same as the charactor is
|
||||
foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
|
||||
{
|
||||
// Don't care about collisions with the terrain
|
||||
if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
|
||||
{
|
||||
OMV.Vector3 touchPosition = kvp.Value.Position;
|
||||
// DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
|
||||
// LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
|
||||
if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
|
||||
{
|
||||
// This contact is within the 'near the feet' range.
|
||||
// The normal should be our contact point to the object so it is pointing away
|
||||
// thus the difference between our facing orientation and the normal should be small.
|
||||
OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
|
||||
OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
|
||||
float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
|
||||
if (diff < BSParam.AvatarStepApproachFactor)
|
||||
{
|
||||
// Found the stairs contact point. Push up a little to raise the character.
|
||||
float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
|
||||
ret = new OMV.Vector3(0f, 0f, upForce);
|
||||
|
||||
// Also move the avatar up for the new height
|
||||
OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
|
||||
ForcePosition = RawPosition + displacement;
|
||||
}
|
||||
DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
|
||||
LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override void RequestPhysicsterseUpdate()
|
||||
{
|
||||
base.RequestPhysicsterseUpdate();
|
||||
|
@ -344,13 +381,11 @@ public sealed class BSCharacter : BSPhysObject
|
|||
}
|
||||
set {
|
||||
_position = value;
|
||||
PositionSanityCheck();
|
||||
|
||||
PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
ForcePosition = _position;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -361,8 +396,11 @@ public sealed class BSCharacter : BSPhysObject
|
|||
}
|
||||
set {
|
||||
_position = value;
|
||||
PositionSanityCheck();
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
PositionSanityCheck();
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,7 +413,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
bool ret = false;
|
||||
|
||||
// TODO: check for out of bounds
|
||||
if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position))
|
||||
if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
|
||||
{
|
||||
// The character is out of the known/simulated area.
|
||||
// Upper levels of code will handle the transition to other areas so, for
|
||||
|
@ -384,7 +422,7 @@ public sealed class BSCharacter : BSPhysObject
|
|||
}
|
||||
|
||||
// If below the ground, move the avatar up
|
||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
|
||||
if (Position.Z < terrainHeight)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||
|
@ -487,6 +525,11 @@ public sealed class BSCharacter : BSPhysObject
|
|||
});
|
||||
}
|
||||
}
|
||||
public override OMV.Vector3 RawVelocity
|
||||
{
|
||||
get { return _velocity; }
|
||||
set { _velocity = value; }
|
||||
}
|
||||
// Directly setting velocity means this is what the user really wants now.
|
||||
public override OMV.Vector3 Velocity {
|
||||
get { return _velocity; }
|
||||
|
|
|
@ -137,6 +137,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; }
|
||||
}
|
||||
|
||||
#region Vehicle parameter setting
|
||||
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
|
||||
{
|
||||
VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
|
||||
|
@ -546,6 +547,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
|
||||
m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
|
||||
}
|
||||
#endregion // Vehicle parameter setting
|
||||
|
||||
// Some of the properties of this prim may have changed.
|
||||
// Do any updating needed for a vehicle
|
||||
|
@ -854,6 +856,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// The movement computed in the linear motor is relative to the vehicle
|
||||
// coordinates. Rotate the movement to world coordinates.
|
||||
linearMotorContribution *= VehicleOrientation;
|
||||
// All the contributions after this are world relative (mostly Z modifications)
|
||||
|
||||
// ==================================================================
|
||||
// Buoyancy: force to overcome gravity.
|
||||
|
@ -925,7 +928,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
// TODO: Consider taking the rotated size of the object or possibly casting a ray.
|
||||
if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
|
||||
{
|
||||
// TODO: correct position by applying force rather than forcing position.
|
||||
// Force position because applying force won't get the vehicle through the terrain
|
||||
Vector3 newPosition = VehiclePosition;
|
||||
newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f;
|
||||
VehiclePosition = newPosition;
|
||||
|
@ -980,14 +983,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
|
||||
|
||||
// TODO: implement m_VhoverEfficiency correctly
|
||||
if (Math.Abs(verticalError) > m_VhoverEfficiency)
|
||||
{
|
||||
ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
|
||||
}
|
||||
ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
|
||||
}
|
||||
|
||||
VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}",
|
||||
Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight);
|
||||
VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},ret={6}",
|
||||
Prim.LocalID, VehiclePosition, m_VhoverEfficiency, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1109,6 +1109,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
+ deflectionContribution
|
||||
+ bankingContribution;
|
||||
|
||||
// Add of the above computation are made relative to vehicle coordinates.
|
||||
// Convert to world coordinates.
|
||||
m_lastAngularVelocity *= VehicleOrientation;
|
||||
|
||||
// ==================================================================
|
||||
// Apply the correction velocity.
|
||||
// TODO: Should this be applied as an angular force (torque)?
|
||||
|
@ -1220,19 +1224,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
public Vector3 ComputeAngularDeflection()
|
||||
{
|
||||
Vector3 ret = Vector3.Zero;
|
||||
return ret; // DEBUG DEBUG DEBUG
|
||||
// Disable angular deflection for the moment.
|
||||
|
||||
// Since angularMotorUp and angularDeflection are computed independently, they will calculate
|
||||
// approximately the same X or Y correction. When added together (when contributions are combined)
|
||||
// this creates an over-correction and then wabbling as the target is overshot.
|
||||
// TODO: rethink how the different correction computations inter-relate.
|
||||
|
||||
if (m_angularDeflectionEfficiency != 0)
|
||||
if (m_angularDeflectionEfficiency != 0 && VehicleVelocity != Vector3.Zero)
|
||||
{
|
||||
// The direction the vehicle is moving
|
||||
Vector3 movingDirection = VehicleVelocity;
|
||||
movingDirection.Normalize();
|
||||
|
||||
// If the vehicle is going backward, it is still pointing forward
|
||||
movingDirection *= Math.Sign(VehicleForwardSpeed);
|
||||
|
||||
// The direction the vehicle is pointing
|
||||
Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
|
||||
pointingDirection.Normalize();
|
||||
|
@ -1241,6 +1247,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
Vector3 deflectionError = movingDirection - pointingDirection;
|
||||
|
||||
// Don't try to correct very large errors (not our job)
|
||||
// if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
|
||||
// if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = PIOverTwo * Math.Sign(deflectionError.Y);
|
||||
// if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = PIOverTwo * Math.Sign(deflectionError.Z);
|
||||
if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
|
||||
if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
|
||||
if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
|
||||
|
@ -1296,33 +1305,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
|||
|
||||
if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
|
||||
{
|
||||
// This works by rotating a unit vector to the orientation of the vehicle. The
|
||||
// roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
|
||||
// up to one for full over).
|
||||
// Rotate a UnitZ vector (pointing up) to how the vehicle is oriented.
|
||||
// As the vehicle rolls to the right or left, the Y value will increase from
|
||||
// zero (straight up) to 1 or -1 (full tilt right or left)
|
||||
Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
|
||||
|
||||
|
||||
// Figure out the yaw value for this much roll.
|
||||
float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
|
||||
// Keep the sign
|
||||
if (rollComponents.Y < 0f)
|
||||
turnComponent = -turnComponent;
|
||||
|
||||
// TODO: there must be a better computation of the banking force.
|
||||
float bankingTurnForce = turnComponent;
|
||||
// Squared because that seems to give a good value
|
||||
float yawAngle = (float)Math.Asin(rollComponents.Y * rollComponents.Y) * m_bankingEfficiency;
|
||||
|
||||
// actual error = static turn error + dynamic turn error
|
||||
float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
|
||||
float mixedYawAngle = yawAngle * (1f - m_bankingMix) + yawAngle * m_bankingMix * VehicleForwardSpeed;
|
||||
|
||||
// TODO: the banking effect should not go to infinity but what to limit it to?
|
||||
mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
|
||||
mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f);
|
||||
|
||||
// Build the force vector to change rotation from what it is to what it should be
|
||||
ret.Z = -mixedBankingError;
|
||||
ret.Z = -mixedYawAngle;
|
||||
|
||||
// Don't do it all at once.
|
||||
ret /= m_bankingTimescale;
|
||||
|
||||
VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
|
||||
Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
|
||||
VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
|
||||
Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,9 @@ public static class BSParam
|
|||
public static float AvatarCapsuleDepth { get; private set; }
|
||||
public static float AvatarCapsuleHeight { get; private set; }
|
||||
public static float AvatarContactProcessingThreshold { get; private set; }
|
||||
public static float AvatarStepHeight { get; private set; }
|
||||
public static float AvatarStepApproachFactor { get; private set; }
|
||||
public static float AvatarStepForceFactor { get; private set; }
|
||||
|
||||
public static float VehicleAngularDamping { get; private set; }
|
||||
|
||||
|
@ -403,6 +406,21 @@ public static class BSParam
|
|||
(s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarContactProcessingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ),
|
||||
new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
||||
0.3f,
|
||||
(s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStepHeight; },
|
||||
(s,p,l,v) => { AvatarStepHeight = v; } ),
|
||||
new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
||||
0.6f,
|
||||
(s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStepApproachFactor; },
|
||||
(s,p,l,v) => { AvatarStepApproachFactor = v; } ),
|
||||
new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
|
||||
2.0f,
|
||||
(s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStepForceFactor; },
|
||||
(s,p,l,v) => { AvatarStepForceFactor = v; } ),
|
||||
|
||||
new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
|
||||
0.95f,
|
||||
|
|
|
@ -79,6 +79,7 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
Material = MaterialAttributes.Material.Wood;
|
||||
|
||||
CollisionCollection = new CollisionEventUpdate();
|
||||
CollisionsLastTick = CollisionCollection;
|
||||
SubscribedEventsMs = 0;
|
||||
CollidingStep = 0;
|
||||
CollidingGroundStep = 0;
|
||||
|
@ -159,6 +160,7 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||
|
||||
// The system is telling us the velocity it wants to move at.
|
||||
// Velocity in world coordinates.
|
||||
// protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
|
||||
public override OMV.Vector3 TargetVelocity
|
||||
{
|
||||
|
@ -169,6 +171,15 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
Velocity = value;
|
||||
}
|
||||
}
|
||||
public virtual float TargetSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
|
||||
return characterOrientedVelocity.X;
|
||||
}
|
||||
}
|
||||
public abstract OMV.Vector3 RawVelocity { get; set; }
|
||||
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||
|
||||
public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
|
||||
|
@ -177,6 +188,15 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
|
||||
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
||||
|
||||
public virtual float ForwardSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
OMV.Vector3 characterOrientedVelocity = RawVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
|
||||
return characterOrientedVelocity.X;
|
||||
}
|
||||
}
|
||||
|
||||
#region Collisions
|
||||
|
||||
// Requested number of milliseconds between collision events. Zero means disabled.
|
||||
|
@ -223,9 +243,13 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
|
||||
// The collisions that have been collected this tick
|
||||
protected CollisionEventUpdate CollisionCollection;
|
||||
// Remember collisions from last tick for fancy collision based actions
|
||||
// (like a BSCharacter walking up stairs).
|
||||
protected CollisionEventUpdate CollisionsLastTick;
|
||||
|
||||
// The simulation step is telling this object about a collision.
|
||||
// Return 'true' if a collision was processed and should be sent up.
|
||||
// Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
|
||||
// Called at taint time from within the Step() function
|
||||
public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
|
||||
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
|
@ -286,6 +310,9 @@ public abstract class BSPhysObject : PhysicsActor
|
|||
// DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
|
||||
base.SendCollisionUpdate(CollisionCollection);
|
||||
|
||||
// Remember the collisions from this tick for some collision specific processing.
|
||||
CollisionsLastTick = CollisionCollection;
|
||||
|
||||
// The CollisionCollection instance is passed around in the simulator.
|
||||
// Make sure we don't have a handle to that one and that a new one is used for next time.
|
||||
// This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
|
||||
|
|
|
@ -562,7 +562,7 @@ public sealed class BSPrim : BSPhysObject
|
|||
}
|
||||
return;
|
||||
}
|
||||
public OMV.Vector3 RawVelocity
|
||||
public override OMV.Vector3 RawVelocity
|
||||
{
|
||||
get { return _velocity; }
|
||||
set { _velocity = value; }
|
||||
|
|
|
@ -27,24 +27,19 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public abstract class BSShape
|
||||
{
|
||||
public IntPtr ptr { get; set; }
|
||||
public BSPhysicsShapeType type { get; set; }
|
||||
public System.UInt64 key { get; set; }
|
||||
public int referenceCount { get; set; }
|
||||
public DateTime lastReferenced { get; set; }
|
||||
|
||||
public BSShape()
|
||||
{
|
||||
ptr = IntPtr.Zero;
|
||||
type = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
key = 0;
|
||||
referenceCount = 0;
|
||||
lastReferenced = DateTime.Now;
|
||||
}
|
||||
|
@ -63,7 +58,7 @@ public abstract class BSShape
|
|||
}
|
||||
|
||||
// Compound shapes are handled special as they are rebuilt from scratch.
|
||||
// This isn't too great a hardship since most of the child shapes will already been created.
|
||||
// This isn't too great a hardship since most of the child shapes will have already been created.
|
||||
if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
|
||||
{
|
||||
// Getting a reference to a compound shape gets you the compound shape with the root prim shape added
|
||||
|
@ -71,6 +66,14 @@ public abstract class BSShape
|
|||
physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
|
||||
}
|
||||
|
||||
// Avatars have their own unique shape
|
||||
if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
|
||||
{
|
||||
// Getting a reference to a compound shape gets you the compound shape with the root prim shape added
|
||||
ret = BSShapeAvatar.GetReference(prim);
|
||||
physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
|
||||
}
|
||||
|
||||
if (ret == null)
|
||||
ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
|
||||
|
||||
|
@ -92,9 +95,9 @@ public abstract class BSShape
|
|||
// protected abstract static BSShape GetReference();
|
||||
|
||||
// Returns a string for debugging that uniquily identifies the memory used by this instance
|
||||
public string AddrString
|
||||
public virtual string AddrString
|
||||
{
|
||||
get { return ptr.ToString("X"); }
|
||||
get { return "unknown"; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -102,10 +105,6 @@ public abstract class BSShape
|
|||
StringBuilder buff = new StringBuilder();
|
||||
buff.Append("<p=");
|
||||
buff.Append(AddrString);
|
||||
buff.Append(",s=");
|
||||
buff.Append(type.ToString());
|
||||
buff.Append(",k=");
|
||||
buff.Append(key.ToString("X"));
|
||||
buff.Append(",c=");
|
||||
buff.Append(referenceCount.ToString());
|
||||
buff.Append(">");
|
||||
|
@ -228,5 +227,131 @@ public class BSShapeAvatar : BSShape
|
|||
return new BSShapeNull();
|
||||
}
|
||||
public override void Dereference(BSScene physicsScene) { }
|
||||
|
||||
// From the front:
|
||||
// A---A
|
||||
// / \
|
||||
// B-------B
|
||||
// / \ +Z
|
||||
// C-----------C |
|
||||
// \ / -Y --+-- +Y
|
||||
// \ / |
|
||||
// \ / -Z
|
||||
// D-----D
|
||||
// \ /
|
||||
// E-E
|
||||
|
||||
// From the top A and E are just lines.
|
||||
// B, C and D are hexagons:
|
||||
//
|
||||
// C1--C2 +X
|
||||
// / \ |
|
||||
// C0 C3 -Y --+-- +Y
|
||||
// \ / |
|
||||
// C5--C4 -X
|
||||
|
||||
// Zero goes directly through the middle so the offsets are from that middle axis
|
||||
// and up and down from a middle horizon (A and E are the same distance from the zero).
|
||||
// The height, width and depth is one. All scaling is done by the simulator.
|
||||
|
||||
// Z component -- how far the level is from the middle zero
|
||||
private const float Aup = 0.5f;
|
||||
private const float Bup = 0.4f;
|
||||
private const float Cup = 0.3f;
|
||||
private const float Dup = -0.4f;
|
||||
private const float Eup = -0.5f;
|
||||
|
||||
// Y component -- distance from center to x0 and x3
|
||||
private const float Awid = 0.25f;
|
||||
private const float Bwid = 0.3f;
|
||||
private const float Cwid = 0.5f;
|
||||
private const float Dwid = 0.3f;
|
||||
private const float Ewid = 0.2f;
|
||||
|
||||
// Y component -- distance from center to x1, x2, x4 and x5
|
||||
private const float Afwid = 0.0f;
|
||||
private const float Bfwid = 0.2f;
|
||||
private const float Cfwid = 0.4f;
|
||||
private const float Dfwid = 0.2f;
|
||||
private const float Efwid = 0.0f;
|
||||
|
||||
// X component -- distance from zero to the front or back of a level
|
||||
private const float Adep = 0f;
|
||||
private const float Bdep = 0.3f;
|
||||
private const float Cdep = 0.5f;
|
||||
private const float Ddep = 0.2f;
|
||||
private const float Edep = 0f;
|
||||
|
||||
private OMV.Vector3[] avatarVertices = {
|
||||
new OMV.Vector3( 0.0f, -Awid, Aup), // A0
|
||||
new OMV.Vector3( 0.0f, +Awid, Aup), // A3
|
||||
|
||||
new OMV.Vector3( 0.0f, -Bwid, Bup), // B0
|
||||
new OMV.Vector3(+Bdep, -Bfwid, Bup), // B1
|
||||
new OMV.Vector3(+Bdep, +Bfwid, Bup), // B2
|
||||
new OMV.Vector3( 0.0f, +Bwid, Bup), // B3
|
||||
new OMV.Vector3(-Bdep, +Bfwid, Bup), // B4
|
||||
new OMV.Vector3(-Bdep, -Bfwid, Bup), // B5
|
||||
|
||||
new OMV.Vector3( 0.0f, -Cwid, Cup), // C0
|
||||
new OMV.Vector3(+Cdep, -Cfwid, Cup), // C1
|
||||
new OMV.Vector3(+Cdep, +Cfwid, Cup), // C2
|
||||
new OMV.Vector3( 0.0f, +Cwid, Cup), // C3
|
||||
new OMV.Vector3(-Cdep, +Cfwid, Cup), // C4
|
||||
new OMV.Vector3(-Cdep, -Cfwid, Cup), // C5
|
||||
|
||||
new OMV.Vector3( 0.0f, -Dwid, Dup), // D0
|
||||
new OMV.Vector3(+Ddep, -Dfwid, Dup), // D1
|
||||
new OMV.Vector3(+Ddep, +Dfwid, Dup), // D2
|
||||
new OMV.Vector3( 0.0f, +Dwid, Dup), // D3
|
||||
new OMV.Vector3(-Ddep, +Dfwid, Dup), // D4
|
||||
new OMV.Vector3(-Ddep, -Dfwid, Dup), // D5
|
||||
|
||||
new OMV.Vector3( 0.0f, -Ewid, Eup), // E0
|
||||
new OMV.Vector3( 0.0f, +Ewid, Eup), // E3
|
||||
};
|
||||
|
||||
// Offsets of the vertices in the vertices array
|
||||
private enum Ind : int
|
||||
{
|
||||
A0, A3,
|
||||
B0, B1, B2, B3, B4, B5,
|
||||
C0, C1, C2, C3, C4, C5,
|
||||
D0, D1, D2, D3, D4, D5,
|
||||
E0, E3
|
||||
}
|
||||
|
||||
// Comments specify trianges and quads in clockwise direction
|
||||
private Ind[] avatarIndices = {
|
||||
Ind.A0, Ind.B0, Ind.B1, // A0,B0,B1
|
||||
Ind.A0, Ind.B1, Ind.B2, Ind.B2, Ind.A3, Ind.A0, // A0,B1,B2,A3
|
||||
Ind.A3, Ind.B2, Ind.B3, // A3,B2,B3
|
||||
Ind.A3, Ind.B3, Ind.B4, // A3,B3,B4
|
||||
Ind.A3, Ind.B4, Ind.B5, Ind.B5, Ind.A0, Ind.A3, // A3,B4,B5,A0
|
||||
Ind.A0, Ind.B5, Ind.B0, // A0,B5,B0
|
||||
|
||||
Ind.B0, Ind.C0, Ind.C1, Ind.C1, Ind.B1, Ind.B0, // B0,C0,C1,B1
|
||||
Ind.B1, Ind.C1, Ind.C2, Ind.C2, Ind.B2, Ind.B1, // B1,C1,C2,B2
|
||||
Ind.B2, Ind.C2, Ind.C3, Ind.C3, Ind.B3, Ind.B2, // B2,C2,C3,B3
|
||||
Ind.B3, Ind.C3, Ind.C4, Ind.C4, Ind.B4, Ind.B3, // B3,C3,C4,B4
|
||||
Ind.B4, Ind.C4, Ind.C5, Ind.C5, Ind.B5, Ind.B4, // B4,C4,C5,B5
|
||||
Ind.B5, Ind.C5, Ind.C0, Ind.C0, Ind.B0, Ind.B5, // B5,C5,C0,B0
|
||||
|
||||
Ind.C0, Ind.D0, Ind.D1, Ind.D1, Ind.C1, Ind.C0, // C0,D0,D1,C1
|
||||
Ind.C1, Ind.D1, Ind.D2, Ind.D2, Ind.C2, Ind.C1, // C1,D1,D2,C2
|
||||
Ind.C2, Ind.D2, Ind.D3, Ind.D3, Ind.C3, Ind.C2, // C2,D2,D3,C3
|
||||
Ind.C3, Ind.D3, Ind.D4, Ind.D4, Ind.C4, Ind.C3, // C3,D3,D4,C4
|
||||
Ind.C4, Ind.D4, Ind.D5, Ind.D5, Ind.C5, Ind.C4, // C4,D4,D5,C5
|
||||
Ind.C5, Ind.D5, Ind.D0, Ind.D0, Ind.C0, Ind.C5, // C5,D5,D0,C0
|
||||
|
||||
Ind.E0, Ind.D0, Ind.D1, // E0,D0,D1
|
||||
Ind.E0, Ind.D1, Ind.D2, Ind.D2, Ind.E3, Ind.E0, // E0,D1,D2,E3
|
||||
Ind.E3, Ind.D2, Ind.D3, // E3,D2,D3
|
||||
Ind.E3, Ind.D3, Ind.D4, // E3,D3,D4
|
||||
Ind.E3, Ind.D4, Ind.D5, Ind.D5, Ind.E0, Ind.E3, // E3,D4,D5,E0
|
||||
Ind.E0, Ind.D5, Ind.D0, // E0,D5,D0
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
|||
PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody);
|
||||
// Frees both the body and the shape.
|
||||
PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody);
|
||||
m_terrainBody.Clear();
|
||||
m_terrainShape.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,8 +114,10 @@ public class BulletShape
|
|||
|
||||
public virtual void Clear() { }
|
||||
public virtual bool HasPhysicalShape { get { return false; } }
|
||||
|
||||
// Make another reference to this physical object.
|
||||
public virtual BulletShape Clone() { return new BulletShape(); }
|
||||
|
||||
// Return 'true' if this and other refer to the same physical object
|
||||
public virtual bool ReferenceSame(BulletShape xx) { return false; }
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
CURRENT PRIORITIES
|
||||
=================================================
|
||||
Redo BulletSimAPI to allow native C# implementation of Bullet option (DONE)
|
||||
Meshes rendering as bounding boxes
|
||||
llMoveToTarget
|
||||
Avatars walking up stairs (HALF DONE)
|
||||
Vehicle movement on terrain smoothness
|
||||
limitMotorUp calibration (more down?)
|
||||
Preferred orientatino angular correction fix
|
||||
Preferred orientation angular correction fix
|
||||
Surfboard go wonky when turning
|
||||
Angular motor direction is global coordinates rather than local coordinates?
|
||||
Boats float low in the water
|
||||
|
@ -90,6 +88,8 @@ setForce should set a constant force. Different than AddImpulse.
|
|||
Implement raycast.
|
||||
Implement ShapeCollection.Dispose()
|
||||
Implement water as a plain so raycasting and collisions can happen with same.
|
||||
Add collision penetration return
|
||||
Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance()
|
||||
Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
|
||||
Also osGetPhysicsEngineVerion() maybe.
|
||||
Linkset.Position and Linkset.Orientation requre rewrite to properly return
|
||||
|
@ -135,6 +135,9 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint)
|
|||
|
||||
MORE
|
||||
======================================================
|
||||
Use the HACD convex hull routine in Bullet rather than the C# version.
|
||||
Do we need to do convex hulls all the time? Can complex meshes be left meshes?
|
||||
There is some problem with meshes and collisions
|
||||
Test avatar walking up stairs. How does compare with SL.
|
||||
Radius of the capsule affects ability to climb edges.
|
||||
Debounce avatar contact so legs don't keep folding up when standing.
|
||||
|
@ -274,3 +277,8 @@ llSetBuoyancy() (DONE)
|
|||
(Resolution: Bullet resets object gravity when added to world. Moved set gravity)
|
||||
Avatar density is WAY off. Compare and calibrate with what's in SL. (DONE)
|
||||
(Resolution: set default density to 3.5 (from 60) which is closer to SL)
|
||||
Redo BulletSimAPI to allow native C# implementation of Bullet option (DONE)
|
||||
(Resolution: added BSAPITemplate and then interfaces for C++ Bullet and C# BulletXNA
|
||||
Meshes rendering as bounding boxes (DONE)
|
||||
(Resolution: Added test for mesh/sculpties in native shapes so it didn't think it was a box)
|
||||
llMoveToTarget (Resolution: added simple motor to update the position.)
|
||||
|
|
|
@ -42,6 +42,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
/// <summary>
|
||||
/// Used by one-off and repeated sensors
|
||||
/// </summary>
|
||||
public class SensorInfo
|
||||
{
|
||||
public uint localID;
|
||||
public UUID itemID;
|
||||
public double interval;
|
||||
public DateTime next;
|
||||
|
||||
public string name;
|
||||
public UUID keyID;
|
||||
public int type;
|
||||
public double range;
|
||||
public double arc;
|
||||
public SceneObjectPart host;
|
||||
|
||||
public SensorInfo Clone()
|
||||
{
|
||||
return (SensorInfo)this.MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncCommandManager m_CmdManager;
|
||||
|
||||
/// <summary>
|
||||
|
@ -77,24 +100,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
private double maximumRange = 96.0;
|
||||
private int maximumToReturn = 16;
|
||||
|
||||
//
|
||||
// SenseRepeater and Sensors
|
||||
//
|
||||
private class SenseRepeatClass
|
||||
{
|
||||
public uint localID;
|
||||
public UUID itemID;
|
||||
public double interval;
|
||||
public DateTime next;
|
||||
|
||||
public string name;
|
||||
public UUID keyID;
|
||||
public int type;
|
||||
public double range;
|
||||
public double arc;
|
||||
public SceneObjectPart host;
|
||||
}
|
||||
|
||||
//
|
||||
// Sensed entity
|
||||
//
|
||||
|
@ -127,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
///
|
||||
/// Always lock SenseRepeatListLock when updating this list.
|
||||
/// </remarks>
|
||||
private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
|
||||
private List<SensorInfo> SenseRepeaters = new List<SensorInfo>();
|
||||
private object SenseRepeatListLock = new object();
|
||||
|
||||
public void SetSenseRepeatEvent(uint m_localID, UUID m_itemID,
|
||||
|
@ -141,7 +146,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
return;
|
||||
|
||||
// Add to timer
|
||||
SenseRepeatClass ts = new SenseRepeatClass();
|
||||
SensorInfo ts = new SensorInfo();
|
||||
ts.localID = m_localID;
|
||||
ts.itemID = m_itemID;
|
||||
ts.interval = sec;
|
||||
|
@ -160,11 +165,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
AddSenseRepeater(ts);
|
||||
}
|
||||
|
||||
private void AddSenseRepeater(SenseRepeatClass senseRepeater)
|
||||
private void AddSenseRepeater(SensorInfo senseRepeater)
|
||||
{
|
||||
lock (SenseRepeatListLock)
|
||||
{
|
||||
List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters);
|
||||
List<SensorInfo> newSenseRepeaters = new List<SensorInfo>(SenseRepeaters);
|
||||
newSenseRepeaters.Add(senseRepeater);
|
||||
SenseRepeaters = newSenseRepeaters;
|
||||
}
|
||||
|
@ -175,8 +180,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
// Remove from timer
|
||||
lock (SenseRepeatListLock)
|
||||
{
|
||||
List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>();
|
||||
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||
List<SensorInfo> newSenseRepeaters = new List<SensorInfo>();
|
||||
foreach (SensorInfo ts in SenseRepeaters)
|
||||
{
|
||||
if (ts.localID != m_localID || ts.itemID != m_itemID)
|
||||
{
|
||||
|
@ -191,7 +196,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
public void CheckSenseRepeaterEvents()
|
||||
{
|
||||
// Go through all timers
|
||||
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||
foreach (SensorInfo ts in SenseRepeaters)
|
||||
{
|
||||
// Time has passed?
|
||||
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
|
||||
|
@ -208,7 +213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
double range, double arc, SceneObjectPart host)
|
||||
{
|
||||
// Add to timer
|
||||
SenseRepeatClass ts = new SenseRepeatClass();
|
||||
SensorInfo ts = new SensorInfo();
|
||||
ts.localID = m_localID;
|
||||
ts.itemID = m_itemID;
|
||||
ts.interval = 0;
|
||||
|
@ -224,7 +229,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
SensorSweep(ts);
|
||||
}
|
||||
|
||||
private void SensorSweep(SenseRepeatClass ts)
|
||||
private void SensorSweep(SensorInfo ts)
|
||||
{
|
||||
if (ts.host == null)
|
||||
{
|
||||
|
@ -300,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
}
|
||||
}
|
||||
|
||||
private List<SensedEntity> doObjectSensor(SenseRepeatClass ts)
|
||||
private List<SensedEntity> doObjectSensor(SensorInfo ts)
|
||||
{
|
||||
List<EntityBase> Entities;
|
||||
List<SensedEntity> sensedEntities = new List<SensedEntity>();
|
||||
|
@ -451,7 +456,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
return sensedEntities;
|
||||
}
|
||||
|
||||
private List<SensedEntity> doAgentSensor(SenseRepeatClass ts)
|
||||
private List<SensedEntity> doAgentSensor(SensorInfo ts)
|
||||
{
|
||||
List<SensedEntity> sensedEntities = new List<SensedEntity>();
|
||||
|
||||
|
@ -630,7 +635,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
{
|
||||
List<Object> data = new List<Object>();
|
||||
|
||||
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||
foreach (SensorInfo ts in SenseRepeaters)
|
||||
{
|
||||
if (ts.itemID == itemID)
|
||||
{
|
||||
|
@ -660,7 +665,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
|
||||
while (idx < data.Length)
|
||||
{
|
||||
SenseRepeatClass ts = new SenseRepeatClass();
|
||||
SensorInfo ts = new SensorInfo();
|
||||
|
||||
ts.localID = localID;
|
||||
ts.itemID = itemID;
|
||||
|
@ -681,5 +686,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
idx += 6;
|
||||
}
|
||||
}
|
||||
|
||||
public List<SensorInfo> GetSensorInfo()
|
||||
{
|
||||
List<SensorInfo> retList = new List<SensorInfo>();
|
||||
|
||||
lock (SenseRepeatListLock)
|
||||
{
|
||||
foreach (SensorInfo i in SenseRepeaters)
|
||||
retList.Add(i.Clone());
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
{
|
||||
public class Timer
|
||||
{
|
||||
public class TimerInfo
|
||||
{
|
||||
public uint localID;
|
||||
public UUID itemID;
|
||||
//public double interval;
|
||||
public long interval;
|
||||
//public DateTime next;
|
||||
public long next;
|
||||
|
||||
public TimerInfo Clone()
|
||||
{
|
||||
return (TimerInfo)this.MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncCommandManager m_CmdManager;
|
||||
|
||||
public int TimersCount
|
||||
|
@ -59,17 +74,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
return localID.ToString() + itemID.ToString();
|
||||
}
|
||||
|
||||
private class TimerClass
|
||||
{
|
||||
public uint localID;
|
||||
public UUID itemID;
|
||||
//public double interval;
|
||||
public long interval;
|
||||
//public DateTime next;
|
||||
public long next;
|
||||
}
|
||||
|
||||
private Dictionary<string,TimerClass> Timers = new Dictionary<string,TimerClass>();
|
||||
private Dictionary<string,TimerInfo> Timers = new Dictionary<string,TimerInfo>();
|
||||
private object TimerListLock = new object();
|
||||
|
||||
public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec)
|
||||
|
@ -81,7 +86,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
}
|
||||
|
||||
// Add to timer
|
||||
TimerClass ts = new TimerClass();
|
||||
TimerInfo ts = new TimerInfo();
|
||||
ts.localID = m_localID;
|
||||
ts.itemID = m_itemID;
|
||||
ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
|
||||
|
@ -118,14 +123,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
if (Timers.Count == 0)
|
||||
return;
|
||||
|
||||
Dictionary<string, TimerClass>.ValueCollection tvals;
|
||||
Dictionary<string, TimerInfo>.ValueCollection tvals;
|
||||
lock (TimerListLock)
|
||||
{
|
||||
// Go through all timers
|
||||
tvals = Timers.Values;
|
||||
}
|
||||
|
||||
foreach (TimerClass ts in tvals)
|
||||
foreach (TimerInfo ts in tvals)
|
||||
{
|
||||
// Time has passed?
|
||||
if (ts.next < DateTime.Now.Ticks)
|
||||
|
@ -149,8 +154,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
|
||||
lock (TimerListLock)
|
||||
{
|
||||
Dictionary<string, TimerClass>.ValueCollection tvals = Timers.Values;
|
||||
foreach (TimerClass ts in tvals)
|
||||
Dictionary<string, TimerInfo>.ValueCollection tvals = Timers.Values;
|
||||
foreach (TimerInfo ts in tvals)
|
||||
{
|
||||
if (ts.itemID == itemID)
|
||||
{
|
||||
|
@ -169,7 +174,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
|
||||
while (idx < data.Length)
|
||||
{
|
||||
TimerClass ts = new TimerClass();
|
||||
TimerInfo ts = new TimerInfo();
|
||||
|
||||
ts.localID = localID;
|
||||
ts.itemID = itemID;
|
||||
|
@ -183,5 +188,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<TimerInfo> GetTimersInfo()
|
||||
{
|
||||
List<TimerInfo> retList = new List<TimerInfo>();
|
||||
|
||||
lock (TimerListLock)
|
||||
{
|
||||
foreach (TimerInfo i in Timers.Values)
|
||||
retList.Add(i.Clone());
|
||||
}
|
||||
|
||||
return retList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
using OpenSim.Region.ScriptEngine.Interfaces;
|
||||
using OpenSim.Region.ScriptEngine.Shared.Api;
|
||||
using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
{
|
||||
public class ScriptEngineConsoleCommands
|
||||
{
|
||||
IScriptEngine m_engine;
|
||||
|
||||
public ScriptEngineConsoleCommands(IScriptEngine engine)
|
||||
{
|
||||
m_engine = engine;
|
||||
}
|
||||
|
||||
public void RegisterCommands()
|
||||
{
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "show script sensors", "show script sensors", "Show script sensors information",
|
||||
HandleShowSensors);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "show script timers", "show script timers", "Show script sensors information",
|
||||
HandleShowTimers);
|
||||
}
|
||||
|
||||
private bool IsSceneSelected()
|
||||
{
|
||||
return MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_engine.World;
|
||||
}
|
||||
|
||||
private void HandleShowSensors(string module, string[] cmdparams)
|
||||
{
|
||||
if (!IsSceneSelected())
|
||||
return;
|
||||
|
||||
SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(m_engine);
|
||||
|
||||
if (sr == null)
|
||||
{
|
||||
MainConsole.Instance.Output("Plugin not yet initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
List<SensorRepeat.SensorInfo> sensorInfo = sr.GetSensorInfo();
|
||||
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Part name", 40);
|
||||
cdt.AddColumn("Script item ID", 36);
|
||||
cdt.AddColumn("Type", 4);
|
||||
cdt.AddColumn("Interval", 8);
|
||||
cdt.AddColumn("Range", 8);
|
||||
cdt.AddColumn("Arc", 8);
|
||||
|
||||
foreach (SensorRepeat.SensorInfo s in sensorInfo)
|
||||
{
|
||||
cdt.AddRow(s.host.Name, s.itemID, s.type, s.interval, s.range, s.arc);
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
MainConsole.Instance.OutputFormat("Total: {0}", sensorInfo.Count);
|
||||
}
|
||||
|
||||
private void HandleShowTimers(string module, string[] cmdparams)
|
||||
{
|
||||
if (!IsSceneSelected())
|
||||
return;
|
||||
|
||||
Timer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
|
||||
|
||||
if (timerPlugin == null)
|
||||
{
|
||||
MainConsole.Instance.Output("Plugin not yet initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
List<Timer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
|
||||
|
||||
ConsoleDisplayTable cdt = new ConsoleDisplayTable();
|
||||
cdt.AddColumn("Part local ID", 13);
|
||||
cdt.AddColumn("Script item ID", 36);
|
||||
cdt.AddColumn("Interval", 10);
|
||||
cdt.AddColumn("Next", 8);
|
||||
|
||||
foreach (Timer.TimerInfo t in timersInfo)
|
||||
{
|
||||
// Convert from 100 ns ticks back to seconds
|
||||
cdt.AddRow(t.localID, t.itemID, (double)t.interval / 10000000, t.next);
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(cdt.ToString());
|
||||
MainConsole.Instance.OutputFormat("Total: {0}", timersInfo.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -237,6 +237,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
}
|
||||
}
|
||||
|
||||
private ScriptEngineConsoleCommands m_consoleCommands;
|
||||
|
||||
public string ScriptEngineName
|
||||
{
|
||||
get { return "XEngine"; }
|
||||
|
@ -386,50 +388,53 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved;
|
||||
}
|
||||
|
||||
m_consoleCommands = new ScriptEngineConsoleCommands(this);
|
||||
m_consoleCommands.RegisterCommands();
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "xengine status", "xengine status", "Show status information",
|
||||
"Show status information on the script engine.",
|
||||
HandleShowStatus);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
|
||||
"Scripts", false, "scripts show", "scripts show [<script-item-uuid>+]", "Show script information",
|
||||
"Show information on all scripts known to the script engine.\n"
|
||||
+ "If a <script-item-uuid> is given then only information on that script will be shown.",
|
||||
+ "If one or more <script-item-uuid>s are given then only information on that script will be shown.",
|
||||
HandleShowScripts);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information",
|
||||
"Scripts", false, "show scripts", "show scripts [<script-item-uuid>+]", "Show script information",
|
||||
"Synonym for scripts show command", HandleShowScripts);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts",
|
||||
"Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>+]", "Suspends all running scripts",
|
||||
"Suspends all currently running scripts. This only suspends event delivery, it will not suspend a"
|
||||
+ " script that is currently processing an event.\n"
|
||||
+ "Suspended scripts will continue to accumulate events but won't process them.\n"
|
||||
+ "If a <script-item-uuid> is given then only that script will be suspended. Otherwise, all suitable scripts are suspended.",
|
||||
+ "If one or more <script-item-uuid>s are given then only that script will be suspended. Otherwise, all suitable scripts are suspended.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
|
||||
"Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>+]", "Resumes all suspended scripts",
|
||||
"Resumes all currently suspended scripts.\n"
|
||||
+ "Resumed scripts will process all events accumulated whilst suspended.\n"
|
||||
+ "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
|
||||
+ "If one or more <script-item-uuid>s are given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
|
||||
"Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>+]", "Stops all running scripts",
|
||||
"Stops all running scripts.\n"
|
||||
+ "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
|
||||
+ "If one or more <script-item-uuid>s are given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
|
||||
"Scripts", false, "scripts start", "scripts start [<script-item-uuid>+]", "Starts all stopped scripts",
|
||||
"Starts all stopped scripts.\n"
|
||||
+ "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
|
||||
+ "If one or more <script-item-uuid>s are given then only that script will be started. Otherwise, all suitable scripts are started.",
|
||||
(module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand(
|
||||
"Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
|
||||
"Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
|
||||
"Activates or deactivates extra debug logging for the given script.\n"
|
||||
+ "Level == 0, deactivate extra debug logging.\n"
|
||||
+ "Level >= 1, log state changes.\n"
|
||||
|
@ -546,29 +551,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
|||
return;
|
||||
}
|
||||
|
||||
rawItemId = cmdparams[2];
|
||||
|
||||
if (!UUID.TryParse(rawItemId, out itemId))
|
||||
for (int i = 2; i < cmdparams.Length; i++)
|
||||
{
|
||||
MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (itemId != UUID.Zero)
|
||||
{
|
||||
IScriptInstance instance = GetInstance(itemId);
|
||||
if (instance == null)
|
||||
rawItemId = cmdparams[i];
|
||||
|
||||
if (!UUID.TryParse(rawItemId, out itemId))
|
||||
{
|
||||
// Commented out for now since this will cause false reports on simulators with more than
|
||||
// one scene where the current command line set region is 'root' (which causes commands to
|
||||
// go to both regions... (sigh)
|
||||
// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
|
||||
return;
|
||||
MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
if (itemId != UUID.Zero)
|
||||
{
|
||||
action(instance);
|
||||
return;
|
||||
IScriptInstance instance = GetInstance(itemId);
|
||||
if (instance == null)
|
||||
{
|
||||
// Commented out for now since this will cause false reports on simulators with more than
|
||||
// one scene where the current command line set region is 'root' (which causes commands to
|
||||
// go to both regions... (sigh)
|
||||
// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
action(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue