public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
{
if (!LinksetRoot.IsPhysicallyActive)
{
// No reason to do this physical stuff for static linksets.
DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
return;
}
// The user moving a child around requires the rebuilding of the linkset compound shape
// One problem is this happens when a border is crossed -- the simulator implementation
// stores the position into the group which causes the move of the object
// but it also means all the child positions get updated.
// What would cause an unnecessary rebuild so we make sure the linkset is in a
// region before bothering to do a rebuild.
if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
{
// If a child of the linkset is updating only the position or rotation, that can be done
// without rebuilding the linkset.
// If a handle for the child can be fetch, we update the child here. If a rebuild was
// scheduled by someone else, the rebuild will just replace this setting.
bool updatedChild = false;
// Anything other than updating position or orientation usually means a physical update
// and that is caused by us updating the object.
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
{
// Find the physical instance of the child
if (!RebuildScheduled && !LinksetRoot.IsIncomplete && LinksetRoot.PhysShape.HasPhysicalShape &&
PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
{
// It is possible that the linkset is still under construction and the child is not yet
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
// build the whole thing with the new position or rotation.
// The index must be checked because Bullet references the child array but does no validity
// checking of the child index passed.
int numLinksetChildren =
PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
if (updated.LinksetChildIndex < numLinksetChildren)
{
BulletShape linksetChildShape =
PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo,
updated.LinksetChildIndex);
if (linksetChildShape.HasPhysicalShape)
{
// Found the child shape within the compound shape
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo,
updated.LinksetChildIndex,
updated.RawPosition - LinksetRoot.RawPosition,
updated.RawOrientation*OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
true /* shouldRecalculateLocalAabb */);
updatedChild = true;
DetailLog(
"{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
}
else // DEBUG DEBUG
{
// DEBUG DEBUG
DetailLog(
"{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
updated.LocalID, linksetChildShape);
} // DEBUG DEBUG
}
else // DEBUG DEBUG
{
// DEBUG DEBUG
// the child is not yet in the compound shape. This is non-fatal.
DetailLog(
"{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
} // DEBUG DEBUG
}
else // DEBUG DEBUG
{
// DEBUG DEBUG
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound",
updated.LocalID);
} // DEBUG DEBUG
if (!updatedChild)
{
// If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info.
// Note: there are several ways through this code that will not update the child if
// the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since
// there will already be a rebuild scheduled.
DetailLog(
"{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
updated.LocalID, whichUpdated);
Refresh(updated);
}
}
}
}