Added the sharedObject library

This commit is contained in:
Anonymous
2014-01-14 09:22:49 -07:00
parent 2931511f72
commit f4243cffeb
229 changed files with 32864 additions and 2 deletions
@@ -0,0 +1,196 @@
set(SHARED_SOURCES
shared/ObjectWatcherList.cpp
shared/ObjectWatcherList.h
shared/appearance/Appearance.cpp
shared/appearance/Appearance.h
shared/appearance/AppearanceTemplate.cpp
shared/appearance/AppearanceTemplate.h
shared/appearance/AppearanceTemplateList.cpp
shared/appearance/AppearanceTemplateList.h
shared/appearance/Hardpoint.cpp
shared/appearance/Hardpoint.h
shared/appearance/NoRenderAppearance.cpp
shared/appearance/NoRenderAppearance.h
shared/appearance/NoRenderAppearanceTemplate.cpp
shared/appearance/NoRenderAppearanceTemplate.h
shared/appearance/TextAppearance.cpp
shared/appearance/TextAppearance.h
shared/appearance/Tweakable.cpp
shared/appearance/Tweakable.h
shared/container/ArrangementDescriptor.cpp
shared/container/ArrangementDescriptor.h
shared/container/ArrangementDescriptorList.cpp
shared/container/ArrangementDescriptorList.h
shared/container/ContainedByProperty.cpp
shared/container/ContainedByProperty.h
shared/container/Container.cpp
shared/container/Container.h
shared/container/SlotDescriptor.cpp
shared/container/SlotDescriptor.h
shared/container/SlotDescriptorList.cpp
shared/container/SlotDescriptorList.h
shared/container/SlotIdArchive.h
shared/container/SlotId.cpp
shared/container/SlotId.h
shared/container/SlotIdManager.cpp
shared/container/SlotIdManager.h
shared/container/SlottedContainer.cpp
shared/container/SlottedContainer.h
shared/container/SlottedContainmentProperty.cpp
shared/container/SlottedContainmentProperty.h
shared/container/SlotType.def
shared/container/VolumeContainer.cpp
shared/container/VolumeContainer.h
shared/container/VolumeContainmentProperty.cpp
shared/container/VolumeContainmentProperty.h
shared/controller/Controller.cpp
shared/controller/Controller.h
shared/controller/NetworkController.cpp
shared/controller/NetworkController.h
shared/controller/ObjectSetMessage.def
shared/controller/ObjectSetMessage.h
shared/core/ConfigSharedObject.cpp
shared/core/ConfigSharedObject.h
shared/core/FirstSharedObject.h
shared/core/SetupSharedObject.cpp
shared/core/SetupSharedObject.h
shared/customization/BasicRangedIntCustomizationVariable.cpp
shared/customization/BasicRangedIntCustomizationVariable.h
shared/customization/CustomizationData.cpp
shared/customization/CustomizationData_Directory.h
shared/customization/CustomizationData.h
shared/customization/CustomizationData_LocalDirectory.cpp
shared/customization/CustomizationData_LocalDirectory.h
shared/customization/CustomizationData_RemoteDirectory.cpp
shared/customization/CustomizationData_RemoteDirectory.h
shared/customization/CustomizationIdManager.cpp
shared/customization/CustomizationIdManager.h
shared/customization/CustomizationVariable.cpp
shared/customization/CustomizationVariable.h
shared/customization/ObjectTemplateCustomizationDataWriter.cpp
shared/customization/ObjectTemplateCustomizationDataWriter.h
shared/customization/PaletteColorCustomizationVariable.cpp
shared/customization/PaletteColorCustomizationVariable.h
shared/customization/RangedIntCustomizationVariable.cpp
shared/customization/RangedIntCustomizationVariable.h
shared/dynamics/Dynamics.cpp
shared/dynamics/Dynamics.h
shared/dynamics/RotationDynamics.cpp
shared/dynamics/RotationDynamics.h
shared/dynamics/SeesawDynamics.cpp
shared/dynamics/SeesawDynamics.h
shared/dynamics/SimpleDynamics.cpp
shared/dynamics/SimpleDynamics.h
shared/dynamics/SpringDynamics.cpp
shared/dynamics/SpringDynamics.h
shared/dynamics/StateDynamics.cpp
shared/dynamics/StateDynamics.h
shared/dynamics/TrackingDynamics.cpp
shared/dynamics/TrackingDynamics.h
shared/lot/LotManager.cpp
shared/lot/LotManager.h
shared/lot/LotType.h
shared/lot/StructureFootprint.cpp
shared/lot/StructureFootprint.h
shared/movement/MovementTable.cpp
shared/movement/MovementTable.h
shared/object/AlterResult.cpp
shared/object/AlterResult.h
shared/object/AlterScheduler.cpp
shared/object/AlterScheduler.h
shared/object/CachedNetworkIdArchive.h
shared/object/CachedNetworkId.cpp
shared/object/CachedNetworkId.h
shared/object/DebugNotification.cpp
shared/object/DebugNotification.h
shared/object/DebugYawedFloorNotification.cpp
shared/object/DebugYawedFloorNotification.h
shared/object/MemoryBlockManagedObject.cpp
shared/object/MemoryBlockManagedObject.h
shared/object/NetworkIdManager.cpp
shared/object/NetworkIdManager.h
shared/object/Object.cpp
shared/object/Object.h
shared/object/ObjectList.cpp
shared/object/ObjectList.h
shared/object/ObjectNotification.cpp
shared/object/ObjectNotification.h
shared/object/ObjectTemplate.cpp
shared/object/ObjectTemplate.h
shared/object/ObjectTemplateList.cpp
shared/object/ObjectTemplateList.h
shared/object/ScheduleData.cpp
shared/object/ScheduleData.h
shared/portal/CellProperty.cpp
shared/portal/CellProperty.h
shared/portal/Portal.cpp
shared/portal/Portal.h
shared/portal/PortallizedSphereTree.h
shared/portal/PortalProperty.cpp
shared/portal/PortalProperty.h
shared/portal/PortalPropertyTemplate.cpp
shared/portal/PortalPropertyTemplate.h
shared/portal/PortalPropertyTemplateList.cpp
shared/portal/PortalPropertyTemplateList.h
shared/portal/SphereGrid.h
shared/property/CustomizationDataProperty.cpp
shared/property/CustomizationDataProperty.h
shared/property/LayerProperty.cpp
shared/property/LayerProperty.h
shared/property/Property.cpp
shared/property/Property.h
shared/property/PropertyId.h
shared/world/World.cpp
shared/world/World.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/FirstSharedObject.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES "")
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCollision/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedGame/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedRandom/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedTerrain/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
)
add_library(sharedObject STATIC
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,457 @@
// ======================================================================
//
// ObjectWatcherList.cpp
// Portions copyright 1998 Bootprint Entertainment
// Portions copyright 2001, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ObjectWatcherList.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/Appearance.h"
#include "sharedObject/Object.h"
#include "sharedFoundation/Watcher.h"
#include <vector>
// ======================================================================
namespace ObjectWatcherListNamespace
{
void setRegionOfInfluenceEnabled(Object const * const object, bool const enabled, bool skipCell)
{
if (skipCell && NULL != object->getCellProperty())
return;
object->setRegionOfInfluenceEnabled(enabled);
for (int i = 0; i < object->getNumberOfChildObjects(); ++i)
setRegionOfInfluenceEnabled(object->getChildObject(i), enabled, skipCell);
}
}
// ======================================================================
// Construct an ObjectWatcherList
ObjectWatcherList::ObjectWatcherList (int initialVectorSize) :
m_altering (false),
m_objectVector (new ObjectVector),
m_alterSafeObjectVector (new ObjectVector),
m_skipCellRegionOfInfluence(false)
{
DEBUG_FATAL(initialVectorSize < 0, ("negative vector size"));
// Reserve the requested amount of entries to reduce further allocation
m_objectVector->reserve (static_cast<size_t> (initialVectorSize));
m_alterSafeObjectVector->reserve (static_cast<size_t> (initialVectorSize));
}
// ----------------------------------------------------------------------
/**
* Destroy an ObjectWatcherList.
*/
ObjectWatcherList::~ObjectWatcherList(void)
{
delete m_objectVector;
m_objectVector = 0;
delete m_alterSafeObjectVector;
m_alterSafeObjectVector = 0;
}
// ----------------------------------------------------------------------
/**
* Add an Object to the ObjectWatcherList.
*
* This routine will call Fatal in debug compiles if it is passed a NULL
* object.
*
* This routine will call Fatal in debug compiles if the object list
* overflows.
*
* @param objectToAdd Object to add to the ObjectWatcherList
*/
void ObjectWatcherList::addObject(Object & objectToAdd)
{
m_objectVector->push_back(Watcher<Object>(&objectToAdd));
}
// ----------------------------------------------------------------------
/**
* Remove an Object from the ObjectWatcherList.
*
* This routine will call Fatal in debug compiles if it is passed a NULL
* object.
*
* @param objectToRemove Pointer to the object to remove
*/
void ObjectWatcherList::removeObject(const Object & objectToRemove)
{
int index = 0;
if (find(objectToRemove, &index))
removeObjectByIndex(objectToRemove, index);
}
// ----------------------------------------------------------------------
void ObjectWatcherList::removeObjectByIndex (const Object & object, int index)
{
DEBUG_FATAL(index >= static_cast<int>(m_objectVector->size()), ("Index out of range"));
DEBUG_FATAL((*m_objectVector)[static_cast<ObjectVector::size_type>(index)] != &object, ("Object is not the one indexed."));
// Replace the found entry with the entry from the back of the vector
// so there is no shifting of the items in the vector.
(*m_objectVector)[static_cast<ObjectVector::size_type>(index)] = m_objectVector->back();
// Remove the last item in the vector.
m_objectVector->pop_back();
// NULL the object from the alter-safe object list.
uint size = m_alterSafeObjectVector->size();
for (uint i = 0; i < size; ++i)
{
if ((*m_alterSafeObjectVector)[i] == &object)
{
(*m_alterSafeObjectVector)[i] = NULL;
return;
}
}
}
// ----------------------------------------------------------------------
/**
* Remove all Objects from the ObjectWatcherList.
*
* Removes all Objects from the ObjectWatcherList
*
* This routine may not be called between prepareToAlter() and alter().
*
* If deleteObjects is true, this routine will call delete for all objects in the list
*
* @param deleteObjects Flag to delete all objects when they are removed
*/
void ObjectWatcherList::removeAll (bool deleteObjects)
{
DEBUG_FATAL(m_altering, ("m_altering"));
if (deleteObjects)
{
ObjectVector::iterator end = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != end; ++i)
delete i->getPointer();
}
m_objectVector->clear();
}
// ----------------------------------------------------------------------
void ObjectWatcherList::addToWorld()
{
ObjectVector::iterator iEnd = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != iEnd; ++i)
{
Object * const object = (*i);
if (object)
object->addToWorld();
}
}
// ----------------------------------------------------------------------
void ObjectWatcherList::removeFromWorld()
{
ObjectVector::iterator iEnd = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != iEnd; ++i)
{
Object * const object = (*i);
if (object)
object->removeFromWorld();
}
}
// ----------------------------------------------------------------------
/**
* Prepare to call alter() on this object list.
*
* This routine must be called before calling alter(). It will copy setup
* the ObjectWatcherList so that objects may be added and removed from the ObjectWatcherList
* during the alter() without affecting that frame's list of objects that are
* are being altered.
*/
void ObjectWatcherList::prepareToAlter(void)
{
DEBUG_FATAL(m_altering, ("m_altering"));
m_altering = true;
// Duplicate the object vector
(*m_alterSafeObjectVector) = (*m_objectVector);
}
// ----------------------------------------------------------------------
/**
* Call alter() for all objects in the ObjectWatcherList.
*
* prepareToAlter() must be called before this routine can be called.
*
* This routine will simply iterate over all the objects in the ObjectWatcherList
* and call their alter routines with the specified time.
*
* @param time Time to pass to each Object's alter routine
* @see ObjectWatcherList::prepareToAlter()
*/
void ObjectWatcherList::alter(real time)
{
DEBUG_FATAL(!m_altering, ("prepareToAlter was not called"));
for (size_t i = 0; i < m_alterSafeObjectVector->size(); ++i)
{
// Cache the object pointer because the iter value may be nulled if the object,
// is removed from the list withing its alter()
Object * const obj = (*m_alterSafeObjectVector)[i];
if (!obj || !obj->isInitialized())
continue;
float const alterResult = obj->alter(time);
if (alterResult == AlterResult::cms_kill)
{
// alter() return false, so remove and delete the object
// Make sure the object is still in the object list before removing it
if ((*m_alterSafeObjectVector)[i] != NULL)
{
removeObject(*obj);
}
delete obj;
}
}
m_alterSafeObjectVector->clear();
m_altering = false;
}
// ----------------------------------------------------------------------
/**
* Call conclude() for all objects in the ObjectWatcherList.
*
* This routine may not be called between prepareToAlter() and alter().
*
* This routine will simply iterate over all the objects in the ObjectWatcherList
* and call their conclude routines with the specified time.
*/
void ObjectWatcherList::conclude()
{
DEBUG_FATAL(m_altering, ("m_altering"));
ObjectVector::iterator end = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != end; ++i)
{
Object * const object = (*i);
if (object && object->isInitialized())
object->conclude();
}
}
// ----------------------------------------------------------------------
/**
* Call addToScene() for all objects in the ObjectWatcherList.
*
* This routine may not be called between prepareToAlter() and alter().
*
* This routine will simply iterate over all the objects in the ObjectWatcherList
* and call their addToScene() routine with the specified camera.
*
* @param camera Camera rendering the scene.
* @param excludedObject Object to exclude from the scene.
*/
void ObjectWatcherList::setRegionOfInfluenceEnabled(bool enabled) const
{
ObjectVector::iterator end = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != end; ++i)
{
Object const * const object = (*i);
if (object)
ObjectWatcherListNamespace::setRegionOfInfluenceEnabled(object, enabled, m_skipCellRegionOfInfluence);
}
}
// ----------------------------------------------------------------------
/**
* Call addToScene() for all objects in the ObjectWatcherList.
*
* This routine may not be called between prepareToAlter() and alter().
*
* This routine will simply iterate over all the objects in the ObjectWatcherList
* and call their addToScene() routine with the specified camera.
*
* @param camera Camera rendering the scene.
* @param excludedObject Object to exclude from the scene.
*/
void ObjectWatcherList::render(const Object *excludedObject) const
{
DEBUG_FATAL(m_altering, ("m_altering"));
const ObjectVector::iterator end = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != end; ++i)
{
Object *const object = *i;
if (object && (object != excludedObject))
{
const Appearance *const appearance = object->getAppearance();
if (appearance)
{
appearance->setTransform_w(object->getTransform_o2w());
appearance->objectListCameraRender();
}
}
}
}
// ----------------------------------------------------------------------
/**
* Find the index of an object in an object list.
*
* Accepts an optional index to be used to return the object's index
* in the object list.
*
* This routine will simply iterate over all the objects in the ObjectWatcherList
* searching for the objectToCheck, and returns true with the index if
* found, and false otherwise.
*
* @param objectToCheck Object to find
* @param index Object's index in the object list
*/
bool ObjectWatcherList::find(const Object & objectToCheck, int *index) const
{
ObjectVector::iterator end = m_objectVector->end();
for (ObjectVector::iterator i = m_objectVector->begin(); i != end; ++i)
{
const Object * const obj = (*i);
if (obj == &objectToCheck)
{
if (index)
*index = std::distance(m_objectVector->begin(), i);
return true;
}
}
return false;
}
//----------------------------------------------------------------------
int ObjectWatcherList::removeNulls ()
{
int count = 0;
for (ObjectVector::iterator i = m_objectVector->begin(); i != m_objectVector->end();)
{
const Object * const obj = (*i);
if (obj)
++i;
else
{
++count;
i = m_objectVector->erase (i);
}
}
return count;
}
// ----------------------------------------------------------------------
/**
* Return the number of objects contained in the object list.
*
* @return The number of objects contained in the object list
*/
int ObjectWatcherList::getNumberOfObjects(void) const
{
return static_cast<int> (m_objectVector->size());
}
// ----------------------------------------------------------------------
/**
* Get an object in the object list.
*
* @param index Index of the object in the object list
*/
Object *ObjectWatcherList::operator [](int index)
{
DEBUG_FATAL(index < 0 || index >= getNumberOfObjects(), ("index out of range %d/%d", index, getNumberOfObjects()));
return (*m_objectVector)[static_cast<unsigned int> (index)];
}
// ----------------------------------------------------------------------
/**
* Get a const object from the object list.
*
* @param index Index of the object in the object list
*/
const Object *ObjectWatcherList::operator [](int index) const
{
DEBUG_FATAL(index < 0 || index >= getNumberOfObjects(), ("index out of range %d/%d", index, getNumberOfObjects()));
return (*m_objectVector)[static_cast<unsigned int> (index)];
}
// ----------------------------------------------------------------------
/**
* Get an object in the object list.
*
* @param index Index of the object in the object list
*/
Object *ObjectWatcherList::getObject(int index)
{
DEBUG_FATAL(index < 0 || index >= getNumberOfObjects(), ("index out of range %d/%d", index, getNumberOfObjects()));
return (*m_objectVector)[static_cast<unsigned int> (index)];
}
// ----------------------------------------------------------------------
/**
* Get a const object from the object list.
*
* @param index Index of the object in the object list
*/
const Object *ObjectWatcherList::getObject(int index) const
{
DEBUG_FATAL(index < 0 || index >= getNumberOfObjects(), ("index out of range %d/%d", index, getNumberOfObjects()));
return (*m_objectVector)[static_cast<unsigned int> (index)];
}
//----------------------------------------------------------------------
void ObjectWatcherList::setSkipCellRegionOfInfluence(bool skip)
{
m_skipCellRegionOfInfluence = skip;
}
// ======================================================================
@@ -0,0 +1,76 @@
// ======================================================================
//
// ObjectWatcherList.h
// copyright 2002, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ObjectWatcherList_H
#define INCLUDED_ObjectWatcherList_H
// ======================================================================
template <typename T> class Watcher;
class Object;
class Camera;
// ======================================================================
// Contain a list of watchers to objects.
//
// Objects may exist in more than one ObjectWatcherList simultaneously.
class ObjectWatcherList
{
public:
explicit ObjectWatcherList (int initialVectorSize=0);
~ObjectWatcherList ();
void addObject (Object & object);
void removeObject (const Object & object);
int removeNulls ();
void removeAll (bool deleteObjects=false);
int getNumberOfObjects () const;
Object * getObject (int index);
const Object * getObject (int index) const;
Object * operator [] (int index);
const Object * operator [] (int index) const;
bool find (const Object & objectToCheck, int* index=0) const;
void removeObjectByIndex (const Object &, int index);
void addToWorld ();
void removeFromWorld ();
void prepareToAlter ();
void alter (real time);
void conclude ();
void setRegionOfInfluenceEnabled (bool enabled) const;
void render (const Object *omitObject) const;
void setSkipCellRegionOfInfluence(bool skip);
private:
typedef stdvector<Watcher<Object> >::fwd ObjectVector;
bool m_altering;
ObjectVector * m_objectVector;
ObjectVector * m_alterSafeObjectVector;
bool m_skipCellRegionOfInfluence;
private:
// disable these routines
ObjectWatcherList (const ObjectWatcherList &);
ObjectWatcherList & operator = (const ObjectWatcherList &);
};
// ======================================================================
#endif
@@ -0,0 +1,896 @@
// ======================================================================
//
// Appearance.cpp
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Appearance.h"
#include "sharedCollision/CollideParameters.h"
#include "sharedCollision/ExtentList.h"
#include "sharedCollision/Extent.h"
#include "sharedCollision/FloorManager.h"
#include "sharedCollision/Floor.h"
#include "sharedCollision/CollisionProperty.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedMath/AxialBox.h"
#include "sharedMath/DebugShapeRenderer.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/AppearanceTemplate.h"
#include "sharedObject/AppearanceTemplateList.h"
#include "sharedObject/CellProperty.h"
#include "sharedObject/CustomizationData.h"
#include "sharedObject/CustomizationDataProperty.h"
#include "sharedObject/Hardpoint.h"
#include "sharedObject/Object.h"
// ======================================================================
namespace AppearanceNamespace
{
#ifdef _DEBUG
bool ms_drawAppearanceFrames;
#endif
int ms_frameNumber;
bool ms_renderHardpoints;
bool ms_renderHardpointNames;
Appearance::RenderHardpointFunction ms_renderHardpointFunction;
bool s_renderEnabled = true;
//----------------------------------------------------------------------
}
using namespace AppearanceNamespace;
// ======================================================================
void Appearance::install()
{
#ifdef _DEBUG
DebugFlags::registerFlag(ms_drawAppearanceFrames, "SharedObject", "drawAppearanceFrames");
DebugFlags::registerFlag(ms_renderHardpoints, "SharedObject", "renderHardpoints");
DebugFlags::registerFlag(ms_renderHardpointNames, "SharedObject", "renderHardpointNames");
#endif
}
// ----------------------------------------------------------------------
void Appearance::beginNewFrame()
{
++ms_frameNumber;
}
// ----------------------------------------------------------------------
void Appearance::setRenderHardpointFunction(RenderHardpointFunction renderHardpointFunction)
{
ms_renderHardpointFunction = renderHardpointFunction;
}
// ======================================================================
// Construct a new Appearance
Appearance::Appearance(const AppearanceTemplate *newAppearanceTemplate) :
m_appearanceTemplate(AppearanceTemplateList::fetch(newAppearanceTemplate)),
m_extent(m_appearanceTemplate ? ExtentList::fetch(m_appearanceTemplate->getExtent()) : NULL),
m_owner(NULL),
m_renderedFrameNumber(0),
m_scale(Vector::xyz111),
m_keepAlive(false),
m_useRenderEffectsFlag(false),
m_shadowBlobAllowed(false)
{
}
// ----------------------------------------------------------------------
/**
* Destroy an Appearance.
*
* This routine will release the AppearanceTemplate used by this Appearance.
*/
Appearance::~Appearance()
{
ExtentList::release(m_extent);
m_extent = NULL;
if (m_appearanceTemplate)
{
AppearanceTemplateList::release(m_appearanceTemplate);
m_appearanceTemplate = NULL;
}
m_owner = NULL;
}
// ----------------------------------------------------------------------
/**
* Check if the data for this appearance has been loaded.
*/
bool Appearance::isLoaded() const
{
return true;
}
// ----------------------------------------------------------------------
/**
* Alter the appearance specifying the amount of time that has passed.
*
* This routine can be used to modify the appearance before it's rendered
*/
float Appearance::alter(float deltaTime)
{
UNREF(deltaTime);
return (isAlive() ? AlterResult::cms_keepNoAlter : AlterResult::cms_kill);
}
// ----------------------------------------------------------------------
/**
* Get an Extent to be used for selection of this object in tools
*
* This routine may be overloaded in derived classes.
*/
const Extent *Appearance::getSelectionExtent() const
{
return getExtent();
}
// ----------------------------------------------------------------------
/**
* Get the Extent of this Appearance.
*
* This routine may be overloaded in derived classes.
*/
const Extent *Appearance::getExtent() const
{
return m_extent;
}
// ----------------------------------------------------------------------
/**
* Set a new Extent for this Appearance.
*
* The current extent will be released.
*
* @param newExtent New extent for this Appearance
*/
void Appearance::setExtent(const Extent *extent)
{
ExtentList::release(m_extent);
m_extent = extent;
extentChanged();
}
// ----------------------------------------------------------------------
/**
* Get the tangible axial box, if applicable, for systems such as targeting.
* Derived appearances can choose how much of the appearance contributes.
*/
AxialBox const Appearance::getTangibleExtent() const
{
return AxialBox();
}
// ----------------------------------------------------------------------
/**
* Return the bounding sphere for the Appearance.
*
* This routine may be overloaded in derived classes. By default it
* gets the spheere from its extents. If the extent doesn't exist, it
* returns the zero sphere
*
* @return The bounding sphere in object space.
*/
const Sphere &Appearance::getSphere() const
{
const Extent *const extent = getExtent();
return extent ? extent->getSphere() : Sphere::zero;
}
// ----------------------------------------------------------------------
void Appearance::addToWorld()
{
DPVS::Object *dpvsObject = getDpvsObject();
if (dpvsObject)
{
NOT_NULL(m_owner);
m_owner->addDpvsObject(dpvsObject);
}
}
// ----------------------------------------------------------------------
void Appearance::removeFromWorld()
{
DPVS::Object *dpvsObject = getDpvsObject();
if (dpvsObject)
{
Object *owner = getOwner();
if (owner)
{
owner->removeDpvsObject(dpvsObject);
}
}
}
// ----------------------------------------------------------------------
void Appearance::preRender() const
{
}
// ----------------------------------------------------------------------
void Appearance::render() const
{
#ifdef _DEBUG
const Object *owner = getOwner();
if (owner)
{
DebugShapeRenderer * const renderer = DebugShapeRenderer::create(owner);
drawDebugShapes(renderer);
delete renderer;
if (ms_renderHardpoints && ms_renderHardpointFunction)
{
for (int i = 0; i < getHardpointCount(); ++i)
{
Hardpoint const & hardpoint = getHardpoint(i);
Transform transform_h2w;
transform_h2w.multiply(getTransform_w(), hardpoint.getTransform());
ms_renderHardpointFunction(transform_h2w, ms_renderHardpointNames, hardpoint.getName().getString());
}
}
}
#endif
}
//----------------------------------------------------------------------
void Appearance::objectListCameraRenderDescend(Object const & obj)
{
//-- don't descend through cells
if (NULL != obj.getCellProperty())
return;
int const childCount = obj.getNumberOfChildObjects();
for (int i = 0; i < childCount; ++i)
{
// Get the child object.
Object const *const childObject = obj.getChildObject(i);
if (!childObject)
continue;
if (!childObject->isActive())
continue;
// Setup child object appearance to world transform.
const_cast<Object*>(childObject)->setTransform_a2w(childObject->getTransform_o2w());
// Render its appearance.
const Appearance *const childAppearance = childObject->getAppearance();
if (childAppearance)
childAppearance->objectListCameraRender();
else
objectListCameraRenderDescend(*childObject);
}
}
// ----------------------------------------------------------------------
void Appearance::objectListCameraRender() const
{
if (!usesRenderEffectsFlag() || canRenderEffects())
{
//-- Render this appearance.
render();
setRenderedThisFrame();
//-- Render the owner's child objects.
Object const *const owner = getOwner();
if (!owner)
return;
int const childCount = owner->getNumberOfChildObjects();
for (int i = 0; i < childCount; ++i)
{
// Get the child object.
Object const *const childObject = owner->getChildObject(i);
if (!childObject)
continue;
if (!childObject->isActive())
continue;
const Appearance *const childAppearance = childObject->getAppearance();
if (childAppearance)
{
// Setup child object appearance to world transform.
childAppearance->setTransform_w(childObject->getTransform_o2w());
// Render its appearance.
childAppearance->objectListCameraRender();
}
else
objectListCameraRenderDescend(*childObject);
}
}
}
// ----------------------------------------------------------------------
void Appearance::setTexture(Tag /*tag*/, const Texture & /*texture*/)
{
}
// ----------------------------------------------------------------------
/**
* Cast a ray through object space and return the result of the collision (if any) to result
*
* @param start_o Object space start position of the ray
* @param end_o Object space end position of the ray
* @param collideParameters Struct which contains information about the type and quality of collision
* @param result Struct which contains information about the collision
* @return Whether or not a collision occurred
*/
bool Appearance::collide(Vector const & /*start_o*/, Vector const & /*end_o*/, CollideParameters const & /*collideParameters*/, CollisionInfo & /*result*/) const
{
return false;
}
// ----------------------------------------------------------------------
bool Appearance::implementsCollide() const
{
return false;
}
// ----------------------------------------------------------------------
/**
* Set the new owning object associated with this appearance.
*
* There is a 1-1 correpsondence between Object instances and Appearance
* instances. This function is called to set the Object instance
* associated with this Appearance instance.
*
* This implementation checks the owner Object instance for a
* CustomizationDataProperty. If there is such a property, this
* function will invoke Appearance::setCustomizationData() with the
* appropriate value. If the property doesn't exist, this function
* will invoke Appearance::setCustomizationData() with NULL. Note if
* the caller sets the CustomizationDataProperty for an Object after
* associating the Object instance with the appearance, the caller is
* responsible for calling Appearance::setCustomizationData().
*
* Implementers overriding this function must ensure they chain back
* to this function as it performs necessary state modification.
*
* -TRF- I'm not sure why this is virtual. I think this probably needs
* to be made non virtual. Currently it is mandatory for descendants
* that override this function to chain back to this function to handle
* the CustomizationData setup.
*/
void Appearance::setOwner(Object* owner)
{
//-- keep track of owner object.
m_owner = owner;
// DBE - This was added to mimic the behavior of when the appearance-to-world
// transform was stored in Object instead of Appearance.
if (owner)
{
Appearance *ownerAppearance = owner->getAppearance();
if (!ownerAppearance)
{
setTransform_w(owner->getTransform_o2w());
}
else if (ownerAppearance!=this)
{
setTransform_w(ownerAppearance->getTransform_w());
}
}
//-- retrieve customization data for new owner
CustomizationData *customizationData = 0;
if (owner)
{
// get the property
CustomizationDataProperty *const property = safe_cast<CustomizationDataProperty*>(owner->getProperty(CustomizationDataProperty::getClassPropertyId()));
if (property)
{
// retrieve the customization data from the property
customizationData = property->fetchCustomizationData();
}
}
//-- set the CustomizationData
setCustomizationData(customizationData);
//-- release local reference
if (customizationData)
customizationData->release();
//-- clear the rendered frame number
m_renderedFrameNumber = 0;
}
// ----------------------------------------------------------------------
void Appearance::setAlpha(bool const /* opaqueEnabled */, float const /* opaqueAlpha*/, bool const /* alphaEnabled */, float const /* alphaAlpha */)
{
}
// ----------------------------------------------------------------------
void Appearance::setTransform_w(const Transform &t) const
{
m_appearanceToWorld=t;
}
// ----------------------------------------------------------------------
const char * Appearance::getFloorName () const
{
if (m_appearanceTemplate)
return m_appearanceTemplate->getFloorName();
return NULL;
}
// ----------------------------------------------------------------------
/**
* Set the CustomizationData associated with this Appearance instance.
*
* This function's primary purpose is to be overridden. It allows
* derived Appearance classes to do something with the CustomizationData
* when the CustomizationData instance is set or changed. The CustomizationData
* instance changes when the owning Object is initially set or changed
* to a new Object instance.
*
* Derived classes are not required to chain call this function.
*
* Callers need only invoke this function directly if CustomizationData
* is initialized for the owning Object after Appearance::setOwner() is
* called. The only feasible time this should happen is when the Object
* and Appearance instances are created and associated prior to creation
* of CustomizationData.
*
* @param customizationData the new CustomizationData instance associated
* with this Appearance instance.
*/
void Appearance::setCustomizationData(CustomizationData * /* customizationData */)
{
}
// ----------------------------------------------------------------------
/**
* Add all CustomizationData variables influencing this Appearance instance
* to the given CustomizationData instance.
*
* This is primarily useful as a mechanism for tools. The game should already
* know which customization variables it has enabled for objects via the
* ObjectTemplate system.
*
* Derived classes do not need to chain down to this function.
*
* Implementers: there are no guarantees as to the order of calls between
* setCustomizationData() and this function. In other words, the implementation
* should use the given CustomizationData arg to add variables.
*
* @param customizationData the CustomizationData instance to which new
* variables will be added. Assumed to be empty
* on entry.
*/
void Appearance::addCustomizationVariables(CustomizationData & /* customizationData */) const
{
}
// ----------------------------------------------------------------------
void Appearance::setKeepAlive(bool const keepAlive)
{
m_keepAlive = keepAlive;
}
// ----------------------------------------------------------------------
bool Appearance::isAlive() const
{
return m_keepAlive ? true : realIsAlive();
}
// ----------------------------------------------------------------------
bool Appearance::realIsAlive() const
{
return true;
}
// ----------------------------------------------------------------------
/**
* Find and return the transform for the given hardpoint.
*
* The transform is returned in local Object (Appearance) space. It is a
* hardpoint-to-Object transform.
*
* Note in the general case, it is not safe to look up an index for
* a hardpoint and then use the index. For skeletal appearances, indices
* change when wearables are applied. Name lookup is a must when
* possibly dealing with skeletal appearances.
*
* @param hardpointName the name of the hardpoint to look up.
* @param hardpointTransform the result is returned in this parameter
* upon successful completion.
*
* @return true if the hardpoint with the given name was found; false
* otherwise.
*/
bool Appearance::findHardpoint(CrcString const &hardpointName, Transform &hardpointTransform) const
{
// There are no hardpoints if there is no appearance template.
if (!m_appearanceTemplate)
return false;
//-- The default implementation is to lookup the hardpoint via the appearance template.
const int hardpointIndex = getHardpointIndex(hardpointName, true);
if (hardpointIndex < 0)
return false;
else
{
//-- Handle the appearance scale.
Transform scaleTransform(Transform::IF_none);
scaleTransform.setToScale(m_scale);
//-- Get the hardpoint transform from the hardpoint object.
const Hardpoint &hardpoint = getHardpoint(hardpointIndex);
hardpointTransform.multiply(scaleTransform, hardpoint.getTransform());
return true;
}
}
// ----------------------------------------------------------------------
/**
* Notify this Appearance of a change in scale.
*
* Implementers of derived classes should chain down to this function to
* ensure that the internal scale variable is set.
*
* @param scale the new scale factor, where a scale of (1,1,1) is equivalent to not scaling.
*/
void Appearance::setScale(const Vector &scale)
{
Vector const oldValue = m_scale;
m_scale = scale;
onScaleModified(oldValue, m_scale);
}
// ----------------------------------------------------------------------
const char * Appearance::getAppearanceTemplateName () const
{
if (m_appearanceTemplate)
return m_appearanceTemplate->getName ();
else
return 0;
}
// ----------------------------------------------------------------------
DPVS::Object *Appearance::getDpvsObject() const
{
return NULL;
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
bool Appearance::debugRenderingEnabled() const
{
return true;
}
#endif
// ----------------------------------------------------------------------
#ifdef _DEBUG
void Appearance::drawDebugShapes(DebugShapeRenderer * renderer) const
{
if (renderer && debugRenderingEnabled())
{
if(m_appearanceTemplate)
m_appearanceTemplate->drawDebugShapes(renderer);
if (ms_drawAppearanceFrames)
renderer->drawFrame(1.0f);
const Object *owner = getOwner();
if (owner)
{
CollisionProperty const * collision = owner->getCollisionProperty();
if(collision)
collision->drawDebugShapes(renderer);
Object const * parent = owner->getParent();
if (parent)
{
CellProperty const * cellProperty = parent->getCellProperty();
if (cellProperty)
cellProperty->drawDebugShapes(renderer);
}
}
}
}
#endif
// ----------------------------------------------------------------------
#ifdef _DEBUG
int Appearance::getPolygonCount () const
{
return 0;
}
#endif
// ----------------------------------------------------------------------
#ifdef _DEBUG
void Appearance::debugDump(std::string & /*result*/, const int /*indentLevel*/) const
{
}
#endif
// ----------------------------------------------------------------------
const IndexedTriangleList* Appearance::getRadarShape () const
{
return 0;
}
// ----------------------------------------------------------------------
bool Appearance::getShadowBlobAllowed() const
{
return m_shadowBlobAllowed;
}
// ----------------------------------------------------------------------
void Appearance::setShadowBlobAllowed()
{
m_shadowBlobAllowed = true;
}
// ----------------------------------------------------------------------
void Appearance::renderShadowBlob (const Vector& /*position_o*/, const float /*radius*/) const
{
}
// ----------------------------------------------------------------------
void Appearance::renderReticle (const Vector& /*position_o*/, const float /*radius*/) const
{
}
// ----------------------------------------------------------------------
void Appearance::setRenderedThisFrame () const
{
m_renderedFrameNumber = ms_frameNumber;
}
// ----------------------------------------------------------------------
bool Appearance::getRenderedThisFrame () const
{
return m_renderedFrameNumber == ms_frameNumber;
}
//----------------------------------------------------------------------
bool Appearance::getRenderedLastFrame () const
{
return m_renderedFrameNumber == (ms_frameNumber - 1);
}
// ----------------------------------------------------------------------
SkeletalAppearance2 * Appearance::asSkeletalAppearance2()
{
return 0;
}
// ----------------------------------------------------------------------
SkeletalAppearance2 const * Appearance::asSkeletalAppearance2() const
{
return 0;
}
// ----------------------------------------------------------------------
ComponentAppearance * Appearance::asComponentAppearance()
{
return NULL;
}
// ----------------------------------------------------------------------
ComponentAppearance const * Appearance::asComponentAppearance() const
{
return NULL;
}
// ----------------------------------------------------------------------
DetailAppearance * Appearance::asDetailAppearance()
{
return 0;
}
// ----------------------------------------------------------------------
DetailAppearance const * Appearance::asDetailAppearance() const
{
return 0;
}
// ----------------------------------------------------------------------
void Appearance::onEvent(LabelHash::Id /* eventId */)
{
// Default: handle no events.
}
// ----------------------------------------------------------------------
int Appearance::getHardpointCount() const
{
return m_appearanceTemplate != NULL ? m_appearanceTemplate->getHardpointCount() : 0;
}
// ----------------------------------------------------------------------
int Appearance::getHardpointIndex(CrcString const &hardpointName, bool optional) const
{
return m_appearanceTemplate != NULL ? m_appearanceTemplate->getHardpointIndex(hardpointName, optional) : -1;
}
// ----------------------------------------------------------------------
const Hardpoint & Appearance::getHardpoint(int index) const
{
NOT_NULL(m_appearanceTemplate);
return m_appearanceTemplate->getHardpoint(index);
}
// ======================================================================
// class Appearance: PROTECTED
// ======================================================================
void Appearance::extentChanged() const
{
const Object *owner = getOwner();
if (owner)
{
const_cast<Object *>(owner)->extentChanged();
}
}
// ----------------------------------------------------------------------
void Appearance::onScaleModified(Vector const &oldScale, Vector const &newScale)
{
// Do nothing.
UNREF(oldScale);
UNREF(newScale);
}
// ----------------------------------------------------------------------
bool Appearance::canRenderEffects()
{
return s_renderEnabled;
}
// ----------------------------------------------------------------------
void Appearance::enableRenderEffects(bool const yesno)
{
s_renderEnabled = yesno;
}
// ----------------------------------------------------------------------
void Appearance::useRenderEffectsFlag(bool const yesno)
{
m_useRenderEffectsFlag = yesno;
}
// ----------------------------------------------------------------------
bool Appearance::usesRenderEffectsFlag() const
{
return m_useRenderEffectsFlag;
}
// ----------------------------------------------------------------------
ParticleEffectAppearance * Appearance::asParticleEffectAppearance()
{
return NULL;
}
// ----------------------------------------------------------------------
ParticleEffectAppearance const * Appearance::asParticleEffectAppearance() const
{
return NULL;
}
// ----------------------------------------------------------------------
SwooshAppearance * Appearance::asSwooshAppearance()
{
return NULL;
}
// ----------------------------------------------------------------------
SwooshAppearance const * Appearance::asSwooshAppearance() const
{
return NULL;
}
// ----------------------------------------------------------------------
LightningAppearance * Appearance::asLightningAppearance()
{
return NULL;
}
// ----------------------------------------------------------------------
LightningAppearance const * Appearance::asLightningAppearance() const
{
return NULL;
}
// ======================================================================
@@ -0,0 +1,273 @@
// ======================================================================
//
// Appearance.h
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001, 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_Appearance_H
#define INCLUDED_Appearance_H
// ======================================================================
#include "sharedFoundation/LabelHash.h"
#include "sharedFoundation/Tag.h"
#include "sharedMath/Vector.h"
#include "sharedMath/Transform.h"
class AppearanceTemplate;
class AxialBox;
class BoxExtent;
class CollideParameters;
class CollisionInfo;
class ComponentAppearance;
class CrcLowerString;
class CrcString;
class CustomizationData;
class DebugShapeRenderer;
class DetailAppearance;
class Extent;
class Hardpoint;
class IndexedTriangleList;
class LightningAppearance;
class LightsaberAppearance;
class Object;
class ParticleEffectAppearance;
class SkeletalAppearance2;
class Sphere;
class SwooshAppearance;
class Texture;
class Vector;
typedef uint32 PropertyId;
namespace DPVS
{
class Object;
};
// ======================================================================
class Appearance
{
// {Detail,Component,Lightsaber}Appearance need access to Appearance::getDpvsObject()
friend class DetailAppearance;
friend class ComponentAppearance;
friend class LightsaberAppearance;
public:
static void install();
static void beginNewFrame ();
typedef void (*RenderHardpointFunction)(Transform const & transform_h2w, bool renderName, char const * name);
static void setRenderHardpointFunction(RenderHardpointFunction renderHardpointFunction);
static bool canRenderEffects();
static void enableRenderEffects(bool yesno);
void useRenderEffectsFlag(bool yesno);
bool usesRenderEffectsFlag() const;
public:
explicit Appearance(const AppearanceTemplate *newAppearanceTemplate);
virtual ~Appearance();
const AppearanceTemplate *getAppearanceTemplate() const;
const char * getAppearanceTemplateName () const;
virtual bool isLoaded() const;
virtual const Sphere &getSphere() const;
virtual bool collide(Vector const & start_o, Vector const & end_o, CollideParameters const & collideParameters, CollisionInfo & result) const;
virtual bool implementsCollide() const;
virtual const Extent *getSelectionExtent() const;
virtual const Extent *getExtent() const;
virtual void setExtent(const Extent *newExent);
virtual AxialBox const getTangibleExtent() const;
virtual float alter(float time);
virtual void setAlpha(bool opaqueEnabled, float opaqueAlpha, bool alphaEnabled, float alphaAlpha);
Object *getOwner();
const Object *getOwner() const;
virtual void setOwner(Object *newOwner);
void setTransform_w(const Transform &t) const;
const Transform & getTransform_w() const;
const char *getFloorName() const;
virtual void setCustomizationData(CustomizationData *customizationData);
virtual void addCustomizationVariables(CustomizationData &customizationData) const;
virtual void setKeepAlive(bool keepAlive);
bool isAlive() const;
virtual bool findHardpoint(CrcString const &hardpointName, Transform &hardpointTransform) const;
virtual int getHardpointCount() const;
virtual int getHardpointIndex(CrcString const &hardpointName, bool optional = false) const;
virtual const Hardpoint& getHardpoint(int index) const;
virtual void setScale(Vector const & scale);
virtual Vector const & getScale() const;
void setUniformScale(float scale);
float getUniformScale() const;
virtual void addToWorld();
virtual void removeFromWorld();
virtual void preRender() const;
virtual void render() const;
virtual void objectListCameraRender() const;
static void objectListCameraRenderDescend(Object const & obj);
virtual void setTexture(Tag tag, const Texture &texture);
bool getShadowBlobAllowed() const;
virtual void setShadowBlobAllowed();
virtual void renderShadowBlob (const Vector& position_o, float radius) const;
virtual void renderReticle (const Vector& position_o, float radius) const;
#ifdef _DEBUG
virtual bool debugRenderingEnabled() const;
virtual void drawDebugShapes ( DebugShapeRenderer * R ) const;
virtual int getPolygonCount () const;
virtual void debugDump(std::string &result, int indentLevel) const;
#endif
virtual const IndexedTriangleList* getRadarShape () const;
void setRenderedThisFrame () const;
bool getRenderedThisFrame () const;
bool getRenderedLastFrame () const;
int getRenderedFrameNumber() const;
virtual SkeletalAppearance2 * asSkeletalAppearance2();
virtual SkeletalAppearance2 const * asSkeletalAppearance2() const;
virtual ComponentAppearance * asComponentAppearance();
virtual ComponentAppearance const * asComponentAppearance() const;
virtual DetailAppearance * asDetailAppearance();
virtual DetailAppearance const * asDetailAppearance() const;
virtual ParticleEffectAppearance * asParticleEffectAppearance();
virtual ParticleEffectAppearance const * asParticleEffectAppearance() const;
virtual SwooshAppearance * asSwooshAppearance();
virtual SwooshAppearance const * asSwooshAppearance() const;
virtual LightningAppearance * asLightningAppearance();
virtual LightningAppearance const * asLightningAppearance() const;
virtual void onEvent(LabelHash::Id eventId);
protected:
void extentChanged() const;
virtual bool realIsAlive() const;
virtual void onScaleModified(Vector const &oldScale, Vector const &newScale);
private:
// disabled
Appearance();
Appearance(const Appearance &);
Appearance &operator =(const Appearance &);
virtual DPVS::Object *getDpvsObject() const;
///////////////////////////////////////////////////////////
const AppearanceTemplate *m_appearanceTemplate;
protected:
const Extent *m_extent;
private:
Object *m_owner;
mutable int m_renderedFrameNumber;
Vector m_scale;
bool m_keepAlive;
bool m_useRenderEffectsFlag;
bool m_shadowBlobAllowed;
mutable Transform m_appearanceToWorld;
};
// ======================================================================
/**
* Get the AppearanceTemplate for this Appearance.
*
* The AppearanceTemplate may be NULL.
*
* AppearanceTemplates may be shared by multiple Appearances.
*
* @return const pointer to the AppearanceTemplate.
*/
inline const AppearanceTemplate *Appearance::getAppearanceTemplate() const
{
return m_appearanceTemplate;
}
// ----------------------------------------------------------------------
inline Object *Appearance::getOwner()
{
return m_owner;
}
// ----------------------------------------------------------------------
inline const Object *Appearance::getOwner() const
{
return m_owner;
}
// ----------------------------------------------------------------------
inline const Transform &Appearance::getTransform_w() const
{
return m_appearanceToWorld;
}
// ----------------------------------------------------------------------
inline Vector const &Appearance::getScale() const
{
return m_scale;
}
// ---------------------------------------------------------------------
inline void Appearance::setUniformScale(float const scale)
{
setScale(Vector(scale, scale, scale));
}
// ---------------------------------------------------------------------
inline float Appearance::getUniformScale() const
{
// When requesting a uniform scale, the x-axis is the only one considered.
return getScale().x;
}
// ---------------------------------------------------------------------
inline int Appearance::getRenderedFrameNumber() const
{
return m_renderedFrameNumber;
}
// ======================================================================
#endif
@@ -0,0 +1,494 @@
// ======================================================================
//
// AppearanceTemplate.cpp
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001-2002 Sony Online Entertainment
// All Rights Reserved
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/AppearanceTemplate.h"
#include "sharedCollision/ConfigSharedCollision.h"
#include "sharedCollision/ExtentList.h"
#include "sharedCollision/Extent.h"
#include "sharedDebug/DataLint.h"
#include "sharedCollision/FloorManager.h"
#include "sharedCollision/FloorMesh.h"
#include "sharedObject/Appearance.h"
#include "sharedObject/AppearanceTemplateList.h"
#include "sharedObject/Hardpoint.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/CrashReportInformation.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/DataResourceList.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedMath/Transform.h"
#include <algorithm>
#include <string>
#include <vector>
//-----------------------------------------------------------------
namespace AppearanceTemplateNamespace
{
const Tag TAG_APPR = TAG (A,P,P,R);
const Tag TAG_HPTS = TAG (H,P,T,S);
const Tag TAG_HPNT = TAG (H,P,N,T);
const Tag TAG_FLOR = TAG (F,L,O,R);
bool ms_verboseWarnings;
char ms_crashReportInfo[MAX_PATH * 2];
void remove();
}
using namespace AppearanceTemplateNamespace;
// ======================================================================
// PRIVATE AppearanceTemplate::PreloadManager
// ======================================================================
class AppearanceTemplate::PreloadManager
{
public:
explicit PreloadManager (const AppearanceTemplate* appearanceTemplate);
~PreloadManager ();
private:
PreloadManager ();
PreloadManager (const PreloadManager&);
PreloadManager& operator= (const PreloadManager&);
private:
const FloorMesh* m_preloadFloorMesh;
};
// ----------------------------------------------------------------------
AppearanceTemplate::PreloadManager::PreloadManager (const AppearanceTemplate* const appearanceTemplate) :
m_preloadFloorMesh (0)
{
if (appearanceTemplate->m_floorName)
m_preloadFloorMesh = FloorMeshList::fetch (appearanceTemplate->m_floorName);
}
// ----------------------------------------------------------------------
AppearanceTemplate::PreloadManager::~PreloadManager ()
{
if (m_preloadFloorMesh)
{
m_preloadFloorMesh->releaseReference ();
m_preloadFloorMesh = 0;
}
}
// ======================================================================
// Construct an AppearanceTemplate
AppearanceTemplate::AppearanceTemplate(const char *newName)
: m_referenceCount(0),
m_crcName(new CrcLowerString(newName)),
m_extent(NULL),
m_collisionExtent(NULL),
m_hardpoints(NULL),
m_floorName(NULL),
m_preloadManager (0)
{
//-- Save info on most recently constructed appearance template.
IGNORE_RETURN(snprintf(ms_crashReportInfo, sizeof(ms_crashReportInfo) - 1, "AppearanceTemplate: %s\n", newName ? newName : "<NULL>"));
ms_crashReportInfo[sizeof(ms_crashReportInfo) - 1] = '\0';
}
// ----------------------------------------------------------------------
/**
* Destroy an AppearanceTemplate.
*/
AppearanceTemplate::~AppearanceTemplate(void)
{
delete m_crcName;
ExtentList::release(m_extent);
m_extent = NULL;
ExtentList::release(m_collisionExtent);
m_collisionExtent = NULL;
if (m_hardpoints)
{
std::for_each(m_hardpoints->begin(), m_hardpoints->end(), PointerDeleter());
delete m_hardpoints;
m_hardpoints = 0;
}
delete [] m_floorName;
if (m_preloadManager)
{
delete m_preloadManager;
m_preloadManager = 0;
}
}
// ----------------------------------------------------------------------
void AppearanceTemplate::install()
{
AppearanceTemplateList::assignBinding(TAG_APPR, create);
ms_crashReportInfo[0] = '\0';
CrashReportInformation::addDynamicText(ms_crashReportInfo);
ExitChain::add(remove, "AppearanceTemplateList::remove");
}
// ----------------------------------------------------------------------
void AppearanceTemplateNamespace::remove()
{
AppearanceTemplateList::removeBinding(TAG_APPR);
CrashReportInformation::removeDynamicText(ms_crashReportInfo);
}
// ----------------------------------------------------------------------
AppearanceTemplate *AppearanceTemplate::create(const char *newName, Iff *iff)
{
AppearanceTemplate * temp = new AppearanceTemplate(newName);
temp->load(*iff);
return temp;
}
// ----------------------------------------------------------------------
/**
* Create a unique Appearance for this AppearanceTemplate.
*
* This routine should be overloaded in derived classes as appropriate.
*
* Derived classes should not chain down to this routine.
*
* @return An Appearance for the specified AppearanceTemplate
*/
Appearance *AppearanceTemplate::createAppearance() const
{
return new Appearance(this);
}
// ----------------------------------------------------------------------
void AppearanceTemplate::load(Iff & iff)
{
iff.enterForm(TAG_APPR);
#ifdef _DEBUG
DEBUG_WARNING (DataLint::isEnabled () && iff.getCurrentName () < TAG_0003, ("AppearanceTemplate [%s] loading older version -- this asset will need to be reexported", getCrcName ().getString ()));
#endif
switch (iff.getCurrentName())
{
case TAG_0001:
load_0001(iff);
break;
case TAG_0002:
load_0002(iff);
break;
case TAG_0003:
load_0003(iff);
break;
default:
FATAL (true, ("AppearanceTemplate::load - unsupported format"));
break;
}
iff.exitForm(TAG_APPR);
}
// ----------------------------------------------------------------------
void AppearanceTemplate::load_0001(Iff &iff)
{
iff.enterForm(TAG_0001);
loadExtents(iff);
loadHardpoints(iff);
iff.exitForm(TAG_0001);
}
// ----------
void AppearanceTemplate::load_0002(Iff &iff)
{
iff.enterForm(TAG_0002);
loadExtents(iff);
loadHardpoints(iff);
IGNORE_RETURN(loadFloors(iff));
iff.exitForm(TAG_0002);
}
// ----------
void AppearanceTemplate::load_0003(Iff & iff)
{
iff.enterForm(TAG_0003);
loadExtents(iff);
loadCollisionExtents(iff);
loadHardpoints(iff);
IGNORE_RETURN(loadFloors(iff));
iff.exitForm(TAG_0003);
}
// ----------------------------------------------------------------------
/**
* Load the extents out of an Iff.
*
* @param iff Iff containing the extent information
*/
void AppearanceTemplate::loadExtents (Iff & iff)
{
m_extent = ExtentList::fetch(iff);
}
void AppearanceTemplate::loadCollisionExtents (Iff & iff)
{
m_collisionExtent = ExtentList::fetch(iff);
if(m_collisionExtent && !m_collisionExtent->validate())
{
DEBUG_WARNING(true,("AppearanceTemplate::loadCollisionExtents - Extent loaded from %s is invalid",iff.getFileName()));
}
}
// ----------------------------------------------------------------------
/**
* Load the hardpoints out of an Iff.
*/
void AppearanceTemplate::loadHardpoints (Iff& iff)
{
// This enterForm call MUST be optional, as older versions of the exporter
// just didn't write out this form if there weren't any hardpoints
// (instead of writing an empty form)
if(iff.enterForm(TAG_HPTS,true))
{
char hardpointName[256];
Transform hardpointTransform;
int nHardpoints = iff.getNumberOfBlocksLeft();
if (m_hardpoints)
{
std::for_each(m_hardpoints->begin(), m_hardpoints->end(), PointerDeleter());
m_hardpoints->clear();
}
else
{
m_hardpoints = new HardpointList();
m_hardpoints->reserve(static_cast<HardpointList::size_type>(nHardpoints));
}
for (int i = 0; i < nHardpoints; ++i)
{
iff.enterChunk(TAG_HPNT);
hardpointTransform = iff.read_floatTransform();
iff.readRest_char(hardpointName, sizeof(hardpointName));
iff.exitChunk(TAG_HPNT);
m_hardpoints->push_back(new Hardpoint (hardpointName, hardpointTransform));
}
iff.exitForm(TAG_HPTS);
//-- Sort the hardpoints by crc name.
std::sort(m_hardpoints->begin(), m_hardpoints->end(), Hardpoint::LessNameComparator());
}
}
// ----------------------------------------------------------------------
bool AppearanceTemplate::loadFloors( Iff & iff )
{
iff.enterForm (TAG_FLOR);
iff.enterChunk(TAG_DATA);
bool hasFloor = iff.read_bool8();
if(hasFloor)
m_floorName = iff.read_string();
iff.exitChunk(TAG_DATA);
iff.exitForm(TAG_FLOR);
return true;
}
//-------------------------------------------------------------------
char const * AppearanceTemplate::getFloorName() const
{
return m_floorName;
}
// ----------------------------------------------------------------------
/**
* Set a new Extent for this AppearanceTemplate.
*
* The current extent will be released.
*
* @param newExtent New extent for this AppearanceTemplate
*/
void AppearanceTemplate::setExtent(const Extent *newExtent)
{
ExtentList::release(m_extent);
m_extent = newExtent;
}
// ----------------------------------------------------------------------
void AppearanceTemplate::setCollisionExtent ( Extent const * newExtent )
{
ExtentList::release(m_collisionExtent);
m_collisionExtent = newExtent;
}
// ----------------------------------------------------------------------
/**
* retrieve the index of a hardpoint given the hardpoint name.
*
* Hardpoint names are compared in a case-insensitive manner.
*
* The argument "optional" controls activity when the hardpoint name is not
* found. The routine will FATAL if optional is false and the hardpoint name
* is not found. The routine will return -1 if optional is true and the
* hardpoint name isn't found.
*
* @return index of hardpoint with given name if found, -1 or FATAL otherwise (see remarks).
*/
int AppearanceTemplate::getHardpointIndex(CrcString const &hardpointName, bool optional) const
{
//-- Handle no-hardpoint case.
if (!m_hardpoints)
{
FATAL(!optional, ("getHardpointIndex(%s) called non-optionally on appearance template [%s] with no hardpoints.", hardpointName.getString(), m_crcName->getString()));
return -1;
}
//-- Search for the hardpoint in Crc order.
std::pair<HardpointList::iterator, HardpointList::iterator> const rangePair = std::equal_range(m_hardpoints->begin(), m_hardpoints->end(), hardpointName, Hardpoint::LessNameComparator());
if (rangePair.first == rangePair.second)
{
FATAL(!optional, ("getHardpointIndex(%s) called non-optionally on appearance template [%s], hardpoint doesn't exist.", hardpointName.getString(), m_crcName->getString()));
return -1;
}
return std::distance(m_hardpoints->begin(), rangePair.first);
}
//-------------------------------------------------------------------
const Hardpoint& AppearanceTemplate::getHardpoint(int index) const
{
NOT_NULL(m_hardpoints);
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getHardpointCount());
return *((*m_hardpoints)[static_cast<HardpointList::size_type>(index)]);
}
// ----------------------------------------------------------------------
int AppearanceTemplate::getHardpointCount(void) const
{
return m_hardpoints ? static_cast<int>(m_hardpoints->size()) : 0;
}
// ----------------------------------------------------------------------
void AppearanceTemplate::drawDebugShapes ( DebugShapeRenderer * renderer ) const
{
UNREF(renderer);
#ifdef _DEBUG
if(ConfigSharedCollision::getDrawExtents())
{
if(m_collisionExtent)
{
m_collisionExtent->drawDebugShapes(renderer);
}
}
#endif
}
// ----------------------------------------------------------------------
void AppearanceTemplate::preloadAssets() const
{
if (!m_preloadManager)
m_preloadManager = new PreloadManager (this);
}
// ----------------------------------------------------------------------
void AppearanceTemplate::preloadAssetsLight () const
{
}
// ----------------------------------------------------------------------
void AppearanceTemplate::garbageCollect() const
{
if (m_preloadManager)
{
delete m_preloadManager;
m_preloadManager = 0;
}
}
// ----------------------------------------------------------------------
/**
*Get the CrcLowerString for this AppearanceTemplate.
*/
const CrcLowerString &AppearanceTemplate::getCrcName() const
{
return *m_crcName;
}
// ----------------------------------------------------------------------
/**
*Get the name of this AppearanceTemplate.
*
*This routine may return NULL.
*/
const char *AppearanceTemplate::getName() const
{
return m_crcName->getString();
}
// ======================================================================
@@ -0,0 +1,153 @@
// ======================================================================
//
// AppearanceTemplate.h
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_AppearanceTemplate_H
#define INCLUDED_AppearanceTemplate_H
// ======================================================================
class Appearance;
class Camera;
class CrcLowerString;
class CrcString;
class Extent;
class Hardpoint;
class Iff;
class Object;
class Sphere;
class Vector;
class DebugShapeRenderer;
// ======================================================================
class AppearanceTemplate
{
public:
static void install();
static AppearanceTemplate *create(const char *newName, Iff *iff);
public:
explicit AppearanceTemplate(const char *newName);
virtual ~AppearanceTemplate();
virtual Appearance *createAppearance() const;
virtual void drawDebugShapes(DebugShapeRenderer *renderer) const;
virtual void preloadAssets () const;
//-- we use this function to do some preloading but nothing big. Characters use it in preloading since loading all .MGNs as done by preloadAssets() generally is too heavy.
virtual void preloadAssetsLight () const;
virtual void garbageCollect () const;
const CrcLowerString &getCrcName() const;
const char *getName() const;
const Extent *getExtent() const;
void setExtent(const Extent *newExent);
const Extent *getCollisionExtent() const;
void setCollisionExtent(Extent const *newExtent);
int getHardpointCount() const;
int getHardpointIndex(CrcString const &hardpointName, bool optional = false) const;
const Hardpoint& getHardpoint(int index) const;
const char *getFloorName() const;
int getReferenceCount() const;
int incrementReference() const;
int decrementReference() const;
void load(Iff &iff);
protected:
void load_0001(Iff &iff);
void load_0002(Iff &iff);
void load_0003(Iff &iff);
void loadExtents(Iff &iff);
void loadCollisionExtents(Iff &iff);
void loadHardpoints(Iff &iff);
bool loadFloors(Iff &iff);
private:
typedef stdvector<Hardpoint*>::fwd HardpointList;
private:
AppearanceTemplate();
AppearanceTemplate(const AppearanceTemplate &);
AppearanceTemplate &operator =(const AppearanceTemplate &);
private:
mutable int m_referenceCount;
CrcLowerString *const m_crcName;
const Extent *m_extent;
const Extent *m_collisionExtent;
HardpointList *m_hardpoints;
char * m_floorName;
class PreloadManager;
friend class PreloadManager;
mutable PreloadManager* m_preloadManager;
};
// ----------------------------------------------------------------------
/**
*Return the Extent for this AppearanceTemplate.
*/
inline const Extent *AppearanceTemplate::getExtent() const
{
return m_extent;
}
inline const Extent *AppearanceTemplate::getCollisionExtent() const
{
return m_collisionExtent;
}
// ----------------------------------------------------------------------
inline int AppearanceTemplate::getReferenceCount() const
{
return m_referenceCount;
}
// ----------
inline int AppearanceTemplate::incrementReference() const
{
m_referenceCount++;
return m_referenceCount;
}
// ----------
inline int AppearanceTemplate::decrementReference() const
{
m_referenceCount--;
return m_referenceCount;
}
// ======================================================================
#endif
@@ -0,0 +1,736 @@
// ======================================================================
//
// AppearanceTemplateList.cpp
// copyright 1999 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/AppearanceTemplateList.h"
#include "sharedDebug/DataLint.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include "sharedFile/AsynchronousLoader.h"
#include "sharedFile/Iff.h"
#include "sharedFile/TreeFile.h"
#include "sharedObject/AppearanceTemplate.h"
#include "sharedObject/ConfigSharedObject.h"
#include "sharedRandom/Random.h"
#include <map>
#include <set>
#include <algorithm>
#include <vector>
// ======================================================================
// AppearanceTemplateListNamespace
// ======================================================================
namespace AppearanceTemplateListNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef std::map<Tag, AppearanceTemplateList::CreateFunction> TagBindingMap;
typedef std::map<const CrcString *, const CrcString *, LessPointerComparator> RedirectorMap;
typedef std::set<AppearanceTemplate *> AnonymousTemplates;
typedef std::map<const CrcString *, AppearanceTemplate *, LessPointerComparator> NamedTemplates;
typedef std::pair<float, AppearanceTemplate *> TimedTemplate;
typedef std::map<const CrcString *, TimedTemplate, LessPointerComparator> NamedTimedTemplates;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Tag TAG_APT = TAG3(A,P,T);
const Tag TAG_MESH = TAG(M,E,S,H);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* const ms_defaultAppearanceTemplateName = "appearance/defaultappearance.apt";
float ms_keepTime;
float ms_keepEpsilon;
bool ms_installed;
bool ms_debugReport;
bool ms_debugReportVerbose;
bool ms_debugReportTimedTemplates;
TagBindingMap ms_tagBindingMap;
RedirectorMap ms_redirectorMap;
AnonymousTemplates ms_anonymousTemplates;
NamedTemplates ms_namedTemplates;
NamedTimedTemplates ms_namedTimedTemplates;
bool ms_allowTimedTemplates;
bool ms_useTimedTemplates;
bool ms_logCreate;
bool ms_logFetch;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void remove();
AppearanceTemplate *create(const char *fileName);
void addAnonymousAppearanceTemplate(AppearanceTemplate *appearanceTemplate);
void addNamedAppearanceTemplate(AppearanceTemplate *appearanceTemplate);
void addNamedTimedAppearanceTemplate(AppearanceTemplate *appearanceTemplate);
void removeAppearanceTemplate(AppearanceTemplate *appearanceTemplate);
void debugReport();
void debugReportVerbose();
void debugReportTimedTemplates();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
using namespace AppearanceTemplateListNamespace;
// ======================================================================
// STATIC PUBLIC AppearanceTemplateList
// ======================================================================
/**
* Install the AppearanceTemplateList.
*/
void AppearanceTemplateList::install(bool useTimedTemplates, bool ensureDefaultAppearanceExists)
{
DEBUG_FATAL(ms_installed, ("double install"));
ms_installed = true;
DebugFlags::registerFlag(ms_debugReport, "SharedObject/AppearanceTemplateList", "debugReport", debugReport);
DebugFlags::registerFlag(ms_debugReportTimedTemplates, "SharedObject/AppearanceTemplateList", "reportTimedTemplates", debugReportTimedTemplates);
DebugFlags::registerFlag(ms_debugReportVerbose, "SharedObject/AppearanceTemplateList", "debugReportVerbose", debugReportVerbose);
DebugFlags::registerFlag(ms_useTimedTemplates, "SharedObject/AppearanceTemplateList", "useTimedTemplates");
DebugFlags::registerFlag(ms_logCreate, "SharedObject/AppearanceTemplateList", "logCreate");
DebugFlags::registerFlag(ms_logFetch, "SharedObject/AppearanceTemplateList", "logFetch");
ms_useTimedTemplates = useTimedTemplates;
ms_keepTime = ConfigSharedObject::getAppearanceTemplateListKeepTime();
ms_keepEpsilon = ConfigSharedObject::getAppearanceTemplateListKeepEpsilon();
//-- verify the default appearance exists
if (ensureDefaultAppearanceExists)
FATAL(!TreeFile::exists(getDefaultAppearanceTemplateName()), ("%s could not be found. Are your paths set up correctly?", getDefaultAppearanceTemplateName()));
if (TreeFile::isLoggingFiles())
delete TreeFile::open(getDefaultAppearanceTemplateName(), AbstractFile::PriorityData, true);
ExitChain::add(AppearanceTemplateListNamespace::remove, "AppearanceTemplateList::remove", 0, false);
}
// ----------------------------------------------------------------------
/**
* Assign a binding between a Tag and a CreateFunction.
*
* If a previous binding for the specified tag exists, it will be replaced
* by the new binding.
*
* @param tag Tag for the binding
* @param createFunction Create function to call for data files with the tag
*/
void AppearanceTemplateList::assignBinding(const Tag tag, const CreateFunction createFunction)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
NOT_NULL(createFunction);
#ifdef _DEBUG
char tagString[5];
ConvertTagToString(tag, tagString);
DEBUG_REPORT_LOG_PRINT(ms_debugReport, ("Added AppearanceTemplateList binding %s\n", tagString));
#endif
ms_tagBindingMap[tag] = createFunction;
}
// ----------------------------------------------------------------------
/**
* Remove a binding from the AppearanceTemplateList.
*
* If the specified Tag is not bound, the routine will return without
* error.
*
* @param tag Tag for the binding to remove
*/
void AppearanceTemplateList::removeBinding(const Tag tag)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
IGNORE_RETURN(ms_tagBindingMap.erase(tag));
}
// ----------------------------------------------------------------------
void AppearanceTemplateList::update(const float elapsedTime)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
//-- walk the timed appearance template list and tick down
NamedTimedTemplates::iterator iter = ms_namedTimedTemplates.begin();
NamedTimedTemplates::iterator end = ms_namedTimedTemplates.end();
while (iter != end)
{
//-- see if the appearance template has expired
iter->second.first -= elapsedTime;
if (iter->second.first <= 0.f)
{
DEBUG_REPORT_LOG(ms_logCreate, ("Destroying timed appearance %s\n", iter->first->getString()));
delete const_cast<AppearanceTemplate *>(iter->second.second);
ms_namedTimedTemplates.erase(iter++);
end = ms_namedTimedTemplates.end();
}
else
++iter;
}
}
// ----------------------------------------------------------------------
void AppearanceTemplateList::setAllowTimedTemplates(const bool allowTimedTemplates)
{
ms_allowTimedTemplates = allowTimedTemplates;
if (!ms_allowTimedTemplates)
update(ms_keepTime + ms_keepEpsilon);
}
// ----------------------------------------------------------------------
const AppearanceTemplate *AppearanceTemplateList::fetch(const char *const fileName)
{
bool found = false;
return fetch(fileName, found);
}
//----------------------------------------------------------------------
const AppearanceTemplate *AppearanceTemplateList::fetch(const char *const fileName, bool & found)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
NOT_NULL(fileName);
DEBUG_REPORT_LOG(ms_logFetch, ("[fetch] AppearanceTemplateList::fetch: %s\n", fileName));
found = false;
char const * actualFileName = fileName;
if (!fileName)
{
DEBUG_WARNING(true, ("AppearanceTemplateList::fetch passed NULL fileName, using default"));
actualFileName = getDefaultAppearanceTemplateName();
}
else if (!*fileName)
{
DEBUG_WARNING(true, ("AppearanceTemplateList::fetch passed empty fileName, using default"));
actualFileName = getDefaultAppearanceTemplateName();
}
else if (!TreeFile::exists(fileName))
{
DEBUG_WARNING(true, ("AppearanceTemplateList::fetch could not open '%s', using default", fileName));
actualFileName = getDefaultAppearanceTemplateName();
}
else
found = true;
//-- search for the appearance
AppearanceTemplate *const appearanceTemplate = create(actualFileName);
//-- up the reference count
return fetch(appearanceTemplate);
}
// ----------------------------------------------------------------------
/**
* Add a reference to the specified Appearance.
*
* This routine will do nothing if passed in NULL. Otherwise, it will
* increase the reference count of the specified AppearanceTemplate
* by one.
*
* @param appearanceTemplate AppearanceTemplate to remove the reference count from
* @return The AppearanceTemplate that was passed into the routine.
* @see AppearanceTemplateList::release()
*/
const AppearanceTemplate *AppearanceTemplateList::fetch(const AppearanceTemplate *const appearanceTemplate)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
if (appearanceTemplate)
IGNORE_RETURN(appearanceTemplate->incrementReference());
return appearanceTemplate;
}
// ----------------------------------------------------------------------
/**
* Fetch an AppearanceTemplate from an Iff.
*
* This routine will increment the reference count of the AppearanceTemplate
* by one.
*
* @param iff File from which to load the AppearanceTemplate
*/
const AppearanceTemplate *AppearanceTemplateList::fetch(Iff *const iff)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
NOT_NULL(iff);
const Tag tag = iff->getCurrentName();
TagBindingMap::iterator iter = ms_tagBindingMap.find(tag);
if (iter == ms_tagBindingMap.end())
{
char tagString[5];
ConvertTagToString(tag, tagString);
DEBUG_FATAL(true, ("AppearanceTemplate binding %s not found", tagString));
return 0; //lint !e527 // unreachable
}
AppearanceTemplate *const appearanceTemplate = (*iter).second(NULL, iff);
NOT_NULL(appearanceTemplate);
addAnonymousAppearanceTemplate(appearanceTemplate);
//-- up the reference count
return fetch(appearanceTemplate);
}
// ----------------------------------------------------------------------
/**
* Fetch an AppearanceTemplate from an existing object and add the object
* to the AppearanceTemplateList.
*
* The AppearanceTemplate object is assumed to be created outside the
* AppearanceTemplateList fetch-from-file or fetch-from-iff mechanism.
* This may happen within an editor that creates an AppearanceTemplate
* object from scratch. In this case, the object is created outside
* the AppearanceTemplateList and must be added to the list. Use this
* function to do so. Failure to add the object to this
* list likely will cause failures when an Appearance making use of the
* AppearanceTemplate object gets released.
*
* @param appearanceTemplate the AppearanceTemplate object to add to the AppearanceTemplateList
*
* @return the AppearanceTemplate object, returned just like all the other fetch routines
*/
const AppearanceTemplate *AppearanceTemplateList::fetchNew(AppearanceTemplate *const appearanceTemplate)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
NOT_NULL(appearanceTemplate);
const CrcLowerString &crcName = appearanceTemplate->getCrcName();
const char *const crcString = crcName.getString();
if (crcString && *crcString)
{
//-- we've got a named appearance template list
addNamedAppearanceTemplate(appearanceTemplate);
}
else
{
//-- we've got an anonymous appearance template list
addAnonymousAppearanceTemplate(appearanceTemplate);
}
//-- up the reference count
return fetch(appearanceTemplate);
}
// ----------------------------------------------------------------------
/**
* Remove a reference to the specified AppearanceTemplate.
*
* This routine will do nothing if passed in NULL.
*
* If the reference count drops to 0, the AppearanceTemplate will be deleted.
*
* @param appearanceTemplate AppearanceTemplate to remove the reference count from
* @see AppearanceTemplateList::release()
*/
void AppearanceTemplateList::release(const AppearanceTemplate *const appearanceTemplate)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
if (appearanceTemplate && appearanceTemplate->decrementReference() <= 0)
{
DEBUG_FATAL(appearanceTemplate->getReferenceCount() < 0, ("referenceCount is negative"));
AppearanceTemplate *const nonConstAppearanceTemplate = const_cast<AppearanceTemplate *>(appearanceTemplate);
//-- remove from list
removeAppearanceTemplate(nonConstAppearanceTemplate);
CrcLowerString const & crcName = appearanceTemplate->getCrcName();
char const * const crcString = crcName.getString();
//-- add it to the timed template list
if (ms_useTimedTemplates && ms_allowTimedTemplates && crcString && *crcString)
{
DEBUG_REPORT_LOG(ms_logCreate, ("Adding timed appearance %s\n", appearanceTemplate->getName()));
addNamedTimedAppearanceTemplate(nonConstAppearanceTemplate);
}
else
delete nonConstAppearanceTemplate;
}
}
// ----------------------------------------------------------------------
/**
* Create an Appearance for the specified AppearanceTemplate.
*
* @param fileName Name of the AppearanceTemplate
* @return An appearance for the specified AppearanceTemplate
*/
Appearance *AppearanceTemplateList::createAppearance(const char *const fileName)
{
DEBUG_FATAL(!ms_installed, ("not installed"));
#ifdef _DEBUG
DataLint::pushAsset(fileName);
#endif
//-- get the appearance template
const AppearanceTemplate *const appearanceTemplate = fetch(fileName);
//-- creating the appearance will increment the reference count
Appearance *const appearance = appearanceTemplate->createAppearance();
#ifdef _DEBUG
DataLint::popAsset();
#endif // _DEBUG
//-- release the appearance template, since the appearance now holds a ref count for it
release(appearanceTemplate);
return appearance;
}
// ----------------------------------------------------------------------
const char* AppearanceTemplateList::getDefaultAppearanceTemplateName()
{
return ms_defaultAppearanceTemplateName;
}
// ----------------------------------------------------------------------
void AppearanceTemplateList::garbageCollect ()
{
//-- release the timed (cached) appearance templates
if (ms_allowTimedTemplates)
{
setAllowTimedTemplates (false);
setAllowTimedTemplates (true);
}
//-- call garbage collect on all appearance templates
{
NamedTemplates::iterator end = ms_namedTemplates.end ();
NamedTemplates::iterator iter = ms_namedTemplates.begin ();
for (; iter != end; ++iter)
const_cast<AppearanceTemplate*> (iter->second)->garbageCollect ();
}
}
// ======================================================================
// STATIC PRIVATE AppearanceTemplateList
// ======================================================================
/**
* Remove a AppearanceTemplateList.
*/
void AppearanceTemplateListNamespace::remove()
{
DEBUG_FATAL(!ms_installed, ("not installed"));
ms_installed = false;
DebugFlags::unregisterFlag(ms_debugReport);
DebugFlags::unregisterFlag(ms_debugReportTimedTemplates);
DebugFlags::unregisterFlag(ms_debugReportVerbose);
DebugFlags::unregisterFlag(ms_useTimedTemplates);
DebugFlags::unregisterFlag(ms_logCreate);
DebugFlags::unregisterFlag(ms_logFetch);
{
//-- report if we leaked anonymous appearance templates
const size_t entryCount = ms_anonymousTemplates.size();
DEBUG_WARNING(entryCount, ("leaked %u anonymous appearance templates", entryCount));
UNREF(entryCount);
// shouldn't delete because item may depend on items that are memory block managed and already deleted, which could cause a crash
}
{
//-- report if we leaked named appearance templates
#ifdef _DEBUG
const size_t entryCount = ms_namedTemplates.size();
DEBUG_WARNING(entryCount, ("leaked %u named appearance templates", entryCount));
NamedTemplates::iterator end = ms_namedTemplates.end();
for (NamedTemplates::iterator it = ms_namedTemplates.begin(); it != end; ++it)
{
DEBUG_REPORT_LOG(true, ("--leaked [%s]\n", it->second->getCrcName().getString()));
// shouldn't delete because item may depend on items that are memory block managed and already deleted, which could cause a crash
}
#endif
}
{
#ifdef _DEBUG
const size_t entryCount = ms_namedTimedTemplates.size();
if (entryCount)
{
DEBUG_REPORT_LOG(true, ("%u timed appearance templates remain\n", entryCount));
}
#endif
}
{
DEBUG_REPORT_LOG(ms_debugReport, ("AppearanceTemplateList redirector map:\n"));
//-- delete the redirector map
for (RedirectorMap::iterator iter = ms_redirectorMap.begin(); iter != ms_redirectorMap.end(); ++iter)
{
DEBUG_REPORT_LOG(ms_debugReport, (" %4i %s -> %s\n", std::distance(ms_redirectorMap.begin(), iter), iter->first->getString(), iter->second->getString()));
delete const_cast<CrcString *>(iter->first);
delete const_cast<CrcString *>(iter->second);
}
}
}
// ----------------------------------------------------------------------
AppearanceTemplate *AppearanceTemplateListNamespace::create(const char *const fileName)
{
NOT_NULL(fileName);
TemporaryCrcString actualFileName(fileName, true);
//-- does the filename end in apt?
if (strstr(fileName, ".apt") != 0)
{
//-- is the filename in the redirector map?
RedirectorMap::iterator iter = ms_redirectorMap.find((const CrcString*)&actualFileName);
if (iter == ms_redirectorMap.end())
{
//-- extract the real name from the apt
Iff iff(fileName);
iff.enterForm(TAG_APT);
iff.enterForm(TAG_0000);
iff.enterChunk(TAG_NAME);
char redirectedFileName[Os::MAX_PATH_LENGTH];
iff.read_string(redirectedFileName, Os::MAX_PATH_LENGTH);
//-- make sure redirector name is not an apt file
FATAL(strstr(redirectedFileName, ".apt") != 0, ("multiple levels of indirection found for appearance template redirector files %s(%s)", fileName, redirectedFileName));
//-- add it to the redirector map
iter = ms_redirectorMap.insert(RedirectorMap::value_type(new PersistentCrcString(actualFileName), new PersistentCrcString(redirectedFileName, true))).first;
iff.exitChunk(TAG_NAME);
iff.exitForm(TAG_0000);
iff.exitForm(TAG_APT);
}
//-- create the target name instead
return create(iter->second->getString());
}
//-- search for the appearance in the named list
{
NamedTemplates::iterator iter = ms_namedTemplates.find((const CrcString*)&actualFileName);
if (iter != ms_namedTemplates.end())
return iter->second;
}
AppearanceTemplate *appearanceTemplate = 0;
//-- search for the appearance in the named timed list
if (ms_useTimedTemplates)
{
NamedTimedTemplates::iterator iter = ms_namedTimedTemplates.find((const CrcString*)&actualFileName);
if (iter != ms_namedTimedTemplates.end())
{
appearanceTemplate = iter->second.second;
ms_namedTimedTemplates.erase(iter);
}
}
DEBUG_REPORT_LOG(ms_logCreate, ("Creating appearance %s\n", actualFileName.getString()));
//-- hack to asynchronously load .msh files
if (!appearanceTemplate && AsynchronousLoader::isEnabled() && (strstr(actualFileName.getString(), ".msh") != 0 || strstr(actualFileName.getString(), ".MSH") != 0))
{
// DEBUG_REPORT_LOG_PRINT(true, ("Loading mesh %s\n", actualFileName.getString()));
TagBindingMap::iterator iter = ms_tagBindingMap.find(TAG_MESH);
if (iter != ms_tagBindingMap.end())
appearanceTemplate = iter->second(actualFileName.getString(), NULL);
}
//-- we now need to create the appearance from disk
if (!appearanceTemplate)
{
Iff iff;
if (!iff.open(actualFileName.getString(), true))
FATAL(true, ("Could not open appearance file %s", actualFileName.getString()));
const Tag tag = iff.getCurrentName();
TagBindingMap::iterator iter = ms_tagBindingMap.find(tag);
if (iter != ms_tagBindingMap.end())
appearanceTemplate = iter->second(actualFileName.getString(), &iff);
else
{
char tagString[5];
ConvertTagToString(tag, tagString);
DEBUG_FATAL(true, ("AppearanceTemplate binding %s not found", tagString));
}
}
//-- add the appearance template to the named list
if (appearanceTemplate)
{
addNamedAppearanceTemplate(appearanceTemplate);
}
return appearanceTemplate;
}
// ----------------------------------------------------------------------
/**
* Add an anonymous appearance template to the AppearanceTemplateList.
*
* @param appearanceTemplate AppearanceTemplate to add
*/
void AppearanceTemplateListNamespace::addAnonymousAppearanceTemplate(AppearanceTemplate *const appearanceTemplate)
{
NOT_NULL(appearanceTemplate);
//-- add to anonymous list
std::pair<AnonymousTemplates::iterator, bool> result = ms_anonymousTemplates.insert(appearanceTemplate);
//-- make sure it's not already there
DEBUG_FATAL(!result.second, ("tried to add an existing anonymous appearanceTemplate"));
UNREF(result);
}
// ----------------------------------------------------------------------
/**
* Add a named appearance template to the AppearanceTemplateList.
*
* @param appearanceTemplate AppearanceTemplate to add
*/
void AppearanceTemplateListNamespace::addNamedAppearanceTemplate(AppearanceTemplate *const appearanceTemplate)
{
NOT_NULL(appearanceTemplate);
//-- add to named list
std::pair<NamedTemplates::iterator, bool> result = ms_namedTemplates.insert(std::make_pair(&appearanceTemplate->getCrcName(), appearanceTemplate));
//-- make sure it's not already there
DEBUG_FATAL(!result.second, ("tried to add existing named appearanceTemplate %s", appearanceTemplate->getName()));
UNREF(result);
}
// ----------------------------------------------------------------------
/**
* Add a named timed appearance template to the AppearanceTemplateList.
*
* @param appearanceTemplate AppearanceTemplate to add
*/
void AppearanceTemplateListNamespace::addNamedTimedAppearanceTemplate(AppearanceTemplate *const appearanceTemplate)
{
NOT_NULL(appearanceTemplate);
//-- add to named list
std::pair<NamedTimedTemplates::iterator, bool> result = ms_namedTimedTemplates.insert(std::make_pair(&appearanceTemplate->getCrcName(), std::make_pair(ms_keepTime + Random::randomReal(ms_keepEpsilon), appearanceTemplate)));
//-- make sure it's not already there
DEBUG_FATAL(!result.second, ("tried to add existing named timed appearanceTemplate %s", appearanceTemplate->getName()));
UNREF(result);
}
// ----------------------------------------------------------------------
/**
* Remove an appearance template from the AppearanceTemplateList.
*
* @param appearanceTemplate AppearanceTemplate to remove
*/
void AppearanceTemplateListNamespace::removeAppearanceTemplate(AppearanceTemplate *const appearanceTemplate)
{
NOT_NULL(appearanceTemplate);
CrcLowerString const & crcName = appearanceTemplate->getCrcName();
char const * const crcString = crcName.getString();
if (crcString && *crcString)
{
//-- remove appearance template from the named list
NamedTemplates::iterator iter = ms_namedTemplates.find((const CrcString*)&appearanceTemplate->getCrcName());
if (iter != ms_namedTemplates.end())
ms_namedTemplates.erase(iter);
else
DEBUG_FATAL(true, ("AppearanceTemplateListNamespace::removeAppearanceTemplate: could not find appearance template %s in named list", crcString));
}
else
{
//-- remove appearance template from the anonymous list
AnonymousTemplates::iterator iter = ms_anonymousTemplates.find(appearanceTemplate);
if (iter != ms_anonymousTemplates.end())
ms_anonymousTemplates.erase(iter);
else
DEBUG_FATAL(true, ("AppearanceTemplateListNamespace::removeAppearanceTemplate: could not find anonymous appearance template in anonymous list"));
}
}
// ----------------------------------------------------------------------
void AppearanceTemplateListNamespace::debugReport()
{
#ifdef _DEBUG
DEBUG_REPORT_PRINT(true, ("Tags installed = %i\n", ms_tagBindingMap.size()));
DEBUG_REPORT_PRINT(true, ("Named templates = %i\n", ms_namedTemplates.size()));
DEBUG_REPORT_PRINT(true, ("Named timed templates = %i\n", ms_namedTimedTemplates.size()));
DEBUG_REPORT_PRINT(true, ("Anonymous templates = %i\n", ms_anonymousTemplates.size()));
#endif
}
// ----------------------------------------------------------------------
void AppearanceTemplateListNamespace::debugReportVerbose()
{
#ifdef _DEBUG
DEBUG_REPORT_PRINT(true, ("AppearanceTemplates loaded:\n"));
DEBUG_OUTPUT_STATIC_VIEW_BEGINFRAME("Engine\\AppearanceTemplateList");
DEBUG_OUTPUT_STATIC_VIEW("Engine\\AppearanceTemplateList", ("AppearanceTemplates loaded:\n"));
for (NamedTemplates::iterator iter = ms_namedTemplates.begin(); iter != ms_namedTemplates.end(); ++iter)
{
const AppearanceTemplate *const t = (*iter).second;
DEBUG_REPORT_PRINT(true, (" %s %d\n", t->getCrcName().getString(), t->getReferenceCount()));
DEBUG_OUTPUT_STATIC_VIEW("Engine\\AppearanceTemplateList", (" %s %d\n", t->getCrcName().getString(), t->getReferenceCount()));
UNREF(t);
}
DEBUG_OUTPUT_STATIC_VIEW_ENDFRAME("Engine\\AppearanceTemplateList");
#endif
}
// ----------------------------------------------------------------------
void AppearanceTemplateListNamespace::debugReportTimedTemplates()
{
#ifdef _DEBUG
for (NamedTimedTemplates::iterator iter = ms_namedTimedTemplates.begin(); iter != ms_namedTimedTemplates.end(); ++iter)
DEBUG_REPORT_PRINT(true, ("% 2.1f %s\n", iter->second.first, iter->first->getString()));
#endif
}
// ======================================================================
@@ -0,0 +1,62 @@
// ======================================================================
//
// AppearanceTemplateList.h
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2000-2002 Sony Online Entertainment
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_AppearanceTemplateList_H
#define INCLUDED_AppearanceTemplateList_H
// ======================================================================
#include "sharedFoundation/Tag.h"
class Appearance;
class AppearanceTemplate;
class Iff;
// ======================================================================
class AppearanceTemplateList
{
public:
typedef AppearanceTemplate *(*CreateFunction)(const char *name, Iff *iff);
public:
static void install(bool useTimedTemplates, bool ensureDefaultAppearanceExists);
static void assignBinding(Tag tag, CreateFunction createFunction);
static void removeBinding(Tag tag);
static void update(float elapsedTime);
static void setAllowTimedTemplates (bool allowTimedTemplates);
static const AppearanceTemplate *fetch(const char *fileName);
static const AppearanceTemplate *fetch(const char *fileName, bool & found);
static const AppearanceTemplate *fetch(Iff *iff);
static const AppearanceTemplate *fetch(const AppearanceTemplate *appearanceTemplate);
static const AppearanceTemplate *fetchNew(AppearanceTemplate *appearanceTemplate);
static void release(const AppearanceTemplate *appearanceTemplate);
static Appearance *createAppearance(const char *fileName);
static const char* getDefaultAppearanceTemplateName();
static void garbageCollect ();
private:
// disabled
AppearanceTemplateList();
AppearanceTemplateList(const AppearanceTemplateList &);
AppearanceTemplateList &operator =(const AppearanceTemplateList &);
};
// ======================================================================
#endif
@@ -0,0 +1,34 @@
// ======================================================================
//
// Hardpoint.cpp
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Hardpoint.h"
// ======================================================================
Hardpoint::Hardpoint (const char* newName, const Transform& newTransform) :
m_name (newName, false),
m_transform (newTransform)
{
}
// ----------------------------------------------------------------------
CrcString const& Hardpoint::getName () const
{
return m_name;
}
// ----------------------------------------------------------------------
Transform const& Hardpoint::getTransform () const
{
return m_transform;
}
// ======================================================================
@@ -0,0 +1,91 @@
// ======================================================================
//
// HardPoint.h
// Copyright 2000 - 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_Hardpoint_H
#define INCLUDED_Hardpoint_H
// ======================================================================
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedMath/Transform.h"
// ======================================================================
class Hardpoint
{
public:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct LessNameComparator
{
bool operator () (Hardpoint const* lhs, Hardpoint const* rhs) const;
bool operator () (CrcString const& lhs, Hardpoint const* rhs) const;
bool operator () (Hardpoint const* lhs, CrcString const& rhs) const;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef const Hardpoint* ConstIterator;
public:
Hardpoint (const char* newName, const Transform& newTransform);
CrcString const& getName () const;
Transform const& getTransform () const;
private:
// Disabled.
Hardpoint (void);
Hardpoint (const Hardpoint&);
Hardpoint& operator= (const Hardpoint&);
private:
PersistentCrcString const m_name;
Transform const m_transform;
};
// ======================================================================
// struct LessNameComparator
// ======================================================================
// Define these comparator functions inline so that STL sorts/searches are inlined.
inline bool Hardpoint::LessNameComparator::operator () (Hardpoint const* lhs, Hardpoint const* rhs) const
{
NOT_NULL (lhs);
NOT_NULL (rhs);
return lhs->getName () < rhs->getName ();
}
// ----------------------------------------------------------------------
inline bool Hardpoint::LessNameComparator::operator () (CrcString const& lhs, Hardpoint const* rhs) const
{
NOT_NULL (rhs);
return lhs < rhs->getName ();
}
// ----------------------------------------------------------------------
inline bool Hardpoint::LessNameComparator::operator () (Hardpoint const* lhs, CrcString const& rhs) const
{
NOT_NULL (lhs);
return lhs->getName () < rhs;
}
// ======================================================================
#endif
@@ -0,0 +1,21 @@
// ======================================================================
//
// NoRenderAppearance.cpp
// Portions copyright 2004 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/NoRenderAppearance.h"
#include "sharedObject/NoRenderAppearanceTemplate.h"
// ======================================================================
NoRenderAppearance::NoRenderAppearance(NoRenderAppearanceTemplate const * myAppearanceTemplate)
: Appearance(myAppearanceTemplate)
{
}
// ======================================================================
@@ -0,0 +1,38 @@
// ======================================================================
//
// NoRenderAppearance.h
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001, 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_NoRenderAppearance_H
#define INCLUDED_NoRenderAppearance_H
// ======================================================================
class NoRenderAppearanceTemplate;
#include "sharedObject/Appearance.h"
// ======================================================================
class NoRenderAppearance : public Appearance
{
friend class NoRenderAppearanceTemplate;
private:
NoRenderAppearance(NoRenderAppearanceTemplate const * appearanceTemplate);
private:
// disabled
NoRenderAppearance();
NoRenderAppearance(NoRenderAppearance const &);
NoRenderAppearance & operator = (NoRenderAppearance const &);
};
// ======================================================================
#endif
@@ -0,0 +1,64 @@
// ======================================================================
//
// NoRenderAppearanceTemplate.cpp
// Portions copyright 2004 Sony Online Entertainment
// All Rights Reserved
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/NoRenderAppearanceTemplate.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/Tag.h"
#include "sharedObject/AppearanceTemplateList.h"
#include "sharedObject/NoRenderAppearance.h"
// ======================================================================
namespace NoRenderAppearanceTemplateNamespace
{
const Tag TAG_NRND = TAG(N,R,N,D);
AppearanceTemplate *create(const char *newName, Iff *iff);
};
using namespace NoRenderAppearanceTemplateNamespace;
// ======================================================================
void NoRenderAppearanceTemplate::install()
{
AppearanceTemplateList::assignBinding(TAG_NRND, NoRenderAppearanceTemplateNamespace::create);
}
// ----------------------------------------------------------------------
AppearanceTemplate *NoRenderAppearanceTemplateNamespace::create(const char *newName, Iff *iff)
{
return new NoRenderAppearanceTemplate(newName, iff);
}
// ======================================================================
NoRenderAppearanceTemplate::NoRenderAppearanceTemplate(const char *name, Iff *iff)
: AppearanceTemplate(name)
{
iff->enterForm(TAG_NRND);
iff->exitForm(TAG_NRND);
}
// ----------------------------------------------------------------------
NoRenderAppearanceTemplate::~NoRenderAppearanceTemplate()
{
}
// ----------------------------------------------------------------------
Appearance * NoRenderAppearanceTemplate::createAppearance() const
{
return new NoRenderAppearance(this);
}
// ======================================================================
@@ -0,0 +1,40 @@
// ======================================================================
//
// NoRenderAppearanceTemplate.h
// Portions copyright 2004 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_NoRenderAppearanceTemplate_H
#define INCLUDED_NoRenderAppearanceTemplate_H
// ======================================================================
#include "sharedObject/AppearanceTemplate.h"
// ======================================================================
class NoRenderAppearanceTemplate : public AppearanceTemplate
{
public:
static void install();
public:
NoRenderAppearanceTemplate(const char *name, Iff *iff);
virtual ~NoRenderAppearanceTemplate();
virtual Appearance * createAppearance() const;
private:
NoRenderAppearanceTemplate();
NoRenderAppearanceTemplate(NoRenderAppearanceTemplate const &);
NoRenderAppearanceTemplate & operator = (NoRenderAppearanceTemplate const &);
};
// ======================================================================
#endif
@@ -0,0 +1,25 @@
// ======================================================================
//
// TextAppearance.cpp
// Copyright 2001, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/TextAppearance.h"
// ======================================================================
TextAppearance::TextAppearance () :
Appearance (0)
{
}
// ----------------------------------------------------------------------
TextAppearance::~TextAppearance ()
{
}
// ======================================================================
@@ -0,0 +1,38 @@
// ======================================================================
//
// TextAppearance.h
// Copyright 2001, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_TextAppearance_H
#define INCLUDED_TextAppearance_H
// ======================================================================
#include "sharedObject/Appearance.h"
class VectorArgb;
// ======================================================================
class TextAppearance : public Appearance
{
public:
TextAppearance ();
virtual ~TextAppearance ()=0;
virtual void setText(const char* text)=0;
virtual void setColor(const VectorArgb& color)=0;
private:
TextAppearance (const TextAppearance& rhs);
TextAppearance& operator= (const TextAppearance& rhs);
};
// ======================================================================
#endif
@@ -0,0 +1,36 @@
// ======================================================================
//
// Tweakable.cpp
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Tweakable.h"
// ======================================================================
Tweakable::~Tweakable()
{
}
// ----------------------------------------------------------------------
float Tweakable::getTweakValue ( int whichValue ) const
{
UNREF(whichValue);
return 0.0f;
}
// ----------------------------------------------------------------------
void Tweakable::setTweakValue ( int whichValue, float newValue )
{
UNREF(whichValue);
UNREF(newValue);
}
// ======================================================================
@@ -0,0 +1,40 @@
// ======================================================================
//
// Tweakable.h
// Portions copyright 1999 Bootprint Entertainment
// Portions copyright 2001, 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_Tweakable_H
#define INCLUDED_Tweakable_H
// ======================================================================
// Simple interface for setting/getting tweak values on objects.
class Tweakable
{
public:
Tweakable();
virtual ~Tweakable();
virtual float getTweakValue ( int whichValue ) const;
virtual void setTweakValue ( int whichValue, float newValue );
private:
Tweakable(const Tweakable &);
Tweakable &operator =(const Tweakable &);
};
// ======================================================================
inline Tweakable::Tweakable()
{
}
// ======================================================================
#endif
@@ -0,0 +1,154 @@
// ======================================================================
//
// ArrangementDescriptor.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ArrangementDescriptor.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedObject/ArrangementDescriptorList.h"
#include "sharedObject/SlotId.h"
#include "sharedObject/SlotIdManager.h"
#include <vector>
// ======================================================================
const Tag TAG_ARG = TAG3(A,R,G);
const Tag TAG_ARGD = TAG(A,R,G,D);
// ======================================================================
ArrangementDescriptor::ArrangementDescriptor(Iff &iff, const CrcLowerString &name)
: m_name(new CrcLowerString(name)),
m_referenceCount(0),
m_arrangements(new ArrangementVector())
{
// load instance data from iff
iff.enterForm(TAG_ARGD);
// handle version loading
const Tag version = iff.getCurrentName();
if (version == TAG_0000)
load_0000(iff);
else
{
char buffer[5];
ConvertTagToString(version, buffer);
FATAL(true, ("unsupported ArrangementDescriptor version [%s]", buffer));
}
iff.exitForm(TAG_ARGD);
}
// ----------------------------------------------------------------------
const CrcLowerString &ArrangementDescriptor::getName() const
{
return *m_name;
}
// ----------------------------------------------------------------------
int ArrangementDescriptor::getReferenceCount() const
{
return m_referenceCount;
}
// ----------------------------------------------------------------------
void ArrangementDescriptor::fetch() const
{
++m_referenceCount;
}
// ----------------------------------------------------------------------
void ArrangementDescriptor::release() const
{
--m_referenceCount;
// check if we need to delete this one
if (m_referenceCount < 1)
{
ArrangementDescriptorList::stopTracking(*this);
delete const_cast<ArrangementDescriptor*>(this);
}
}
// ----------------------------------------------------------------------
int ArrangementDescriptor::getArrangementCount() const
{
return static_cast<int>(m_arrangements->size());
}
// ----------------------------------------------------------------------
const ArrangementDescriptor::SlotIdVector &ArrangementDescriptor::getArrangement(int index) const
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, static_cast<int>(m_arrangements->size()));
return (*m_arrangements)[static_cast<size_t>(index)];
}
// ======================================================================
ArrangementDescriptor::~ArrangementDescriptor()
{
DEBUG_WARNING(m_referenceCount != 0, ("non-zero reference count upon deletion: bad reference handling (%d)", m_referenceCount));
delete m_arrangements;
delete m_name;
}
// ----------------------------------------------------------------------
void ArrangementDescriptor::load_0000(Iff &iff)
{
iff.enterForm(TAG_0000);
{
CrcLowerString slotName("");
char buffer[1024];
SlotIdVector arrangement;
// load the arrangement list
while (!iff.atEndOfForm())
{
iff.enterChunk(TAG_ARG);
{
// load the arrangement
while (iff.getChunkLengthLeft())
{
// load slot name
iff.read_string(buffer, sizeof(buffer) - 1);
slotName.setString(buffer);
// convert slot name to SlotId
const SlotId slotId = SlotIdManager::findSlotId(slotName);
if (slotId == SlotId::invalid)
WARNING(true, ("ArrangementDescriptor [%s] specified invalid slot name [%s], ignoring", m_name->getString(), slotName.getString()));
else
arrangement.push_back(slotId);
}
}
iff.exitChunk(TAG_ARG);
// add arrangement to list of arrangements
m_arrangements->push_back(arrangement);
// cleanup temp vector
arrangement.clear();
}
}
iff.exitForm(TAG_0000);
}
// ======================================================================
@@ -0,0 +1,66 @@
// ======================================================================
//
// ArrangementDescriptor.h
// Copyright 2001 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ArrangementDescriptor_H
#define INCLUDED_ArrangementDescriptor_H
// ======================================================================
class CrcLowerString;
class Iff;
class SlotId;
// ======================================================================
class ArrangementDescriptor
{
friend class ArrangementDescriptorList;
public:
typedef stdvector<SlotId>::fwd SlotIdVector;
public:
ArrangementDescriptor(Iff &iff, const CrcLowerString &name);
const CrcLowerString &getName() const;
int getReferenceCount() const;
void fetch() const;
void release() const;
int getArrangementCount() const;
const SlotIdVector &getArrangement(int index) const;
private:
typedef stdvector<SlotIdVector>::fwd ArrangementVector;
private:
~ArrangementDescriptor();
void load_0000(Iff &iff);
// disabled
ArrangementDescriptor(const ArrangementDescriptor&);
ArrangementDescriptor &operator =(const ArrangementDescriptor&);
private:
CrcLowerString *m_name;
mutable int m_referenceCount;
ArrangementVector *m_arrangements;
};
// ======================================================================
#endif
@@ -0,0 +1,156 @@
// ======================================================================
//
// ArrangementDescriptorList.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ArrangementDescriptorList.h"
#include "sharedDebug/DataLint.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/ConstCharCrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedObject/ArrangementDescriptor.h"
#include <map>
#include <string>
// ======================================================================
bool ArrangementDescriptorList::ms_installed;
ArrangementDescriptorList::DescriptorMap *ArrangementDescriptorList::ms_descriptors;
ConstCharCrcLowerString ArrangementDescriptorList::ms_defaultFilename("arrangement/arrangement_none.iff");
// ======================================================================
void ArrangementDescriptorList::install()
{
DEBUG_FATAL(ms_installed, ("ArrangementDescriptorList already installed"));
ms_descriptors = new DescriptorMap();
ms_installed = true;
ExitChain::add(remove, "ArrangementDescriptorList");
}
// ----------------------------------------------------------------------
const ArrangementDescriptor *ArrangementDescriptorList::fetch(const CrcLowerString &filename)
{
DEBUG_FATAL(!ms_installed, ("ArrangementDescriptorList not installed"));
ArrangementDescriptor *descriptor = 0;
//-- check if we've got this one cached
DescriptorMap::iterator lowerBoundResult = ms_descriptors->lower_bound(&filename);
if ((lowerBoundResult != ms_descriptors->end()) && !ms_descriptors->key_comp()(&filename, lowerBoundResult->first))
{
// it's cached, return it
descriptor = lowerBoundResult->second;
}
else
{
// it's not available
Iff iff;
if (!iff.open(filename.getString(), true))
{
//-- make sure we didn't just fail on the default filename
if (filename != ms_defaultFilename)
{
WARNING(true, ("ArrangementDescriptor file [%s] does not exist, using default", filename.getString()));
return fetch(ms_defaultFilename);
}
else
{
WARNING(true, ("default ArrangementDescriptor [%s] could not be loaded, returning NULL ArrangementDescriptor", filename.getString()));
return 0;
}
}
#ifdef _DEBUG
DataLint::pushAsset(filename.getString());
#endif // _DEBUG
//-- load it
descriptor = new ArrangementDescriptor(iff, filename);
#ifdef _DEBUG
DataLint::popAsset();
#endif // _DEBUG
//-- add to managed container
IGNORE_RETURN(ms_descriptors->insert(lowerBoundResult, DescriptorMap::value_type(&descriptor->getName(), descriptor)));
}
// we should have a valid slot descriptor here
NOT_NULL(descriptor);
//-- bump up reference count
descriptor->fetch();
return descriptor;
}
// ----------------------------------------------------------------------
const ArrangementDescriptor *ArrangementDescriptorList::fetch(const std::string &filename)
{
DEBUG_FATAL(!ms_installed, ("ArrangementDescriptorList not installed"));
return fetch(CrcLowerString(filename.c_str()));
}
// ======================================================================
void ArrangementDescriptorList::remove()
{
DEBUG_FATAL(!ms_installed, ("ArrangementDescriptorList not installed"));
//-- handle leaks
if (!ms_descriptors->empty())
{
DEBUG_WARNING(true, ("ArrangementDescriptorList detected %u ArrangementDescriptor leaks:", ms_descriptors->size()));
const DescriptorMap::iterator endIt = ms_descriptors->end();
for (DescriptorMap::iterator it = ms_descriptors->begin(); it != endIt; ++it)
{
ArrangementDescriptor *const descriptor = it->second;
DEBUG_WARNING(descriptor, ("-- leaked ArrangementDescriptor [%s]", descriptor->getName().getString()));
delete descriptor;
}
}
delete ms_descriptors;
ms_installed = false;
}
// ----------------------------------------------------------------------
void ArrangementDescriptorList::stopTracking(const ArrangementDescriptor &descriptor)
{
DEBUG_FATAL(!ms_installed, ("ArrangementDescriptorList not installed"));
//-- find the descriptor within our managed container
const CrcLowerString &filename = descriptor.getName();
DescriptorMap::iterator lowerBoundResult = ms_descriptors->lower_bound(&filename);
if ((lowerBoundResult == ms_descriptors->end()) || ms_descriptors->key_comp()(&filename, lowerBoundResult->first))
{
// Specified descriptor not managed. It could be unnamed (i.e. anonymous).
return;
}
//-- remove from managed container
ms_descriptors->erase(lowerBoundResult);
}
// ======================================================================
@@ -0,0 +1,52 @@
// ======================================================================
//
// ArrangementDescriptorList.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ArrangementDescriptorList_H
#define INCLUDED_ArrangementDescriptorList_H
// ======================================================================
class ArrangementDescriptor;
class ConstCharCrcLowerString;
class CrcLowerString;
class LessPointerComparator;
// ======================================================================
class ArrangementDescriptorList
{
friend class ArrangementDescriptor;
public:
static void install();
static const ArrangementDescriptor *fetch(const CrcLowerString &filename);
static const ArrangementDescriptor *fetch(const std::string &filename);
private:
typedef stdmap<const CrcLowerString*, ArrangementDescriptor*, LessPointerComparator>::fwd DescriptorMap;
private:
static void remove();
static void stopTracking(const ArrangementDescriptor &descriptor);
private:
static bool ms_installed;
static DescriptorMap *ms_descriptors;
static ConstCharCrcLowerString ms_defaultFilename;
};
// ======================================================================
#endif
@@ -0,0 +1,81 @@
// ======================================================================
//
// ContainedByProperty.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedObject/CellProperty.h"
#include "sharedObject/Container.h"
#include "sharedObject/Object.h"
#include "sharedObject/NetworkIdManager.h"
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(ContainedByProperty, true, 0, 0, 0);
// ======================================================================
PropertyId ContainedByProperty::getClassPropertyId()
{
return PROPERTY_HASH(ContainedBy, 0x704360EC);
}
// ======================================================================
ContainedByProperty::ContainedByProperty(Object& thisObject, Object* containedByObject) :
Property(getClassPropertyId(), thisObject),
m_containedBy(CachedNetworkId::cms_cachedInvalid)
{
if (containedByObject)
m_containedBy = CachedNetworkId(*containedByObject);
}
//-------------------------------------------------------------------------
ContainedByProperty::~ContainedByProperty()
{
}
// ======================================================================
/**
* Return the container that contains the object that has this ContainedBy
* property.
*
* @return Pointer to the object that contains the object with this
* ContainedByProperty. Returns NULL if the object isn't
* contained by anything at the moment.
*/
Object* ContainedByProperty::getContainedBy() const
{
return m_containedBy.getObject();
}
// ----------------------------------------------------------------------
const NetworkId& ContainedByProperty::getContainedByNetworkId() const
{
return m_containedBy;
}
// ----------------------------------------------------------------------
void ContainedByProperty::setContainedBy(const NetworkId & id, bool local)
{
if (m_containedBy != id)
{
NetworkId oldValue = m_containedBy;
m_containedBy = id;
getOwner().containedByModified(oldValue, id, local);
}
}
// ======================================================================
@@ -0,0 +1,48 @@
// ======================================================================
//
// ContainedByProperty.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ContainedByProperty_H
#define INCLUDED_ContainedByProperty_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/CachedNetworkId.h"
#include "sharedObject/Property.h"
// ======================================================================
class ContainedByProperty : public Property
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
static PropertyId getClassPropertyId();
public:
ContainedByProperty(Object& thisObject, Object* containedByObject);
~ContainedByProperty();
Object* getContainedBy() const;
const NetworkId & getContainedByNetworkId() const;
void setContainedBy(const NetworkId &id, bool local = true);
private:
CachedNetworkId m_containedBy;
ContainedByProperty();
ContainedByProperty(const ContainedByProperty&);
ContainedByProperty& operator= (const ContainedByProperty&);
};
// ======================================================================
#endif
@@ -0,0 +1,856 @@
// ======================================================================
//
// Container.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Container.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/AlterScheduler.h"
#include "sharedObject/ConfigSharedObject.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedObject/Object.h"
#include <cstdio>
// ======================================================================
//Lint suppressions.
//lint -esym(613, ContainerIterator::m_iterator) // (Warning -- Possible use of null pointer 'ContainerIterator::m_iterator' ) // This is an opaque data type to us. We can only check against a container::end().
//lint -esym(1540, ContainerIterator::m_iterator) // (Warning -- Pointer member 'ContainerIterator::m_iterator' neither freed nor zero'ed by destructor -- Effective C++ #6) // It's okay, the iterator type is opaque to us, we have no idea it's a pointer.
//lint -esym(1554, ContainerIterator::m_iterator) // (Warning -- Direct copy of pointer 'ContainerIterator::m_iterator'. // It's okay, the iterator type is opaque to us, we have no idea it's a pointer.
//lint -esym(1555, ContainerIterator::m_iterator) // (Warning -- Direct pointer copy of member 'ContainerIterator::m_iterator' within copy assignment operator: 'ContainerIterator::operator=(const ContainerIterator &) // Opaque type, we don't know its a pointer.
//lint -esym(1555, ContainerIterator::m_owner) // (Warning -- Direct pointer copy of member 'ContainerIterator::m_owner' within copy assignment operator: 'ContainerIterator::operator=(const ContainerIterator &) // We do not own this memory, so it's okay to overwrite the pointer. We can't leak it.
//lint -esym(613, ContainerConstIterator::m_iterator) // (Warning -- Possible use of null pointer 'ContainerConstIterator::m_iterator' ) // This is an opaque data type to us. We can only check against a container::end().
//lint -esym(1540, ContainerConstIterator::m_iterator) // (Warning -- Pointer member 'ContainerConstIterator::m_iterator' neither freed nor zero'ed by destructor -- Effective C++ #6) // It's okay, the iterator type is opaque to us, we have no idea it's a pointer.
//lint -esym(1554, ContainerConstIterator::m_iterator) // (Warning -- Direct copy of pointer 'ContainerConstIterator::m_iterator'. // It's okay, the iterator type is opaque to us, we have no idea it's a pointer.
//lint -esym(1555, ContainerConstIterator::m_iterator) // (Warning -- Direct pointer copy of member 'ContainerConstIterator::m_iterator' within copy assignment operator: 'ContainerConstIterator::operator=(const ContainerConstIterator &) // Opaque type, we don't know its a pointer.
//lint -esym(1555, ContainerConstIterator::m_owner) // (Warning -- Direct pointer copy of member 'ContainerConstIterator::m_owner' within copy assignment operator: 'ContainerConstIterator::operator=(const ContainerConstIterator &) // We do not own this memory, so it's okay to overwrite the pointer. We can't leak it.
//-----------------------------------------------------------------------
namespace ContainerNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int checkDepth(const Container& container)
{
int count = 0;
const ContainedByProperty* parentCpb = container.getOwner().getContainedByProperty();
if (!parentCpb)
return count;
const Object* parentObject = parentCpb->getContainedBy();
if (!parentObject)
return count;
while(parentObject)
{
++count;
parentCpb = parentObject->getContainedByProperty();
if (!parentCpb)
return count;
parentObject = parentCpb->getContainedBy();
}
return count;
}
}
using namespace ContainerNamespace;
//-----------------------------------------------------------------------
ContainerIterator::ContainerIterator() :
m_iterator(0),
m_owner(0)
{
}
//-----------------------------------------------------------------------
ContainerIterator::ContainerIterator(Container & owner, const std::vector<CachedNetworkId>::iterator & iter) :
m_iterator(iter),
m_owner(&owner)
{
}
//-----------------------------------------------------------------------
ContainerIterator::~ContainerIterator()
{
// We don't own the owner pointer.
m_owner = 0;
}
//-----------------------------------------------------------------------
ContainerIterator::ContainerIterator(const ContainerIterator & rhs) :
m_iterator(rhs.m_iterator),
m_owner(rhs.m_owner) //lint !e1554 // Direct copy of pointer member. // @todo revisit. There doesn't appear to be any mechanism in place to guarantee the owner container sticks around for the iterator. This is dangerous.
{
}
//-----------------------------------------------------------------------
ContainerIterator & ContainerIterator::operator= (const ContainerIterator & rhs)
{
if ((&rhs == this) || (rhs == *this))
return *this;
m_iterator = rhs.m_iterator;
m_owner = rhs.m_owner;
return *this;
}
//-----------------------------------------------------------------------
CachedNetworkId & ContainerIterator::operator*()
{
// @todo fix this interface -- it is broken. It is possible to
// construct a ContainerIterator with a NULL m_iterator, but there is
// no way to gracefully exit from this function since it requires a non-const
// reference. Otherwise I would return CachedNetworkId::cms_cachedIvalid.
NOT_NULL(m_owner);
DEBUG_FATAL(m_iterator == m_owner->m_contents.end(), ("Tried to dereference invalid iterator.\n"));
return *m_iterator;
}
//-----------------------------------------------------------------------
bool ContainerIterator::operator==(const ContainerIterator & rhs) const
{
return m_iterator == rhs.m_iterator;
}
//-----------------------------------------------------------------------
bool ContainerIterator::operator!=(const ContainerIterator & rhs) const
{
return !(rhs == *this);
}
ContainerIterator ContainerIterator::operator++(int tmp)
{
UNREF(tmp);
ContainerIterator *retval = this;
++(*this);
return *retval;
}
//-----------------------------------------------------------------------
ContainerIterator& ContainerIterator::operator++()
{
NOT_NULL(m_owner);
if (m_iterator == m_owner->m_contents.end())
return *this;
++m_iterator;
while (m_iterator != m_owner->m_contents.end() && *m_iterator == NetworkId::cms_invalid)
{
++m_iterator;
}
return *this;
}
//-----------------------------------------------------------------------
ContainerConstIterator::ContainerConstIterator() :
m_iterator(0),
m_owner(0)
{
}
//-----------------------------------------------------------------------
ContainerConstIterator::ContainerConstIterator(const Container & owner, const std::vector<CachedNetworkId>::const_iterator & iter) :
m_iterator(iter),
m_owner(&owner)
{
}
//-----------------------------------------------------------------------
ContainerConstIterator::~ContainerConstIterator()
{
// We don't own the m_owner pointer.
m_owner = 0;
}
//-----------------------------------------------------------------------
ContainerConstIterator::ContainerConstIterator(const ContainerConstIterator & rhs) :
m_iterator(rhs.m_iterator),
m_owner(rhs.m_owner) //lint !e1554 // Direct copy of pointer member. // @todo revisit. There doesn't appear to be any mechanism in place to guarantee the owner container sticks around for the iterator. This is dangerous.
{
}
//-----------------------------------------------------------------------
ContainerConstIterator & ContainerConstIterator::operator= (const ContainerConstIterator & rhs)
{
if ((&rhs == this) || (rhs == *this))
return *this;
m_iterator = rhs.m_iterator;
m_owner = rhs.m_owner;
return *this;
}
//-----------------------------------------------------------------------
const CachedNetworkId & ContainerConstIterator::operator*() const
{
// @todo fix this interface -- it is broken. It is possible to
// construct a ContainerIterator with a NULL m_iterator, but there is
// no way to gracefully exit from this function since it requires a non-const
// reference. Otherwise I would return CachedNetworkId::cms_cachedIvalid.
NOT_NULL(m_owner);
if (m_iterator == m_owner->m_contents.end())
{
DEBUG_WARNING(true, ("Tried to dereference invalid iterator.\n"));
return CachedNetworkId::cms_cachedInvalid;
}
return *m_iterator;
}
//-----------------------------------------------------------------------
bool ContainerConstIterator::operator==(const ContainerConstIterator & rhs) const
{
return m_iterator == rhs.m_iterator;
}
//-----------------------------------------------------------------------
bool ContainerConstIterator::operator!=(const ContainerConstIterator & rhs) const
{
return !(rhs == *this);
}
//-----------------------------------------------------------------------
ContainerConstIterator ContainerConstIterator::operator++(int tmp)
{
UNREF(tmp);
ContainerConstIterator *retval = this;
++(*this);
return *retval;
}
//-----------------------------------------------------------------------
ContainerConstIterator& ContainerConstIterator::operator++()
{
NOT_NULL(m_owner);
if (m_iterator == m_owner->m_contents.end())
return *this;
++m_iterator;
while (m_iterator != m_owner->m_contents.end() && *m_iterator == NetworkId::cms_invalid)
{
++m_iterator;
}
return *this;
}
//-----------------------------------------------------------------------
Container::Container(PropertyId propertyId, Object& owner) :
Property(propertyId, owner),
m_changed(false),
m_contents(),
m_numContents(0)
{
}
//-----------------------------------------------------------------------
Container::~Container()
{
Contents::const_iterator i = m_contents.begin();
for(;i != m_contents.end(); ++i)
{
if (*i != NetworkId::cms_invalid) //was getValue
{
Object *const object = i->getObject();
if (object)
{
IGNORE_RETURN(AlterScheduler::removeObject(*object));
delete object;
}
}
}
}
//-----------------------------------------------------------------------
ContainerIterator Container::begin()
{
//Getting ready to put in fix for iterator code.
ContainerIterator ret(*this, m_contents.begin());
while (ret.m_iterator != m_contents.end() && *ret == NetworkId::cms_invalid)
{
++ret.m_iterator;
}
return ret;
}
//-----------------------------------------------------------------------
ContainerIterator Container::end()
{
return ContainerIterator(*this, m_contents.end());
}
//-----------------------------------------------------------------------
ContainerConstIterator Container::begin() const
{
//Getting ready to put in fix for iterator code.
ContainerConstIterator ret(*this, m_contents.begin());
while (ret.m_iterator != m_contents.end() && *ret == NetworkId::cms_invalid)
{
++ret.m_iterator;
}
return ret;
}
//-----------------------------------------------------------------------
ContainerConstIterator Container::end() const
{
return ContainerConstIterator(*this, m_contents.end());
}
//-----------------------------------------------------------------------
int Container::addToContents(Object& item, ContainerErrorCode& error)
{
error = CEC_Success;
if (!mayAdd(item, error))
return -1;
ContainedByProperty * containedItem = item.getContainedByProperty();
FATAL(!containedItem, ("Cannot add an item with no containedByProperty to a container."));
if (containedItem->getContainedBy() && containedItem->getContainedBy() != &getOwner())
{
WARNING_STRICT_FATAL(true, ("Cannot add an item [%s] to a container [%s] when it is already contained!", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_AlreadyIn;
return -1;
}
if (ConfigSharedObject::getContainerLoopChecking())
{
//Check that we don't introduce an infinite loop
//First check for container property. Only containers can introduce a loop
Container* contCheck = item.getContainerProperty();
if (contCheck)
{
ContainedByProperty * cbIter = getOwner().getContainedByProperty();
if (cbIter)
{
NetworkId iterId = cbIter->getContainedByNetworkId();
if (iterId != NetworkId::cms_invalid)
{
std::vector<NetworkId> checkVector;
checkVector.reserve(10);
checkVector.push_back(getOwner().getNetworkId());
for( int count = 0; iterId != NetworkId::cms_invalid; ++count)
{
if (count > ConfigSharedObject::getContainerMaxDepth())
{
DEBUG_FATAL(true, ("Too deep a container heirarchy"));
WARNING(true, ("Too deep a container heirarchy")); //lint !e527 // unreachable // reachable in release.
error = CEC_TooDeep;
return -1;
}
checkVector.push_back(iterId);
Object* obj = cbIter->getContainedBy();
iterId = NetworkId::cms_invalid;
if (obj)
{
cbIter = obj->getContainedByProperty();
if (cbIter)
{
iterId = cbIter->getContainedByNetworkId();
}
}
}
if (std::find(checkVector.begin(), checkVector.end(), item.getNetworkId()) != checkVector.end())
{
//detected a loop.
WARNING_STRICT_FATAL(true, ("Adding item %s to %s would have introduced a container loop", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_AlreadyIn;
return -1;
}
}
}
}
}
if (checkDepth(*this) > ConfigSharedObject::getContainerMaxDepth())
{
error = CEC_TooDeep;
return -1;
}
if (isItemContained(item.getNetworkId(), error))
{
WARNING_STRICT_FATAL(true, ("Cannot add an item [%s] to a container [%s] when it is already in it! This shouldn't happen because the item's contained by property says it is not in this container, but it is in the container's internal list.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_AlreadyIn;
return -1;
}
const CachedNetworkId id(item);
containedItem->setContainedBy(getOwner().getNetworkId());
int retval = insertNewItem(id);
if (retval == -1)
error = CEC_Unknown;
return retval;
}
//-----------------------------------------------------------------------
PropertyId Container::getClassPropertyId()
{
return PROPERTY_HASH(Container, 0x55DC5726);
}
//-----------------------------------------------------------------------
int Container::insertNewItem(const Container::ContainedItem& id)
{
ContainerErrorCode tmp = CEC_Success;;
if (isItemContained(id, tmp))
{
DEBUG_WARNING(true, ("Cannot add item [%s] to container [%s] when it is already in it!", id.getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
return -1;
}
if (id == getOwner().getNetworkId())
{
WARNING_STRICT_FATAL(true, ("Tried to add an item %s to itself!\n", id.getValueString().c_str()));
return -1;
}
Contents::iterator i = m_contents.begin();
int count = 0;
++m_numContents;
for(;i != m_contents.end(); ++i)
{
if (*i == NetworkId::cms_invalid)
{
(*i) = id;
return count;
}
++count;
}
m_contents.push_back(id);
return count;
}
//-----------------------------------------------------------------------
int Container::find(const NetworkId& item, ContainerErrorCode& error) const
{
error = CEC_Success;
int count = 0;
Contents::const_iterator i = m_contents.begin();
for(;i != m_contents.end(); ++i)
{
if ((*i) == item)
{
return count;
}
++count;
}
error = CEC_NotFound;
return -1;
}
//-----------------------------------------------------------------------
int Container::getNumberOfItems (void) const
{
return m_numContents;
}
//-----------------------------------------------------------------------
void Container::addToWorld()
{
for (Contents::const_iterator i = m_contents.begin(); i != m_contents.end(); ++i)
{
Object *obj = (*i).getObject();
if (obj && isContentItemExposedWith(*obj))
obj->addToWorld();
}
}
//-----------------------------------------------------------------------
void Container::removeFromWorld()
{
for (Contents::const_iterator i = m_contents.begin(); i != m_contents.end(); ++i)
{
Object *obj = (*i).getObject();
if (obj && isContentItemExposedWith(*obj))
obj->removeFromWorld();
}
}
// ----------------------------------------------------------------------
/**
* Returns true if the item is or would be observed with its container.
*
* This function can be called on an item in the container or an item
* that the caller already knows it will be putting in the container.
*
* If this function returns true, it indicates that the contained item
* should be added to the world and should be observed whenever the same
* happens to the container. In other words, the item within the container
* has the same visibility as the container itself. Mounts make use of this
* to expose the rider whenever the mount is exposed.
*
* Derived container class note: derived containers should chain up to
* this function first. If it returns true, you're done because that
* implies the container blanket-exposes all contents. If the function
* returns false, then do any container-specific checks that might
* allow this particular object to be exposed. Slotted containers work
* this way to allow slot-by-slot specification of observation
* characteristics.
*
* @param item the item that is contained or will soon be contained by
* the container.
*
* @return true if the item should be exposed with the same observation
* and world characterstics as the container.
*/
bool Container::isContentItemObservedWith(Object const &item) const
{
UNREF(item);
return false;
}
//-----------------------------------------------------------------------
/**
* Returns true if the item should be in the world if its container is
* in the world.
*
* This function can be called on an item in the container or an item
* that the caller already knows it will be putting in the container.
*
* If this function returns true, it indicates that the contained item
* should be added to the world whenever the container is added to the world.
*
* Derived container class note: derived containers should chain up to
* this function first. If it returns true, you're done because that
* implies the container blanket-exposes all contents. If the function
* returns false, then do any container-specific checks that might
* allow this particular object to be exposed. Slotted containers work
* this way to allow slot-by-slot specification of exposing
* characteristics.
*
* @param item the item that is contained or will soon be contained by
* the container.
*
* @return true if the item should be exposed with the same observation
* and world characterstics as the container.
*/
bool Container::isContentItemExposedWith(Object const &item) const
{
UNREF(item);
return false;
}
//-----------------------------------------------------------------------
bool Container::canContentsBeObservedWith() const
{
return false;
}
//-----------------------------------------------------------------------
void Container::alter(real time)
{
FATAL(!Object::shouldObjectsAlterChildrenAndContents(), ("Container::alter called when containers should not be altering!"));
std::vector<Object *> objectsToDelete;
for (Contents::const_iterator i = m_contents.begin(); i != m_contents.end(); ++i)
{
Object *obj = (*i).getObject();
if (obj)
{
if (obj->isInitialized() && !isContentItemExposedWith(*obj) && !obj->isChildObject())
{
AlterScheduler::setMostRecentAlterTime(*obj);
if (obj->alter(time) == AlterResult::cms_kill) //lint !e777 // testing floats for equality // it's okay, set/compare against constants.
{
objectsToDelete.push_back(obj);
}
}
}
}
for (std::vector<Object *>::iterator j = objectsToDelete.begin(); j != objectsToDelete.end(); ++j)
{
Object *const objectToKill = *j;
ContainerErrorCode error = CEC_Success;
IGNORE_RETURN(remove (*objectToKill, error));
delete objectToKill;
}
objectsToDelete.clear();
}
//-----------------------------------------------------------------------
void Container::conclude()
{
}
//-----------------------------------------------------------------------
bool Container::isItemContained (const NetworkId& item, ContainerErrorCode& error) const
{
return (Container::find(item, error) != -1);
}
//-----------------------------------------------------------------------
bool Container::remove (Object &item, ContainerErrorCode& error)
{
error = CEC_Unknown;
bool retval = false;
ContainedByProperty* property = item.getContainedByProperty();
WARNING_STRICT_FATAL(!property, ("Cannot remove an item that has no containedby property"));
if (property)
{
if (property->getContainedBy() != &getOwner())
{
WARNING_STRICT_FATAL(true, ("Cannot remove an item [%s] from container [%s] whose containedBy says it isn't in this container.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_NotFound;
return false;
}
retval = internalRemoveItem(item);
if (retval)
{
error = CEC_Success;
property->setContainedBy(NetworkId::cms_invalid);
}
}
return retval;
}
//-----------------------------------------------------------------------
const Container::ContainedItem& Container::getContents (int position) const
{
DEBUG_FATAL(position > static_cast<int>(m_contents.size()), ("Tried to index a container larger than the number of contents."));
return m_contents[static_cast<Contents::size_type>(position)];
}
//-----------------------------------------------------------------------
void Container::debugPrint(std::string &buffer) const
{
char tempBuffer[1024];
buffer += "====[BEGIN: container]====\n";
//-- List supported slots and container indices.
sprintf(tempBuffer, "container id [%s]: contains [%d] objects.\n", getOwner().getNetworkId().getValueString().c_str(), static_cast<int>(m_contents.size()));
buffer += tempBuffer;
int index = 0;
Contents::const_iterator const endIt = m_contents.end();
for (Contents::const_iterator it = m_contents.begin(); it != endIt; ++it, ++index)
{
Object const *const object = it->getObject();
sprintf(tempBuffer, "\tindex [%d]: object id [%s], template [%s]\n", index, it->getValueString().c_str(), object ? object->getObjectTemplateName() : "<getObject() reported NULL object>");
buffer += tempBuffer;
}
buffer += "====[END: container]====\n";
}
// ----------------------------------------------------------------------
void Container::debugLog() const
{
#ifdef _DEBUG
DEBUG_REPORT_LOG(true, ("====[BEGIN: container]====\n"));
//-- List supported slots and container indices.
DEBUG_REPORT_LOG(true, ("container id [%s]: contains [%d] objects.\n", getOwner().getNetworkId().getValueString().c_str(), static_cast<int>(m_contents.size())));
int index = 0;
Contents::const_iterator const endIt = m_contents.end();
for (Contents::const_iterator it = m_contents.begin(); it != endIt; ++it, ++index)
{
Object const *const object = it->getObject();
DEBUG_REPORT_LOG(true, ("\tindex [%d]: object id [%s], template [%s]\n", index, it->getValueString().c_str(), object ? object->getObjectTemplateName() : "<getObject() reported NULL object>"));
}
DEBUG_REPORT_LOG(true, ("====[END: container]====\n"));
#endif
}
//-----------------------------------------------------------------------
bool Container::internalRemoveItem(const Object & item)
{
Contents::iterator i = m_contents.begin();
for(; i != m_contents.end(); ++i)
{
if ((*i) == item.getNetworkId())
{
(*i) = NetworkId::cms_invalid;
--m_numContents;
return true;
}
}
return false;
}
// ----------------------------------------------------------------------
/**
* Remove an item, identified by an iterator.
* Note that this does not invalidate iterators into the container.
*/
bool Container::remove(ContainerIterator &pos, ContainerErrorCode& error)
{
error = CEC_Success;
if (*(pos.m_iterator) != NetworkId::cms_invalid)
{
Object *obj = (*(pos.m_iterator)).getObject();
ContainedByProperty* property = 0;
if (obj)
property = obj->getContainedByProperty();
WARNING_STRICT_FATAL(!property, ("Cannot remove an item that has no containedby property"));
if (property)
{
if (property->getContainedBy() != &getOwner())
{
WARNING_STRICT_FATAL(true, ("Cannot remove an item [%s] from container [%s] whose containedBy says it isn't in this container.", (*pos).getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_NotFound;
return false;
}
property->setContainedBy(NetworkId::cms_invalid);
}
(*pos.m_iterator) = NetworkId::cms_invalid;
--m_numContents;
return true;
}
else
{
error = CEC_Unknown;
return false;
}
}
//------------------------------------------------------------------------------------------
bool Container::mayAdd (const Object& item, ContainerErrorCode& error) const
{
error = CEC_Success;
if (item.getNetworkId() == getOwner().getNetworkId())
{
error = CEC_AddSelf;
return false;
}
if (ConfigSharedObject::getContainerLoopChecking())
{
//Check that we don't introduce an infinite loop
//First check for container property. Only containers can introduce a loop
const Container* contCheck = item.getContainerProperty();
if (contCheck)
{
const ContainedByProperty * cbIter = getOwner().getContainedByProperty();
if (cbIter)
{
NetworkId iterId = cbIter->getContainedByNetworkId();
if (iterId != NetworkId::cms_invalid)
{
std::vector<NetworkId> checkVector;
checkVector.reserve(10);
checkVector.push_back(getOwner().getNetworkId());
for( int count = 0; iterId != NetworkId::cms_invalid; ++count)
{
if (count > ConfigSharedObject::getContainerMaxDepth())
{
WARNING(true, ("Too deep a container heirarchy"));
error = CEC_TooDeep;
return false;
}
checkVector.push_back(iterId);
const Object* obj = cbIter->getContainedBy();
iterId = NetworkId::cms_invalid;
if (obj)
{
cbIter = obj->getContainedByProperty();
if (cbIter)
{
iterId = cbIter->getContainedByNetworkId();
}
}
}
if (std::find(checkVector.begin(), checkVector.end(), item.getNetworkId()) != checkVector.end())
{
//detected a loop.
error = CEC_AlreadyIn;
return false;
}
}
}
}
}
if (checkDepth(*this) > ConfigSharedObject::getContainerMaxDepth())
{
error = CEC_TooDeep;
return false;
}
if (item.getNetworkId() == getOwner().getNetworkId())
{
error = CEC_AddSelf;
return false;
}
return true;
}
//-----------------------------------------------------------------------
//DO NOT CALL DIRECTLY
int Container::depersistContents(const Object& item)
{
CachedNetworkId id(item.getNetworkId());
return insertNewItem(id);
}
//-----------------------------------------------------------------------
//DO NOT CALL DIRECTLY
bool Container::internalItemRemoved(const Object& item)
{
return internalRemoveItem(item);
}
//-----------------------------------------------------------------------
@@ -0,0 +1,199 @@
// ======================================================================
//
// Container.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_Container_H
#define INCLUDED_Container_H
//-----------------------------------------------------------------------
#include "sharedObject/SlotIdArchive.h"
#include "sharedObject/CachedNetworkId.h"
#include "sharedObject/Property.h"
namespace Archive
{
class AutoDeltaByteStream;
}
class Object;
//-----------------------------------------------------------------------
class ContainerIterator
{
friend class Container;
public:
ContainerIterator();
ContainerIterator(Container &, const std::vector<CachedNetworkId>::iterator &);
~ContainerIterator();
ContainerIterator(const ContainerIterator &);
ContainerIterator & operator= (const ContainerIterator &);
ContainerIterator operator++(int);
ContainerIterator& operator++();
CachedNetworkId & operator*();
bool operator==(const ContainerIterator &) const;
bool operator!=(const ContainerIterator &) const;
private:
std::vector<CachedNetworkId>::iterator m_iterator;
Container * m_owner;
};
//-----------------------------------------------------------------------
class ContainerConstIterator
{
friend class Container;
public:
ContainerConstIterator();
ContainerConstIterator(const Container &, const std::vector<CachedNetworkId>::const_iterator &);
~ContainerConstIterator();
ContainerConstIterator(const ContainerConstIterator &);
ContainerConstIterator & operator= (const ContainerConstIterator &);
ContainerConstIterator operator++(int);
ContainerConstIterator& operator++();
const CachedNetworkId & operator*() const;
bool operator==(const ContainerConstIterator &) const;
bool operator!=(const ContainerConstIterator &) const;
private:
std::vector<CachedNetworkId>::const_iterator m_iterator;
const Container * m_owner;
};
//-----------------------------------------------------------------------
/** Abstract base class for containers
*/
class Container : public Property
{
public:
static PropertyId getClassPropertyId();
public:
typedef CachedNetworkId ContainedItem;
typedef std::vector<CachedNetworkId> Contents;
//Error Codes
enum ContainerErrorCode
{
CEC_Success = 0,
CEC_Unknown,
CEC_AddSelf,
CEC_Full,
CEC_SlotOccupied,
CEC_NoSlot,
CEC_InvalidArrangement,
CEC_WrongType,
CEC_NoPermission,
CEC_OutOfRange,
CEC_NotFound,
CEC_AlreadyIn,
CEC_TooLarge,
CEC_HouseItemLimit,
CEC_TooDeep,
CEC_TryAgain,
CEC_UnmovableType,
CEC_Unmovable,
CEC_CantSee,
CEC_InventoryFull,
CEC_TradeEquipped,
CEC_HopperNotEmpty,
CEC_VirtualContainerUnreachable,
CEC_VirtualContainerUserUnreachable,
CEC_VirtualContainerUserInvalid,
CEC_BlockedByScript,
CEC_BlockedByItemBeingTransferred,
CEC_BlockedBySourceContainer,
CEC_BlockedByDestinationContainer,
CEC_NoContainer,
CEC_SilentError,
CEC_BioLinkedToOtherPlayer,
CEC_Last //This must always be the last errorCode
};
//Iterator
friend class ContainerIterator;
friend class ContainerConstIterator;
// game interface:
virtual ~Container(void) = 0;
virtual void addToWorld();
virtual void removeFromWorld();
virtual bool isContentItemObservedWith(Object const &item) const;
virtual bool isContentItemExposedWith(Object const &item) const;
virtual bool canContentsBeObservedWith() const;
virtual void alter(real time);
virtual void conclude();
int getNumberOfItems (void) const;
virtual bool mayAdd (const Object& item, ContainerErrorCode& reason) const = 0;
virtual bool remove (Object &item, ContainerErrorCode& reason) = 0;
virtual bool remove (ContainerIterator &pos, ContainerErrorCode& reason) = 0;
ContainerIterator begin();
ContainerIterator end();
ContainerConstIterator begin() const;
ContainerConstIterator end() const;
// persistence interface:
// @todo would be nice to protect this somehow.
// but no good way now so DO NOT CALL THESE FUNCTIONS DIRECTLY
virtual int depersistContents(const Object& item);
virtual bool internalItemRemoved(const Object& item);
public:
bool hasChanged(void) const;
// debugging functions:
virtual void debugPrint(std::string &buffer) const =0;
virtual void debugLog() const;
protected:
/** add an item to the contents. Returns its new position. */
int addToContents(Object& item, ContainerErrorCode& error);
void clearChanged(void);
int find (const NetworkId& item, ContainerErrorCode& error) const;
const ContainedItem& getContents (int position) const;
Container(PropertyId propertyId, Object& owner);
private:
bool internalRemoveItem(const Object & item);
int insertNewItem(const ContainedItem & item);
/** This function is for use only by this class for debugging.
* You should use the containedBy pointer on the item to check for whether it is contained.
*/
bool isItemContained (const NetworkId& item, ContainerErrorCode & error) const;
bool m_changed;
Contents m_contents;
int m_numContents;
Container();
Container(const Container&);
Container& operator= (const Container&);
};
//-----------------------------------------------------------------------
#endif
@@ -0,0 +1,134 @@
// ======================================================================
//
// SlotDescriptor.cpp
// Copyright 2001 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlotDescriptor.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedObject/SlotDescriptorList.h"
#include "sharedObject/SlotId.h"
#include "sharedObject/SlotIdManager.h"
#include <vector>
// ======================================================================
const Tag TAG_SLTD = TAG(S,L,T,D);
// ======================================================================
SlotDescriptor::SlotDescriptor(Iff &iff, const CrcLowerString &name)
: m_name(new CrcLowerString(name)),
m_slots(new SlotIdVector()),
m_referenceCount(0)
{
// load object from Iff
iff.enterForm(TAG_SLTD);
const Tag version = iff.getCurrentName();
if (version == TAG_0000)
load_0000(iff);
else
{
char buffer[5];
ConvertTagToString(version, buffer);
DEBUG_FATAL(true, ("unsupported SlotDescriptor version [%s]\n", buffer));
}
iff.exitForm(TAG_SLTD);
}
// ----------------------------------------------------------------------
const CrcLowerString &SlotDescriptor::getName() const
{
return *m_name;
}
// ----------------------------------------------------------------------
const SlotDescriptor::SlotIdVector &SlotDescriptor::getSlots() const
{
return *m_slots;
}
// ----------------------------------------------------------------------
void SlotDescriptor::fetch() const
{
++m_referenceCount;
}
// ----------------------------------------------------------------------
void SlotDescriptor::release() const
{
--m_referenceCount;
if (m_referenceCount < 1)
{
// time to delete
//-- make sure SlotDescriptorList stops tracking this instance
SlotDescriptorList::stopTracking(*this);
//-- delete the instance
delete const_cast<SlotDescriptor*>(this);
}
}
// ----------------------------------------------------------------------
int SlotDescriptor::getReferenceCount() const
{
return m_referenceCount;
}
// ======================================================================
SlotDescriptor::~SlotDescriptor()
{
// if you get this warning, check if you are trying to delete the
// object when you should be fetch()ing and release()ing. Call
// release() instead.
DEBUG_WARNING(m_referenceCount != 0, ("SlotDescriptor %s destroyed with non-zero reference count [%d]", m_name->getString(), m_referenceCount));
delete m_slots;
delete m_name;
}
// ----------------------------------------------------------------------
void SlotDescriptor::load_0000(Iff &iff)
{
iff.enterForm(TAG_0000);
iff.enterChunk(TAG_DATA);
{
char buffer[1024];
CrcLowerString slotName("");
while (iff.getChunkLengthLeft())
{
//-- load the slot name
iff.read_string(buffer, sizeof(buffer)-1);
slotName.setString(buffer);
//-- convert to slot id
const SlotId slotId = SlotIdManager::findSlotId(slotName);
if (slotId == SlotId::invalid)
WARNING(true, ("SlotDescriptor [%s] specified invalid slot [%s], ignoring", m_name->getString(), slotName.getString()));
else
m_slots->push_back(slotId);
}
}
iff.exitChunk(TAG_DATA);
iff.exitForm(TAG_0000);
}
// ======================================================================
@@ -0,0 +1,74 @@
// ======================================================================
//
// SlotDescriptor.h
// Copyright 2001 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlotDescriptor_H
#define INCLUDED_SlotDescriptor_H
// ======================================================================
class CrcLowerString;
class Iff;
class SlotId;
// ======================================================================
/**
* Describes a collection of slots.
*
* ObjectTemplate instances that have slotted containers will reference
* a SlotDescriptor instance. The SlotDescriptor instance will list
* the slots available in the slotted container.
*
* This class is a shared resource since (1) both server and client
* need access to this data, (2) we don't want to need to send this
* data around needlessly, and (3) several ObjectTemplate instances
* may reference a single SlotDescriptor instance. For example,
* most (if not all) player species have the same slots available
* for equipping.
*/
class SlotDescriptor
{
friend class SlotDescriptorList;
public:
typedef stdvector<SlotId>::fwd SlotIdVector;
public:
explicit SlotDescriptor(Iff &iff, const CrcLowerString &name);
const CrcLowerString &getName() const;
const SlotIdVector &getSlots() const;
void fetch() const;
void release() const;
int getReferenceCount() const;
private:
~SlotDescriptor();
void load_0000(Iff &iff);
// disabled
SlotDescriptor(const SlotDescriptor&);
SlotDescriptor &operator =(const SlotDescriptor&);
private:
CrcLowerString *m_name;
SlotIdVector *m_slots;
mutable int m_referenceCount;
};
// ======================================================================
#endif
@@ -0,0 +1,153 @@
// ======================================================================
//
// SlotDescriptorList.cpp
// Copyright 2001 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlotDescriptorList.h"
#include "sharedDebug/DataLint.h"
#include "sharedFile/Iff.h"
#include "sharedFile/TreeFile.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedObject/SlotDescriptor.h"
#include <map>
#include <string>
// ======================================================================
bool SlotDescriptorList::ms_installed;
SlotDescriptorList::DescriptorMap *SlotDescriptorList::ms_descriptors;
// ======================================================================
// class SlotDescriptorList
// ======================================================================
void SlotDescriptorList::install()
{
DEBUG_FATAL(ms_installed, ("SlotDescriptorList already installed"));
ms_descriptors = new DescriptorMap();
ms_installed = true;
ExitChain::add(remove, "SlotDescriptorList");
}
// ----------------------------------------------------------------------
const SlotDescriptor *SlotDescriptorList::fetch(const CrcLowerString &filename)
{
DEBUG_FATAL(!ms_installed, ("SlotDescriptorList not installed"));
SlotDescriptor *descriptor = 0;
//-- check if we've got this one cached
DescriptorMap::iterator lowerBoundResult = ms_descriptors->lower_bound(&filename);
if ((lowerBoundResult != ms_descriptors->end()) && !ms_descriptors->key_comp()(&filename, lowerBoundResult->first))
{
// it's cached, return it
descriptor = lowerBoundResult->second;
}
else
{
// it's not available
//-- ensure sure file exists
if (!TreeFile::exists(filename.getString()))
{
WARNING(true, ("specified SlotDescriptor file [%s] does not exist", filename.getString()));
return 0;
}
#ifdef _DEBUG
DataLint::pushAsset(filename.getString());
#endif // _DEBUG
//-- load it
Iff iff(filename.getString());
descriptor = new SlotDescriptor(iff, filename);
#ifdef _DEBUG
DataLint::popAsset();
#endif // _DEBUG
//-- add to managed container
IGNORE_RETURN(ms_descriptors->insert(lowerBoundResult, DescriptorMap::value_type(&descriptor->getName(), descriptor)));
}
// we should have a valid slot descriptor here
NOT_NULL(descriptor);
//-- bump up reference count
descriptor->fetch();
return descriptor;
}
// ----------------------------------------------------------------------
/**
* Return the SlotDescriptor instance contained in the given file.
*
* Prefer the variant of this function taking a CrcLowerString if you
* already have the filename in that format.
*/
const SlotDescriptor *SlotDescriptorList::fetch(const std::string &filename)
{
DEBUG_FATAL(!ms_installed, ("SlotDescriptorList not installed"));
return fetch(CrcLowerString(filename.c_str()));
}
// ======================================================================
void SlotDescriptorList::remove()
{
DEBUG_FATAL(!ms_installed, ("SlotDescriptorList not installed"));
//-- handle leaks
if (!ms_descriptors->empty())
{
DEBUG_WARNING(true, ("SlotDescriptorList: %u named SlotDescriptor leaks", ms_descriptors->size()));
const DescriptorMap::iterator endIt = ms_descriptors->end();
for (DescriptorMap::iterator it = ms_descriptors->begin(); it != endIt; ++it)
{
SlotDescriptor *const descriptor = it->second;
DEBUG_WARNING(descriptor, ("-- leaked SlotDescriptor [%s]", descriptor->getName().getString()));
delete descriptor;
}
}
delete ms_descriptors;
ms_installed = false;
}
// ----------------------------------------------------------------------
void SlotDescriptorList::stopTracking(const SlotDescriptor &descriptor)
{
DEBUG_FATAL(!ms_installed, ("SlotDescriptorList not installed"));
const CrcLowerString &filename = descriptor.getName();
DescriptorMap::iterator lowerBoundResult = ms_descriptors->lower_bound(&filename);
if ((lowerBoundResult == ms_descriptors->end()) || ms_descriptors->key_comp()(&filename, lowerBoundResult->first))
{
// we don't manage this descriptor
return;
}
//-- remove the SlotDescriptor from the map
ms_descriptors->erase(lowerBoundResult);
}
// ======================================================================
@@ -0,0 +1,58 @@
// ======================================================================
//
// SlotDescriptorList.h
// Copyright 2001 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlotDescriptorList_H
#define INCLUDED_SlotDescriptorList_H
// ======================================================================
class CrcLowerString;
class LessPointerComparator;
class SlotDescriptor;
// ======================================================================
/**
* Manages the list of SlotDescriptor objects.
*
* This class provides an interface for creating SlotDescriptor
* objects based on SlotDescriptor files. So long as a single reference exists
* to a SlotDescriptor, that SlotDescriptor will stay loaded and will be returned
* to any caller that asks for it by the same filename.
*/
class SlotDescriptorList
{
friend class SlotDescriptor;
public:
static void install();
static const SlotDescriptor *fetch(const CrcLowerString &filename);
static const SlotDescriptor *fetch(const std::string &filename);
private:
typedef stdmap<const CrcLowerString*, SlotDescriptor*, LessPointerComparator>::fwd DescriptorMap;
private:
static void remove();
static void stopTracking(const SlotDescriptor &descriptor);
private:
static bool ms_installed;
static DescriptorMap *ms_descriptors;
};
// ======================================================================
#endif
@@ -0,0 +1,46 @@
// ======================================================================
//
// SlotId.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlotId.h"
// ======================================================================
const SlotId SlotId::invalid(-1);
// ======================================================================
SlotId::SlotId() :
m_slot(-1)
{
}
// ----------------------------------------------------------------------
SlotId::SlotId(int slot) :
m_slot(slot)
{
}
// ----------------------------------------------------------------------
SlotId::~SlotId()
{
}
// ----------------------------------------------------------------------
SlotId& SlotId::operator=(const SlotId& rhs)
{
if ((&rhs == this) || (rhs == *this))
return *this;
m_slot = rhs.getSlotId();
return *this;
}
// ======================================================================
@@ -0,0 +1,77 @@
// ======================================================================
//
// SlotId.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlotId_H
#define INCLUDED_SlotId_H
class SlotId
{
public:
static const SlotId invalid;
public:
SlotId();
explicit SlotId(int slot);
~SlotId();
int getSlotId() const;
SlotId& operator=(const SlotId&);
bool operator==(const SlotId&) const;
bool operator!=(const SlotId&) const;
bool operator<(const SlotId&) const;
bool render() const;
private:
int m_slot;
};
// ------------------------------------------------------------------------
inline int SlotId::getSlotId() const
{
return m_slot;
}
// ------------------------------------------------------------------------
inline bool SlotId::operator==(const SlotId& rhs) const
{
return (m_slot == rhs.getSlotId());
}
// ------------------------------------------------------------------------
inline bool SlotId::operator!=(const SlotId& rhs) const
{
return !(rhs == *this);
}
// ------------------------------------------------------------------------
inline bool SlotId::operator<(const SlotId& rhs) const
{
return (m_slot < rhs.getSlotId());
}
// ------------------------------------------------------------------------
/** Query the slot to find out if we should render its contents.
*/
inline bool SlotId::render() const
{
return true;
}
// -------------------------------------------------------------------------
#endif
@@ -0,0 +1,41 @@
// SlotIdArchive.h
// copyright 2001 Verant Interactive
#ifndef _INCLUDED_SlotIdArchive_H
#define _INCLUDED_SlotIdArchive_H
//-----------------------------------------------------------------------
#include "Archive/Archive.h"
#include "Archive/ByteStream.h"
#include "sharedObject/SlotId.h"
//-----------------------------------------------------------------------
namespace Archive
{
//-----------------------------------------------------------------------
inline void get(ReadIterator & source, SlotId & target)
{
int id;
get(source, id);
target = SlotId(id);
}
//-----------------------------------------------------------------------
inline void put(ByteStream & target, const SlotId & source)
{
int tmp = source.getSlotId();
put(target, tmp);
}
//-----------------------------------------------------------------------
}// namespace Archive
//-----------------------------------------------------------------------
#endif
@@ -0,0 +1,565 @@
// ======================================================================
//
// SlotIdManager.cpp
// Copyright 2001, 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlotIdManager.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedFoundation/Tag.h"
#include "sharedObject/SlotId.h"
#include <algorithm>
#include <string>
#include <vector>
#include <map>
// ======================================================================
namespace SlotIdManagerNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class Slot
{
public:
struct LessSlotNameComparator
{
public:
bool operator ()(const Slot *lhs, const Slot *rhs) const;
bool operator ()(const CrcString *lhs, const Slot *rhs) const;
bool operator ()(const Slot *lhs, const CrcString *rhs) const;
};
public:
Slot(const char *slotName, bool isPlayerModifiable, bool isAppearanceRelated, char const *hardpointName, uint16 combatBone, bool observeWithParent, bool exposeWithParent);
CrcString const &getSlotName() const;
bool isPlayerModifiable() const;
bool isAppearanceRelated() const;
CrcString const &getHardpointName() const;
uint16 getCombatBone() const;
bool getObserveWithParent() const;
bool getExposeWithParent() const;
private:
// disabled
Slot();
Slot(const Slot&); //lint -esym(754, Slot::Slot) // defensive hiding
Slot &operator =(const Slot&); //lint -esym(754, Slot::operator=) // defensive hiding
private:
PersistentCrcString m_slotName;
bool m_isPlayerModifiable;
bool m_isAppearanceRelated;
PersistentCrcString m_hardpointName;
uint16 m_combatBone;
bool m_observeWithParent;
bool m_exposeWithParent;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef std::vector<Slot*> SlotVector;
typedef std::multimap<uint32, Slot* > SlotBoneMap;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool s_installed;
SlotVector s_slots;
SlotBoneMap s_slotsSortedByBone;
SlotIdManager::AnythingSlotVector s_slotsThatHoldAnything;
}
using namespace SlotIdManagerNamespace;
// ======================================================================
// class SlotIdManager::Slot
// ======================================================================
SlotIdManagerNamespace::Slot::Slot(const char *slotName, bool newIsPlayerModifiable, bool newIsAppearanceRelated, char const *hardpointName, uint16 combatBone, bool observeWithParent, bool exposeWithParent) :
m_slotName(slotName, true),
m_isPlayerModifiable(newIsPlayerModifiable),
m_isAppearanceRelated(newIsAppearanceRelated),
m_hardpointName(hardpointName, true),
m_combatBone(combatBone),
m_observeWithParent(observeWithParent),
m_exposeWithParent(exposeWithParent)
{
}
// ----------------------------------------------------------------------
inline CrcString const &SlotIdManagerNamespace::Slot::getSlotName() const
{
return m_slotName;
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::isPlayerModifiable() const
{
return m_isPlayerModifiable;
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::isAppearanceRelated() const
{
return m_isAppearanceRelated;
}
// ----------------------------------------------------------------------
inline CrcString const &SlotIdManagerNamespace::Slot::getHardpointName() const
{
return m_hardpointName;
}
// ----------------------------------------------------------------------
inline uint16 SlotIdManagerNamespace::Slot::getCombatBone() const
{
return m_combatBone;
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::getObserveWithParent() const
{
return m_observeWithParent;
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::getExposeWithParent() const
{
return m_exposeWithParent;
}
// ======================================================================
// struct SlotIdManager::Slot::LessSlotNameComparator
// ======================================================================
inline bool SlotIdManagerNamespace::Slot::LessSlotNameComparator::operator ()(const Slot *lhs, const Slot *rhs) const
{
NOT_NULL(lhs);
NOT_NULL(rhs);
return lhs->getSlotName() < rhs->getSlotName();
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::LessSlotNameComparator::operator ()(const CrcString *lhs, const Slot *rhs) const
{
NOT_NULL(lhs);
NOT_NULL(rhs);
return *lhs < rhs->getSlotName();
}
// ----------------------------------------------------------------------
inline bool SlotIdManagerNamespace::Slot::LessSlotNameComparator::operator ()(const Slot *lhs, const CrcString *rhs) const
{
NOT_NULL(lhs);
NOT_NULL(rhs);
return lhs->getSlotName() < *rhs;
}
// ======================================================================
/**
* Install the SlotIdManager.
*
* Clients should specify true for loadHardpointNameData. Servers will
* not need this Appearance-related data loaded.
*
* @param filename The name of the file containing the valid slot data.
* @param loadHardpointNameData If true, hardpoint names associated with slots
* will be loaded.
*/
void SlotIdManager::install(const std::string &filename, bool loadHardpointNameData)
{
DEBUG_FATAL(s_installed, ("SlotIdManager already installed"));
//-- load valid slot names from file
Iff iff(filename.c_str());
const Tag version = iff.getCurrentName();
switch (version)
{
case TAG_0006:
load_0006(iff, loadHardpointNameData);
break;
default:
{
char buffer[5];
ConvertTagToString(version, buffer);
FATAL(true, ("unsupported SlotIdManager file format [%s]", buffer));
}
}
s_installed = true;
ExitChain::add(remove, "SlotIdManager");
}
// ----------------------------------------------------------------------
bool SlotIdManager::isInstalled()
{
return s_installed;
}
// ----------------------------------------------------------------------
/**
* Retrieve a SlotId instance for the Slot corresponding to the given
* slot name.
*
* If the specified slot name does not exist, the returned SlotId will be
* equivalent to SlotId::invalid.
*
* @param slotName the name of the slot to lookup.
*
* @return a SlotId instance that may be used in future calls to retrieve
* information regarding the slot. Also used by the SlottedContainer.
*/
SlotId SlotIdManager::findSlotId(CrcString const &slotName)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
//lint -e18 // error, redeclared template // lint appears to be confused by std::equal_range and its return type
std::pair<SlotVector::iterator, SlotVector::iterator> findResult = std::equal_range(s_slots.begin(), s_slots.end(), &slotName, Slot::LessSlotNameComparator()); //lint !e64 // type mismatch // I think Lint is confused.
if (findResult.first == findResult.second)
{
// return invalid: slot not found.
return SlotId::invalid;
}
else
{
// construct a SlotId from the index of the entry just found.
const int foundIndex = static_cast<int>(std::distance(s_slots.begin(), findResult.first));
return SlotId(foundIndex);
}
}
// ----------------------------------------------------------------------
/**
* Retrieves the slots ids associated with a given combat skeleton bone.
*
* @param bone the combat skeleton bone id
* @param slots vector to be filled in with SlotIds
*/
void SlotIdManager::findSlotIdsForCombatBone(uint32 bone, std::vector<SlotId> & slots)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
SlotBoneMap::const_iterator low = s_slotsSortedByBone.lower_bound(bone);
if (low != s_slotsSortedByBone.end())
{
SlotBoneMap::const_iterator high = s_slotsSortedByBone.upper_bound(bone);
SlotBoneMap::const_iterator i;
for (i = low; i != high; ++i)
{
slots.push_back(findSlotId((*i).second->getSlotName()));
}
}
}
// ----------------------------------------------------------------------
/**
* Retrieve the name of a slot given the slot's SlotId.
*
* @param slotId a SlotId instance for the slot under question.
*
* @return the name of the slot.
*/
const CrcString &SlotIdManager::getSlotName(const SlotId &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
//-- return a zero-length string for SlotId::invalid.
if (slotId == SlotId::invalid)
return PersistentCrcString::empty;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->getSlotName();
}
// ----------------------------------------------------------------------
/**
* Get a list of slots that can hold any item regardless of arrangement.
* Used by SlottedContainmentProperty
*
* @return a vector of SlotIds that hold anything.
*/
const SlotIdManager::AnythingSlotVector& SlotIdManager::getSlotsThatHoldAnything()
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
return s_slotsThatHoldAnything;
}
// ----------------------------------------------------------------------
/**
* Retrieve whether the given slot is allowed to be modified directly by the
* player.
*
* @param slotId a SlotId instance for the slot under question.
*
* @return true if the player may modify a slot directly, false otherwise.
*/
bool SlotIdManager::isSlotPlayerModifiable(const SlotId &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
//-- return a zero-length string for SlotId::invalid.
if (slotId == SlotId::invalid)
return false;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->isPlayerModifiable();
}
// ----------------------------------------------------------------------
/**
* Retrieve whether the given slot corresponds to an appearance slot with
* a hardpoint.
*
* If the slot can have something put in it that directly affects what you
* see on the client, this will return true. If this returns false,
* getSlotHardpointName() will return a NULL string.
*
* @param slotId a SlotId instance for the slot under question.
*
* @return true if the given slot corresponds to an appearance slot with
* a hardpoint, false otherwise.
*/
bool SlotIdManager::isSlotAppearanceRelated(const SlotId &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
//-- return a zero-length string for SlotId::invalid.
if (slotId == SlotId::invalid)
return false;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->isAppearanceRelated();
}
// ----------------------------------------------------------------------
/**
* Retrieve the name of hardpoint associated with the specified slot.
*
* The caller should check the result of isSlotAppearanceRelated() before
* calling this function. If the slot is not appearance related, this function
* will always return NULL. Also, if the SlotIdManager is installed such that
* hardpoint names are not loaded (currently the server is loaded this way),
* the specified hardpoint name will return NULL.
*
* @param slotId a SlotId instance for the slot under question.
*
* @return the name of the hardpoint associated with the specified slot.
*/
CrcString const &SlotIdManager::getSlotHardpointName(SlotId const &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
//-- return a zero-length string for SlotId::invalid.
if (slotId == SlotId::invalid)
return PersistentCrcString::empty;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->getHardpointName();
}
// ----------------------------------------------------------------------
/**
* Retrieve whether the slot should have its contents observed when
* the parent is observed.
*
* Here we use observation to mean the concept that a particular object
* is known and visible to a client.
*
* Example usage: the rider slot on a mountable creature is filled with
* the rider when the rider gets on the mount. We need all clients
* that observe the mount (i.e. the parent) to observe the player.
*/
bool SlotIdManager::getSlotObserveWithParent(const SlotId &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
if (slotId == SlotId::invalid)
return false;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->getObserveWithParent();
}
// ----------------------------------------------------------------------
/**
* Retrieve whether the slot should have its contents exposed to the when
* world when the parent is exposed to the world.
*
* Example usage: the rider slot on a mountable creature keeps its rider
* in the world.
*/
bool SlotIdManager::getSlotExposeWithParent(const SlotId &slotId)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
if (slotId == SlotId::invalid)
return false;
//-- retrieve the specified slot
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, slotId.getSlotId(), static_cast<int>(s_slots.size()));
const Slot *const slot = s_slots[static_cast<size_t>(slotId.getSlotId())];
NOT_NULL(slot);
return slot->getExposeWithParent();
}
// ----------------------------------------------------------------------
/**
* Retrieve the number of valid, unique slots supported by the system.
*
* @return the number of valid, unique slots supported by the system.
*/
int SlotIdManager::getSlotCount()
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
return static_cast<int>(s_slots.size());
}
// ----------------------------------------------------------------------
/**
* Retrieve a SlotId for the specified slot index.
*
* @param index must be in the range 0 .. getSlotCount() - 1, inclusive.
*
* @return a SlotId referencing the index'th slot known to the system.
*/
SlotId SlotIdManager::getSlotIdByIndex(int index)
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getSlotCount());
return SlotId(index);
}
// ======================================================================
void SlotIdManager::remove()
{
DEBUG_FATAL(!s_installed, ("SlotIdManager not installed"));
AnythingSlotVector().swap(s_slotsThatHoldAnything);
SlotBoneMap().swap(s_slotsSortedByBone);
std::for_each(s_slots.begin(), s_slots.end(), PointerDeleter());
SlotVector().swap(s_slots);
}
//------------------------------------------------------------------------
void SlotIdManager::load_0006(Iff &iff, bool loadHardpointNameData)
{
//-- load the Slot data
iff.enterForm(TAG_0006);
iff.enterChunk(TAG_DATA);
{
char slotName[512];
char hardpointName[512];
// keep loading entries until done. we don't include count here
// because that would prove error prone for the maintainer of the
// miff data.
while (iff.getChunkLengthLeft())
{
//-- read the slot name
iff.read_string(slotName, sizeof(slotName) - 1);
slotName[sizeof(slotName) - 1] = '\0';
//-- read flags
const bool canAcceptAnyItem = (iff.read_uint8() != 0);
const bool isPlayerModifiable = (iff.read_uint8() != 0);
const bool isAppearanceRelated = (iff.read_uint8() != 0);
iff.read_string(hardpointName, sizeof(hardpointName) - 1);
hardpointName[sizeof(hardpointName) - 1] = '\0';
//-- read the combat skeleton "bone" id
const uint16 combatBone = iff.read_uint16();
//-- get the slot's observation characteristics.
bool const observeWithParent = (iff.read_uint8() != 0);
//-- get the slot's world expose characteristics.
bool const exposeWithParent = (iff.read_uint8() != 0);
//-- construct the slot
Slot * slot = new Slot(slotName, isPlayerModifiable, isAppearanceRelated, loadHardpointNameData ? hardpointName : "", combatBone, observeWithParent, exposeWithParent);
s_slots.push_back(slot);
if (canAcceptAnyItem)
{
std::string slotString = slotName;
s_slotsThatHoldAnything.push_back(slotString);
}
//-- add the slot bone list for every bone it's associated with
for (uint16 mask = 0x8000; mask != 0; mask >>= 1)
{
if (mask & combatBone)
IGNORE_RETURN(s_slotsSortedByBone.insert(SlotBoneMap::value_type(mask & combatBone, slot)));
}
}
}
iff.exitChunk(TAG_DATA);
iff.exitForm(TAG_0006);
//-- sort the Slot data
std::sort(s_slots.begin(), s_slots.end(), Slot::LessSlotNameComparator());
}
// ======================================================================
@@ -0,0 +1,61 @@
// ======================================================================
//
// SlotIdManager.h
// Copyright 2001, 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlotIdManager_H
#define INCLUDED_SlotIdManager_H
// ======================================================================
class CrcString;
class Iff;
class SlotId;
// ======================================================================
/**
* The SlotIdManager class maps valid slot names to SlotId objects.
* For clients, it can also provide the Appearance-related hardpoint names
* associated with a given slot.
*/
class SlotIdManager
{
public:
typedef stdvector<std::string>::fwd AnythingSlotVector;
public:
static void install(const std::string &filename, bool loadHardpointNameData);
static bool isInstalled();
static SlotId findSlotId(const CrcString &slotName);
static void findSlotIdsForCombatBone(uint32 bone, stdvector<SlotId>::fwd & slots);
static CrcString const &getSlotName(SlotId const &slotId);
static bool isSlotPlayerModifiable(const SlotId &slotId);
static bool isSlotAppearanceRelated(const SlotId &slotId);
static CrcString const &getSlotHardpointName(SlotId const &slotId);
static bool getSlotObserveWithParent(const SlotId &slotId);
static bool getSlotExposeWithParent(const SlotId &slotId);
static int getSlotCount();
static SlotId getSlotIdByIndex(int index);
static const AnythingSlotVector& getSlotsThatHoldAnything();
private:
static void remove();
static void load_0006(Iff &iff, bool loadHardpointNameData);
};
// ======================================================================
#endif
@@ -0,0 +1,6 @@
#ifndef _SLOT_TYPE_DEF
#define _SLOT_TYPE_DEF
typedef int SlotType;
#endif
@@ -0,0 +1,875 @@
// ======================================================================
//
// SlottedContainer.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlottedContainer.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedObject/SlotIdManager.h"
#include "sharedObject/SlottedContainmentProperty.h"
#include "sharedObject/Object.h"
#include <cstdio>
#include <map>
// ----------------------------------------------------------------------
namespace SlottedContainerNamespace
{
std::vector<int> s_tempIntContainer;
}
using namespace SlottedContainerNamespace;
// ------------------------------------------------------------------------
SlottedContainer::SlottedContainer(Object& owner, const std::vector<SlotId>& validSlots) :
Container(SlottedContainer::getClassPropertyId(), owner),
m_slotMap(new std::map<SlotId, int>)
{
//Inialize the slot list with empty values.
std::vector<SlotId>::const_iterator i = validSlots.begin();
for (; i != validSlots.end(); ++i)
{
IGNORE_RETURN(m_slotMap->insert(SlotMap::value_type(*i ,-1)));
}
}
// ------------------------------------------------------------------------
SlottedContainer::~SlottedContainer()
{
if (m_slotMap)
{
delete m_slotMap;
m_slotMap = NULL;
}
}
// ------------------------------------------------------------------------
bool SlottedContainer::isContentItemObservedWith(Object const &item) const
{
//-- Rule 1: if base container claims that the item is visible with the container,
// we stick with that. This prevents us from changing any existing behavior at
// the time this code is written.
bool const observedWithBaseContainer = Container::isContentItemObservedWith(item);
if (observedWithBaseContainer)
return true;
//-- Rule 2: if the item is in this container, check if any of the current arrangement's
// slots have the observeWithParent attribute set. If so, return true, if not, return false.
ContainedByProperty const *const containedByProperty = item.getContainedByProperty();
if (!containedByProperty)
return false;
SlottedContainmentProperty const *const slottedContainmentProperty = safe_cast<SlottedContainmentProperty const*>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedContainmentProperty)
return false;
int const arrangementIndex = slottedContainmentProperty->getCurrentArrangement();
// Note: when checking if item is in container, we must also check
// that contained item's arrangement is set to a valid arrangement.
// This function can be called during container transfers prior to
// the arrangementIndex being set. When this occurs, handle this
// case as if the item is not in the container because it's not really
// there in its entirety yet.
Object const *const containedByObject = containedByProperty->getContainedBy();
bool const isInThisContainer = (containedByObject == &getOwner()) && (arrangementIndex >= 0);
if (isInThisContainer)
{
SlottedContainmentProperty::SlotArrangement const &slots = slottedContainmentProperty->getSlotArrangement(arrangementIndex);
SlottedContainmentProperty::SlotArrangement::const_iterator const endIt = slots.end();
for (SlottedContainmentProperty::SlotArrangement::const_iterator it = slots.begin(); it != endIt; ++it)
{
bool const observeWithParent = SlotIdManager::getSlotObserveWithParent(*it);
if (observeWithParent)
return true;
}
return false;
}
//-- Rule 3: if the item is not in this container, determine which arrangement it would
// use if it went in this slot. If no arrangement is valid, return false. If an arrangement
// is valid, check each slot in the arrangement. If any slot has observeWithParent set true,
// return true; otherwise, return false.
{
ContainerErrorCode errorCode;
int arrangementIndex = -1;
bool const result = getFirstUnoccupiedArrangement(item, arrangementIndex, errorCode);
if (!result || (errorCode != CEC_Success))
return false;
SlottedContainmentProperty::SlotArrangement const &slots = slottedContainmentProperty->getSlotArrangement(arrangementIndex);
SlottedContainmentProperty::SlotArrangement::const_iterator const endIt = slots.end();
for (SlottedContainmentProperty::SlotArrangement::const_iterator it = slots.begin(); it != endIt; ++it)
{
bool const observeWithParent = SlotIdManager::getSlotObserveWithParent(*it);
if (observeWithParent)
return true;
}
return false;
}
}
// ------------------------------------------------------------------------
bool SlottedContainer::isContentItemExposedWith(Object const &item) const
{
//-- Rule 1: if base container claims that the item is visible with the container,
// we stick with that. This prevents us from changing any existing behavior at
// the time this code is written.
bool const exposedWithBaseContainer = Container::isContentItemExposedWith(item);
if (exposedWithBaseContainer)
return true;
//-- Rule 2: if the item is in this container, check if any of the current arrangement's
// slots have the exposeWithParent attribute set. If so, return true, if not, return false.
ContainedByProperty const *const containedByProperty = item.getContainedByProperty();
if (!containedByProperty)
return false;
SlottedContainmentProperty const *const slottedContainmentProperty = safe_cast<SlottedContainmentProperty const*>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedContainmentProperty)
return false;
int const arrangementIndex = slottedContainmentProperty->getCurrentArrangement();
// Note: when checking if item is in container, we must also check
// that contained item's arrangement is set to a valid arrangement.
// This function can be called during container transfers prior to
// the arrangementIndex being set. When this occurs, handle this
// case as if the item is not in the container because it's not really
// there in its entirety yet.
Object const *const containedByObject = containedByProperty->getContainedBy();
bool const isInThisContainer = (containedByObject == &getOwner()) && (arrangementIndex >= 0);
if (isInThisContainer)
{
SlottedContainmentProperty::SlotArrangement const &slots = slottedContainmentProperty->getSlotArrangement(arrangementIndex);
SlottedContainmentProperty::SlotArrangement::const_iterator const endIt = slots.end();
for (SlottedContainmentProperty::SlotArrangement::const_iterator it = slots.begin(); it != endIt; ++it)
{
bool const exposeWithParent = SlotIdManager::getSlotExposeWithParent(*it);
if (exposeWithParent)
return true;
}
return false;
}
//-- Rule 3: if the item is not in this container, determine which arrangement it would
// use if it went in this slot. If no arrangement is valid, return false. If an arrangement
// is valid, check each slot in the arrangement. If any slot has exposeWithParent set true,
// return true; otherwise, return false.
{
ContainerErrorCode errorCode;
int arrangementIndex = -1;
bool const result = getFirstUnoccupiedArrangement(item, arrangementIndex, errorCode);
if (!result || (errorCode != CEC_Success))
return false;
SlottedContainmentProperty::SlotArrangement const &slots = slottedContainmentProperty->getSlotArrangement(arrangementIndex);
SlottedContainmentProperty::SlotArrangement::const_iterator const endIt = slots.end();
for (SlottedContainmentProperty::SlotArrangement::const_iterator it = slots.begin(); it != endIt; ++it)
{
bool const exposeWithParent = SlotIdManager::getSlotExposeWithParent(*it);
if (exposeWithParent)
return true;
}
return false;
}
}
// ------------------------------------------------------------------------
bool SlottedContainer::canContentsBeObservedWith() const
{
// Content items can be observed with this container if any of our slots are marked for observe with parent.
for (SlotMap::const_iterator i = m_slotMap->begin(); i != m_slotMap->end(); ++i)
if (SlotIdManager::getSlotObserveWithParent((*i).first))
return true;
return false;
}
// ------------------------------------------------------------------------
bool SlottedContainer::add (Object& item, int arrangementIndex, ContainerErrorCode & error)
{
error = CEC_Success;
if (arrangementIndex < 0)
{
error = CEC_InvalidArrangement;
return false;
}
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedProperty)
{
WARNING_STRICT_FATAL(true, ("Tried to add an item %s to a slot container with no slotted property. Make sure its shared object template has a valid arrangement", item.getNetworkId().getValueString().c_str()));
error = CEC_Unknown;
return false;
}
if (!internalCheckSlottedAdd (item, arrangementIndex, error))
return false;
int position = addToContents(item, error);
if (position < 0)
return false;
if (!internalDoSlottedAdd(item, position, arrangementIndex))
{
WARNING_STRICT_FATAL(true, ("internal Check add worked, but trying to do it failed."));
error = CEC_Unknown;
return false;
}
slottedProperty->setCurrentArrangement(arrangementIndex);
return true;
}
// ------------------------------------------------------------------------
bool SlottedContainer::add (Object& item, const SlotId & slotId, ContainerErrorCode& error)
{
error = CEC_Success;
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedProperty)
{
WARNING_STRICT_FATAL(true, ("Tried to add an item %s to a slot container with no slotted property Make sure its shared object template has a valid arrangement ", item.getNetworkId().getValueString().c_str()));
error = CEC_Unknown;
return false;
}
return add(item, slottedProperty->getBestArrangementForSlot(slotId), error);
}
// ------------------------------------------------------------------------
bool SlottedContainer::internalCheckSlottedAdd( Object& item, int arrangementIndex, ContainerErrorCode & error ) const
{
error = CEC_Success;
if (arrangementIndex < 0)
{
error = CEC_InvalidArrangement;
return false;
}
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedProperty)
{
WARNING_STRICT_FATAL(true, ("Tried to add an item %s to a slot container with no slotted property Make sure its shared object template has a valid arrangement", item.getNetworkId().getValueString().c_str()));
error = CEC_Unknown;
return false;
}
// realize that this is a 2*O(1) search, once for the mayAdd, the once for the fill.
if (!mayAdd(item, arrangementIndex, error))
return false;
return true;
}
// ------------------------------------------------------------------------
bool SlottedContainer::internalDoSlottedAdd( Object& item, int position, int arrangementIndex )
{
if (arrangementIndex < 0)
return false;
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
// get the arrangement from the item with arrangementIndex
const int numSlots = slottedProperty->getNumberOfSlots(arrangementIndex);
// fill each slot in the list with our own slot map
for (int i = 0; i < numSlots; ++i)
{
SlotMap::iterator j = m_slotMap->find(slottedProperty->getSlotId(arrangementIndex, i));
if (j != m_slotMap->end() && j->second == -1)
{
j->second = position;
}
else
WARNING_STRICT_FATAL(true, ("We're trying to add an item to a slotted container that does not have a slot that this item %s with this arrangment %d can go into or has something in it already.", item.getNetworkId().getValueString().c_str(), arrangementIndex));
}
return true;
}
// ------------------------------------------------------------------------
int SlottedContainer::find(const SlotId &slot) const
{
SlotMap::const_iterator i = m_slotMap->find(slot);
if (i == m_slotMap->end()) //lint !e1702 STL operator== both a member and not
{
DEBUG_WARNING(true, ("Tried to find from an invalid slot on this container [%s]. Check the container's slot descriptor file to make sure it has slot %s.", getOwner().getNetworkId().getValueString().c_str(), SlotIdManager::getSlotName(slot).getString() ));
return -1;
}
return i->second; //lint !e1702 STL operator== both a member and not
}
// ------------------------------------------------------------------------
Container::ContainedItem SlottedContainer::getObjectInSlot (const SlotId &slot, ContainerErrorCode & error)
{
error = CEC_Success;
if (!hasSlot(slot))
{
error = CEC_NoSlot;
return CachedNetworkId::cms_cachedInvalid;
}
int position = find(slot);
if (position < 0)
{
error = CEC_NotFound;
return CachedNetworkId::cms_cachedInvalid;
}
return getContents(position);
} //lint !e1762 // function could be made const // yes, but we don't want you to modify contents of a const container
// ------------------------------------------------------------------------
const Container::ContainedItem SlottedContainer::getObjectInSlot (const SlotId &slot, ContainerErrorCode & error) const
{
error = CEC_Success;
//@todo I must not be doing this right...I should be sharing code with the above routine.
if (!hasSlot(slot))
{
error = CEC_NoSlot;
return CachedNetworkId::cms_cachedInvalid;
}
int position = find(slot);
if (position < 0)
{
error = CEC_NotFound;
return CachedNetworkId::cms_cachedInvalid;
}
return getContents(position);
}
// ------------------------------------------------------------------------
/**
* Retrieves all the objects in slots associated with a combat bone.
*
* @param bone the combat bone id
* @param objects list that will be filled with the objects in the slots
*/
void SlottedContainer::getObjectsForCombatBone(uint32 bone,
std::vector<Container::ContainedItem> & objects) const
{
std::vector<SlotId> slots;
SlotIdManager::findSlotIdsForCombatBone(bone, slots);
std::vector<SlotId>::const_iterator iter;
ContainerErrorCode tmp = CEC_Success;
for (iter = slots.begin(); iter != slots.end(); ++iter)
{
Container::ContainedItem item = getObjectInSlot(*iter, tmp);
if (item != NetworkId::cms_invalid)
objects.push_back(item);
}
}
// ------------------------------------------------------------------------
PropertyId SlottedContainer::getClassPropertyId()
{
return PROPERTY_HASH(SlottedContainer, 0x7ED71F2E);
}
// ------------------------------------------------------------------------
bool SlottedContainer::getFirstUnoccupiedArrangement(const Object &item, int& arrangementIndex, ContainerErrorCode& error) const
{
error = CEC_Success;
arrangementIndex = -1;
//-- get list of valid arrangements
std::vector<int> tmp;
getValidArrangements(item, tmp, error, true, true);
bool result = false;
if (tmp.empty())
{
result = false;
}
else
{
arrangementIndex = tmp.front();
result = true;
}
return result;
}
// ------------------------------------------------------------------------
/**
* Return a list of valid arrangement indices for the item in this container.
*
* @todo Modify getValidArrangements to take an argument that checks for unoccupied arrangements.
*/
void SlottedContainer::getValidArrangements(const Object& item, std::vector<int>& returnList, ContainerErrorCode& error, bool returnOnFirst, bool unoccupiedArrangementsOnly) const
{
error = CEC_Success;
returnList.clear();
const SlottedContainmentProperty* slottedContainment = safe_cast<const SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedContainment)
{
error = CEC_WrongType;
return;
}
//@todo revisit slotted properties to use iterators
int numArrangements = slottedContainment->getNumberOfArrangements();
//For each arrangement, check ourself to see if each slot in that arrangement exists.
//As soon as we find an arrangement that has all of our slots, we can return that arrangement index
for (int i = 0; i < numArrangements; ++i)
{
const int numSlots = slottedContainment->getNumberOfSlots(i);
int availableSlots = 0;
bool slotPresent = true;
for (int j = 0; j < numSlots; ++j)
{
SlotId slot = slottedContainment->getSlotId(i,j);
// check if slot is present in this container
if (!hasSlot(slot))
{
//A slot is not present, flag for next loop and break to the next loop
slotPresent = false;
break;
}
// check if slot is available
if (unoccupiedArrangementsOnly && isSlotEmpty(slot, error))
++availableSlots;
}
//If we haven't been flagged above then we found a valid arrangement
if (slotPresent)
{
// check if we're ignoring unoccupied slots or if all slots were unoccupied
if (!unoccupiedArrangementsOnly || (availableSlots == numSlots))
{
returnList.push_back(i);
if (returnOnFirst)
return;
}
}
}
//We found no arrangements on the item that only contains slot ids that we have.
error = CEC_SlotOccupied;
return;
}
// ------------------------------------------------------------------------
/**
* Append the contents of the slotted container to the specified buffer.
*
* @param buffer the string that will have debug information appended to it on return.
*/
void SlottedContainer::debugPrint(std::string &buffer) const
{
char tempBuffer[1024];
buffer += "====[BEGIN: slotted container]====\n";
//-- List supported slots and container indices.
sprintf(tempBuffer, "container id [%s]: contains [%d] slots.\n", getOwner().getNetworkId().getValueString().c_str(), static_cast<int>(m_slotMap->size()));
buffer += tempBuffer;
SlotMap::const_iterator const endIt = m_slotMap->end();
for (SlotMap::const_iterator it = m_slotMap->begin(); it != endIt; ++it)
{
sprintf(tempBuffer, "\tslot [%3d, %20s]: index [%3d]\n", it->first.getSlotId(), SlotIdManager::getSlotName(it->first).getString(), it->second);
buffer += tempBuffer;
}
buffer += "embedding container contents now:\n";
Container::debugPrint(buffer);
buffer += "====[END: slotted container]====\n";
}
// ----------------------------------------------------------------------
void SlottedContainer::debugLog() const
{
#ifdef _DEBUG
DEBUG_REPORT_LOG(true, ("====[BEGIN: slotted container]====\n"));
//-- List supported slots and container indices.
DEBUG_REPORT_LOG(true, ("container id [%s]: contains [%d] slots.\n", getOwner().getNetworkId().getValueString().c_str(), static_cast<int>(m_slotMap->size())));
SlotMap::const_iterator const endIt = m_slotMap->end();
for (SlotMap::const_iterator it = m_slotMap->begin(); it != endIt; ++it)
{
DEBUG_REPORT_LOG(true, ("\tslot [%20s]: index [%3d]\n", SlotIdManager::getSlotName(it->first).getString(), it->second));
}
DEBUG_REPORT_LOG(true, ("Embedding container contents now:\n"));
Container::debugLog();
DEBUG_REPORT_LOG(true, ("====[END: slotted container]====\n"));
#endif
}
// --------------------------------------------------------------------------------
bool SlottedContainer::hasSlot (const SlotId &slot) const
{
SlotMap::const_iterator i = m_slotMap->find(slot);
if (i == m_slotMap->end()) //lint !e1702 STL operator== both a member and not
return false;
return true;
}
// --------------------------------------------------------------------------------
/**
* Returns the slot ids for this container.
*
* @param slots list that will be filled in with the slot ids
*/
void SlottedContainer::getSlotIdList(std::vector<SlotId> & slots) const
{
SlotMap::const_iterator iter;
for (iter = m_slotMap->begin(); iter != m_slotMap->end(); ++iter)
{
if ((*iter).first != SlotId::invalid)
slots.push_back(iter->first);
}
}
// ----------------------------------------------------------------------
bool SlottedContainer::isSlotEmpty (const SlotId &slot, ContainerErrorCode& error) const
{
error = CEC_Success;
// find slot data
if (!hasSlot(slot))
{
error = CEC_NoSlot;
return false;
}
bool retval = (find(slot) == -1);
if (!retval)
error = CEC_SlotOccupied;
return retval;
}
// ------------------------------------------------------------------------
bool SlottedContainer::mayAdd(const Object& item, ContainerErrorCode& error) const
{
error = CEC_Success;
//@todo This is an inefficient function. getValidArrangements and mayAdd(object, int) both do a lot of searching that is redundant.
s_tempIntContainer.clear();
getValidArrangements(item, s_tempIntContainer, error);
std::vector<int>::iterator const endIt = s_tempIntContainer.end();
for(std::vector<int>::iterator i = s_tempIntContainer.begin(); i != endIt; ++i)
{
if (mayAdd(item, (*i), error))
return true;
}
return false;
}
// ------------------------------------------------------------------------
bool SlottedContainer::mayAdd(const Object& item, int arrangementIndex, ContainerErrorCode& error) const
{
error = CEC_Success;
if (arrangementIndex < 0)
{
error = CEC_InvalidArrangement;
return false;
}
if (item.getNetworkId() == getOwner().getNetworkId())
{
error = CEC_AddSelf;
return false;
}
const SlottedContainmentProperty* slottedContainment = safe_cast<const SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedContainment)
{
WARNING_STRICT_FATAL(true, ("Tried to check slots with an item with no slotted containement property."));
error = CEC_Unknown;
return false;
}
int numSlots = slottedContainment->getNumberOfSlots(arrangementIndex);
for (int j = 0; j < numSlots; ++j)
{
SlotId slot = slottedContainment->getSlotId(arrangementIndex,j);
if (!isSlotEmpty(slot, error))
{
//A slot does not exist or is occupied in the arrangement already.
return false;
}
}
return Container::mayAdd(item, error);
}
// ------------------------------------------------------------------------
bool SlottedContainer::mayAdd(const Object& item, const SlotId& slotId, ContainerErrorCode& error) const
{
error = CEC_Success;
if (!isSlotEmpty(slotId, error))
{
return false;
}
const SlottedContainmentProperty* slottedContainment = safe_cast<const SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedContainment)
{
WARNING_STRICT_FATAL(true, ("Tried to check slots with an item with no slotted containement property."));
error = CEC_Unknown;
return false;
}
return mayAdd(item, slottedContainment->getBestArrangementForSlot(slotId), error);
}
// ------------------------------------------------------------------------
bool SlottedContainer::internalRemove(const Object& item, int overrideArrangement)
{
ContainerErrorCode tmp = CEC_Success;
UNREF(overrideArrangement);
//Check for the item's position in contents
int position = Container::find(item.getNetworkId(), tmp);
if (position == -1)
{
WARNING_STRICT_FATAL(true, ("SlottedContainer::internalRemove() called with an invalid item: container owner id=[%s], template=[%s]; item id=[%s], template=[%s]",
getOwner().getNetworkId().getValueString().c_str(), getOwner().getObjectTemplateName(),
item.getNetworkId().getValueString().c_str(), item.getObjectTemplateName()));
return false;
}
//Clean up the slot map
SlotMap::iterator i = m_slotMap->begin();
for(;i != m_slotMap->end(); ++i) //lint !e1702 STL operator== both a member and not
{
if(i->second == position) //lint !e1702 STL operator== both a member and not
{
i->second = -1;
}
}
return true;
}
// ------------------------------------------------------------------------
bool SlottedContainer::remove(Object& item, ContainerErrorCode& error)
{
error = CEC_Success;
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedProperty)
{
WARNING_STRICT_FATAL(true, ("Tried to remove an item %s to a slot container with no slotted property", item.getNetworkId().getValueString().c_str()));
error = CEC_Unknown;
return false;
}
//Check for the item's position in contents
int position = Container::find(item.getNetworkId(), error);
if (position == -1)
{
DEBUG_WARNING(true, ("Called SlottedContainer::remove() with item [%s] from container [%s], but the item was not found in the base container's contents. This means the item was not in the container.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
error = CEC_NotFound;
return false;
}
//Try to remove it from contents
if (!internalRemove(item))
{
error = CEC_Unknown;
return false;
}
if (!Container::remove(item, error))
{
return false;
}
slottedProperty->setCurrentArrangement(-1);
return true;
}
// ----------------------------------------------------------------------
bool SlottedContainer::remove(ContainerIterator &pos, ContainerErrorCode& error)
{
error = CEC_Success;
Object *obj=(*pos).getObject();
if (obj)
return remove(*obj, error);
else
{
error = CEC_Unknown;
return false;
}
}
// ------------------------------------------------------------------------
void SlottedContainer::removeItemFromSlotOnly(const Object &item)
{
IGNORE_RETURN(internalRemove(item));
}
// ------------------------------------------------------------------------
int SlottedContainer::depersistContents(Object&)
{
WARNING_STRICT_FATAL(true, ("Do not use this interface. Use interface with arrangement instead."));
return -1;
}
// ------------------------------------------------------------------------
void SlottedContainer::depersistSlotContents(Object& item, int arrangementIndex)
{
ContainerErrorCode tmp = CEC_Success;
SlottedContainmentProperty * slottedProperty = safe_cast<SlottedContainmentProperty *>(item.getProperty(SlottedContainmentProperty::getClassPropertyId()));
if (!slottedProperty)
{
WARNING_STRICT_FATAL(true, ("Tried to add an item %s to a slot container with no slotted property\n", item.getNetworkId().getValueString().c_str()));
return;
}
//Special case...when depersisting an object its to have arrangmentIndex = -1 for baselines
if (arrangementIndex < 0)
{
int tmp2 = Container::depersistContents(item);
UNREF(tmp2);
return;
}
//Make sure we can depersist into the arrangement we had last saved.
if (!internalCheckSlottedAdd(item, arrangementIndex, tmp))
{
//if not try to find a valid one to depersist to.
int arrangement = -1;
DEBUG_WARNING(true, ("Could not depersist item [%s] into container [%s] with arrangement %d, ContainerErrorCode=%d. This is typically bad, and may result in the item being in an invalid state or even moved to 0 0 0 in the world. We will now attempt to find a different arrangement to depersist this item with.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str(), arrangementIndex, static_cast<int>(tmp)));
if (!getFirstUnoccupiedArrangement(item, arrangement, tmp))
{
//warning/fatal if we can't find a valid arrangement
WARNING_STRICT_FATAL(true, ("Could not depersist item [%s] into container [%s] because there was no good arrangement, ContainerErrorCode=%d. See previous warning. We then attempted to find a different arrangement to put the item into, because the item really belongs in this container, but could not because it was either already occupied or the arrangement of the item was changed so that it cannot be placed in this container anymore. This is typically bad, and may result in the item being in an invalid state or even moved to 0 0 0 in the world. This might happen because the arrangement file was changed for this object and existing objects could no longer be persisted into their containers.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str(), static_cast<int>(tmp)));
}
else
{
int position = Container::depersistContents(item);
if (position >= 0 && internalDoSlottedAdd(item, position, arrangement))
{
//change the current arrangement to the new one we found
slottedProperty->setCurrentArrangement(arrangement);
}
else
{
WARNING_STRICT_FATAL(true, ("Could not depersist item [%s] into container [%s] because add item failed. We found a good different arrangement to add the item to, but the base container prevented the transfer.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
}
}
}
//It's ok to depersist into the arrangement we were saved with.
else
{
int position = Container::depersistContents(item);
if (arrangementIndex >= 0 && !internalDoSlottedAdd(item, position, arrangementIndex))
{
WARNING_STRICT_FATAL(true, ("Could not depersist item [%s] into container [%s] because add item failed. For some reason the base container prevented the transfer.", item.getNetworkId().getValueString().c_str(), getOwner().getNetworkId().getValueString().c_str()));
}
}
}
// ------------------------------------------------------------------------
bool SlottedContainer::internalItemRemoved(const Object& item)
{
if (internalRemove(item))
{
return Container::internalItemRemoved(item);
}
return false;
}
// ------------------------------------------------------------------------
void SlottedContainer::updateArrangement(Object& item, int oldArrangement, int newArrangement)
{
ContainerErrorCode tmp = CEC_Success;
if (!internalRemove(item, oldArrangement))
{
DEBUG_WARNING(true, ("Remove part of update failed in slotted container"));
}
int position = Container::find(item.getNetworkId(), tmp);
if (position < 0)
{
DEBUG_WARNING(true, ("could not find object in update slotted container"));
}
else if (newArrangement >= 0 && !internalDoSlottedAdd(item, position, newArrangement))
{
DEBUG_WARNING(true, ("updating slotted container failed"));
}
}
//----------------------------------------------------------------------
const SlotId & SlottedContainer::findFirstSlotIdForObject (const NetworkId & id) const
{
Container::ContainerErrorCode tmp = Container::CEC_Success;
const int position = Container::find (id, tmp);
if (position >= 0)
{
for (SlottedContainer::SlotMap::const_iterator sit = m_slotMap->begin(); sit != m_slotMap->end(); ++sit)
{
const int objPosition = (*sit).second;
if (objPosition == position)
return (*sit).first;
}
}
return SlotId::invalid;
}
// ------------------------------------------------------------------------
@@ -0,0 +1,92 @@
// ======================================================================
//
// SlottedContainer.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlottedContainer_H
#define INCLUDED_SlottedContainer_H
// ======================================================================
#include "sharedObject/Container.h"
// ======================================================================
class SlottedContainer : public Container
{
public:
static PropertyId getClassPropertyId();
public:
SlottedContainer(Object& owner, const std::vector<SlotId>& validSlots);
~SlottedContainer();
virtual bool isContentItemObservedWith(Object const &item) const;
virtual bool isContentItemExposedWith(Object const &item) const;
virtual bool canContentsBeObservedWith() const;
bool add (Object& item, int arrangementIndex, ContainerErrorCode& error);
bool add (Object& item, const SlotId & slotId, ContainerErrorCode& error);
Container::ContainedItem getObjectInSlot (const SlotId &slot, ContainerErrorCode& error);
const Container::ContainedItem getObjectInSlot (const SlotId &slot, ContainerErrorCode& error) const;
void getObjectsForCombatBone(uint32 bone, std::vector<Container::ContainedItem> & objects) const;
bool getFirstUnoccupiedArrangement(const Object& item, int& arrangementIndex, ContainerErrorCode& error) const;
void getValidArrangements(const Object& item, std::vector<int>& returnList, ContainerErrorCode & error, bool returnOnFirst = false, bool unoccupiedArrangementsOnly = false) const;
bool hasSlot (const SlotId &slot) const;
bool isSlotEmpty (const SlotId &slot, ContainerErrorCode& error) const;
virtual void debugPrint(std::string &buffer) const;
virtual void debugLog() const;
virtual bool mayAdd(const Object& item, ContainerErrorCode& error) const;
bool mayAdd(const Object& item, int arrangementIndex, ContainerErrorCode& error) const;
bool mayAdd(const Object& item, const SlotId & slotId, ContainerErrorCode& error) const;
virtual bool remove(Object &item, ContainerErrorCode& error);
virtual bool remove(ContainerIterator &pos, ContainerErrorCode& error);
void removeItemFromSlotOnly(const Object &item);
void getSlotIdList(std::vector<SlotId> & slots) const;
const SlotId & findFirstSlotIdForObject (const NetworkId & id) const;
//might need an addSlot() interface for the loader
//persistance interface. Do not call directly.
virtual int depersistContents(Object& item);
void depersistSlotContents(Object& item, int arrangement);
virtual bool internalItemRemoved(const Object& item);
void updateArrangement(Object& item, int oldArrangement, int newArrangement);
private:
typedef stdmap<SlotId, int>::fwd SlotMap;
private:
/** shortened find on the map. Returns -1 if not found.
*/
int find(const SlotId &slot) const;
bool internalCheckSlottedAdd( Object& item, int arrangementIndex, ContainerErrorCode& error ) const;
bool internalDoSlottedAdd( Object& item, int position, int arrangementIndex );
bool internalRemove(const Object& item, int overrideArrangement = -1);
/** This is the map of slot ids to contents. It is initialized with -1 values.
* Anything greater than or equal to 0 indicates a position in the contents list.
*/
SlotMap *m_slotMap;
SlottedContainer();
SlottedContainer(const SlottedContainer&);
SlottedContainer& operator= (const SlottedContainer&);
};
// ======================================================================
#endif
@@ -0,0 +1,243 @@
// ======================================================================
//
// SlottedContainmentProperty.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SlottedContainmentProperty.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedObject/Object.h"
#include "sharedObject/SlotId.h"
#include "sharedObject/SlotIdManager.h"
#include <string>
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(SlottedContainmentProperty, true, 0, 0, 0);
// ======================================================================
SlottedContainmentProperty::SlottedContainmentProperty(Object& owner) :
Property(SlottedContainmentProperty::getClassPropertyId(), owner),
m_arrangementList(),
m_currentArrangement(-1)
{
//Add slots that can hold anything
SlotIdManager::AnythingSlotVector anythingSlots = SlotIdManager::getSlotsThatHoldAnything();
for (SlotIdManager::AnythingSlotVector::iterator i = anythingSlots.begin(); i != anythingSlots.end(); ++i)
{
SlotArrangement tmp;
CrcLowerString tmp2(i->c_str());
SlotId slotId = SlotIdManager::findSlotId(tmp2);
tmp.push_back(slotId);
addArrangement(tmp);
}
}
// ---------------------------------------------------------------------
SlottedContainmentProperty::~SlottedContainmentProperty()
{
}
// ---------------------------------------------------------------------
void SlottedContainmentProperty::addArrangement(const SlotArrangement &arrangement)
{
if (arrangement.size() >= SCP_MaxArrangementSize)
{
WARNING_STRICT_FATAL(true, ("Cannot add this arrangement. It is too big."));
return;
}
m_arrangementList.push_back(arrangement);
}
// ---------------------------------------------------------------------
bool SlottedContainmentProperty::canManipulateArrangement(int arrangementIndex) const
{
if (arrangementIndex < 0)
{
WARNING_STRICT_FATAL(true, ("Passed -1 to canManipulateArrangement"));
return true;
}
int numArrangements = getNumberOfArrangements();
if (numArrangements == 0)
return false;
if (arrangementIndex >= numArrangements)
{
const Object& owner = getOwner();
WARNING_STRICT_FATAL(true, ("Tried to pass an invalid arrangement index %d for object %s", arrangementIndex, owner.getNetworkId().getValueString().c_str()));
return false;
}
std::vector<SlotId>::const_iterator i = m_arrangementList[static_cast<ArrangementList::size_type>(arrangementIndex)].begin();
for (;i != m_arrangementList[static_cast<ArrangementList::size_type>(arrangementIndex)].end(); ++i)
{
if (!SlotIdManager::isSlotPlayerModifiable(*i))
return false;
}
return true;
}
// ---------------------------------------------------------------------
/**
* This function returns the "best" arrangement that has a given slotId.
* The best arrangement is the one that has the given slotId nearest to the front of
* the slot list.
*/
int SlottedContainmentProperty::getBestArrangementForSlot(const SlotId & slotId) const
{
//@todo Make sure arrangements are added in data in the correct order to ensure "bestness"
int bestValue = SCP_MaxArrangementSize;
int bestArrangement = -1;
int arrangementIndex = 0;
for (ArrangementList::const_iterator i = m_arrangementList.begin(); i != m_arrangementList.end(); ++i, ++arrangementIndex)
{
int slotIndex = 0;
for (SlotArrangement::const_iterator j = i->begin(); j != i->end(); ++j, ++slotIndex)
{
if (slotId == *j && slotIndex < bestValue)
{
bestValue = slotIndex;
bestArrangement = arrangementIndex;
break;
}
}
// quick test to see if we can stop iterating.
if (bestValue == 0)
break;
}
return bestArrangement;
}
// ---------------------------------------------------------------------
int SlottedContainmentProperty::getNumberOfArrangements () const
{
return static_cast<int>(m_arrangementList.size());
}
// ---------------------------------------------------------------------
int SlottedContainmentProperty::getNumberOfSlots (int arrangementIndex) const
{
int numArrangements = getNumberOfArrangements();
if (numArrangements == 0)
return 0;
if (arrangementIndex < 0 || arrangementIndex >= numArrangements)
{
WARNING_STRICT_FATAL(true, ("Tried to pass an invalid arrangement index to this slotted container"));
return 0;
}
return static_cast<int>(m_arrangementList[static_cast<ArrangementList::size_type>(arrangementIndex)].size());
}
// ---------------------------------------------------------------------
PropertyId SlottedContainmentProperty::getClassPropertyId()
{
return PROPERTY_HASH(SlottedContainment, 0xED3067A9);
}
// -----------------------------------------------------------
const SlottedContainmentProperty::SlotArrangement & SlottedContainmentProperty::getSlotArrangement(int arrangementIndex) const
{
if (arrangementIndex < 0 || arrangementIndex >= getNumberOfArrangements())
{
WARNING_STRICT_FATAL(true, ("Tried to pass an invalid arrangement index to getSlotArrangement"));
return m_arrangementList[0];
}
return m_arrangementList[static_cast<ArrangementList::size_type>(arrangementIndex)];
}
// -----------------------------------------------------------
SlotId SlottedContainmentProperty::getSlotId (int arrangementIndex, int slotIndex) const
{
if (arrangementIndex < 0)
{
WARNING_STRICT_FATAL(true, ("Tried to pass a negative arrangement index [%d] to this slotted container", arrangementIndex));
return SlotId::invalid;
}
if (slotIndex < 0)
{
WARNING_STRICT_FATAL(true, ("Tried to pass a negative slotIndex [%d] to this slotted container", slotIndex));
return SlotId::invalid;
}
int num = getNumberOfArrangements();
if (num == 0)
return SlotId::invalid;
if (num < arrangementIndex)
{
WARNING_STRICT_FATAL(true, ("Tried to pass an invalid arrangement index to this slotted container"));
return SlotId::invalid;
}
num = getNumberOfSlots(arrangementIndex);
if (num == 0)
return SlotId::invalid;
if (num < slotIndex)
{
WARNING_STRICT_FATAL(true, ("Tried to pass an invalid slot index to this slotted container"));
return SlotId::invalid;
}
return m_arrangementList[static_cast<ArrangementList::size_type>(arrangementIndex)][static_cast<SlotArrangement::size_type>(slotIndex)];
}
// ---------------------------------------------------------------------
bool SlottedContainmentProperty::isInAppearanceSlot() const
{
int arrangement = getCurrentArrangement();
int numSlots = getNumberOfSlots(arrangement);
for (int i = 0; i < numSlots; ++i)
{
SlotId id = getSlotId(arrangement, i);
if (SlotIdManager::isSlotAppearanceRelated(id))
return true;
}
return false;
}
// ---------------------------------------------------------------------
int SlottedContainmentProperty::getCurrentArrangement() const
{
return m_currentArrangement;
}
// ------------------------------------------------------------------------
void SlottedContainmentProperty::setCurrentArrangement(int arrangement, bool local)
{
if (m_currentArrangement != arrangement)
{
int oldValue = m_currentArrangement;
m_currentArrangement = arrangement;
getOwner().arrangementModified(oldValue, arrangement, local);
}
}
// ======================================================================
@@ -0,0 +1,73 @@
// ======================================================================
//
// SlottedContainmentProperty.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SlottedContainmentProperty_H
#define INCLUDED_SlottedContainmentProperty_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/Property.h"
#include <vector>
// ======================================================================
class SlotId;
// ======================================================================
class SlottedContainmentProperty : public Property
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
static PropertyId getClassPropertyId();
enum
{
SCP_MaxArrangementSize = 0xFFF
};
typedef std::vector<SlotId> SlotArrangement;
typedef std::vector<SlotArrangement> ArrangementList;
//revisit possibly using iterators
public:
explicit SlottedContainmentProperty(Object& owner);
~SlottedContainmentProperty();
void addArrangement(const SlotArrangement &arrangement);
bool canManipulateArrangement(int arrangementIndex) const;
int getBestArrangementForSlot(const SlotId & slotId) const;
int getCurrentArrangement() const;
int getNumberOfArrangements () const;
int getNumberOfSlots (int arrangementIndex) const;
const SlotArrangement & getSlotArrangement(int arrangementIndex) const;
SlotId getSlotId (int arrangementIndex, int slotIndex) const;
bool isInAppearanceSlot() const;
void setCurrentArrangement(int arrangement, bool local = true);
private:
ArrangementList m_arrangementList; //This could also be with the object template! Definately not persisted
int m_currentArrangement;
SlottedContainmentProperty();
SlottedContainmentProperty(const SlottedContainmentProperty&);
SlottedContainmentProperty& operator= (const SlottedContainmentProperty&);
};
// ======================================================================
#endif
@@ -0,0 +1,480 @@
// ======================================================================
//
// VolumeContainer.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/VolumeContainer.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedObject/Object.h"
#include "sharedObject/VolumeContainmentProperty.h"
#include "sharedObject/ObjectTemplate.h"
#include "sharedFoundation/CrcLowerString.h"
#include <cstdio>
//-----------------------------------------------------------------------
namespace VolumeContainerNamespace
{
VolumeContainer* getVolumeContainerParent(VolumeContainer& self)
{
Object & owner = self.getOwner ();
ContainedByProperty * containedByProperty = owner.getContainedByProperty ();
if (containedByProperty)
{
Object * parent = containedByProperty->getContainedBy ();
if (parent)
{
return parent->getVolumeContainerProperty();
}
}
return NULL;
}
const VolumeContainer* getVolumeContainerParent(const VolumeContainer& self)
{
const Object & owner = self.getOwner ();
const ContainedByProperty * const containedByProperty = owner.getContainedByProperty ();
if (containedByProperty)
{
const Object * const parent = containedByProperty->getContainedBy ();
if (parent)
{
return parent->getVolumeContainerProperty();
}
}
return NULL;
}
const unsigned int serverHolocronCrc = CrcLowerString::calculateCrc("object/player_quest/pgc_quest_holocron.iff");
}
using namespace VolumeContainerNamespace;
//-----------------------------------------------------------------------
VolumeContainer::VolumeContainer(Object& owner, int totalVolume) :
Container(VolumeContainer::getClassPropertyId(), owner),
m_currentVolume(0),
m_totalVolume(totalVolume)
{
}
//-----------------------------------------------------------------------
VolumeContainer::~VolumeContainer()
{
}
//-----------------------------------------------------------------------
void VolumeContainer::childVolumeChanged(int volume, bool updateParent)
{
if (m_totalVolume != VL_NoVolumeLimit)
m_currentVolume += volume;
if (updateParent)
{
VolumeContainer *parent = getVolumeContainerParent(*this);
if (parent)
parent->childVolumeChanged(volume, true);
}
}
//-----------------------------------------------------------------------
void VolumeContainer::insertNewItem(const Object & item, const VolumeContainmentProperty * itemProp)
{
const VolumeContainmentProperty * prop = itemProp ? itemProp : safe_cast<const VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
WARNING_STRICT_FATAL(true, ("Item %s has no volume property", item.getNetworkId().getValueString().c_str()));
return;
}
if (m_totalVolume != VL_NoVolumeLimit)
m_currentVolume += prop->getVolume();
}
//-----------------------------------------------------------------------
bool VolumeContainer::add (Object& item, ContainerErrorCode& error, bool allowOverloaded)
{
// save off current volume
const int oldVolume = m_currentVolume;
error = CEC_Success;
VolumeContainmentProperty * prop = safe_cast<VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
WARNING_STRICT_FATAL(true, ("Cannot add an item to a volume container without a containment property."));
error = CEC_Unknown;
return false;
}
if (!allowOverloaded && !checkVolume(*prop))
{
error = CEC_Full;
return false;
}
if (addToContents(item, error) == -1)
{
return false;
}
insertNewItem(item, prop);
// if volume has changed, update parent volume count
if (m_currentVolume != oldVolume)
{
VolumeContainer *parent = getVolumeContainerParent(*this);
if (parent)
parent->childVolumeChanged((m_currentVolume - oldVolume), true);
}
return true;
}
//-----------------------------------------------------------------------
bool VolumeContainer::checkVolume (const VolumeContainmentProperty &item) const
{
return checkVolume(item.getVolume());
}
//-----------------------------------------------------------------------
bool VolumeContainer::checkVolume (int addedVolume) const
{
if (m_totalVolume == VL_NoVolumeLimit)
return true;
bool retval = false;
retval = (m_currentVolume + addedVolume <= m_totalVolume);
//-- check parent to make sure it isn't full
if (retval)
{
const VolumeContainer * const volumeContainer = getVolumeContainerParent(*this);
if (volumeContainer)
{
retval = volumeContainer->checkVolume(addedVolume);
}
}
return retval;
}
//-----------------------------------------------------------------------
int VolumeContainer::debugDoNotUseSetCapacity(int newValue)
{
int oldValue = m_totalVolume;
m_totalVolume = newValue;
return oldValue;
}
//-----------------------------------------------------------------------
void VolumeContainer::debugPrint(std::string &buffer) const
{
char tempBuffer[1024];
buffer += "====[BEGIN: volume container]====\n";
sprintf(tempBuffer, "container id [%s]: current volume [%d] total volume [%d].\n", getOwner().getNetworkId().getValueString().c_str(),
m_currentVolume, m_totalVolume);
buffer += tempBuffer;
buffer += "embedding container contents now:\n";
Container::debugPrint(buffer);
buffer += "====[END: volume container]====\n";
}
//-----------------------------------------------------------------------
PropertyId VolumeContainer::getClassPropertyId()
{
return PROPERTY_HASH(VolumeContainer, 0xA5193F23);
}
//-----------------------------------------------------------------------
bool VolumeContainer::mayAdd(const Object& item, ContainerErrorCode& error) const
{
error = CEC_Success;
if (item.getNetworkId() == getOwner().getNetworkId())
{
error = CEC_AddSelf;
return false;
}
const VolumeContainmentProperty * prop = safe_cast<const VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
error = CEC_Unknown;
return false;
}
const VolumeContainer * vol = safe_cast<const VolumeContainer *>(item.getProperty(VolumeContainer::getClassPropertyId()));
if (vol)
{
if (m_totalVolume != VL_NoVolumeLimit && vol->getTotalVolume() >= getTotalVolume())
{
unsigned int ownerCrc = CrcLowerString::calculateCrc(getOwner().getObjectTemplateName());
unsigned int itemCrc = CrcLowerString::calculateCrc(item.getObjectTemplateName());
if(ownerCrc == serverHolocronCrc && itemCrc == serverHolocronCrc)
{
// We're moving a holocron into another holocron, let it continue.
}
else
{
error = CEC_TooLarge;
return false;
}
}
}
if (!checkVolume(*prop))
{
error = CEC_Full;
return false;
}
return Container::mayAdd(item, error);
}
//-----------------------------------------------------------------------
int VolumeContainer::recalculateVolume()
{
int volume = 0;
for (ContainerIterator iter = begin(); iter != end(); ++iter)
{
Object* const obj = (*iter).getObject();
if (!obj)
{
WARNING_STRICT_FATAL(true, ("Container with non-existant object %s", (*iter).getValueString().c_str()));
}
else
{
VolumeContainmentProperty * const prop = safe_cast<VolumeContainmentProperty *>(obj->getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
WARNING_STRICT_FATAL(true, ("We have an item in a volume container with no property %s", (*iter).getValueString().c_str()));
}
else if (m_totalVolume != VL_NoVolumeLimit)
{
volume += prop->getVolume();
}
}
}
m_currentVolume = volume;
//-- if our volume is recalculated, we must inform our parent if contained by a volume container
VolumeContainer * const volumeContainer = getVolumeContainerParent(*this);
if (volumeContainer)
IGNORE_RETURN (volumeContainer->recalculateVolume ());
WARNING_STRICT_FATAL(m_totalVolume > 0 && m_currentVolume > m_totalVolume, ("Recalculate Volume ended up being greater than our capacity"));
return m_currentVolume;
}
//-----------------------------------------------------------------------
bool VolumeContainer::internalRemove(const Object & item, const VolumeContainmentProperty * itemProp)
{
const VolumeContainmentProperty * prop = itemProp ? itemProp : safe_cast<const VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
WARNING_STRICT_FATAL(true, ("Item %s has no volume property", item.getNetworkId().getValueString().c_str()));
return false;
}
if (m_totalVolume != VL_NoVolumeLimit)
m_currentVolume = m_currentVolume - prop->getVolume();
return true;
}
//-----------------------------------------------------------------------
bool VolumeContainer::remove (Object &item, ContainerErrorCode& error)
{
// save off current volume
const int oldVolume = m_currentVolume;
error = CEC_Success;
VolumeContainmentProperty * prop = safe_cast<VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (!prop)
{
WARNING_STRICT_FATAL(true, ("Cannot remove an item from a volume container without a containment property."));
error = CEC_Unknown;
return false;
}
bool retval = Container::remove(item, error);
if (!retval)
{
return false;
}
if (!internalRemove(item))
{
WARNING_STRICT_FATAL(true, ("tried to remove item %s from volume container in internal routine but failed", item.getNetworkId().getValueString().c_str()));
error = CEC_Unknown;
return false;
}
// if volume has changed, update parent volume count
if (m_currentVolume != oldVolume)
{
VolumeContainer *parent = getVolumeContainerParent(*this);
if (parent)
parent->childVolumeChanged((m_currentVolume - oldVolume), true);
}
return true;
}
// ----------------------------------------------------------------------
bool VolumeContainer::remove(ContainerIterator &pos, ContainerErrorCode & error)
{
error = CEC_Success;
Object *obj=(*pos).getObject();
if (obj)
return remove(*obj, error);
else
{
error = CEC_Unknown;
return false;
}
}
//-----------------------------------------------------------------------
int VolumeContainer::depersistContents(const Object& item)
{
// save off current volume
const int oldVolume = m_currentVolume;
insertNewItem(item);
// if volume has changed, update parent volume count
if (m_currentVolume != oldVolume)
{
// if we are contained in another volume container, we
// need up update the count in the parent container;
// however, if we are here because of a baseline, we don't
// need to update the parent container because when the
// parent adds us, it will update the count at that time;
// if we are here because of a delta, then we need to
// update the parent; if we are here because of a baseline,
// then we are not yet in the parent container, even though
// we have a pointer to the parent container
VolumeContainer *parent = getVolumeContainerParent(*this);
if (parent)
{
bool containedInParent = false;
for (ContainerIterator i = parent->begin(); i != parent->end(); ++i)
{
if ((*i) == getOwner().getNetworkId())
{
containedInParent = true;
break;
}
}
if (containedInParent)
parent->childVolumeChanged((m_currentVolume - oldVolume), true);
}
}
return Container::depersistContents(item);
}
//-----------------------------------------------------------------------
bool VolumeContainer::internalItemRemoved(const Object& item)
{
// save off current volume
const int oldVolume = m_currentVolume;
if (internalRemove(item))
{
// if volume has changed, update parent volume count
if (m_currentVolume != oldVolume)
{
const VolumeContainmentProperty * prop = safe_cast<const VolumeContainmentProperty *>(item.getProperty(VolumeContainmentProperty::getClassPropertyId()));
if (prop)
{
VolumeContainer *parent = getVolumeContainerParent(*this);
if (parent)
parent->childVolumeChanged((m_currentVolume - oldVolume), true);
}
}
return Container::internalItemRemoved(item);
}
return false;
}
//----------------------------------------------------------------------
int VolumeContainer::getTotalVolumeLimitedByParents () const
{
int totalVolume = m_totalVolume;
//-- container is unlimited
if (totalVolume <= 0)
return totalVolume;
int remainingVolume = m_totalVolume - m_currentVolume;
const Object * parent = &getOwner ();
while (parent)
{
const ContainedByProperty * const containedByProperty = parent->getContainedByProperty ();
parent = containedByProperty->getContainedBy ();
if (parent)
{
const VolumeContainer * const volumeContainer = parent->getVolumeContainerProperty();
if (!volumeContainer)
break;
const int parentTotalVolume = volumeContainer->getTotalVolume ();
const int parentCurrentVolume = volumeContainer->getCurrentVolume ();
//-- we've reached an unlimited container
if (parentTotalVolume <= 0)
break;
const int remainingInParent = std::max (0, parentTotalVolume - parentCurrentVolume);
remainingVolume = std::min (remainingVolume, remainingInParent);
}
}
return m_currentVolume + remainingVolume;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,98 @@
// ===============================================================
// VolumeContainer.h
// copyright 2000 Verant Interactive
// All rights reserved
// ===============================================================
#ifndef INCLUDED_VolumeContainer_H
#define INCLUDED_VolumeContainer_H
//-----------------------------------------------------------------------
#include "sharedObject/Container.h"
#include "Archive/AutoDeltaByteStream.h"
//-----------------------------------------------------------------------
class VolumeContainmentProperty;
//-----------------------------------------------------------------------
/** A volume container is a container that holds items, limited to a
* maximum volume. It represents things like chests, bags, etc.
*/
class VolumeContainer:public Container
{
public:
static PropertyId getClassPropertyId();
public:
VolumeContainer(Object& owner, int totalVolume);
~VolumeContainer();
bool add (Object& item, ContainerErrorCode& error, bool allowOverloaded = false);
bool checkVolume(int addedVolume) const;
int getCurrentVolume () const;
int getTotalVolume () const;
int getTotalVolumeLimitedByParents () const;
virtual bool mayAdd (const Object& item, ContainerErrorCode& error) const;
int recalculateVolume();
virtual bool remove (Object &item, ContainerErrorCode& error);
virtual bool remove (ContainerIterator &pos, ContainerErrorCode& error);
virtual void debugPrint(std::string &buffer) const;
// persistence interface:
// @todo would be nice to protect this somehow.
// but no good way now so DO NOT CALL THESE FUNCTIONS DIRECTLY
virtual int depersistContents(const Object& item);
virtual bool internalItemRemoved(const Object& item);
int debugDoNotUseSetCapacity(int newValue);
enum
{
VL_NoVolumeLimit = -1
};
private:
int m_currentVolume;
int m_totalVolume;
public:
/** Called by the loader to add an item.
*/
void addItemFromLoader(int objectId);
private:
bool checkVolume(const VolumeContainmentProperty &item) const;
bool internalRemove(const Object & item, const VolumeContainmentProperty *itemProp = NULL);
void insertNewItem(const Object & item, const VolumeContainmentProperty *itemProp = NULL);
void childVolumeChanged(int volume, bool updateParent);
VolumeContainer();
VolumeContainer(const VolumeContainer&);
VolumeContainer& operator=(const VolumeContainer&);
};
//-----------------------------------------------------------------------
inline int VolumeContainer::getCurrentVolume() const
{
return m_currentVolume;
}
//-----------------------------------------------------------------------
inline int VolumeContainer::getTotalVolume() const
{
return m_totalVolume;
}
//-----------------------------------------------------------------------
#endif
@@ -0,0 +1,62 @@
// ======================================================================
//
// VolumeContainmentProperty.cpp
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/VolumeContainmentProperty.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedObject/VolumeContainer.h"
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(VolumeContainmentProperty, true, 0, 0, 0);
// ======================================================================
VolumeContainmentProperty::VolumeContainmentProperty(Object& owner, int volume) :
Property(VolumeContainmentProperty::getClassPropertyId(), owner),
m_volume(volume)
{
}
//----------------------------------------------------------------------
void VolumeContainmentProperty::setVolume (int volume)
{
m_volume = volume;
}
// -----------------------------------------------------------
VolumeContainmentProperty::~VolumeContainmentProperty()
{
}
// -----------------------------------------------------------
PropertyId VolumeContainmentProperty::getClassPropertyId()
{
return PROPERTY_HASH(VolumeContainment, 0x8701647C);
}
// -----------------------------------------------------------
int VolumeContainmentProperty::getVolume() const
{
int retval = m_volume;
const VolumeContainer* container = getOwner().getVolumeContainerProperty();
if (container)
{
retval += container->getCurrentVolume();
}
return retval;
}
//-----------------------------------------------------------
@@ -0,0 +1,48 @@
// ======================================================================
//
// VolumeContainmentProperty.h
// Copyright 2001 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_VolumeContainmentProperty_H
#define INCLUDED_VolumeContainmentProperty_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/Property.h"
// ======================================================================
class VolumeContainmentProperty : public Property
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
static PropertyId getClassPropertyId();
public:
VolumeContainmentProperty(Object& owner, int volume);
~VolumeContainmentProperty();
int getVolume () const;
void setVolume (int volume);
private:
int m_volume;
VolumeContainmentProperty();
VolumeContainmentProperty(const VolumeContainmentProperty&);
VolumeContainmentProperty& operator= (const VolumeContainmentProperty&);
};
// -----------------------------------------------------------
#endif
@@ -0,0 +1,267 @@
// ======================================================================
//
// Controller.cpp
// copyright 1998 Bootprint Entertainment
// Copyright 2000-2001 Sony Online Entertainment
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Controller.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/Object.h"
#include "sharedFoundation/Clock.h"
// ======================================================================
Controller::Controller(Object *const owner) :
m_messageQueue(new MessageQueue(16)),
m_owner(owner)
{
}
// ----------------------------------------------------------------------
Controller::~Controller()
{
HeldMessageMap::iterator iter;
for ( iter = m_heldMessages.begin(); iter != m_heldMessages.end(); ++iter )
{
delete( iter->second.data );
}
m_heldMessages.clear();
delete m_messageQueue;
m_owner = 0;
}
// ----------------------------------------------------------------------
float Controller::alter(float time)
{
NOT_NULL(m_messageQueue);
m_messageQueue->beginFrame();
processHeldMessages();
return realAlter(time);
}
// ----------------------------------------------------------------------
void Controller::conclude()
{
}
// ----------------------------------------------------------------------
void Controller::setOwner(Object *const owner)
{
m_owner = owner;
}
//
// Hold onto this message for a while before sending
//
void Controller::holdMessage( int holdMs, int message, float value, MessageQueue::Data *data, uint32 flags)
{
if ( m_heldMessages.count(message) ) // only one per type
sendHeldMessage( message );
m_heldMessages[ message ].sendTime = Clock::getCurrentTime() + (double(holdMs) / 1000.0);
m_heldMessages[ message ].value = value;
m_heldMessages[ message ].data = data;
m_heldMessages[ message ].flags = flags;
if (m_owner && m_owner->isInitialized())
m_owner->scheduleForAlter();
}
//
// Check out the current held message
//
MessageQueue::Data* Controller::peekHeldMessage( int message, float *value, uint32 *flags )
{
HeldMessageMap::iterator iter = m_heldMessages.find( message );
if ( iter == m_heldMessages.end() )
return NULL;
if ( value )
*value = iter->second.value;
if ( flags )
*flags = iter->second.flags;
return iter->second.data;
}
//
// Cause the held message of this type to get sent now
//
void Controller::sendHeldMessage( int message )
{
HeldMessageMap::iterator iter = m_heldMessages.find( message );
if ( iter == m_heldMessages.end() )
return;
appendMessage( message, iter->second.value, iter->second.data, iter->second.flags );
m_heldMessages.erase( iter );
}
//
// Cause the held message of this type to get sent if the hold time has expired
//
void Controller::processHeldMessages( void )
{
double now = Clock::getCurrentTime();
HeldMessageMap::iterator iter;
for ( iter = m_heldMessages.begin(); iter != m_heldMessages.end(); )
{
if ( iter->second.sendTime <= now )
{
appendMessage( iter->first, iter->second.value, iter->second.data, iter->second.flags );
m_heldMessages.erase( iter++ );
}
else
{
++iter;
}
}
if ( ! m_heldMessages.empty() )
{
if (m_owner && m_owner->isInitialized())
m_owner->scheduleForAlter();
}
}
// ----------------------------------------------------------------------
void Controller::appendMessage(const int message, const float value, const uint32 flags)
{
NOT_NULL(m_messageQueue);
m_messageQueue->appendMessage(message, value, flags);
if (message==0)
{
WARNING(true, ("trying to append message 0"));
}
//-- We must guarantee that the owner object gets an alter to process this message.
// @todo resolve: if this object is handled via object lists (e.g. a UI object), this
// should not go on the alter scheduler.
if (m_owner && m_owner->isInitialized())
m_owner->scheduleForAlter();
}
// ----------------------------------------------------------------------
void Controller::appendMessage(const int message, const float value, MessageQueue::Data *const data, const uint32 flags)
{
NOT_NULL(m_messageQueue);
m_messageQueue->appendMessage(message, value, data, flags);
//-- We must guarantee that the owner object gets an alter to process this message.
// @todo resolve: if this object is handled via object lists (e.g. a UI object), this
// should not go on the alter scheduler.
if (m_owner && m_owner->isInitialized())
m_owner->scheduleForAlter();
}
// ----------------------------------------------------------------------
int Controller::getNumberOfMessages() const
{
return m_messageQueue->getNumberOfMessages();
}
// ----------------------------------------------------------------------
void Controller::getMessage(int index, int *message, float *value, uint32 *flags) const
{
m_messageQueue->getMessage(index, message, value, flags);
}
// ----------------------------------------------------------------------
void Controller::getMessage(int index, int *message, float *value, MessageQueue::Data **data, uint32 *flags) const
{
m_messageQueue->getMessage(index, message, value, data, flags);
}
// ----------------------------------------------------------------------
void Controller::clearMessageAndData(int index)
{
m_messageQueue->clearMessageData(index);
m_messageQueue->clearMessage(index);
}
// ----------------------------------------------------------------------
void Controller::setMessageQueueNotification(MessageQueue::Notification *notification)
{
m_messageQueue->setNotification(notification);
}
//----------------------------------------------------------------------
MessageQueue * Controller::getMessageQueue()
{
return m_messageQueue;
}
//----------------------------------------------------------------------
TangibleController * Controller::asTangibleController()
{
return NULL;
}
//----------------------------------------------------------------------
TangibleController const * Controller::asTangibleController() const
{
return NULL;
}
//----------------------------------------------------------------------
CreatureController * Controller::asCreatureController()
{
return NULL;
}
//----------------------------------------------------------------------
CreatureController const * Controller::asCreatureController() const
{
return NULL;
}
//----------------------------------------------------------------------
ShipController * Controller::asShipController()
{
return NULL;
}
//----------------------------------------------------------------------
ShipController const * Controller::asShipController() const
{
return NULL;
}
// ======================================================================
// PROTECTED Controller
// ======================================================================
float Controller::realAlter(float /*time*/)
{
// Indicate that no alter is required for this class' functionality.
return AlterResult::cms_keepNoAlter;
}
// ======================================================================
@@ -0,0 +1,114 @@
// ======================================================================
//
// Controller.h
// copyright 1998 Bootprint Entertainment
// Copyright 2000-2001 Sony Online Entertainment
// All Rights Reserved.
//
// Abstract controller entity for an object
//
// ======================================================================
#ifndef INCLUDED_Controller_H
#define INCLUDED_Controller_H
// ======================================================================
#include "sharedFoundation/MessageQueue.h"
#include <map>
class CreatureController;
class Object;
class ShipController;
class TangibleController;
// ======================================================================
class Controller
{
public:
explicit Controller(Object *owner);
virtual ~Controller();
float alter(float time);
virtual void conclude();
virtual TangibleController * asTangibleController();
virtual TangibleController const * asTangibleController() const;
virtual CreatureController * asCreatureController();
virtual CreatureController const * asCreatureController() const;
virtual ShipController * asShipController();
virtual ShipController const * asShipController() const;
virtual void setOwner(Object *newOwner);
Object *getOwner();
const Object *getOwner() const;
// hold message for a little while before sending
// only one message per type may be held
void holdMessage( int holdMs, int message, float value, MessageQueue::Data *data, uint32 flags=0);
MessageQueue::Data* peekHeldMessage( int message, float *value=0, uint32 *flags=0 );
void sendHeldMessage( int message );
void processHeldMessages( void );
void appendMessage(int message, float value, uint32 flags=0);
void appendMessage(int message, float value, MessageQueue::Data *data, uint32 flags=0);
int getNumberOfMessages() const;
void getMessage(int index, int *message, float *value, uint32 *flags=0) const;
void getMessage(int index, int *message, float *value, MessageQueue::Data **data, uint32 *flags=0) const;
void clearMessageAndData(int i);
void setMessageQueueNotification(MessageQueue::Notification *notification);
MessageQueue * getMessageQueue();
protected:
struct HeldMessageInfo
{
double sendTime;
float value;
MessageQueue::Data* data;
uint32 flags;
};
virtual float realAlter(float time);
private:
Controller();
Controller(const Controller &);
Controller &operator =(const Controller &);
protected:
typedef std::map< int, HeldMessageInfo > HeldMessageMap;
HeldMessageMap m_heldMessages; // message type -> held info
MessageQueue *const m_messageQueue;
private:
Object *m_owner;
};
// ======================================================================
inline Object *Controller::getOwner()
{
return m_owner;
}
// ----------------------------------------------------------------------
inline const Object *Controller::getOwner() const
{
return m_owner;
}
// ======================================================================
#endif
@@ -0,0 +1,139 @@
// ======================================================================
//
// NetworkController.cpp
// copyright 2000 Verant Interactive
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/NetworkController.h"
#include "sharedFoundation/NetworkIdArchive.h"
#include "sharedNetworkMessages/MessageQueueDataTransform.h"
#include "sharedNetworkMessages/MessageQueueDataTransformWithParent.h"
#include "sharedNetworkMessages/ObjectChannelMessages.h"
#include "sharedFoundation/GameControllerMessage.h"
#include "sharedObject/Object.h"
//-----------------------------------------------------------------------
NetworkController::NetworkController(Object *const owner) :
Controller(owner)
{
}
//-----------------------------------------------------------------------
NetworkController::~NetworkController()
{
}
//-----------------------------------------------------------------------
void NetworkController::conclude()
{
//-- if the object is valid
const Object *const object = getOwner ();
if (object)
{
//-- if the network id is valid
const NetworkId networkId = object->getNetworkId ();
if (networkId != NetworkId::cms_invalid)
{
int const messageCount = getNumberOfMessages ();
for (int i = 0; i < messageCount; ++i)
{
int message;
float value;
uint32 flags;
MessageQueue::Data* data;
getMessage (i, &message, &value, &data, &flags);
if (message == 0)
{
// WARNING(true, ("Pulled message with id 0 from queue"));
}
//-- if the message is flagged for sending
else if (flags & GameControllerMessageFlags::SEND)
{
DEBUG_FATAL ((flags & GameControllerMessageFlags::DESTINATIONS) == 0, ("SEND controller message %d with no destination!", message));
const ObjControllerMessage c (networkId, static_cast<uint32>(message), value, flags, data);
sendControllerMessage (c);
}
//-- delete the message queue data if it exists
if (data)
{
if ((flags & GameControllerMessageFlags::SEND) != 0 ||
(flags & GameControllerMessageFlags::SOURCE_REMOTE_SERVER) != 0 ||
(flags & GameControllerMessageFlags::SOURCE_REMOTE_CLIENT) != 0)
{
clearMessageAndData (i);
delete data;
data = 0;
}
}
}
}
}
//-- chain up to the base class
Controller::conclude ();
}
//-----------------------------------------------------------------------
bool NetworkController::getAuthoritative() const
{
return getOwner()->isAuthoritative();
}
//-----------------------------------------------------------------------
/**
* Processes a message.
*
* @param message message id
* @param data message data
* @param value message value
* @param time time since last update
* @param flags delivery flags
*/
void NetworkController::handleMessage (const int message, const float /*value*/, const MessageQueue::Data* const data, const uint32 /*flags*/)
{
switch (message)
{
case CM_netUpdateTransformWithParent:
{
const MessageQueueDataTransformWithParent *const messageData = dynamic_cast<const MessageQueueDataTransformWithParent *>(data);
if (messageData)
handleNetUpdateTransformWithParent(*messageData);
}
break;
case CM_netUpdateTransform:
{
const MessageQueueDataTransform *const messageData = dynamic_cast<const MessageQueueDataTransform *>(data);
if (messageData)
handleNetUpdateTransform(*messageData);
}
break;
default:
break;
}
}
//-----------------------------------------------------------------------
/**
* Sets this controller's object to be authoritative.
*
* @param authoritative authoritative flag
*/
void NetworkController::setAuthoritative(bool authoritative)
{
getOwner()->setAuthoritative(authoritative);
}
//-----------------------------------------------------------------------
@@ -0,0 +1,58 @@
// ======================================================================
//
// NetworkController.h
// copyright 2000 Verant Interactive
//
// ======================================================================
#ifndef INCLUDED_NetworkController_H
#define INCLUDED_NetworkController_H
// ======================================================================
#include "sharedObject/Controller.h"
class Baselines;
class GameNetworkMessage;
class MessageQueueDataTransform;
class MessageQueueDataTransformWithParent;
class MessageQueueSetMemberData;
class ObjControllerMessage;
// ======================================================================
class NetworkController : public Controller
{
public:
explicit NetworkController(Object* newOwner);
virtual ~NetworkController();
/**
NetworkController::conclude() gathers all messages in it's
message queue and sends those with the ControllerMessageFlag::SEND
option set.
*/
virtual void conclude ();
virtual void sendControllerMessage(const ObjControllerMessage& msg) = 0;
bool getAuthoritative () const;
virtual void setAuthoritative (bool newAuthoritative);
protected:
virtual void handleMessage (int message, float value, const MessageQueue::Data* data, uint32 flags);
virtual void handleNetUpdateTransform (const MessageQueueDataTransform& message) = 0;
virtual void handleNetUpdateTransformWithParent (const MessageQueueDataTransformWithParent& message) = 0;
private:
NetworkController();
NetworkController(const NetworkController & other);
NetworkController& operator=(const NetworkController & rhs);
};
// ======================================================================
#endif
@@ -0,0 +1,83 @@
//========================================================================
//
// ObjectSetMessage.def - sub-message ids for controller message CM_setMemberData
//
// copyright 2001 Sony Online Entertainment
//
// data files should be including ObjectSetMessage.def
// code files should be including ObjectSetMessage.h
//
//========================================================================
#ifndef _INCLUDED_ObjectSetMessage_DEF
#define _INCLUDED_ObjectSetMessage_DEF
#ifndef _INCLUDED_ObjectSetMessage_H
#error include ObjectSetMessage.h instead of ObjectSetMessage.def
#endif
enum ObjectSetMessage
{
OSM_nothing,
// ids for StarwarsObject and below
OSM_game_FIRST,
OSM_game_objectName,
OSM_game_sceneId,
OSM_game_LAST,
// ids for TangibleObject
OSM_tangible_FIRST, // all Tangible properties are > OSM_tangible_FIRST
OSM_tangible_armorEffectiveness,
OSM_tangible_decayTime,
OSM_tangible_hitPoints,
OSM_tangible_isFrozen,
OSM_tangible_isSquelched,
OSM_tangible_maxHitPoints,
OSM_tangible_ownerId,
OSM_tangible_popupHelpId,
OSM_tangible_qualityRating,
OSM_tangible_visible,
OSM_tangible_weight,
OSM_tangible_LAST, // all Tangible properties are < OSM_tangible_LAST
// ids for CreatureObject
OSM_creature_FIRST,
OSM_creature_attributes, // takes an index and value
OSM_creature_maxAttributes, // takes an index and value
OSM_creature_gender,
OSM_creature_LAST,
// ids for VehicleObject
OSM_vehicle_FIRST,
OSM_vehicle_bogus,
OSM_vehicle_LAST,
// ids for BuildingObject
OSM_building_FIRST,
OSM_building_LAST,
// ids for VenueObject
OSM_venue_FIRST,
OSM_venue_LAST,
// ids for InstallationObject
OSM_installation_FIRST,
OSM_installation_LAST,
// ids for ProducerObject
OSM_producer_FIRST,
OSM_producer_LAST,
// ids for CountingObject
OSM_counting_FIRST,
OSM_counting_LAST,
// ids for WeaponObject
OSM_weapon_FIRST,
OSM_weapon_LAST,
OSM_last
};
#endif // _INCLUDED_ObjectSetMessage_DEF
@@ -0,0 +1,42 @@
//========================================================================
//
// ObjectSetMessage.def - sub-message ids for controller message CM_setMemberData
//
// copyright 2001 Sony Online Entertainment
//
// data files should be including ObjectSetMessage.def
// code files should be including ObjectSetMessage.h
//
//========================================================================
#ifndef _INCLUDED_ObjectSetMessage_H
#define _INCLUDED_ObjectSetMessage_H
#include "sharedObject/ObjectSetMessage.def"
// data types for ObjectSetMessage
enum OsmDataType
{
ODT_bool, // maps to bool
ODT_char, // maps to char
ODT_int16, // maps to int16
ODT_int32, // maps to int32
ODT_uint16, // maps to uint16
ODT_uint32, // maps to uint32
ODT_real, // maps to real
ODT_stdstring, // maps to an stl string
ODT_unicodestring, // maps to our unicode wide character strings
ODT_attrib // maps to struct OdtAttribute
};
// types for CreatureObject
struct OdtAttribute
{
signed char type; // attribute type (CreatureObject::AttributeEnumerator)
int16 value; // attribute value
};
#endif // _INCLUDED_ObjectSetMessage_H
@@ -0,0 +1,10 @@
$value = 0;
while (<>)
{
if (/(CM_[^,]+)/)
{
print "$1: $value\n";
++$value;
}
}
@@ -0,0 +1,168 @@
// =====================================================================
//
// ConfigSharedObject.cpp
// asommers
//
// copyright 2002, sony online entertainment
//
// =====================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ConfigSharedObject.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/ConfigFile.h"
// =====================================================================
#define KEY_BOOL(s, a,b) (ms_ ## a = ConfigFile::getKeyBool(s, #a, b))
#define KEY_INT(s, a,b) (ms_ ## a = ConfigFile::getKeyInt(s, #a, b))
#define KEY_FLOAT(s, a,b) (ms_ ## a = ConfigFile::getKeyFloat(s, #a, b))
//#define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedObject", #a, b))
// =====================================================================
// ConfigSharedObjectNamespace
// =====================================================================
namespace ConfigSharedObjectNamespace
{
float ms_portalScale;
bool ms_allowDisabledPortals;
float ms_appearanceTemplateListKeepTime;
float ms_appearanceTemplateListKeepEpsilon;
bool ms_validateCellContentsAttached;
bool ms_validateWorld;
int ms_alterSchedulerNoAlterScheduleDelay;
bool ms_logCustomizationDataIssues;
bool ms_debugAlterChecking;
bool ms_containerLoopChecking;
int ms_containerMaxDepth;
bool ms_allowDisallowObjectDelete;
}
using namespace ConfigSharedObjectNamespace;
// =====================================================================
// STATIC PUBLIC ConfigSharedObjectNamespace
// =====================================================================
void ConfigSharedObject::install()
{
KEY_FLOAT ("SharedObject", portalScale, 1.1f);
KEY_BOOL("SharedObject", allowDisabledPortals, false);
KEY_FLOAT ("SharedObject", appearanceTemplateListKeepTime, 15.f);
KEY_FLOAT ("SharedObject", appearanceTemplateListKeepEpsilon, 5.f);
KEY_BOOL ("SharedObject", validateCellContentsAttached, true);
KEY_BOOL ("SharedObject", validateWorld, false);
KEY_BOOL ("SharedObject", logCustomizationDataIssues, false);
KEY_INT ("SharedObject/AlterScheduler", alterSchedulerNoAlterScheduleDelay, 0);
KEY_BOOL ("SharedObject", debugAlterChecking, false);
KEY_BOOL ("SharedObject", containerLoopChecking, true);
KEY_INT ("SharedObject", containerMaxDepth, 9);
KEY_BOOL ("SharedObject", allowDisallowObjectDelete, true);
}
// =====================================================================
// STATIC PRIVATE ConfigSharedObjectNamespace
// =====================================================================
float ConfigSharedObject::getPortalScale ()
{
return ms_portalScale;
}
// ---------------------------------------------------------------------
bool ConfigSharedObject::getAllowDisabledPortals()
{
return ms_allowDisabledPortals;
}
// ---------------------------------------------------------------------
float ConfigSharedObject::getAppearanceTemplateListKeepTime ()
{
return ms_appearanceTemplateListKeepTime;
}
// ---------------------------------------------------------------------
float ConfigSharedObject::getAppearanceTemplateListKeepEpsilon ()
{
return ms_appearanceTemplateListKeepEpsilon;
}
// ---------------------------------------------------------------------
bool ConfigSharedObject::getValidateCellContentsAttached ()
{
return ms_validateCellContentsAttached;
}
// ---------------------------------------------------------------------
bool ConfigSharedObject::getValidateWorld ()
{
return ms_validateWorld;
}
// ----------------------------------------------------------------------
/**
* If set to non-zero, the alter scheduler will schedule objects requesting
* no alter at this return value's number of seconds into the future.
*
* @return the number of seconds in the future in which no-alter-desired objects
* will be altered into the future.
*/
int ConfigSharedObject::getAlterSchedulerNoAlterScheduleDelay ()
{
return ms_alterSchedulerNoAlterScheduleDelay;
}
// ----------------------------------------------------------------------
bool ConfigSharedObject::getLogCustomizationDataIssues ()
{
return ms_logCustomizationDataIssues;
}
// ----------------------------------------------------------------------
bool ConfigSharedObject::getDebugAlterChecking()
{
return ms_debugAlterChecking;
}
// ----------------------------------------------------------------------
bool ConfigSharedObject::getContainerLoopChecking()
{
return ms_containerLoopChecking;
}
// ----------------------------------------------------------------------
int ConfigSharedObject::getContainerMaxDepth()
{
return ms_containerMaxDepth;
}
// ----------------------------------------------------------------------
bool ConfigSharedObject::getAllowDisallowObjectDelete()
{
return ms_allowDisallowObjectDelete;
}
// =====================================================================
@@ -0,0 +1,47 @@
// =====================================================================
//
// ConfigSharedObject.h
// asommers
//
// copyright 2002, sony online entertainment
//
// =====================================================================
#ifndef INCLUDED_ConfigSharedObject_H
#define INCLUDED_ConfigSharedObject_H
// =====================================================================
class ConfigSharedObject
{
public:
static void install ();
static float getPortalScale ();
static bool getAllowDisabledPortals();
static float getAppearanceTemplateListKeepTime ();
static float getAppearanceTemplateListKeepEpsilon ();
static bool getValidateCellContentsAttached ();
static bool getValidateWorld ();
static int getAlterSchedulerNoAlterScheduleDelay ();
static bool getLogCustomizationDataIssues ();
static bool getDebugAlterChecking();
static bool getContainerLoopChecking();
static int getContainerMaxDepth();
static bool getAllowDisallowObjectDelete();
private:
ConfigSharedObject ();
ConfigSharedObject (const ConfigSharedObject&);
ConfigSharedObject& operator= (const ConfigSharedObject&);
};
// =====================================================================
#endif
@@ -0,0 +1,18 @@
// ======================================================================
//
// FirstObject.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_FirstObject_H
#define INCLUDED_FirstObject_H
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
// ======================================================================
#endif
@@ -0,0 +1,195 @@
// ======================================================================
//
// SetupSharedObject.cpp
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SetupSharedObject.h"
#include "sharedCollision/ExtentList.h"
#include "sharedObject/AlterScheduler.h"
#include "sharedObject/Appearance.h"
#include "sharedObject/AppearanceTemplate.h"
#include "sharedObject/AppearanceTemplateList.h"
#include "sharedObject/ArrangementDescriptorList.h"
#include "sharedObject/BasicRangedIntCustomizationVariable.h"
#include "sharedObject/CellProperty.h"
#include "sharedObject/ConfigSharedObject.h"
#include "sharedObject/ContainedByProperty.h"
#include "sharedObject/CustomizationData.h"
#include "sharedObject/CustomizationIdManager.h"
#include "sharedObject/MemoryBlockManagedObject.h"
#include "sharedObject/MovementTable.h"
#include "sharedObject/NoRenderAppearanceTemplate.h"
#include "sharedObject/Object.h"
#include "sharedObject/ObjectTemplate.h"
#include "sharedObject/ObjectTemplateList.h"
#include "sharedObject/PaletteColorCustomizationVariable.h"
#include "sharedObject/PortalPropertyTemplate.h"
#include "sharedObject/ScheduleData.h"
#include "sharedObject/SlotDescriptorList.h"
#include "sharedObject/SlotIdManager.h"
#include "sharedObject/SlottedContainmentProperty.h"
#include "sharedObject/TrackingDynamics.h"
#include "sharedObject/VolumeContainmentProperty.h"
#include "sharedDebug/InstallTimer.h"
#include <string>
// ======================================================================
// class SetupSharedObject::Data
// ======================================================================
SetupSharedObject::Data::Data()
: version(0),
useContainers(false),
slotDefinitionFilename(new std::string("")),
loadAssociatedHardpointNames(false),
useMovementTable(false),
movementStateTableFilename(new std::string("")),
useTimedAppearanceTemplates(false),
ensureDefaultAppearanceExists(true),
customizationIdManagerFilename(0),
objectsAlterChildrenAndContents(true),
loadObjectTemplateCrcStringTable(true),
pobEjectionTransformFilename(NULL)
{
}
// ----------------------------------------------------------------------
SetupSharedObject::Data::~Data()
{
delete customizationIdManagerFilename;
delete movementStateTableFilename;
delete slotDefinitionFilename;
}
// ======================================================================
// class SetupSharedObject
// ======================================================================
/**
* Install sharedObject.
*
* The settings in the Data structure will determine which subsystems
* get initialized.
*/
void SetupSharedObject::install(const Data &data)
{
InstallTimer const installTimer("SetupSharedObject::install");
DEBUG_FATAL(data.version != DATA_VERSION, ("SetupSharedObject::install wrong version %d/%d", data.version, DATA_VERSION));
ConfigSharedObject::install();
ScheduleData::install();
Appearance::install();
AppearanceTemplateList::install(data.useTimedAppearanceTemplates, data.ensureDefaultAppearanceExists);
NoRenderAppearanceTemplate::install();
// this is needed by plug-ins that aren't using the rest of the 3d system
ExtentList::install();
ObjectTemplateList::install(data.loadObjectTemplateCrcStringTable);
ObjectTemplate::install();
Object::install(data.objectsAlterChildrenAndContents);
MemoryBlockManagedObject::install();
CellProperty::install();
AppearanceTemplate::install();
ContainedByProperty::install();
SlottedContainmentProperty::install();
VolumeContainmentProperty::install();
CustomizationData::install();
BasicRangedIntCustomizationVariable::install();
PaletteColorCustomizationVariable::install();
PortalPropertyTemplate::install(data.pobEjectionTransformFilename);
// Dynamics.
TrackingDynamics::install();
// install container-related systems
if (data.useContainers)
{
DEBUG_FATAL(data.slotDefinitionFilename->empty(), ("must specify a slotDefinitionFilename if you're using containers\n"));
SlotIdManager::install(*data.slotDefinitionFilename, data.loadAssociatedHardpointNames);
SlotDescriptorList::install();
ArrangementDescriptorList::install();
}
// install movement table
if (data.useMovementTable)
{
DEBUG_FATAL(data.movementStateTableFilename->empty(), ("must specify a movementStateTableFilename if using the movement table\n"));
MovementTable::install(*data.movementStateTableFilename);
}
AlterScheduler::install();
// Optionally install customization id manager
if (data.customizationIdManagerFilename)
CustomizationIdManager::install(data.customizationIdManagerFilename->c_str());
}
// ----------------------------------------------------------------------
void SetupSharedObject::setupDefaultGameData(Data &data)
{
data.version = DATA_VERSION;
}
// ----------------------------------------------------------------------
void SetupSharedObject::setupDefaultConsoleData(Data &data)
{
data.version = DATA_VERSION;
data.loadObjectTemplateCrcStringTable = false;
}
// ----------------------------------------------------------------------
void SetupSharedObject::setupDefaultMFCData(Data &data)
{
data.version = DATA_VERSION;
}
// ----------------------------------------------------------------------
void SetupSharedObject::addSlotIdManagerData(Data &data, bool loadAssociatedHardpointNames)
{
data.useContainers = true;
*data.slotDefinitionFilename = "abstract/slot/slot_definition/slot_definitions.iff";
data.loadAssociatedHardpointNames = loadAssociatedHardpointNames;
}
// ----------------------------------------------------------------------
void SetupSharedObject::addMovementTableData(Data &data)
{
data.useMovementTable = true;
*data.movementStateTableFilename = "datatables/movement/movementstates.iff";
}
// ----------------------------------------------------------------------
void SetupSharedObject::addCustomizationSupportData(Data &data)
{
IS_NULL(data.customizationIdManagerFilename);
data.customizationIdManagerFilename = new std::string("customization/customization_id_manager.iff");
}
// ----------------------------------------------------------------------
void SetupSharedObject::addPobEjectionTransformData(Data &data)
{
IS_NULL(data.pobEjectionTransformFilename);
data.pobEjectionTransformFilename = "datatables/pob/pob_ejection_point.iff";
}
// ======================================================================
@@ -0,0 +1,100 @@
// ======================================================================
//
// SetupSharedObject.h
// copyright 1998 Bootprint Entertainment
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_SetupSharedObject_H
#define INCLUDED_SetupSharedObject_H
// ======================================================================
class SetupSharedObject
{
private:
// **** INCREMENT THIS VERSION NUMBER WHENEVER THIS STRUCT CHANAGES ****
// This enum is private so that a game can't use it directly. If the
// struct changes, the game programmers should be forced to look at the
// changes and update their data and version number manually.
enum
{
DATA_VERSION = 13
};
public:
struct Data
{
public:
Data();
~Data();
public:
int version;
// Specifies if Object container support should be installed.
bool useContainers;
// Specifies the valid slot definition file. Must be specified
// if container support is installed.
std::string *slotDefinitionFilename;
// If loading a slot definition file, this value controls if the
// hardpoint names associated with a slot are loaded. This should
// be set true for clients and false for servers.
bool loadAssociatedHardpointNames;
// specifies if the movement state tables should be installed
bool useMovementTable;
std::string *movementStateTableFilename;
bool useTimedAppearanceTemplates;
bool ensureDefaultAppearanceExists;
// Specifies the name of the customization id manager data file.
// Must be specified to use appearance customization system.
// See addCustomizationSupportData().
std::string *customizationIdManagerFilename;
// specifies whether objects should alter their child and contained objects, rather than expecting them to be scheduled separately
bool objectsAlterChildrenAndContents;
// Specifies whether or not ObjectTemplateList should load the object template crc table
bool loadObjectTemplateCrcStringTable;
// Specifies the name of the POB ejection point transform override filename to use; use NULL (default) if no ejection point support.
char const *pobEjectionTransformFilename;
private:
// disabled
Data(const Data&);
Data &operator =(const Data&);
};
public:
static void setupDefaultGameData(Data &data);
static void setupDefaultConsoleData(Data &data);
static void setupDefaultMFCData(Data &data);
static void addSlotIdManagerData(Data &data, bool loadAssociatedHardpointNames);
static void addMovementTableData(Data &data);
static void addCustomizationSupportData(Data &data);
static void addPobEjectionTransformData(Data &data);
static void install(const Data &data);
};
// ======================================================================
#endif
@@ -0,0 +1,97 @@
// ======================================================================
//
// BasicRangedIntCustomizationVariable.cpp
// Copyright 2002, 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/BasicRangedIntCustomizationVariable.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedObject/ObjectTemplateCustomizationDataWriter.h"
#include <string>
#include <cstdio>
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(BasicRangedIntCustomizationVariable, true, 0, 0, 0);
// ======================================================================
BasicRangedIntCustomizationVariable::BasicRangedIntCustomizationVariable(int minRangeInclusive, int value, int maxRangeExclusive) :
RangedIntCustomizationVariable(),
m_value(value),
m_minRangeInclusive(minRangeInclusive),
m_maxRangeExclusive(maxRangeExclusive)
{
}
// ----------------------------------------------------------------------
int BasicRangedIntCustomizationVariable::getValue() const
{
return m_value;
}
// ----------------------------------------------------------------------
bool BasicRangedIntCustomizationVariable::setValue(int value)
{
if ((value >= m_minRangeInclusive) && (value < m_maxRangeExclusive))
{
// change the value
m_value = value;
// notify owner CustomizationData about change.
signalVariableModified();
}
else
{
DEBUG_WARNING(true, ("attempted to set BasicRangedIntCustomizationVariable to %d, outside valid range [%d,%d).", value, m_minRangeInclusive, m_maxRangeExclusive));
return false;
}
return RangedIntCustomizationVariable::setValue(value);
}
// ----------------------------------------------------------------------
void BasicRangedIntCustomizationVariable::getRange(int &minRangeInclusive, int &maxRangeExclusive) const
{
minRangeInclusive = m_minRangeInclusive;
maxRangeExclusive = m_maxRangeExclusive;
}
// ----------------------------------------------------------------------
void BasicRangedIntCustomizationVariable::writeObjectTemplateExportString(const std::string &variablePathName, ObjectTemplateCustomizationDataWriter &writer) const
{
#if !(USE_OBJ_TEMPLATE_CUSTOM_VAR_WRITER)
UNREF(variablePathName);
UNREF(writer);
#else
//-- this assumes that the current value is the default value --- if the user changed values at all, they
// will not be the artist's built in default.
writer.addRangedIntCustomizationVariable(variablePathName, m_minRangeInclusive, m_value, m_maxRangeExclusive);
#endif
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
std::string BasicRangedIntCustomizationVariable::debugToString() const
{
char buffer[128];
sprintf(buffer, "[%d,%d,%d)", m_minRangeInclusive, m_value, m_maxRangeExclusive);
return std::string(buffer);
}
#endif
// ======================================================================
@@ -0,0 +1,57 @@
// ======================================================================
//
// BasicRangedIntCustomizationVariable.h
// Copyright 2002, 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_BasicRangedIntCustomizationVariable_H
#define INCLUDED_BasicRangedIntCustomizationVariable_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/RangedIntCustomizationVariable.h"
class MemoryBlockManager;
// ======================================================================
class BasicRangedIntCustomizationVariable: public RangedIntCustomizationVariable
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
BasicRangedIntCustomizationVariable(int minRangeInclusive, int value, int maxRangeExclusive);
virtual int getValue() const;
virtual bool setValue(int value);
virtual void getRange(int &minRangeInclusive, int &maxRangeExclusive) const;
virtual void writeObjectTemplateExportString(const std::string &variablePathName, ObjectTemplateCustomizationDataWriter &writer) const;
#ifdef _DEBUG
virtual std::string debugToString() const;
#endif
private:
// disabled
BasicRangedIntCustomizationVariable();
BasicRangedIntCustomizationVariable(const BasicRangedIntCustomizationVariable&);
BasicRangedIntCustomizationVariable &operator =(const BasicRangedIntCustomizationVariable&);
private:
int m_value;
int m_minRangeInclusive;
int m_maxRangeExclusive;
};
// ======================================================================
#endif
@@ -0,0 +1,214 @@
// ======================================================================
//
// CustomizationData.h
// Copyright 2002, 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationData_H
#define INCLUDED_CustomizationData_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
class CrcLowerString;
class CustomizationVariable;
class Object;
// ======================================================================
/**
* Provides access to customization data.
*
* Typically a CustomizationData instance is embedded in a
* CustomizationDataProperty. That property is attached to
* an Object instance.
*
* Appearance-derived classes make use of the CustomizationData to
* customize the look of an appearance based on the values of customization
* variables.
*
* CustomizationData variables resides in a directory structure much like a
* Unix filesystem. A CustomizationData instance can mount the directory
* of another CustomizationData instance. The mounting feature is used by
* wearables to grab the body size customization variables from the current
* owner of the wearable.
*
* @see CustomizationDataProperty
* @see Object
*/
class CustomizationData
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITHOUT_INSTALL;
public:
class Directory;
class LocalDirectory; // should be private by mbm macros needs it to be public.
class RemoteDirectory; // should be private by mbm macros needs it to be public.
friend class RemoteDirectory;
typedef void (*ModificationCallback)(const CustomizationData &customizationData, const void *context);
typedef void (*ConstIteratorCallback)(const std::string &fullVariablePathName, const CustomizationVariable *customizationVariable, void *context);
typedef void (*IteratorCallback)(const std::string &fullVariablePathName, CustomizationVariable *customizationVariable, void *context);
typedef stdvector<byte>::fwd ByteVector;
public:
static void install();
static int parseSeparatedHexInt(const std::string &data, int startPosition, int &endPosition);
static std::string parseSeparatedString(const std::string &data, int startPosition, int &endPosition);
static std::string makeSelectDumpFormat(char const *source);
public:
explicit CustomizationData(Object &owner);
void addVariableTakeOwnership(const std::string &fullVariablePathName, CustomizationVariable *variable);
const CustomizationVariable *findConstVariable(const std::string &fullVariablePathName) const;
CustomizationVariable *findVariable(const std::string &fullVariablePathName);
void iterateOverConstVariables(ConstIteratorCallback callback, void *context, bool includeRemoteVariables = true) const;
void iterateOverVariables(IteratorCallback callback, void *context, bool includeRemoteVariables = true);
bool mountRemoteCustomizationData(CustomizationData &customizationDataToAttach, const std::string &remoteDirectory, const std::string &localDirectory, bool nonExistentLeafDirectoryOk = false);
bool dismountRemoteCustomizationData(const std::string &localDirectoryPathName, bool nonExistentLeafDirectoryOk = false);
const CustomizationData *getDirectoryOwner(const std::string &directory) const;
std::string writeLocalDataToString() const;
void loadLocalDataFromString(const std::string &stringData);
void registerModificationListener(ModificationCallback modificationCallback, const void *context);
void deregisterModificationListener(ModificationCallback modificationCallback, const void *context);
void signalModified() const;
void fetch() const;
void release() const;
int getReferenceCount() const;
Object &getOwnerObject();
const Object &getOwnerObject() const;
void alterLocalVariables();
#ifdef _DEBUG
void debugDump() const;
#endif
public:
static const char cms_directorySeparator;
static const char cms_stringFieldSeparator;
static bool ms_installed;
private:
struct ModificationCallbackData;
typedef stdmap<CustomizationData*, int>::fwd CustomizationDataIntMap;
typedef stdvector<ModificationCallbackData>::fwd ModificationCallbackDataVector;
private:
static void remove();
#ifdef _DEBUG
static void debugDumpIterationCallback(const std::string &fullVariablePathName, const CustomizationVariable *customizationVariable, void *context);
#endif
private:
~CustomizationData();
const Directory *findConstDirectoryFromPathName(const std::string &variablePathName, bool traverseRemoteDirectories, int &directoryEntryStartIndex) const;
Directory *findDirectoryFromPathName(const std::string &variablePathName, bool traverseRemoteDirectories, bool createLocalMissingDirectories, int &directoryEntryStartIndex);
void addDependentCustomizationData(CustomizationData *customizationData);
void removeDependentCustomizationData(CustomizationData *customizationData);
void notifyPendingRemoteDestruction(const CustomizationData *customizationData);
void loadLocalDataFromString_1(const std::string &stringData);
void loadLocalDataFromString_2(const std::string &stringData);
void saveToByteVector(ByteVector &data, bool persistRemoteData = false) const;
bool restoreFromByteVector(ByteVector const &data);
bool restoreFromByteVector_1(ByteVector const &data);
bool restoreFromByteVector_2(ByteVector const &data);
// Disabled.
CustomizationData();
CustomizationData(const CustomizationData&);
CustomizationData &operator =(const CustomizationData&);
private:
mutable int m_referenceCount;
Object &m_owner;
Directory *m_rootDirectory;
CustomizationDataIntMap *m_dependentCustomizationDataMap;
ModificationCallbackDataVector *m_modificationCallbacks;
};
// ======================================================================
/**
* Increment the reference count associated with the CustomizationData
* instance.
*
* The user should fetch() a reference for each logical reference the
* user makes to the CustomizationData instance. When a logical reference
* no longer is needed, the caller should call release().
*
* @see CustomizationData::release()
*/
inline void CustomizationData::fetch() const
{
++m_referenceCount;
}
// ----------------------------------------------------------------------
/**
* Retrieve the reference count.
*
* @return reference count.
*/
inline int CustomizationData::getReferenceCount() const
{
return m_referenceCount;
}
// ----------------------------------------------------------------------
inline Object &CustomizationData::getOwnerObject()
{
return m_owner;
}
// ----------------------------------------------------------------------
inline const Object &CustomizationData::getOwnerObject() const
{
return m_owner;
}
// ======================================================================
#endif
@@ -0,0 +1,92 @@
// PRIVATE
// ======================================================================
//
// CustomizationData_Directory.h
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationData_Directory_H
#define INCLUDED_CustomizationData_Directory_H
// ======================================================================
#include "sharedObject/CustomizationData.h"
// ======================================================================
class CustomizationData::Directory
{
public:
virtual ~Directory() {}
virtual bool resolvePathNameToDirectory(const std::string &pathName, int pathStartIndex, bool traverseRemoteDirectories, bool createLocalMissingDirectories, Directory *&directory, int &directoryEntryStartIndex) = 0;
virtual bool addVariableTakeOwnership(const std::string &fullVariablePathName, int variableNameStartIndex, CustomizationVariable *variable) = 0;
virtual const CustomizationVariable *findConstVariable(const std::string &variablePathName, int variableNameStartIndex) const = 0;
virtual CustomizationVariable *findVariable(const std::string &variablePathName, int variableNameStartIndex) = 0;
virtual Directory *findDirectory(const std::string &directoryPathName, int directoryNameStartIndex) = 0;
virtual void deleteDirectory(Directory *childDirectory) = 0;
virtual void iterateOverConstVariables(const std::string &parentPathName, ConstIteratorCallback callback, void *context, bool traverseRemoteDirectories) const = 0;
virtual void iterateOverVariables(const std::string &parentPathName, IteratorCallback callback, void *context, bool traverseRemoteDirectories) = 0;
virtual void replaceOrAddDirectory(const std::string &directoryPathName, int directoryNameStartIndex, Directory *directory) = 0;
virtual bool linksTo(const CustomizationData &customizationData) const = 0;
virtual void deleteLinksTo(const CustomizationData &customizationData) = 0;
virtual bool isLocalDirectory() const = 0;
#if 0
virtual std::string writeLocalDirectoryToString() const = 0;
virtual void loadLocalDirectoryFromString(int version, const std::string &string, int startIndex) = 0;
#endif
CustomizationData &getOwner();
const CustomizationData &getOwner() const;
protected:
explicit Directory(CustomizationData &owner);
private:
// Disabled.
Directory();
Directory(const Directory&);
Directory &operator =(const Directory&);
private:
CustomizationData &m_owner;
};
// ======================================================================
inline CustomizationData &CustomizationData::Directory::getOwner()
{
return m_owner;
}
// ----------------------------------------------------------------------
inline const CustomizationData &CustomizationData::Directory::getOwner() const
{
return m_owner;
}
// ======================================================================
inline CustomizationData::Directory::Directory(CustomizationData &owner) :
m_owner(owner)
{
}
// ======================================================================
#endif
@@ -0,0 +1,625 @@
// ======================================================================
//
// CustomizationData_LocalDirectory.cpp
// Copyright 2002, 2003 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/CustomizationData_LocalDirectory.h"
#include "sharedFoundation/CrcLowerString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedObject/CustomizationVariable.h"
#include "sharedObject/Object.h"
#include <algorithm>
#include <string>
#include <cstdio>
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(CustomizationData::LocalDirectory, true, 0, 0, 0);
// ======================================================================
CustomizationData::LocalDirectory::LocalDirectory(CustomizationData &owner) :
Directory(owner),
m_variables(),
m_directories()
{
}
// ----------------------------------------------------------------------
CustomizationData::LocalDirectory::~LocalDirectory()
{
//-- delete the variables we own
std::for_each(m_variables.begin(), m_variables.end(), PointerDeleterPairSecond());
//-- delete the directories
std::for_each(m_directories.begin(), m_directories.end(), PointerDeleterPairSecond());
}
// ----------------------------------------------------------------------
bool CustomizationData::LocalDirectory::resolvePathNameToDirectory(const std::string &pathName, int pathStartIndex, bool traverseRemoteDirectories, bool createLocalMissingDirectories, Directory *&directory, int &directoryEntryStartIndex)
{
//-- check if there's a directory embedded in the path name
const std::string::size_type endOfDirectoryName = pathName.find(CustomizationData::cms_directorySeparator, static_cast<std::string::size_type>(pathStartIndex));
const bool hasEmbeddedDirectory = (static_cast<int>(endOfDirectoryName) != static_cast<int>(std::string::npos));
if (!hasEmbeddedDirectory)
{
// The specified pathname does not have another complete subdirectory component
// embedded within it. That indicates the given pathName refers to a directory
// entry that is a direct child of this directory.
directory = this;
directoryEntryStartIndex = pathStartIndex;
return true;
}
//-- handle embedded directory reference
// get a CrcLowerString for the subdirectory
const std::string subdirName = pathName.substr(static_cast<std::string::size_type>(pathStartIndex), endOfDirectoryName - static_cast<std::string::size_type>(pathStartIndex));
const CrcLowerString crcSubdirName(subdirName.c_str());
// check if subdir exists
const DirectoryMap::iterator lowerBoundResult = m_directories.lower_bound(crcSubdirName);
const bool subdirExists = ((lowerBoundResult != m_directories.end()) && !m_directories.key_comp()(crcSubdirName, lowerBoundResult->first));
Directory *subdir = 0;
// handle traversal of directory
if (subdirExists)
subdir = lowerBoundResult->second;
else
{
if (!createLocalMissingDirectories)
{
// specified subdir doesn't exist and shouldn't be created. We must bail.
return false;
}
else
{
// create the missing subdirectory
subdir = new LocalDirectory(getOwner());
IGNORE_RETURN(m_directories.insert(lowerBoundResult, DirectoryMap::value_type(crcSubdirName, subdir)));
}
}
//-- ensure we've got a directory
if (!subdir)
{
WARNING(true, ("resolvePathNameToDirectory(): logic failure, subdir is null"));
return false;
}
//-- traverse the directory
return subdir->resolvePathNameToDirectory(pathName, static_cast<int>(endOfDirectoryName) + 1, traverseRemoteDirectories, createLocalMissingDirectories, directory, directoryEntryStartIndex);
}
// ----------------------------------------------------------------------
bool CustomizationData::LocalDirectory::addVariableTakeOwnership(const std::string &fullVariablePathName, int variableNameStartIndex, CustomizationVariable *variable)
{
//-- ensure caller passed in valid customizationVariable
if (!variable)
{
WARNING(true, ("addVariableTakeOwnership(): caller passed in NULL variable"));
return false;
}
//-- create CrcLowerString name for variable
const std::string variableName = fullVariablePathName.substr(static_cast<std::string::size_type>(variableNameStartIndex));
const CrcLowerString crcVariableName(variableName.c_str());
//-- handle assigning variable to variable name
CustomizationVariableMap::iterator lowerBoundResult = m_variables.lower_bound(crcVariableName);
const bool variableExists = ((lowerBoundResult != m_variables.end()) && !m_variables.key_comp()(crcVariableName, lowerBoundResult->first));
if (variableExists)
{
//-- replace existing variable. This probably is in error as the caller can
// lookup a value.
WARNING(true, ("addVariableTakeOwnership(): variable %s already exists, replacing old value", crcVariableName.getString()));
delete lowerBoundResult->second;
lowerBoundResult->second = variable;
}
else
{
//-- insert new variable
IGNORE_RETURN(m_variables.insert(lowerBoundResult, CustomizationVariableMap::value_type(crcVariableName, variable)));
}
// success
return true;
}
// ----------------------------------------------------------------------
const CustomizationVariable *CustomizationData::LocalDirectory::findConstVariable(const std::string &variablePathName, int variableNameStartIndex) const
{
const CustomizationVariable *variable = 0;
{
//-- create CrcLowerString name for variable
const std::string variableName = variablePathName.substr(static_cast<std::string::size_type>(variableNameStartIndex));
const CrcLowerString crcVariableName(variableName.c_str());
//-- check if variable exists
const CustomizationVariableMap::const_iterator lowerBoundResult = m_variables.lower_bound(crcVariableName);
const bool variableExists = ((lowerBoundResult != m_variables.end()) && !m_variables.key_comp()(crcVariableName, lowerBoundResult->first));
if (variableExists)
variable = lowerBoundResult->second;
}
return variable;
}
// ----------------------------------------------------------------------
CustomizationVariable *CustomizationData::LocalDirectory::findVariable(const std::string &variablePathName, int variableNameStartIndex)
{
CustomizationVariable *variable = 0;
{
//-- create CrcLowerString name for variable
const std::string variableName = variablePathName.substr(static_cast<std::string::size_type>(variableNameStartIndex));
const CrcLowerString crcVariableName(variableName.c_str());
//-- check if variable exists
const CustomizationVariableMap::iterator lowerBoundResult = m_variables.lower_bound(crcVariableName);
const bool variableExists = ((lowerBoundResult != m_variables.end()) && !m_variables.key_comp()(crcVariableName, lowerBoundResult->first));
if (variableExists)
variable = lowerBoundResult->second;
}
return variable;
}
// ----------------------------------------------------------------------
CustomizationData::Directory *CustomizationData::LocalDirectory::findDirectory(const std::string &directoryPathName, int directoryNameStartIndex)
{
CustomizationData::Directory *directory = 0;
{
//-- create CrcLowerString name for directory
const std::string directoryName = directoryPathName.substr(static_cast<std::string::size_type>(directoryNameStartIndex));
const CrcLowerString crcDirectoryName(directoryName.c_str());
//-- check if directory exists
const DirectoryMap::iterator lowerBoundResult = m_directories.lower_bound(crcDirectoryName);
const bool directoryExists = ((lowerBoundResult != m_directories.end()) && !m_directories.key_comp()(crcDirectoryName, lowerBoundResult->first));
if (directoryExists)
directory = lowerBoundResult->second;
}
return directory;
}
// ----------------------------------------------------------------------
void CustomizationData::LocalDirectory::deleteDirectory(Directory *childDirectory)
{
//-- check for null directory
if (!childDirectory)
{
WARNING(true, ("deleteDirectory(): NULL childDirectory arg"));
return;
}
//-- find the directory map entry with the given directory
DirectoryMap::iterator it = m_directories.begin();
const DirectoryMap::iterator endIt = m_directories.end();
for (; (it != endIt) && (it->second != childDirectory); ++it)
{
}
if (it == m_directories.end())
{
WARNING(true, ("deleteDirectory(): specified directory 0x%08x is not a child of this directory", childDirectory));
return;
}
//-- delete child directory
delete it->second;
m_directories.erase(it);
}
// ----------------------------------------------------------------------
void CustomizationData::LocalDirectory::iterateOverConstVariables(const std::string &parentPathName, ConstIteratorCallback callback, void *context, bool traverseRemoteDirectories) const
{
//-- invoke callback for each variable
{
const CustomizationVariableMap::const_iterator endIt = m_variables.end();
for (CustomizationVariableMap::const_iterator it = m_variables.begin(); it != endIt; ++it)
{
const std::string fullChildVariablePathName = parentPathName + it->first.getString();
(*callback)(fullChildVariablePathName, it->second, context);
}
}
//-- invoke iterator over each child directory
{
const DirectoryMap::const_iterator endIt = m_directories.end();
for (DirectoryMap::const_iterator it = m_directories.begin(); it != endIt; ++it)
{
//-- check for null directory pointer (shouldn't happen but shouldn't FATAL)
if (!it->second)
{
WARNING(true, ("iterateOverConstVariables(): directory 0x%08x has null child directory for [%s].", this, it->first.getString()));
return;
}
//-- build child directory name
std::string fullChildDirPathName(parentPathName);
fullChildDirPathName += it->first.getString();
fullChildDirPathName += '/';
//-- instruct child to iterate over its contents
it->second->iterateOverConstVariables(fullChildDirPathName, callback, context, traverseRemoteDirectories);
}
}
}
// ----------------------------------------------------------------------
void CustomizationData::LocalDirectory::iterateOverVariables(const std::string &parentPathName, IteratorCallback callback, void *context, bool traverseRemoteDirectories)
{
//-- invoke callback for each variable
{
const CustomizationVariableMap::iterator endIt = m_variables.end();
for (CustomizationVariableMap::iterator it = m_variables.begin(); it != endIt; ++it)
{
const std::string fullChildVariablePathName = parentPathName + it->first.getString();
(*callback)(fullChildVariablePathName, it->second, context);
}
}
//-- invoke iterator over each child directory
{
const DirectoryMap::iterator endIt = m_directories.end();
for (DirectoryMap::iterator it = m_directories.begin(); it != endIt; ++it)
{
//-- check for null directory pointer (shouldn't happen but shouldn't FATAL)
if (!it->second)
{
WARNING(true, ("iterateOverConstVariables(): directory 0x%08x has null child directory for [%s].", this, it->first.getString()));
return;
}
//-- build child directory name
std::string fullChildDirPathName(parentPathName);
fullChildDirPathName += it->first.getString();
fullChildDirPathName += '/';
//-- instruct child to iterate over its contents
it->second->iterateOverVariables(fullChildDirPathName, callback, context, traverseRemoteDirectories);
}
}
}
// ----------------------------------------------------------------------
void CustomizationData::LocalDirectory::replaceOrAddDirectory(const std::string &directoryPathName, int directoryNameStartIndex, Directory *directory)
{
//-- ensure attached directory is not null
if (!directory)
{
WARNING(true, ("replaceOrAddDirectory(): directory arg is NULL"));
return;
}
//-- create CrcLowerString name for directory
const std::string directoryName = directoryPathName.substr(static_cast<std::string::size_type>(directoryNameStartIndex));
const CrcLowerString crcDirectoryName(directoryName.c_str());
//-- check if directory exists
DirectoryMap::iterator lowerBoundResult = m_directories.lower_bound(crcDirectoryName);
const bool directoryExists = ((lowerBoundResult != m_directories.end()) && !m_directories.key_comp()(crcDirectoryName, lowerBoundResult->first));
if (!directoryExists)
{
// add new directory map entry
IGNORE_RETURN(m_directories.insert(lowerBoundResult, DirectoryMap::value_type(crcDirectoryName, directory)));
}
else
{
// check for self assignment
if (directory == lowerBoundResult->second)
{
WARNING(true, ("replaceOrAddDirectory(): attempting to replace directory [%s] with self", crcDirectoryName.getString()));
return;
}
// delete existing directory
delete lowerBoundResult->second;
// replace existing directory with new directory
lowerBoundResult->second = directory;
}
}
// ----------------------------------------------------------------------
bool CustomizationData::LocalDirectory::linksTo(const CustomizationData &customizationData) const
{
UNREF(customizationData);
//-- LocalDirectory instances never link to remote directories.
return false;
}
// ----------------------------------------------------------------------
void CustomizationData::LocalDirectory::deleteLinksTo(const CustomizationData &customizationData)
{
const DirectoryMap::iterator endIt = m_directories.end();
for (DirectoryMap::iterator it = m_directories.begin(); it != endIt;)
{
//-- save old iterator (may be deleted), increment loop iterator.
DirectoryMap::iterator oldIt = it;
++it;
Directory *const directory = oldIt->second;
if (directory)
{
//-- tell the child directory to delete any links it has to the specified customization data.
directory->deleteLinksTo(customizationData);
//-- check if child directory links to specified CustomizationData instance. If so, delete it.
if (directory->linksTo(customizationData))
{
delete oldIt->second;
m_directories.erase(oldIt);
}
}
}
}
// ----------------------------------------------------------------------
bool CustomizationData::LocalDirectory::isLocalDirectory() const
{
return true;
}
// ----------------------------------------------------------------------
#if 0
std::string CustomizationData::LocalDirectory::writeLocalDirectoryToString() const
{
char scratchBuffer[1024];
std::string data;
//-- count # persistable variables
int variableCount = 0;
{
const CustomizationVariableMap::const_iterator endIt = m_variables.end();
for (CustomizationVariableMap::const_iterator it = m_variables.begin(); it != endIt; ++it)
{
//-- verify it's a non-null variable
const CustomizationVariable *const variable = it->second;
if (variable && variable->doesVariablePersist())
{
// we will write this variable
++variableCount;
}
}
}
//-- write # variables
sprintf(scratchBuffer, "%x%c", variableCount, cms_stringFieldSeparator);
data += scratchBuffer;
//-- write each variable
{
const CustomizationVariableMap::const_iterator endIt = m_variables.end();
for (CustomizationVariableMap::const_iterator it = m_variables.begin(); it != endIt; ++it)
{
//-- verify it's a non-null variable
const CustomizationVariable *const variable = it->second;
if (!variable)
{
WARNING(true, ("writeLocalDirectoryToString: NULL variable for [%s], skipping variable writing."));
continue;
}
//-- skip variables that should not be written. typically this will be constant data
// that doesn't need to be customized or transmitted/persisted.
if (!variable->doesVariablePersist())
continue;
//-- write variable name
data += it->first.getString();
data += cms_stringFieldSeparator;
//-- write variable data
// get variable content data
const std::string variableContents = variable->writeToString();
// write content length (we do this so we can skip a variable if its not supported at load time)
sprintf(scratchBuffer, "%x%c", variableContents.size(), cms_stringFieldSeparator);
data += scratchBuffer;
// write variable content
data += variableContents;
}
}
//-- get # local directories to write
int directoryCount = 0;
{
const DirectoryMap::const_iterator endIt = m_directories.end();
for (DirectoryMap::const_iterator it = m_directories.begin(); it != endIt; ++it)
{
if (it->second && it->second->isLocalDirectory())
++directoryCount;
}
}
//-- write # directories
sprintf(scratchBuffer, "%x%c", directoryCount, cms_stringFieldSeparator);
data += scratchBuffer;
//-- write directory contents
{
const DirectoryMap::const_iterator endIt = m_directories.end();
for (DirectoryMap::const_iterator it = m_directories.begin(); it != endIt; ++it)
{
if (it->second && it->second->isLocalDirectory())
{
// write directory name
data += it->first.getString();
data += cms_stringFieldSeparator;
// get directory data contents
const std::string subdirData = it->second->writeLocalDirectoryToString();
// write directory data size (we do this so we can skip a directory if its not supported at load time)
sprintf(scratchBuffer, "%x%c", subdirData.size(), cms_stringFieldSeparator);
data += scratchBuffer;
// write directory contents
data += subdirData;
}
}
}
return data;
}
#endif
// ----------------------------------------------------------------------
#if 0
void CustomizationData::LocalDirectory::loadLocalDirectoryFromString(int version, const std::string &string, int startIndex)
{
if (version == 2)
loadLocalDirectoryFromString_0002(string, startIndex);
else
WARNING(true, ("loadLocalDirectoryFromString(): unsupported version [%d]", version));
}
#endif
// ======================================================================
#if 0
void CustomizationData::LocalDirectory::loadLocalDirectoryFromString_0002(const std::string &data, int startIndex)
{
int currentPosition = startIndex;
//-- get # variables
const int variableCount = parseSeparatedHexInt(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load variable count, aborting load."));
return;
}
//-- load each variable
{
for (int i = 0; i < variableCount; ++i)
{
//-- load the variable name
const std::string variableName = parseSeparatedString(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load variable name, aborting load."));
return;
}
//-- load the # characters in the value data
const int valueCharacterCount = parseSeparatedHexInt(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load variable data size, aborting load."));
return;
}
//-- find the customization variable
CustomizationVariable *const variable = findVariable(variableName, 0);
if (!variable)
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): variable [%s] does not exist to be restored.", variableName.c_str()));
return;
}
else
{
//-- load the data
if (!variable->loadFromString(2, std::string(data, static_cast<std::string::size_type>(currentPosition), static_cast<std::string::size_type>(valueCharacterCount))))
WARNING(true, ("loadLocalDirectoryFromString_0002(): variable [%s] failed to load.", variableName.c_str()));
}
//-- pass the variable data
currentPosition += valueCharacterCount;
}
}
//-- get # subdirectories
const int directoryCount = parseSeparatedHexInt(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load directory count, aborting load."));
return;
}
//-- load each subdirectory
{
for (int i = 0; i < directoryCount; ++i)
{
//-- load the directory name
const std::string directoryName = parseSeparatedString(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load directory name, aborting load."));
return;
}
//-- load the # characters in the value data
const int directoryCharacterCount = parseSeparatedHexInt(data, currentPosition, currentPosition);
if (currentPosition == static_cast<int>(std::string::npos))
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): failed to load directory data size, aborting load."));
return;
}
//-- find the customization variable
Directory *const directory = findDirectory(directoryName, 0);
if (!directory)
{
WARNING(true, ("loadLocalDirectoryFromString_0002(): object id=[%s], directory [%s] does not exist to be restored.", getOwner().getOwnerObject().getNetworkId().getValueString().c_str(), directoryName.c_str()));
return;
}
else
{
//-- load the data
directory->loadLocalDirectoryFromString(2, data, currentPosition);
}
//-- pass the variable data
currentPosition += directoryCharacterCount;
}
}
}
#endif
// ======================================================================
@@ -0,0 +1,83 @@
// PRIVATE
// ======================================================================
//
// CustomizationData_LocalDirectory.h
// Copyright 2002, 2003 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationData_LocalDirectory_H
#define INCLUDED_CustomizationData_LocalDirectory_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/CustomizationData_Directory.h"
#include <map>
class MemoryBlockManager;
// ======================================================================
class CustomizationData::LocalDirectory: public CustomizationData::Directory
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
explicit LocalDirectory(CustomizationData &owner);
virtual ~LocalDirectory();
virtual bool resolvePathNameToDirectory(const std::string &pathName, int pathStartIndex, bool traverseRemoteDirectories, bool createLocalMissingDirectories, Directory *&directory, int &directoryEntryStartIndex);
virtual bool addVariableTakeOwnership(const std::string &fullVariablePathName, int variableNameStartIndex, CustomizationVariable *variable);
virtual const CustomizationVariable *findConstVariable(const std::string &variableName, int variableNameStartIndex) const;
virtual CustomizationVariable *findVariable(const std::string &variableName, int variableNameStartIndex);
virtual Directory *findDirectory(const std::string &directoryPathName, int directoryNameStartIndex);
virtual void deleteDirectory(Directory *childDirectory);
virtual void iterateOverConstVariables(const std::string &parentPathName, ConstIteratorCallback callback, void *context, bool traverseRemoteDirectories) const;
virtual void iterateOverVariables(const std::string &parentPathName, IteratorCallback callback, void *context, bool traverseRemoteDirectories);
virtual void replaceOrAddDirectory(const std::string &directoryPathName, int directoryNameStartIndex, Directory *directory);
virtual bool linksTo(const CustomizationData &customizationData) const;
virtual void deleteLinksTo(const CustomizationData &customizationData);
virtual bool isLocalDirectory() const;
#if 0
virtual std::string writeLocalDirectoryToString() const;
virtual void loadLocalDirectoryFromString(int version, const std::string &string, int startIndex);
#endif
private:
typedef stdmap<const CrcLowerString, Directory*>::fwd DirectoryMap;
typedef stdmap<const CrcLowerString, CustomizationVariable*>::fwd CustomizationVariableMap;
private:
#if 0
void loadLocalDirectoryFromString_0002(const std::string &string, int startIndex);
#endif
// Disabled.
LocalDirectory();
LocalDirectory(const LocalDirectory&);
LocalDirectory &operator =(const LocalDirectory&);
private:
CustomizationVariableMap m_variables;
DirectoryMap m_directories;
};
// ======================================================================
#endif
@@ -0,0 +1,194 @@
// ======================================================================
//
// CustomizationData_RemoteDirectory.cpp
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/CustomizationData_RemoteDirectory.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include <string>
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(CustomizationData::RemoteDirectory, true, 0, 0, 0);
// ======================================================================
CustomizationData::RemoteDirectory::RemoteDirectory(CustomizationData &remoteCustomizationData, CustomizationData &localCustomizationData, Directory &targetDirectory) :
Directory(localCustomizationData),
m_remoteCustomizationData(remoteCustomizationData),
m_targetDirectory(targetDirectory)
{
//-- tell remote customization data (for which targetDirectory is a local directory)
// that the local customization data is dependent on it.
m_remoteCustomizationData.addDependentCustomizationData(&getOwner());
}
// ----------------------------------------------------------------------
CustomizationData::RemoteDirectory::~RemoteDirectory()
{
//-- tell remote customization data that the local customization data
// no longer is dependent on it.
m_remoteCustomizationData.removeDependentCustomizationData(&getOwner());
}
// ----------------------------------------------------------------------
bool CustomizationData::RemoteDirectory::resolvePathNameToDirectory(const std::string &pathName, int pathStartIndex, bool traverseRemoteDirectories, bool createLocalMissingDirectories, Directory *&directory, int &directoryEntryStartIndex)
{
UNREF(createLocalMissingDirectories);
//-- forward the call to the remote directory only if forwarding is permitted
if (!traverseRemoteDirectories)
return false;
else
{
// continue to allow traversal of remote directories.
// do not permit creation of missing directories once we cross a remote directory.
return m_targetDirectory.resolvePathNameToDirectory(pathName, pathStartIndex, traverseRemoteDirectories, false, directory, directoryEntryStartIndex);
}
}
// ----------------------------------------------------------------------
bool CustomizationData::RemoteDirectory::addVariableTakeOwnership(const std::string &fullVariablePathName, int variableNameStartIndex, CustomizationVariable *variable)
{
UNREF(variableNameStartIndex);
UNREF(variable);
WARNING(true, ("addVariableTakeOwnership([%s]): operation makes no sense on RemoteDirectory instances.", fullVariablePathName.c_str()));
return false;
}
// ----------------------------------------------------------------------
const CustomizationVariable *CustomizationData::RemoteDirectory::findConstVariable(const std::string &variablePathName, int variableNameStartIndex) const
{
UNREF(variableNameStartIndex);
WARNING(true, ("findConstVariable([%s]): operation makes no sense on RemoteDirectory instances.", variablePathName.c_str()));
return 0;
}
// ----------------------------------------------------------------------
CustomizationVariable *CustomizationData::RemoteDirectory::findVariable(const std::string &variablePathName, int variableNameStartIndex)
{
UNREF(variableNameStartIndex);
WARNING(true, ("findVariable([%s]): operation makes no sense on RemoteDirectory instances.\n", variablePathName.c_str()));
return 0;
}
// ----------------------------------------------------------------------
CustomizationData::Directory *CustomizationData::RemoteDirectory::findDirectory(const std::string &directoryPathName, int directoryNameStartIndex)
{
UNREF(directoryNameStartIndex);
WARNING(true, ("findDirectory([%s]): operation makes no sense on RemoteDirectory instances.\n", directoryPathName.c_str()));
return 0;
}
// ----------------------------------------------------------------------
void CustomizationData::RemoteDirectory::deleteDirectory(Directory *childDirectory)
{
UNREF(childDirectory);
WARNING(true, ("deleteDirectory(): operation makes no sense on RemoteDirectory instances.\n"));
}
// ----------------------------------------------------------------------
void CustomizationData::RemoteDirectory::iterateOverConstVariables(const std::string &parentPathName, ConstIteratorCallback callback, void *context, bool traverseRemoteDirectories) const
{
if (traverseRemoteDirectories)
{
// foward the call. continue to allow traversal of remote directories.
m_targetDirectory.iterateOverConstVariables(parentPathName, callback, context, traverseRemoteDirectories);
}
}
// ----------------------------------------------------------------------
void CustomizationData::RemoteDirectory::iterateOverVariables(const std::string &parentPathName, IteratorCallback callback, void *context, bool traverseRemoteDirectories)
{
if (traverseRemoteDirectories)
{
// foward the call. continue to allow traversal of remote directories.
m_targetDirectory.iterateOverVariables(parentPathName, callback, context, traverseRemoteDirectories);
}
}
// ----------------------------------------------------------------------
void CustomizationData::RemoteDirectory::replaceOrAddDirectory(const std::string &directoryPathName, int directoryNameStartIndex, Directory *directory)
{
UNREF(directoryNameStartIndex);
//-- indicate misuse, delete the directory so it doesn't get leaked
WARNING(true, ("replaceOrAddDirectory([%s]): operation makes no sense on RemoteDirectory instances.\n", directoryPathName.c_str()));
delete directory;
}
// ----------------------------------------------------------------------
bool CustomizationData::RemoteDirectory::linksTo(const CustomizationData &customizationData) const
{
//-- this RemoteDirectory instance links to the specified CustomizationData instance.
return (&m_remoteCustomizationData == &customizationData);
}
// ----------------------------------------------------------------------
void CustomizationData::RemoteDirectory::deleteLinksTo(const CustomizationData &customizationData)
{
UNREF(customizationData);
//-- RemoteDirectory doesn't propagate this call across remote boundaries.
return;
}
// ----------------------------------------------------------------------
bool CustomizationData::RemoteDirectory::isLocalDirectory() const
{
return false;
}
// ----------------------------------------------------------------------
#if 0
std::string CustomizationData::RemoteDirectory::writeLocalDirectoryToString() const
{
WARNING(true, ("writeLocalDirectoryToString(): operation makes no sense on RemoteDirectory instances.\n"));
return "";
}
#endif
// ----------------------------------------------------------------------
#if 0
void CustomizationData::RemoteDirectory::loadLocalDirectoryFromString(int version, const std::string &string, int startIndex)
{
UNREF(version);
UNREF(string);
UNREF(startIndex);
WARNING(true, ("loadLocalDirectoryFromString(): operation makes no sense on RemoteDirectory instances."));
}
#endif
// ======================================================================
@@ -0,0 +1,72 @@
// PRIVATE
// ======================================================================
//
// CustomizationData_RemoteDirectory.h
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationData_RemoteDirectory_H
#define INCLUDED_CustomizationData_RemoteDirectory_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/CustomizationData_Directory.h"
class MemoryBlockManager;
// ======================================================================
class CustomizationData::RemoteDirectory: public CustomizationData::Directory
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
RemoteDirectory(CustomizationData &remoteCustomizationData, CustomizationData &localCustomizationData, Directory &targetDirectory);
virtual ~RemoteDirectory();
virtual bool resolvePathNameToDirectory(const std::string &pathName, int pathStartIndex, bool traverseRemoteDirectories, bool createLocalMissingDirectories, Directory *&directory, int &directoryEntryStartIndex);
virtual bool addVariableTakeOwnership(const std::string &fullVariablePathName, int variableNameStartIndex, CustomizationVariable *variable);
virtual const CustomizationVariable *findConstVariable(const std::string &variablePathName, int variableNameStartIndex) const;
virtual CustomizationVariable *findVariable(const std::string &variablePathName, int variableNameStartIndex);
virtual Directory *findDirectory(const std::string &directoryPathName, int directoryNameStartIndex);
virtual void deleteDirectory(Directory *childDirectory);
virtual void iterateOverConstVariables(const std::string &parentPathName, ConstIteratorCallback callback, void *context, bool traverseRemoteDirectories) const;
virtual void iterateOverVariables(const std::string &parentPathName, IteratorCallback callback, void *context, bool traverseRemoteDirectories);
virtual void replaceOrAddDirectory(const std::string &directoryPathName, int directoryNameStartIndex, Directory *directory);
virtual bool linksTo(const CustomizationData &customizationData) const;
virtual void deleteLinksTo(const CustomizationData &customizationData);
virtual bool isLocalDirectory() const;
#if 0
virtual std::string writeLocalDirectoryToString() const;
virtual void loadLocalDirectoryFromString(int version, const std::string &string, int startIndex);
#endif
private:
// disabled
RemoteDirectory();
RemoteDirectory(const RemoteDirectory&);
RemoteDirectory &operator =(const RemoteDirectory&);
private:
CustomizationData &m_remoteCustomizationData;
Directory &m_targetDirectory;
};
// ======================================================================
#endif
@@ -0,0 +1,222 @@
// ======================================================================
//
// CustomizationIdManager.cpp
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/CustomizationIdManager.h"
#include "sharedFile/Iff.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedFoundation/PersistentCrcString.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include <algorithm>
#include <map>
#include <string>
#include <vector>
// ======================================================================
namespace CustomizationIdManagerNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void remove();
void load(Iff &iff);
void load_0001(Iff &iff);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tag const TAG_CIDM = TAG(C,I,D,M);
Tag const TAG_DATA = TAG(D,A,T,A);
int const cs_firstAssignedId = 1;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef std::vector<CrcString*> StringVector;
typedef std::map<CrcString const*, int, LessPointerComparator> StringIntMap;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StringVector s_idToVariableName;
StringIntMap s_variableNameToId;
bool s_installed;
}
using namespace CustomizationIdManagerNamespace;
// ======================================================================
// namespace CustomizationIdManagerNamespace
// ======================================================================
void CustomizationIdManagerNamespace::remove()
{
DEBUG_FATAL(!s_installed, ("CustomizationIdManager not installed."));
s_installed = false;
//-- s_idToVariableName owns the strings. Delete from here, then clean up vector.
std::for_each(s_idToVariableName.begin(), s_idToVariableName.end(), PointerDeleter());
StringVector().swap(s_idToVariableName);
//-- Clear out s_variableNameToId map.
s_variableNameToId.clear();
}
// ----------------------------------------------------------------------
void CustomizationIdManagerNamespace::load(Iff &iff)
{
iff.enterForm(TAG_CIDM);
{
Tag const version = iff.getCurrentName();
switch (version)
{
case TAG_0001:
load_0001(iff);
break;
default:
{
char name[5];
ConvertTagToString(version, name);
FATAL(true, ("CustomizationIdManager: unsupported data file version [%s].", name));
}
}
}
iff.exitForm(TAG_CIDM);
}
// ----------------------------------------------------------------------
void CustomizationIdManagerNamespace::load_0001(Iff &iff)
{
iff.enterForm(TAG_0001);
{
iff.enterChunk(TAG_DATA);
{
for (int expectedId = 1; iff.getChunkLengthLeft() > 0; ++expectedId)
{
//-- Read id mapping.
char variableName[MAX_PATH];
int const id = static_cast<int>(iff.read_int16());
iff.read_string(variableName, sizeof(variableName) - 1);
//-- Add to id->variableName vector.
FATAL(id != expectedId, ("CustomizationIdManager load error: non-consecutive ids listed: expecting [%d], found [%d] for [%s].", expectedId, id, variableName));
FATAL(id >= 128, ("CustomizationIdManager load error: exceeded limit of supported customization variable IDs [%d] for variable [%s].", id, variableName));
CrcString *crcVariableName = 0;
s_idToVariableName.push_back(crcVariableName = new PersistentCrcString(variableName, true));
//-- Add to variableName->id map.
std::pair<StringIntMap::iterator, bool> result = s_variableNameToId.insert(StringIntMap::value_type(crcVariableName, id));
FATAL(!result.second, ("CustomizationIdManager: failed to insert variable name [%s], id [%d] into map. Most likely duplicate entries for variabe name.", variableName, id));
}
}
iff.exitChunk(TAG_DATA);
}
iff.exitForm(TAG_0001);
}
// ======================================================================
// class CustomizationIdManager
// ======================================================================
void CustomizationIdManager::install(char const *dataFilename)
{
DEBUG_FATAL(s_installed, ("CustomizationIdManager already installed."));
//-- Load up data.
Iff iff;
bool const openSuccess = iff.open(dataFilename, true);
FATAL(!openSuccess, ("CustomizationIdManager: could not load initialization data file [%s], are TreeFile paths set correctly?", dataFilename));
load(iff);
s_installed = true;
ExitChain::add(remove, "CustomizationIdManager");
}
// ----------------------------------------------------------------------
bool CustomizationIdManager::mapIdToString(int id, std::string &variableName)
{
DEBUG_FATAL(!s_installed, ("CustomizationIdManager not installed."));
//-- Adjust id for first-assigned id offset.
id -= cs_firstAssignedId;
//-- Handle out-of-range id.
if ((id < 0) || (id >= static_cast<int>(s_idToVariableName.size())))
{
// Not found.
return false;
}
//-- Set string value.
variableName = NON_NULL(s_idToVariableName[static_cast<StringVector::size_type>(id)])->getString();
return true;
}
// ----------------------------------------------------------------------
bool CustomizationIdManager::mapIdToString(int id, char *variableName, int bufferLength)
{
DEBUG_FATAL(!s_installed, ("CustomizationIdManager not installed."));
//-- Adjust id for first-assigned id offset.
id -= cs_firstAssignedId;
//-- Handle out-of-range id.
if ((id < 0) || (id >= static_cast<int>(s_idToVariableName.size())))
{
// Not found.
return false;
}
//-- Set string value.
NOT_NULL(variableName);
DEBUG_FATAL(bufferLength < 1, ("CustomizationIdManager: bufferLength of [%d] too small to hold anything.", bufferLength));
//-- Copy variable name to user buffer, ensure it gets NULL terminated.
strncpy(variableName, NON_NULL(s_idToVariableName[static_cast<StringVector::size_type>(id)])->getString(), static_cast<size_t>(bufferLength - 1));
variableName[bufferLength - 1] = '\0';
return true;
}
// ----------------------------------------------------------------------
bool CustomizationIdManager::mapStringToId(char const *variableName, int &id)
{
DEBUG_FATAL(!s_installed, ("CustomizationIdManager not installed."));
//-- Lookup variable name in map.
TemporaryCrcString const crcVariableName(variableName, true);
StringIntMap::iterator const findIt = s_variableNameToId.find((const CrcString*)&crcVariableName);
if (findIt == s_variableNameToId.end())
{
// Not found.
return false;
}
else
{
// Found it.
id = findIt->second;
return true;
}
}
// ======================================================================
@@ -0,0 +1,28 @@
// ======================================================================
//
// CustomizationIdManager.h
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationIdManager_H
#define INCLUDED_CustomizationIdManager_H
// ======================================================================
class CustomizationIdManager
{
public:
static void install(char const *dataFilename);
static bool mapIdToString(int id, std::string &variableName);
static bool mapIdToString(int id, char *variableName, int bufferLength);
static bool mapStringToId(char const *variableName, int &id);
};
// ======================================================================
#endif
@@ -0,0 +1,49 @@
// ======================================================================
//
// CustomizationVariable.h
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/CustomizationVariable.h"
#include "sharedObject/CustomizationData.h"
// ======================================================================
CustomizationVariable::~CustomizationVariable()
{
m_owner = 0;
}
// ======================================================================
CustomizationVariable::CustomizationVariable() :
m_owner(0)
{
}
// ----------------------------------------------------------------------
void CustomizationVariable::signalVariableModified() const
{
if (m_owner)
{
// tell the owner one of its variables has been modified.
m_owner->signalModified();
}
}
// ----------------------------------------------------------------------
void CustomizationVariable::alter(CustomizationData & /* owner */)
{
// Default does nothing. Very few of these need to handle alter.
// Alter is not called every frame --- on client it is only called after
// processing container changes, and then it only does something for
// the SlotRuleCustomizationVariable.
}
// ======================================================================
@@ -0,0 +1,106 @@
// ======================================================================
//
// CustomizationVariable.h
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_CustomizationVariable_H
#define INCLUDED_CustomizationVariable_H
// ======================================================================
class CustomizationVariable;
class ObjectTemplateCustomizationDataWriter;
// ======================================================================
class CustomizationVariable
{
friend class CustomizationData;
public:
typedef stdvector<byte>::fwd ByteVector;
public:
virtual ~CustomizationVariable();
virtual bool doesVariablePersist() const = 0;
virtual int getPersistedDataByteCount() const = 0;
/**
* Append state of this variable to data buffer for subsequent restoration.
*
* @param data a vector of bytes where the state of this variable will be stored.
*/
virtual void saveToByteVector(ByteVector &data) const = 0;
/**
* Restore the state of the variable using the data and offset provided.
*
* @param data a vector of bytes where the state of this variable was previously stored.
* @param startIndex a 0-based index into the data buffer indicating where this variable's state data begins.
* @param length length of the data recorded for this variable.
*
* @return true if data restoration occurred successfully; false if some error occured.
*/
virtual bool restoreFromByteVector(ByteVector const &data, int startIndex, int length) = 0;
const CustomizationData *getOwner() const;
CustomizationData* getOwner();
virtual void writeObjectTemplateExportString(const std::string &variablePathName, ObjectTemplateCustomizationDataWriter &writer) const = 0;
#ifdef _DEBUG
virtual std::string debugToString() const = 0;
#endif
virtual void alter(CustomizationData &owner);
protected:
CustomizationVariable();
void signalVariableModified() const;
private:
void setOwner(CustomizationData *owner);
// disabled
CustomizationVariable(const CustomizationVariable&);
CustomizationVariable &operator =(const CustomizationVariable&);
private:
CustomizationData *m_owner;
};
// ======================================================================
inline const CustomizationData *CustomizationVariable::getOwner() const
{
return m_owner;
}
// ======================================================================
inline CustomizationData *CustomizationVariable::getOwner()
{
return m_owner;
}
// ======================================================================
inline void CustomizationVariable::setOwner(CustomizationData *owner)
{
m_owner = owner;
}
// ======================================================================
#endif
@@ -0,0 +1,228 @@
// ======================================================================
//
// ObjectTemplateCustomizationDataWriter.cpp
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/ObjectTemplateCustomizationDataWriter.h"
#include "sharedFoundation/TemporaryCrcString.h"
#include "sharedMath/PaletteArgb.h"
#include "sharedMath/PaletteArgbList.h"
#include <list>
#include <cstdio>
#include <string>
// ======================================================================
ObjectTemplateCustomizationDataWriter::ObjectTemplateCustomizationDataWriter(bool writeSharedOwnerVariables) :
m_rangedIntData(new StringList()),
m_paletteColorData(new StringList()),
m_writeSharedOwnerVariables(writeSharedOwnerVariables)
{
}
// ----------------------------------------------------------------------
ObjectTemplateCustomizationDataWriter::~ObjectTemplateCustomizationDataWriter()
{
delete m_paletteColorData;
delete m_rangedIntData;
}
// ----------------------------------------------------------------------
void ObjectTemplateCustomizationDataWriter::addRangedIntCustomizationVariable(const std::string &variableName, int minValueInclusive, int defaultValue, int maxValueExclusive)
{
//-- Check for skipping shared_owner variables.
if (!m_writeSharedOwnerVariables)
{
bool const isSharedOwnerVariable = (static_cast<int>(variableName.find("shared_owner")) != static_cast<int>(std::string::npos));
if (isSharedOwnerVariable)
{
// Skip it.
return;
}
}
//-- Check for special case variable for breasts.
if (static_cast<int>(variableName.find("blend_flat_chest")) != static_cast<int>(std::string::npos))
{
// Found this one, adjust minimum value.
minValueInclusive = -155;
maxValueExclusive = 156;
}
//-- Write it out.
char conversionBuffer[64];
std::string buildString = "[variableName=\"";
buildString += variableName;
buildString += "\", minValueInclusive=";
sprintf(conversionBuffer, "%d", minValueInclusive);
buildString += conversionBuffer;
buildString += ", defaultValue=";
sprintf(conversionBuffer, "%d", defaultValue);
buildString += conversionBuffer;
buildString += ", maxValueExclusive=";
sprintf(conversionBuffer, "%d", maxValueExclusive);
buildString += conversionBuffer;
buildString += "],";
m_rangedIntData->push_back(buildString);
}
// ----------------------------------------------------------------------
void ObjectTemplateCustomizationDataWriter::addPaletteColorCustomizationVariable(const std::string &variableName, const std::string &paletteReferenceName, int defaultPaletteIndex)
{
//-- Check for skipping shared_owner variables.
if (!m_writeSharedOwnerVariables)
{
bool const isSharedOwnerVariable = (static_cast<int>(variableName.find("shared_owner")) != static_cast<int>(std::string::npos));
if (isSharedOwnerVariable)
{
// Skip it.
return;
}
}
//-- Fetch the palette, get the maxValueExclusive for it.
PaletteArgb const *const palette = PaletteArgbList::fetch(TemporaryCrcString(paletteReferenceName.c_str(), true));
if (!palette)
{
FATAL(true, ("variable [%s] references non-existent palette [%s], variable will not be reported.", variableName.c_str(), paletteReferenceName.c_str()));
return; //lint !e527 // unreachable // Right, this is for MSDEV.
}
int const paletteMaxValueExclusive = palette->getEntryCount();
palette->release();
//-- Build export string.
char conversionBuffer[64];
std::string buildString = "[variableName=\"";
buildString += variableName;
buildString += "\", palettePathName=\"";
buildString += paletteReferenceName;
buildString += "\", defaultPaletteIndex=";
sprintf(conversionBuffer, "%d", defaultPaletteIndex);
buildString += conversionBuffer;
buildString += "], // maxValueExclusive=";
sprintf(conversionBuffer, "%d", paletteMaxValueExclusive);
buildString += conversionBuffer;
m_paletteColorData->push_back(buildString);
}
// ----------------------------------------------------------------------
bool ObjectTemplateCustomizationDataWriter::writeToFile(const std::string &pathName, bool allowOverwrite)
{
//-- Don't write anything if there's no data to write.
bool hasData = false;
if (!m_paletteColorData->empty())
hasData = true;
if (!m_rangedIntData->empty())
hasData = true;
if (!hasData)
{
DEBUG_REPORT_LOG(true, ("writeToFile(): no data: skipped writing [%s].\n", pathName.c_str()));
return true;
}
//-- Handle no-overwrite case.
if (!allowOverwrite)
{
FILE *const testFile = fopen(pathName.c_str(), "r");
if (testFile != NULL)
{
fclose(testFile);
DEBUG_REPORT_LOG(true, ("writeToFile(): overwrite attempt: skipped writing [%s] because it already exists and allowOverwrite == false.\n", pathName.c_str()));
return false;
}
}
//-- open file
FILE *const file = fopen(pathName.c_str(), "w");
if (!file)
{
WARNING(true, ("failed to create file [%s].", pathName.c_str()));
return false;
}
//-- sort the output data
m_paletteColorData->sort();
m_rangedIntData->sort();
//-- write palette color variables
fprintf(file, "paletteColorCustomizationVariables = [");
{
int i = 0;
int const count = static_cast<int>(m_paletteColorData->size());
const StringList::iterator endIt = m_paletteColorData->end();
for (StringList::iterator it = m_paletteColorData->begin(); it != endIt; ++it, ++i)
{
if (i == (count - 1))
{
// -- Fixup last entry to use ] in place of final comma.
std::string::size_type position = it->rfind(',');
DEBUG_FATAL(static_cast<int>(position) == static_cast<int>(std::string::npos), ("bad data, where's the final comma?"));
(*it)[position] = ']';
}
fprintf(file, "\n %s", it->c_str());
}
}
if (m_paletteColorData->empty())
fprintf(file, "]");
fprintf(file, "\n\n");
//-- write ranged int variables
fprintf(file, "rangedIntCustomizationVariables = [");
{
int i = 0;
int const count = static_cast<int>(m_rangedIntData->size());
const StringList::iterator endIt = m_rangedIntData->end();
for (StringList::iterator it = m_rangedIntData->begin(); it != endIt; ++it, ++i)
{
if (i == (count - 1))
{
// -- Fixup last entry to use ] in place of final comma.
std::string::size_type position = it->rfind(',');
DEBUG_FATAL(static_cast<int>(position) == static_cast<int>(std::string::npos), ("bad data, where's the final comma?"));
(*it)[position] = ']';
}
fprintf(file, "\n %s", it->c_str());
}
}
if (m_rangedIntData->empty())
fprintf(file, "]");
fprintf(file, "\n\n");
fclose(file);
//-- return success
return true;
}
// ======================================================================
@@ -0,0 +1,58 @@
// ======================================================================
//
// ObjectTemplateCustomizationDataWriter.h
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ObjectTemplateCustomizationDataWriter_H
#define INCLUDED_ObjectTemplateCustomizationDataWriter_H
// ======================================================================
// -TRF- replace this with whatever flag is needed to include for internal-only
// builds. For now it is DEBUG-enabled only.
#ifdef _DEBUG
#define USE_OBJ_TEMPLATE_CUSTOM_VAR_WRITER 1
#else
#define USE_OBJ_TEMPLATE_CUSTOM_VAR_WRITER 0
#endif
// ======================================================================
class ObjectTemplateCustomizationDataWriter
{
public:
ObjectTemplateCustomizationDataWriter(bool writeSharedOwnerVariables);
~ObjectTemplateCustomizationDataWriter();
void addRangedIntCustomizationVariable(const std::string &variableName, int minValueInclusive, int defaultValue, int maxValueExclusive);
void addPaletteColorCustomizationVariable(const std::string &variableName, const std::string &paletteReferenceName, int defaultPaletteIndex);
bool writeToFile(const std::string &pathName, bool allowOverwrite);
private:
typedef stdlist<std::string>::fwd StringList;
private:
// Disabled.
ObjectTemplateCustomizationDataWriter(const ObjectTemplateCustomizationDataWriter&);
ObjectTemplateCustomizationDataWriter &operator =(const ObjectTemplateCustomizationDataWriter&);
private:
StringList *m_rangedIntData;
StringList *m_paletteColorData;
bool m_writeSharedOwnerVariables;
};
// ======================================================================
#endif
@@ -0,0 +1,146 @@
// ======================================================================
//
// PaletteColorCustomizationVariable.cpp
// Copyright 2002 Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/PaletteColorCustomizationVariable.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedMath/PackedArgb.h"
#include "sharedMath/PaletteArgb.h"
#include "sharedObject/ObjectTemplateCustomizationDataWriter.h"
#include <string>
#include <cstdio>
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(PaletteColorCustomizationVariable, true, 0, 0, 0);
// ======================================================================
PaletteColorCustomizationVariable::PaletteColorCustomizationVariable(const PaletteArgb *palette, int selectedIndex)
: RangedIntCustomizationVariable(),
m_palette(palette),
m_paletteIndex(selectedIndex)
{
NOT_NULL(palette);
palette->fetch();
int const paletteEntryCount = m_palette->getEntryCount();
if ((m_paletteIndex < 0) || (m_paletteIndex >= paletteEntryCount))
{
DEBUG_WARNING(true, ("Initializing palette var for palette=[%s] with out-of-range value [%d], valid range is [0..%d], defaulting to [%d].", m_palette->getName().getString(), m_paletteIndex, paletteEntryCount - 1, paletteEntryCount - 1));
m_paletteIndex = paletteEntryCount - 1;
}
}
// ----------------------------------------------------------------------
PaletteColorCustomizationVariable::~PaletteColorCustomizationVariable()
{
//lint -esym(1540, PaletteColorCustomizationVariable::m_palette) // not freed or zero'ed // yes, but released
m_palette->release();
}
// ----------------------------------------------------------------------
int PaletteColorCustomizationVariable::getValue() const
{
return m_paletteIndex;
}
// ----------------------------------------------------------------------
bool PaletteColorCustomizationVariable::setValue(int value)
{
if ((value >= 0) && (value < m_palette->getEntryCount()))
{
// change the value
m_paletteIndex = value;
// notify owner CustomizationData about change.
signalVariableModified();
}
else
{
DEBUG_WARNING(true, ("attempted to set PaletteColorCustomizationVariable to %d, outside valid range [%d,%d).", value, 0, m_palette->getEntryCount()));
return false;
}
return RangedIntCustomizationVariable::setValue(value);
}
// ----------------------------------------------------------------------
const PackedArgb &PaletteColorCustomizationVariable::getValueAsColor() const
{
if (!m_palette)
return PackedArgb::solidMagenta;
int const usePaletteIndex = clamp(0, m_paletteIndex, m_palette->getEntryCount() - 1);
bool error = false;
PackedArgb const & color = m_palette->getEntry(usePaletteIndex, error);
WARNING(error, ("PaletteColorCustomizationVariable::getValueAsColor error"));
return color;
}
// ----------------------------------------------------------------------
void PaletteColorCustomizationVariable::getRange(int &minRangeInclusive, int &maxRangeExclusive) const
{
minRangeInclusive = 0;
maxRangeExclusive = m_palette->getEntryCount();
}
// ----------------------------------------------------------------------
const PaletteArgb *PaletteColorCustomizationVariable::fetchPalette() const
{
m_palette->fetch();
return m_palette;
}
// ----------------------------------------------------------------------
void PaletteColorCustomizationVariable::setClosestColor(const PackedArgb &targetColor)
{
setValue(m_palette->findClosestMatch(targetColor));
}
// ----------------------------------------------------------------------
void PaletteColorCustomizationVariable::writeObjectTemplateExportString(const std::string &variablePathName, ObjectTemplateCustomizationDataWriter &writer) const
{
#if !(USE_OBJ_TEMPLATE_CUSTOM_VAR_WRITER)
UNREF(variablePathName);
UNREF(writer);
#else
//-- this assumes that the current value is the default value --- if the user changed values at all, they
// will not be the artist's built in default.
writer.addPaletteColorCustomizationVariable(variablePathName, m_palette->getName().getString(), m_paletteIndex);
#endif
}
// ----------------------------------------------------------------------
#ifdef _DEBUG
std::string PaletteColorCustomizationVariable::debugToString() const
{
char buffer[1024];
sprintf(buffer, "palette (%s): index %d", m_palette->getName().getString(), m_paletteIndex);
return std::string(buffer);
}
#endif
// ======================================================================
@@ -0,0 +1,64 @@
// ======================================================================
//
// PaletteColorCustomizationVariable.h
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_PaletteColorCustomizationVariable_H
#define INCLUDED_PaletteColorCustomizationVariable_H
// ======================================================================
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedObject/RangedIntCustomizationVariable.h"
class MemoryBlockManager;
class PackedArgb;
class PaletteArgb;
// ======================================================================
class PaletteColorCustomizationVariable: public RangedIntCustomizationVariable
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
PaletteColorCustomizationVariable(const PaletteArgb *palette, int selectedIndex = 0);
virtual ~PaletteColorCustomizationVariable();
virtual int getValue() const;
virtual bool setValue(int value);
const PackedArgb &getValueAsColor() const;
virtual void getRange(int &minRangeInclusive, int &maxRangeExclusive) const;
virtual void writeObjectTemplateExportString(const std::string &variablePathName, ObjectTemplateCustomizationDataWriter &writer) const;
const PaletteArgb *fetchPalette() const;
void setClosestColor(const PackedArgb &targetColor);
#ifdef _DEBUG
virtual std::string debugToString() const;
#endif
private:
// disabled
PaletteColorCustomizationVariable();
PaletteColorCustomizationVariable(const PaletteColorCustomizationVariable&);
PaletteColorCustomizationVariable &operator =(const PaletteColorCustomizationVariable&);
private:
const PaletteArgb *const m_palette;
int m_paletteIndex;
};
// ======================================================================
#endif
@@ -0,0 +1,285 @@
// ======================================================================
//
// RangedIntCustomizationVariable.cpp
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/RangedIntCustomizationVariable.h"
#include "sharedObject/CustomizationData.h"
#include <cstdio>
#include <limits>
#include <string>
#include <vector>
// ======================================================================
bool RangedIntCustomizationVariable::doesVariablePersist() const
{
// all ranged ints are meant to persist
return true;
}
// ----------------------------------------------------------------------
int RangedIntCustomizationVariable::getPersistedDataByteCount() const
{
//-- Get the range.
int minInclusive = 0;
int maxExclusive = 0;
getRange(minInclusive, maxExclusive);
if ((minInclusive >= 0) && (minInclusive < 255) && (maxExclusive > 0) && (maxExclusive <= 256))
{
// Value fits in a single unsigned byte.
return 1;
}
else
{
//-- If either of these get hit, we've got to upgrade the customization data format.
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(std::numeric_limits<int16>::min(), static_cast<int16>(minInclusive), std::numeric_limits<int16>::max());
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(static_cast<int>(std::numeric_limits<int16>::min()), maxExclusive, static_cast<int>(std::numeric_limits<int16>::max()) + 1);
// Value fits in a signed 16-bit int.
return 2;
}
}
// ----------------------------------------------------------------------
#if 0
std::string RangedIntCustomizationVariable::writeToString() const
{
char buffer[64];
sprintf(buffer, "%x", getValue());
return std::string(buffer);
}
#endif
// ----------------------------------------------------------------------
#if 0
bool RangedIntCustomizationVariable::loadFromString(int version, const std::string &data)
{
if (version == 2)
return loadFromString_0002(data);
else
{
WARNING(true, ("loadFromString(): version %d unsupported.\n", version));
return false;
}
}
#endif
// ----------------------------------------------------------------------
void RangedIntCustomizationVariable::saveToByteVector(ByteVector &data) const
{
int const byteCount = getPersistedDataByteCount();
switch (byteCount)
{
case 1:
{
// Store as single unsigned byte.
byte const value = static_cast<byte>(getValue());
data.push_back(value);
break;
}
case 2:
{
// Treated as little-endian signed 16-bit number (least significant byte earliest/first in memory).
int16 const value = static_cast<int16>(getValue());
byte const lowerByte = static_cast<byte>(static_cast<uint16>(value) & 0x00ff);
data.push_back(lowerByte);
byte const upperByte = static_cast<byte>((static_cast<uint16>(value) >> 8) & 0x00ff);
data.push_back(upperByte);
break;
}
default:
FATAL(true, ("saveToByteVector(): failed, unsupported byte count [%d] specified, should be 1 or 2.", byteCount));
}
}
// ----------------------------------------------------------------------
bool RangedIntCustomizationVariable::restoreFromByteVector(ByteVector const &data, int startIndex, int length)
{
if (startIndex < 0)
{
WARNING(true, ("restoreFromByteVector(): invalid startIndex [%d]", startIndex));
return false;
}
switch (length)
{
case 1:
{
//-- Handle unsigned byte packing.
// Check range.
if (startIndex >= static_cast<int>(data.size()))
{
WARNING(true, ("restoreFromByteVector(): attempting to restore unsigned byte int but not enough data."));
return false;
}
// Restore as single unsigned byte.
setValue(static_cast<int>(data[static_cast<ByteVector::size_type>(startIndex)]));
break;
}
case 2:
{
//-- Handle signed int packing.
// Check range.
if (startIndex + 1 >= static_cast<int>(data.size()))
{
WARNING(true, ("restoreFromByteVector(): attempting to restore short signed int but not enough data."));
return false;
}
// Restore as single unsigned byte.
uint32 const lowByte = static_cast<uint32>(data[static_cast<ByteVector::size_type>(startIndex)]);
uint32 const hiByte = static_cast<uint32>(data[static_cast<ByteVector::size_type>(startIndex + 1)]);
int16 const value = static_cast<int16>((hiByte << 8) | lowByte);
setValue(value);
break;
}
default:
FATAL(true, ("saveToByteVector(): failed, unsupported length [%d] specified, should be 1 or 2.", length));
}
// Success.
return true;
}
// ======================================================================
RangedIntCustomizationVariable::RangedIntCustomizationVariable()
: CustomizationVariable(),
m_dependentVariable(0),
m_isDependentVariable(false)
{
}
// ======================================================================
#if 0
bool RangedIntCustomizationVariable::loadFromString_0002(const std::string &data)
{
int newValue;
const int scanfResult = sscanf(data.c_str(), "%x", &newValue);
if (scanfResult != 1)
{
// failed
return false;
}
else
{
setValue(newValue);
return true;
}
}
#endif
//----------------------------------------------------------------------
/**
* This function computes the normalized value.
* @return a number in [0.0,1.0]
*/
float RangedIntCustomizationVariable::getNormalizedFloatValue() const
{
int low = 0, high = 0;
getRange (low, high);
const float range = static_cast<float>(high - low);
if (range <= 0.0f)
return 0.0f;
return clamp (0.0f, static_cast<float>(getValue () - low) / range, 1.0f);
}
//----------------------------------------------------------------------
/**
* This function sets the normalized value
* @param value a number in [0.0,1.0]
*/
void RangedIntCustomizationVariable::setNormalizedFloatValue(float value)
{
int low = 0, high = 0;
getRange (low, high);
const float range = static_cast<float>(high - low);
setValue (std::min (low + static_cast<int>(value * range), (high - 1)));
}
//----------------------------------------------------------------------
int RangedIntCustomizationVariable::getRangeSize() const
{
int low = 0;
int high = 0;
getRange (low, high);
return high - low;
}
// ======================================================================
void RangedIntCustomizationVariable::setDependentVariable(const std::string &variablePathName)
{
if(getOwner())
{
RangedIntCustomizationVariable * const var = safe_cast<RangedIntCustomizationVariable *>(getOwner()->findVariable(variablePathName));
if(var)
{
m_dependentVariable = var;
var->setIsDependentVariable(true);
}
}
}
// ======================================================================
void RangedIntCustomizationVariable::setIsDependentVariable(bool const isDependentVariable)
{
m_isDependentVariable = isDependentVariable;
}
// ======================================================================
bool RangedIntCustomizationVariable::getIsDependentVariable() const
{
return m_isDependentVariable;
}
// ======================================================================
bool RangedIntCustomizationVariable::setValue(int value)
{
if(m_dependentVariable)
{
if (!m_dependentVariable->setValue(value))
return false;
}
return true;
}
//----------------------------------------------------------------------
@@ -0,0 +1,63 @@
// ======================================================================
//
// RangedIntCustomizationVariable.h
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_RangedIntCustomizationVariable_H
#define INCLUDED_RangedIntCustomizationVariable_H
// ======================================================================
#include "sharedObject/CustomizationVariable.h"
// ======================================================================
class RangedIntCustomizationVariable: public CustomizationVariable
{
public:
virtual bool doesVariablePersist() const;
virtual int getPersistedDataByteCount() const;
virtual void saveToByteVector(ByteVector &data) const;
virtual bool restoreFromByteVector(ByteVector const &data, int startIndex, int length);
virtual int getValue() const = 0;
virtual bool setValue(int value);
virtual void getRange(int &minRangeInclusive, int &maxRangeExclusive) const = 0;
float getNormalizedFloatValue() const;
void setNormalizedFloatValue(float value);
int getRangeSize() const;
void setDependentVariable(const std::string &variablePathName);
void setIsDependentVariable(bool isDependentVariable);
bool getIsDependentVariable() const;
protected:
RangedIntCustomizationVariable();
private:
#if 0
bool loadFromString_0002(const std::string &data);
#endif
// disabled
RangedIntCustomizationVariable(const RangedIntCustomizationVariable&);
RangedIntCustomizationVariable &operator =(const RangedIntCustomizationVariable&);
RangedIntCustomizationVariable *m_dependentVariable;
bool m_isDependentVariable;
};
// ======================================================================
#endif
@@ -0,0 +1,56 @@
// ======================================================================
//
// Dynamics.cpp
// copyright 1999, bootprint entertainment
// copyright 2002, sony online entertainment
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/Dynamics.h"
#include "sharedObject/AlterResult.h"
// ======================================================================
// Construct a new dynamics
//
// Remarks:
//
// This routine does nothing, but is provided for interface reasons for
// this base class.
Dynamics::Dynamics (Object* const owner) :
m_owner (owner)
{
}
// ----------------------------------------------------------------------
/**
* Destroy a new dynamics.
*
* This routine does nothing, but is provided for interface reasons for
* this base class.
*/
Dynamics::~Dynamics ()
{
m_owner = 0;
}
// ----------------------------------------------------------------------
/**
* Alter a dynamics.
*
* This routine does nothing, but is provided for interface reasons for
* this base class.
*
* @param time The amount of time elapse since the last alter
*/
float Dynamics::alter (float /*time*/)
{
// Indicate there's no reason to alter based on functionality in this class.
return AlterResult::cms_keepNoAlter;
}
// ======================================================================
@@ -0,0 +1,69 @@
// ======================================================================
//
// Dynamics.h
// copyright 1999, bootprint entertainment
// copyright 2002, sony online entertainment
//
// derived classes from dynamics should be using dynamics templates
//
// ======================================================================
#ifndef INCLUDED_Dynamics_H
#define INCLUDED_Dynamics_H
// ======================================================================
class Object;
// ======================================================================
// Abstract dynamics entity for an object
class Dynamics
{
public:
explicit Dynamics (Object* newOwner);
virtual ~Dynamics () = 0;
virtual float alter(float time);
void setOwner (Object* newOwner);
const Object* getOwner () const;
Object* getOwner ();
private:
// disable these
Dynamics ();
Dynamics (const Dynamics&);
Dynamics& operator= (const Dynamics&);
private:
Object* m_owner;
};
// ======================================================================
inline void Dynamics::setOwner (Object* const owner)
{
m_owner = owner;
}
// ----------------------------------------------------------------------
inline const Object* Dynamics::getOwner () const
{
return m_owner;
}
// ----------------------------------------------------------------------
inline Object* Dynamics::getOwner ()
{
return m_owner;
}
// ======================================================================
#endif
@@ -0,0 +1,61 @@
// ======================================================================
//
// PulseDynamics.cpp
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/PulseDynamics.h"
#include "sharedMath/Vector.h"
#include "sharedObject/Object.h"
//======================================================================
PulseDynamics::PulseDynamics(Object *owner, float minimumSize, float maximumSize, float speed)
: SimpleDynamics(owner)
, m_minimumSize(minimumSize)
, m_maximumSize(maximumSize)
, m_speed(speed)
, m_baseScale(owner->getScale())
, m_currentSize(1.0f)
, m_pulseGrowDirection(1.0f)
{
}
// ----------------------------------------------------------------------
PulseDynamics::~PulseDynamics()
{
Object *const ownerObject = getOwner();
if (ownerObject != 0)
{
ownerObject->setRecursiveScale(m_baseScale);
}
}
// ----------------------------------------------------------------------
float PulseDynamics::alter(float elapsedTime)
{
Object *const ownerObject = getOwner();
if (ownerObject != 0)
{
m_currentSize += (elapsedTime * m_speed * m_pulseGrowDirection);
if (!WithinRangeInclusiveInclusive(m_minimumSize, m_currentSize, m_maximumSize))
{
m_currentSize = clamp(m_minimumSize, m_currentSize, m_maximumSize);
m_pulseGrowDirection *= -1.0f;
}
Vector scale = m_baseScale * m_currentSize;
ownerObject->setRecursiveScale(scale);
}
return SimpleDynamics::alter(elapsedTime);
}
// ======================================================================
@@ -0,0 +1,42 @@
// ======================================================================
//
// PulseDynamics.h
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_PulseDynamics_H
#define INCLUDED_PulseDynamics_H
// ======================================================================
#include "sharedObject/SimpleDynamics.h"
// ======================================================================
class PulseDynamics: public SimpleDynamics
{
public:
PulseDynamics(Object *owner, float minimumSize, float maximumSize, float speed = 1.0f);
virtual ~PulseDynamics();
virtual float alter(float elapsedTime);
private:
PulseDynamics();
PulseDynamics(const PulseDynamics &);
PulseDynamics &operator =(const PulseDynamics &);
private:
float m_minimumSize;
float m_maximumSize;
float m_speed;
Vector m_baseScale;
float m_currentSize;
float m_pulseGrowDirection; // this should only ever by 1.0f or -1.0f
};
// ======================================================================
#endif
@@ -0,0 +1,71 @@
//===================================================================
//
// RotationDynamics.cpp
// asommers 6-19-99
//
// copyright 1999, bootprint entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/RotationDynamics.h"
#include "sharedObject/Object.h"
#include "sharedRandom/Random.h"
//===================================================================
// PUBLIC RotationDynamics
//===================================================================
RotationDynamics::RotationDynamics (Object* const owner, const Vector& rotationsPerSecond) :
StateDynamics (owner),
m_rotationsPerSecond (rotationsPerSecond),
m_rotateAroundAppearanceCenter(false)
{
}
//-------------------------------------------------------------------
RotationDynamics::~RotationDynamics ()
{
}
//----------------------------------------------------------------------
void RotationDynamics::setRotateAroundAppearanceCenter(bool rotateAroundAppearanceCenter)
{
m_rotateAroundAppearanceCenter = rotateAroundAppearanceCenter;
}
//===================================================================
// PROTECTED RotationDynamics
//===================================================================
void RotationDynamics::realAlter (const float elapsedTime)
{
StateDynamics::realAlter (elapsedTime);
Object* const owner = getOwner ();
if (!owner)
return;
if (m_rotateAroundAppearanceCenter)
{
Transform t = owner->getTransform_o2p();
t.move_l(owner->getAppearanceSphereCenter());
t.yaw_l(m_rotationsPerSecond.x * elapsedTime);
t.pitch_l(m_rotationsPerSecond.y * elapsedTime);
t.roll_l(m_rotationsPerSecond.z * elapsedTime);
t.move_l(-owner->getAppearanceSphereCenter());
owner->setTransform_o2p(t);
}
else
{
owner->yaw_o (m_rotationsPerSecond.x * elapsedTime);
owner->pitch_o (m_rotationsPerSecond.y * elapsedTime);
owner->roll_o (m_rotationsPerSecond.z * elapsedTime);
}
}
//===================================================================
@@ -0,0 +1,47 @@
//===================================================================
//
// RotationDynamics.h
// asommers 12-12-2000
//
// a simple dynamics class showing how to use it
//
//===================================================================
#ifndef INCLUDED_RotationDynamics_H
#define INCLUDED_RotationDynamics_H
//===================================================================
#include "sharedMath/Vector.h"
#include "sharedObject/StateDynamics.h"
//===================================================================
class RotationDynamics : public StateDynamics
{
public:
RotationDynamics (Object* owner, const Vector& rotationsPerSecond);
virtual ~RotationDynamics ();
void setRotateAroundAppearanceCenter(bool rotateAroundAppearanceCenter);
protected:
virtual void realAlter (float elapsedTime);
private:
RotationDynamics ();
RotationDynamics (const RotationDynamics&);
RotationDynamics& operator= (const RotationDynamics&);
private:
const Vector m_rotationsPerSecond;
bool m_rotateAroundAppearanceCenter;
};
//===================================================================
#endif
@@ -0,0 +1,61 @@
//===================================================================
//
// SeesawDynamics.cpp
// asommers 6-19-99
//
// copyright 1999, bootprint entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SeesawDynamics.h"
#include "sharedObject/Object.h"
#include "sharedRandom/Random.h"
//===================================================================
// PUBLIC SeesawDynamics
//===================================================================
SeesawDynamics::SeesawDynamics (Object* const owner, const Type type, const float seesawsPerSecond, const float seesawMagnitude) :
StateDynamics (owner),
m_type (type),
m_seesawsPerSecond (seesawsPerSecond),
m_seesawMagnitude (seesawMagnitude),
m_dy (Random::randomReal (0.0f, PI_TIMES_2))
{
}
//-------------------------------------------------------------------
SeesawDynamics::~SeesawDynamics ()
{
}
//-------------------------------------------------------------------
void SeesawDynamics::realAlter (const float elapsedTime)
{
StateDynamics::realAlter (elapsedTime);
Object* const owner = getOwner ();
if (!owner)
return;
//-- rotation
m_dy += elapsedTime;
const float t = (sin (m_seesawsPerSecond * m_dy) + 1.f) * 0.5f;
const float angle = linearInterpolate (-m_seesawMagnitude, m_seesawMagnitude, t);
owner->resetRotate_o2p ();
switch (m_type)
{
case T_yaw: owner->yaw_o (angle); break;
case T_pitch: owner->pitch_o (angle); break;
case T_roll: owner->roll_o (angle); break;
}
}
//===================================================================
@@ -0,0 +1,56 @@
//===================================================================
//
// SeesawDynamics.h
// asommers 12-12-2000
//
// a simple dynamics class showing how to use it
//
//===================================================================
#ifndef INCLUDED_SeesawDynamics_H
#define INCLUDED_SeesawDynamics_H
//===================================================================
#include "sharedObject/StateDynamics.h"
//===================================================================
class SeesawDynamics : public StateDynamics
{
public:
enum Type
{
T_yaw,
T_pitch,
T_roll
};
public:
SeesawDynamics (Object* owner, Type type, float seesawsPerSecond, float seesawMagnitude);
virtual ~SeesawDynamics ();
protected:
virtual void realAlter (float elapsedTime);
private:
SeesawDynamics ();
SeesawDynamics (const SeesawDynamics&);
SeesawDynamics& operator= (const SeesawDynamics&);
private:
const Type m_type;
const float m_seesawsPerSecond;
const float m_seesawMagnitude;
float m_dy;
};
//===================================================================
#endif
@@ -0,0 +1,110 @@
//===================================================================
//
// SimpleDynamics.cpp
// copyright 1999, bootprint entertainment
// copyright 2002, sony online entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SimpleDynamics.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/Object.h"
//===================================================================
SimpleDynamics::SimpleDynamics (Object* const owner) :
Dynamics (owner),
m_currentVelocity (),
m_movementSpace (WorldSpace)
{
}
//-------------------------------------------------------------------
SimpleDynamics::~SimpleDynamics ()
{
}
//-------------------------------------------------------------------
Vector const &SimpleDynamics::getCurrentVelocity_w() const
{
FATAL(m_movementSpace != WorldSpace && m_currentVelocity != Vector::zero, ("SimpleDynamics::getCurrentVelocity_w called when velocity is not in world space"));
return m_currentVelocity;
}
//-------------------------------------------------------------------
void SimpleDynamics::setCurrentVelocity_w(Vector const &newCurrentVelocity_w)
{
m_movementSpace = WorldSpace;
m_currentVelocity = newCurrentVelocity_w;
}
//-------------------------------------------------------------------
Vector const &SimpleDynamics::getCurrentVelocity_p() const
{
FATAL(m_movementSpace != ParentSpace && m_currentVelocity != Vector::zero, ("SimpleDynamics::getCurrentVelocity_p called when velocity is not in parent space"));
return m_currentVelocity;
}
//-------------------------------------------------------------------
void SimpleDynamics::setCurrentVelocity_p(Vector const &newCurrentVelocity_p)
{
m_movementSpace = ParentSpace;
m_currentVelocity = newCurrentVelocity_p;
}
//-------------------------------------------------------------------
Vector const &SimpleDynamics::getCurrentVelocity_o() const
{
FATAL(m_movementSpace != ObjectSpace && m_currentVelocity != Vector::zero, ("SimpleDynamics::getCurrentVelocity_o called when velocity is not in object space"));
return m_currentVelocity;
}
//-------------------------------------------------------------------
void SimpleDynamics::setCurrentVelocity_o(Vector const &newCurrentVelocity_o)
{
m_movementSpace = ObjectSpace;
m_currentVelocity = newCurrentVelocity_o;
}
//-------------------------------------------------------------------
float SimpleDynamics::alter (const float time)
{
float const baseAlterResult = Dynamics::alter (time);
UNREF (baseAlterResult);
if (getOwner () && m_currentVelocity != Vector::zero)
{
switch (m_movementSpace)
{
case WorldSpace:
getOwner ()->move_o (getOwner ()->rotate_w2o (m_currentVelocity * time));
break;
case ParentSpace:
getOwner ()->move_o (getOwner ()->rotate_p2o (m_currentVelocity * time));
break;
case ObjectSpace:
getOwner ()->move_o (m_currentVelocity * time);
break;
}
}
// @todo if worthwhile, figure out a way to have an inactive SimpleDynamics
// return that it doesn't need an alter next frame. Then a mechanism
// will be needed to cause an AlterScheduler::submitForAlter() if
// something causes the dynamics to require an alter.
//
// For now, all simple dynamics get an alter every frame.
return AlterResult::cms_alterNextFrame;
}
//===================================================================
@@ -0,0 +1,58 @@
//===================================================================
//
// SimpleDynamics.h
// copyright 1999, bootprint entertainment
// copyright 2002, sony online entertainment
//
//===================================================================
#ifndef INCLUDED_SimpleDynamics_H
#define INCLUDED_SimpleDynamics_H
//===================================================================
#include "sharedObject/Dynamics.h"
#include "sharedMath/Vector.h"
//===================================================================
class SimpleDynamics : public Dynamics
{
public:
enum MovementSpace
{
WorldSpace,
ParentSpace,
ObjectSpace
};
explicit SimpleDynamics(Object *newOwner);
virtual ~SimpleDynamics();
virtual float alter(float time);
Vector const &getCurrentVelocity_w() const;
void setCurrentVelocity_w(Vector const &newCurrentVelocity_w);
Vector const &getCurrentVelocity_p() const;
void setCurrentVelocity_p(Vector const &newCurrentVelocity_p);
Vector const &getCurrentVelocity_o() const;
void setCurrentVelocity_o(Vector const &newCurrentVelocity_o);
private:
SimpleDynamics();
SimpleDynamics(SimpleDynamics const &);
SimpleDynamics &operator=(SimpleDynamics const &);
private:
Vector m_currentVelocity;
MovementSpace m_movementSpace;
};
//===================================================================
#endif
@@ -0,0 +1,69 @@
//===================================================================
//
// SpringDynamics.cpp
// asommers 6-19-99
//
// copyright 1999, bootprint entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/SpringDynamics.h"
#include "sharedObject/Object.h"
#include "sharedRandom/Random.h"
//===================================================================
// PUBLIC SpringDynamics
//===================================================================
SpringDynamics::SpringDynamics (Object* const owner, const Vector& offset, const Vector& springDirection, float springMagnitude, float springsPerSecond) :
StateDynamics (owner),
m_parent (0),
m_offset (offset),
m_springDirection (springDirection),
m_springMagnitude (springMagnitude),
m_springsPerSecond (springsPerSecond),
m_dy (Random::randomReal (0.0f, PI_TIMES_2)),
m_position ()
{
}
//-------------------------------------------------------------------
SpringDynamics::~SpringDynamics ()
{
// the parent object isn't owned by this instance
m_parent = 0;
}
//-------------------------------------------------------------------
void SpringDynamics::setPosition (const Vector& position)
{
m_position = position;
}
//===================================================================
// PROTECTED SpringDynamics
//===================================================================
void SpringDynamics::realAlter (const float time)
{
StateDynamics::realAlter (time);
Object* const owner = getOwner ();
if (!owner)
return;
if (m_springsPerSecond > 0.f)
{
m_dy += time;
const Vector springDirection = owner->rotate_o2p (m_springDirection) * sin (m_springsPerSecond * m_dy * 8.0f) * m_springMagnitude;
owner->setPosition_p (m_position + m_offset + springDirection);
}
}
//===================================================================
@@ -0,0 +1,53 @@
//===================================================================
//
// SpringDynamics.h
// asommers 12-12-2000
//
// a simple dynamics class showing how to use it
//
//===================================================================
#ifndef INCLUDED_SpringDynamics_H
#define INCLUDED_SpringDynamics_H
//===================================================================
#include "sharedObject/StateDynamics.h"
#include "sharedMath/Vector.h"
//===================================================================
class SpringDynamics : public StateDynamics
{
public:
SpringDynamics (Object* owner, const Vector& offset, const Vector& springDirection, float springMagnitude, float springsPerSecond);
virtual ~SpringDynamics ();
void setPosition (const Vector& position);
protected:
virtual void realAlter (float time);
private:
SpringDynamics ();
SpringDynamics (const SpringDynamics&);
SpringDynamics& operator= (const SpringDynamics&);
private:
const Object* m_parent;
const Vector m_offset;
const Vector m_springDirection;
const float m_springMagnitude;
const float m_springsPerSecond;
float m_dy;
Vector m_position;
};
//===================================================================
#endif
@@ -0,0 +1,106 @@
//===================================================================
//
// StateDynamics.cpp
// asommers 6-19-99
//
// copyright 1999, bootprint entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/StateDynamics.h"
#include "sharedObject/AlterResult.h"
#include "sharedObject/Object.h"
#include "sharedRandom/Random.h"
//===================================================================
// PUBLIC StateDynamics
//===================================================================
StateDynamics::StateDynamics (Object* const owner) :
Dynamics (owner),
m_state (S_off),
m_stateTimer (5.f)
{
}
//-------------------------------------------------------------------
StateDynamics::~StateDynamics ()
{
}
//-------------------------------------------------------------------
float StateDynamics::alter (const float elapsedTime)
{
float const baseAlterResult = Dynamics::alter (elapsedTime);
UNREF (baseAlterResult);
Object* const owner = getOwner ();
if (!owner)
{
// @todo should we request a kill in this condition?
return AlterResult::cms_alterNextFrame;
}
switch (m_state)
{
case S_off:
break;
case S_offToOn:
{
if (m_stateTimer.updateZero (elapsedTime))
{
m_state = S_on;
realAlter (elapsedTime);
}
else
realAlter (elapsedTime * m_stateTimer.getElapsedRatio ());
}
break;
case S_on:
realAlter (elapsedTime);
break;
case S_onToOff:
{
if (m_stateTimer.updateZero (elapsedTime))
m_state = S_off;
else
realAlter (elapsedTime * m_stateTimer.getRemainingRatio ());
}
break;
}
// @todo if worthwhile, come up with a way to have this only alter when
// necessary.
//
// For now, alter every frame.
return AlterResult::cms_alterNextFrame;
}
//-------------------------------------------------------------------
void StateDynamics::setState (const bool on)
{
if (on)
m_state = S_offToOn;
else
m_state = S_onToOff;
m_stateTimer.reset ();
}
//===================================================================
// PROTECTED StateDynamics
//===================================================================
void StateDynamics::realAlter (const float /*elapsedTime*/)
{
}
//===================================================================
@@ -0,0 +1,59 @@
//===================================================================
//
// StateDynamics.h
// asommers 12-12-2000
//
// a simple dynamics class showing how to use it
//
//===================================================================
#ifndef INCLUDED_StateDynamics_H
#define INCLUDED_StateDynamics_H
//===================================================================
#include "sharedFoundation/Timer.h"
#include "sharedObject/Dynamics.h"
//===================================================================
class StateDynamics : public Dynamics
{
public:
StateDynamics (Object* owner);
virtual ~StateDynamics ();
virtual float alter (float elapsedTime);
void setState (bool on);
protected:
virtual void realAlter (float elapsedTime);
private:
StateDynamics ();
StateDynamics (const StateDynamics&);
StateDynamics& operator= (const StateDynamics&);
private:
enum State
{
S_off,
S_offToOn,
S_on,
S_onToOff
};
private:
State m_state;
Timer m_stateTimer;
};
//===================================================================
#endif
@@ -0,0 +1,91 @@
// ======================================================================
//
// TrackingDynamics.cpp
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/TrackingDynamics.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/MemoryBlockManager.h"
#include "sharedMath/Vector.h"
#include "sharedObject/Object.h"
// ======================================================================
MEMORY_BLOCK_MANAGER_IMPLEMENTATION_WITH_INSTALL(TrackingDynamics, true, 0, 0, 0);
// ======================================================================
TrackingDynamics::TrackingDynamics(Object *owner, Object const *targetObject, float speed, Vector const &rotationRadiansPerSecond) :
SimpleDynamics(owner),
m_targetWatcher(targetObject),
m_speed(speed),
m_radiansPerSecond(rotationRadiansPerSecond)
{
}
// ----------------------------------------------------------------------
float TrackingDynamics::alter(float elapsedTime)
{
Object *const ownerObject = getOwner();
if (ownerObject)
{
Object const *const targetObject = m_targetWatcher.getPointer();
if (targetObject)
{
//-- Get world position of owner and target.
Vector const ownerPosition_w = ownerObject->getPosition_w();
Vector const targetPosition_w = targetObject->getPosition_w();
//-- Compute world-space direction vector.
Vector direction_w = targetPosition_w - ownerPosition_w;
IGNORE_RETURN(direction_w.normalize());
//-- Set current velocity.
setCurrentVelocity_w(direction_w * m_speed);
}
//-- Handle object rotation.
ownerObject->yaw_o (m_radiansPerSecond.y * elapsedTime);
ownerObject->pitch_o (m_radiansPerSecond.x * elapsedTime);
ownerObject->roll_o (m_radiansPerSecond.z * elapsedTime);
}
//-- Chain up alter. This will handle the object translation.
return SimpleDynamics::alter(elapsedTime);
}
// ----------------------------------------------------------------------
void TrackingDynamics::setTarget(Object const *targetObject)
{
m_targetWatcher = targetObject;
}
// ----------------------------------------------------------------------
float TrackingDynamics::getDistanceToTargetSquared() const
{
Object const *const ownerObject = getOwner();
if (ownerObject)
{
Object const *const targetObject = m_targetWatcher.getPointer();
if (targetObject)
{
//-- Get world position of owner and target.
Vector const ownerPosition_w = ownerObject->getPosition_w();
Vector const targetPosition_w = targetObject->getPosition_w();
return ownerPosition_w.magnitudeBetweenSquared(targetPosition_w);
}
}
return 0.0f;
}
// ======================================================================
@@ -0,0 +1,53 @@
// ======================================================================
//
// TrackingDynamics.h
// Copyright 2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_TrackingDynamics_H
#define INCLUDED_TrackingDynamics_H
// ======================================================================
#include "sharedObject/SimpleDynamics.h"
#include "sharedFoundation/MemoryBlockManagerMacros.h"
#include "sharedFoundation/Watcher.h"
#include "sharedMath/Vector.h"
class MemoryBlockManager;
// ======================================================================
class TrackingDynamics: public SimpleDynamics
{
MEMORY_BLOCK_MANAGER_INTERFACE_WITH_INSTALL;
public:
TrackingDynamics(Object *owner, Object const *targetObject, float speed, Vector const &rotationRadiansPerSecond);
virtual float alter(float elapsedTime);
void setTarget(Object const *targetObject);
float getDistanceToTargetSquared() const;
private:
// Disabled.
TrackingDynamics();
TrackingDynamics(const TrackingDynamics&);
TrackingDynamics &operator =(const TrackingDynamics&);
private:
ConstWatcher<Object> m_targetWatcher;
float m_speed;
Vector m_radiansPerSecond;
};
// ======================================================================
#endif
@@ -0,0 +1,536 @@
//===================================================================
//
// LotManager.cpp
// asommers
//
// copyright 2002, sony online entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/LotManager.h"
#include "sharedCollision/BoxExtent.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFoundation/PointerDeleter.h"
#include "sharedMath/Rectangle2d.h"
#include "sharedObject/StructureFootprint.h"
#include "sharedObject/World.h"
#include "sharedTerrain/TerrainObject.h"
#include <algorithm>
#include <map>
#include <string>
//===================================================================
// LotManager::NoBuildEntry
//===================================================================
LotManager::NoBuildEntry::NoBuildEntry (Vector const & position_w, float radius) :
m_position_w (position_w),
m_radius (radius),
m_spatialSubdivisionHandle (0)
{
}
// ----------------------------------------------------------------------
LotManager::NoBuildEntry::~NoBuildEntry ()
{
}
// ----------------------------------------------------------------------
Sphere const LotManager::NoBuildEntry::getSphere () const
{
return Sphere (m_position_w, m_radius);
}
// ----------------------------------------------------------------------
SpatialSubdivisionHandle * LotManager::NoBuildEntry::getSpatialSubdivisionHandle ()
{
return m_spatialSubdivisionHandle;
}
// ----------------------------------------------------------------------
void LotManager::NoBuildEntry::setSpatialSubdivisionHandle (SpatialSubdivisionHandle * const spatialSubdivisionHandle)
{
m_spatialSubdivisionHandle = spatialSubdivisionHandle;
}
//===================================================================
// LotManagerNamespace
//===================================================================
namespace LotManagerNamespace
{
bool ms_logEntries;
bool ms_debugReport;
void debugReport (void * context)
{
LotManager const * lotManager = reinterpret_cast<LotManager const *> (context);
if (lotManager)
{
DEBUG_REPORT_PRINT (true, ("-- LotManager\n"));
DEBUG_REPORT_PRINT (true, (" noBuildEntries = %i\n", lotManager->getNumberOfNoBuildEntries ()));
DEBUG_REPORT_PRINT (true, ("structureFootprintEntries = %i\n", lotManager->getNumberOfStructureFootprintEntries ()));
}
}
}
using namespace LotManagerNamespace;
//===================================================================
// PUBLIC LotManager
//===================================================================
LotManager::LotManager (const float mapWidthInMeters, const float chunkWidthInMeters) :
m_mapWidthInMeters (mapWidthInMeters),
m_chunkWidthInMeters (chunkWidthInMeters),
m_width (static_cast<int> (mapWidthInMeters / chunkWidthInMeters)),
m_width_2 (m_width / 2),
m_noBuildEntryMap (new NoBuildEntryMap),
m_structureFootprintEntryMap (new StructureFootprintEntryMap)
{
DebugFlags::registerFlag (ms_logEntries, "SharedObject/LotManager", "logEntries");
DebugFlags::registerFlag (ms_debugReport, "SharedObject/LotManager", "debugReport", debugReport, this);
}
//-------------------------------------------------------------------
LotManager::~LotManager ()
{
DebugFlags::unregisterFlag (ms_logEntries);
DebugFlags::unregisterFlag (ms_debugReport);
DEBUG_WARNING (!m_noBuildEntryMap->empty (), ("LotManager::~LotManager: m_noBuildEntryMap is not empty"));
std::for_each (m_noBuildEntryMap->begin (), m_noBuildEntryMap->end (), PointerDeleterPairSecond ());
delete m_noBuildEntryMap;
DEBUG_WARNING (!m_structureFootprintEntryMap->empty (), ("LotManager::~LotManager: m_structureFootprintEntryMap is not empty"));
delete m_structureFootprintEntryMap;
}
//-------------------------------------------------------------------
void LotManager::addNoBuildEntry (Object const & object, float const noBuildRadius)
{
NOT_NULL (m_noBuildEntryMap);
Vector position_w = object.getPosition_w ();
position_w.y = 0.f;
NoBuildEntry * const noBuildEntry = new NoBuildEntry (position_w, noBuildRadius);
noBuildEntry->setSpatialSubdivisionHandle (m_sphereTree.addObject (noBuildEntry));
bool const result = m_noBuildEntryMap->insert (std::make_pair (&object, noBuildEntry)).second;
UNREF (result);
DEBUG_FATAL (!result, ("LotManager::addNoBuildEntry - entry already exists"));
DEBUG_REPORT_LOG (ms_logEntries, ("LotManager: added no build entry for object %s [%s] at <%1.2f, %1.2f>\n", object.getNetworkId ().getValueString ().c_str (), object.getObjectTemplateName () ? object.getObjectTemplateName () : "null", position_w.x, position_w.z));
}
//-------------------------------------------------------------------
void LotManager::removeNoBuildEntry (const Object& object)
{
NoBuildEntryMap::iterator iter = m_noBuildEntryMap->find (&object);
NoBuildEntryMap::iterator end = m_noBuildEntryMap->end ();
if (iter != end)
{
NoBuildEntry * const noBuildEntry = iter->second;
m_sphereTree.removeObject (noBuildEntry->getSpatialSubdivisionHandle ());
delete noBuildEntry;
IGNORE_RETURN (m_noBuildEntryMap->erase (iter));
}
else
DEBUG_FATAL (true, ("LotManager::removeNoBuildEntry - entry not found"));
DEBUG_REPORT_LOG (ms_logEntries, ("LotManager: removed no build entry for object %s [%s]\n", object.getNetworkId ().getValueString ().c_str (), object.getObjectTemplateName () ? object.getObjectTemplateName () : "null"));
}
//-------------------------------------------------------------------
int LotManager::getNumberOfNoBuildEntries () const
{
NOT_NULL (m_noBuildEntryMap);
return static_cast<int> (m_noBuildEntryMap->size ());
}
//-------------------------------------------------------------------
void LotManager::addStructureFootprintEntry (const Object& object, const StructureFootprint& structureFootprint, const int x, const int z, const RotationType rotation)
{
NOT_NULL (m_structureFootprintEntryMap);
StructureFootprintEntry structureFootprintEntry;
structureFootprintEntry.m_structureFootprint = &structureFootprint;
structureFootprintEntry.m_x = x;
structureFootprintEntry.m_z = z;
structureFootprintEntry.m_rotation = rotation;
const bool result = m_structureFootprintEntryMap->insert (std::make_pair (&object, structureFootprintEntry)).second;
UNREF (result);
DEBUG_FATAL (!result, ("LotManager::addStructureFootprintEntry - entry already exists"));
DEBUG_REPORT_LOG (ms_logEntries, ("LotManager: added structure footprint entry for object %s [%s] at <%1.2f, %1.2f>\n", object.getNetworkId ().getValueString ().c_str (), object.getObjectTemplateName () ? object.getObjectTemplateName () : "null", x * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.5f, z * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.5f));
}
//-------------------------------------------------------------------
void LotManager::removeStructureFootprintEntry (const Object& object)
{
StructureFootprintEntryMap::iterator iter = m_structureFootprintEntryMap->find (&object);
StructureFootprintEntryMap::iterator end = m_structureFootprintEntryMap->end ();
if (iter != end)
IGNORE_RETURN (m_structureFootprintEntryMap->erase (iter));
else
DEBUG_FATAL (true, ("LotManager::removeStructureFootprintEntry - entry not found"));
DEBUG_REPORT_LOG (ms_logEntries, ("LotManager: removed structure footprint entry for object %s [%s]\n", object.getNetworkId ().getValueString ().c_str (), object.getObjectTemplateName () ? object.getObjectTemplateName () : "null"));
}
//-------------------------------------------------------------------
int LotManager::getNumberOfStructureFootprintEntries () const
{
NOT_NULL (m_structureFootprintEntryMap);
return static_cast<int> (m_structureFootprintEntryMap->size ());
}
//-------------------------------------------------------------------
bool LotManager::canPlace (const StructureFootprint* const structureFootprint, const int x, const int z, const RotationType rotation, float& height_w, bool const forceChunkCreation) const
{
NOT_NULL (structureFootprint);
BoxExtent boxExtent;
boxExtent.setMin (Vector::maxXYZ);
boxExtent.setMax (Vector::negativeMaxXYZ);
switch (rotation)
{
default:
case RT_0:
{
const int pivotX = structureFootprint->getPivotX ();
const int pivotZ = structureFootprint->getPivotZ ();
int sj = structureFootprint->getHeight () - 1;
int j;
for (j = 0; j < structureFootprint->getHeight (); ++j)
{
int si = 0;
int i;
for (i = 0; i < structureFootprint->getWidth (); ++i)
{
if (!canPlace (boxExtent, (x - pivotX) + i, (z - pivotZ) + j, structureFootprint, si, sj, forceChunkCreation))
return false;
++si;
}
--sj;
}
}
break;
case RT_90:
{
const int pivotX = structureFootprint->getPivotZ ();
const int pivotZ = structureFootprint->getPivotX ();
int sj = structureFootprint->getWidth () - 1;
int j;
for (j = 0; j < structureFootprint->getWidth (); ++j)
{
int si = structureFootprint->getHeight () - 1;
int i;
for (i = 0; i < structureFootprint->getHeight (); ++i)
{
if (!canPlace (boxExtent, (x - pivotX) + i, (z - (structureFootprint->getWidth () - 1 - pivotZ)) + j, structureFootprint, sj, si, forceChunkCreation))
return false;
--si;
}
--sj;
}
}
break;
case RT_180:
{
const int pivotX = structureFootprint->getPivotX ();
const int pivotZ = (structureFootprint->getHeight () - 1) - structureFootprint->getPivotZ ();
int sj = 0;
int j;
for (j = 0; j < structureFootprint->getHeight (); ++j)
{
int si = structureFootprint->getWidth () - 1;
int i;
for (i = 0; i < structureFootprint->getWidth (); ++i)
{
if (!canPlace (boxExtent, (x - (structureFootprint->getWidth () - 1 - pivotX)) + i, (z - pivotZ) + j, structureFootprint, si, sj, forceChunkCreation))
return false;
--si;
}
++sj;
}
}
break;
case RT_270:
{
const int pivotX = (structureFootprint->getHeight () - 1) - structureFootprint->getPivotZ ();
const int pivotZ = structureFootprint->getPivotX ();
int sj = 0;
int j;
for (j = 0; j < structureFootprint->getWidth (); ++j)
{
int si = 0;
int i;
for (i = 0; i < structureFootprint->getHeight (); ++i)
{
if (!canPlace (boxExtent, (x - pivotX) + i, (z - pivotZ) + j, structureFootprint, sj, si, forceChunkCreation))
return false;
++si;
}
++sj;
}
}
break;
}
if (boxExtent.getHeight() < 0.0f)
{
WARNING(true, ("LotManager invalid boxExtent"));
return false;
}
//-- if box extent is smaller than the tolerance, we're ok
if (boxExtent.getHeight () > structureFootprint->getStructureReservationTolerance ())
return false;
height_w = boxExtent.getTop ();
return true;
}
//-------------------------------------------------------------------
bool LotManager::canPlace (Rectangle2d const & rectangle2d) const
{
const int x0 = TerrainObject::getConstInstance ()->calculateChunkX (Vector (rectangle2d.x0, 0.f, rectangle2d.y0));
const int z0 = TerrainObject::getConstInstance ()->calculateChunkZ (Vector (rectangle2d.x0, 0.f, rectangle2d.y0));
const int x1 = TerrainObject::getConstInstance ()->calculateChunkX (Vector (rectangle2d.x1, 0.f, rectangle2d.y1));
const int z1 = TerrainObject::getConstInstance ()->calculateChunkZ (Vector (rectangle2d.x1, 0.f, rectangle2d.y1));
int x;
int z;
for (z = z0; z <= z1; ++z)
for (x = x0; x <= x1; ++x)
if (getLotType (x, z) == LT_illegal)
return false;
return true;
}
//-------------------------------------------------------------------
int LotManager::getWidth () const
{
return m_width;
}
//-------------------------------------------------------------------
LotType LotManager::getLotType (const int x, const int z) const
{
//-- all we want to know is if the lot is occupied
if (x < -m_width_2 || x >= m_width_2 || z < -m_width_2 || z >= m_width_2)
return LT_illegal;
//-- go through the no build entries
{
const Vector position_w (x * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.5f, 0.f, z * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.5f);
if (m_sphereTree.isWithin (position_w))
return LT_illegal;
}
//-- go through the structure footprint entries
{
StructureFootprintEntryMap::iterator iter = m_structureFootprintEntryMap->begin ();
StructureFootprintEntryMap::iterator end = m_structureFootprintEntryMap->end ();
for (; iter != end; ++iter)
{
const StructureFootprintEntry& structureFootprintEntry = iter->second;
switch (structureFootprintEntry.m_rotation)
{
default:
case RT_0:
{
const int pivotX = structureFootprintEntry.m_structureFootprint->getPivotX ();
const int pivotZ = structureFootprintEntry.m_structureFootprint->getPivotZ ();
const int minX = structureFootprintEntry.m_x - pivotX;
const int maxX = minX + structureFootprintEntry.m_structureFootprint->getWidth ();
const int minZ = structureFootprintEntry.m_z - pivotZ;
const int maxZ = minZ + structureFootprintEntry.m_structureFootprint->getHeight ();
if (x >= minX && x < maxX && z >= minZ && z < maxZ)
{
const int sx = x - minX;
const int sz = (structureFootprintEntry.m_structureFootprint->getHeight () - 1) - (z - minZ);
const LotType lotType = structureFootprintEntry.m_structureFootprint->getLotType (sx, sz);
if (lotType == LT_hard || lotType == LT_structure)
return LT_illegal;
}
}
break;
case RT_90:
{
const int pivotX = structureFootprintEntry.m_structureFootprint->getPivotZ ();
const int pivotZ = structureFootprintEntry.m_structureFootprint->getPivotX ();
const int minX = structureFootprintEntry.m_x - pivotX;
const int maxX = minX + structureFootprintEntry.m_structureFootprint->getHeight ();
const int minZ = structureFootprintEntry.m_z - (structureFootprintEntry.m_structureFootprint->getWidth () - 1 - pivotZ);
const int maxZ = minZ + structureFootprintEntry.m_structureFootprint->getWidth ();
if (x >= minX && x < maxX && z >= minZ && z < maxZ)
{
const int sx = (structureFootprintEntry.m_structureFootprint->getHeight () - 1) - (x - minX);
const int sz = (structureFootprintEntry.m_structureFootprint->getWidth () - 1) - (z - minZ);
const LotType lotType = structureFootprintEntry.m_structureFootprint->getLotType (sz, sx);
if (lotType == LT_hard || lotType == LT_structure)
return LT_illegal;
}
}
break;
case RT_180:
{
const int pivotX = structureFootprintEntry.m_structureFootprint->getPivotX ();
const int pivotZ = (structureFootprintEntry.m_structureFootprint->getHeight () - 1) - structureFootprintEntry.m_structureFootprint->getPivotZ ();
const int minX = structureFootprintEntry.m_x - (structureFootprintEntry.m_structureFootprint->getWidth () - 1 - pivotX);
const int maxX = minX + structureFootprintEntry.m_structureFootprint->getWidth ();
const int minZ = structureFootprintEntry.m_z - pivotZ;
const int maxZ = minZ + structureFootprintEntry.m_structureFootprint->getHeight ();
if (x >= minX && x < maxX && z >= minZ && z < maxZ)
{
const int sx = (structureFootprintEntry.m_structureFootprint->getWidth () - 1) - (x - minX);
const int sz = z - minZ;
const LotType lotType = structureFootprintEntry.m_structureFootprint->getLotType (sx, sz);
if (lotType == LT_hard || lotType == LT_structure)
return LT_illegal;
}
}
break;
case RT_270:
{
const int pivotX = (structureFootprintEntry.m_structureFootprint->getHeight () - 1) - structureFootprintEntry.m_structureFootprint->getPivotZ ();
const int pivotZ = structureFootprintEntry.m_structureFootprint->getPivotX ();
const int minX = structureFootprintEntry.m_x - pivotX;
const int maxX = minX + structureFootprintEntry.m_structureFootprint->getHeight ();
const int minZ = structureFootprintEntry.m_z - pivotZ;
const int maxZ = minZ + structureFootprintEntry.m_structureFootprint->getWidth ();
if (x >= minX && x < maxX && z >= minZ && z < maxZ)
{
const int sx = x - minX;
const int sz = z - minZ;
const LotType lotType = structureFootprintEntry.m_structureFootprint->getLotType (sz, sx);
if (lotType == LT_hard || lotType == LT_structure)
return LT_illegal;
}
}
break;
}
}
}
return LT_nothing;
}
//===================================================================
// PRIVATE LotManager
//===================================================================
bool LotManager::canPlace (BoxExtent& boxExtent, const int x, const int z, const StructureFootprint* const structureFootprint, const int structureX, const int structureZ, bool const forceChunkCreation) const
{
const TerrainObject* const terrainObject = TerrainObject::getConstInstance ();
if (!terrainObject)
{
DEBUG_WARNING (true, ("LotManager::canPlace - no terrain"));
return false;
}
//-- verify not in water
if (terrainObject->getWater (x, z))
return false;
//-- check lot types and grow extent
const LotType sourceLotType = structureFootprint->getLotType (structureX, structureZ);
const LotType destinationLotType = getLotType (x, z);
const Vector position_w (x * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.495f, 0.f, z * m_chunkWidthInMeters + m_chunkWidthInMeters * 0.495f);
const BoxExtent* const chunkExtent = forceChunkCreation ? terrainObject->getChunkExtentForceChunkCreation (position_w) : terrainObject->getChunkExtent (position_w);
if (!chunkExtent)
{
DEBUG_WARNING (true, ("LotManager::canPlace - could not find extent for <%1.2f, %1.2f>\n", position_w.x, position_w.z));
return false;
}
bool ok = false;
bool growExtent = false;
if (sourceLotType == LT_nothing)
ok = true;
if (sourceLotType == LT_hard && destinationLotType == LT_nothing)
{
ok = true;
growExtent = true;
}
if (sourceLotType == LT_structure && destinationLotType == LT_nothing)
{
ok = true;
growExtent = true;
}
bool const updateBoxExtent = structureFootprint->getBoxTestRect().isWithin(static_cast<float>(structureX), static_cast<float>(structureZ));
if (updateBoxExtent && growExtent)
boxExtent.grow (*chunkExtent);
return ok;
}
//===================================================================
@@ -0,0 +1,138 @@
//===================================================================
//
// LotManager.h
// asommers
//
// copyright 2002, sony online entertainment
//
//===================================================================
#ifndef INCLUDED_LotManager_H
#define INCLUDED_LotManager_H
//===================================================================
class BoxExtent;
class Object;
class Rectangle2d;
class SpatialSubdivisionHandle;
class StructureFootprint;
#include "sharedMath/SphereTree.h"
#include "sharedMath/Vector.h"
#include "sharedObject/LotType.h"
//===================================================================
class LotManager
{
public:
LotManager (float mapWidthInMeters, float chunkWidthInMeters);
~LotManager ();
void addNoBuildEntry (const Object& object, float noBuildRadius);
void removeNoBuildEntry (const Object& object);
int getNumberOfNoBuildEntries () const;
void addStructureFootprintEntry (const Object& object, const StructureFootprint& structureFootprint, int x, int z, RotationType rotation);
void removeStructureFootprintEntry (const Object& object);
int getNumberOfStructureFootprintEntries () const;
bool canPlace (const StructureFootprint* structureFootprint, int x, int z, RotationType rotation, float& height_w, bool forceChunkCreation=true) const;
bool canPlace (Rectangle2d const & rectangle2d) const;
//-- tool interface
int getWidth () const;
LotType getLotType (int x, int z) const;
private:
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class NoBuildEntry
{
public:
NoBuildEntry (Vector const & position_w, float radius);
~NoBuildEntry ();
Sphere const getSphere () const;
SpatialSubdivisionHandle * getSpatialSubdivisionHandle ();
void setSpatialSubdivisionHandle (SpatialSubdivisionHandle * spatialSubdivisionHandle);
private:
NoBuildEntry (NoBuildEntry const & rhs);
NoBuildEntry & operator = (NoBuildEntry const & rhs);
private:
Vector const m_position_w;
float const m_radius;
SpatialSubdivisionHandle * m_spatialSubdivisionHandle;
};
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class NoBuildEntrySphereExtentAccessor: public BaseSphereTreeAccessor<NoBuildEntry const *, NoBuildEntrySphereExtentAccessor>
{
public:
static Sphere const getExtent(NoBuildEntry const * const noBuildEntry)
{
return noBuildEntry ? noBuildEntry->getSphere () : Sphere::zero;
}
static char const *getDebugName(NoBuildEntry const * const /*noBuildEntry*/)
{
return 0;
}
};
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class StructureFootprintEntry
{
public:
const StructureFootprint* m_structureFootprint;
int m_x;
int m_z;
RotationType m_rotation;
};
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private:
bool canPlace (BoxExtent& boxExtent, int x, int z, const StructureFootprint* structureFootprint, int structureX, int structureZ, bool forceChunkCreation) const;
private:
LotManager ();
LotManager (const LotManager&);
LotManager& operator= (const LotManager&);
private:
const float m_mapWidthInMeters;
const float m_chunkWidthInMeters;
const int m_width;
const int m_width_2;
typedef stdmap<const Object*, NoBuildEntry*>::fwd NoBuildEntryMap;
NoBuildEntryMap* const m_noBuildEntryMap;
typedef stdmap<const Object*, StructureFootprintEntry>::fwd StructureFootprintEntryMap;
StructureFootprintEntryMap* const m_structureFootprintEntryMap;
SphereTree<const NoBuildEntry*, NoBuildEntrySphereExtentAccessor> m_sphereTree;
};
//===================================================================
#endif
@@ -0,0 +1,35 @@
//===================================================================
//
// LotType.h
// asommers
//
// copyright 2002, sony online entertainment
//
//===================================================================
#ifndef INCLUDED_LotType_H
#define INCLUDED_LotType_H
//===================================================================
enum LotType
{
LT_nothing,
LT_hard,
LT_structure,
LT_illegal
};
//-------------------------------------------------------------------
enum RotationType
{
RT_0,
RT_90,
RT_180,
RT_270
};
//===================================================================
#endif
@@ -0,0 +1,306 @@
//===================================================================
//
// StructureFootprint.cpp
// asommers
//
// copyright 2002, sony online entertainment
//
//===================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/StructureFootprint.h"
#include "sharedFile/Iff.h"
#include <string>
//===================================================================
namespace StructureFootprintLoaderNamespace
{
const Tag TAG_FOOT = TAG (F,O,O,T);
const Tag TAG_PRNT = TAG (P,R,N,T);
}
using namespace StructureFootprintLoaderNamespace;
//===================================================================
// PUBLIC StructureFootprint
//===================================================================
StructureFootprint::StructureFootprint () :
m_width (1),
m_height (1),
m_boxTestRect(),
m_pivotX (0),
m_pivotZ (0),
m_data (new LotType [1]),
m_hardReservationTolerance (1.f),
m_structureReservationTolerance (1.f),
m_numberOfReservations (1),
m_numberOfHardReservations (0),
m_numberOfStructureReservations (1)
{
//-- the default reservation takes up just lot itself
m_data [0] = LT_structure;
}
//-------------------------------------------------------------------
StructureFootprint::~StructureFootprint ()
{
delete [] m_data;
m_data = 0;
}
//-------------------------------------------------------------------
void StructureFootprint::load (const char* const filename)
{
delete [] m_data;
m_data = 0;
Iff iff;
if (iff.open (filename, true))
load (iff);
else
DEBUG_WARNING (true, ("StructureFootprint::load - %s not found", filename));
}
//-------------------------------------------------------------------
int StructureFootprint::getWidth () const
{
return m_width;
}
//-------------------------------------------------------------------
int StructureFootprint::getHeight () const
{
return m_height;
}
//-------------------------------------------------------------------
Rectangle2d const & StructureFootprint::getBoxTestRect () const
{
return m_boxTestRect;
}
//-------------------------------------------------------------------
int StructureFootprint::getPivotX () const
{
return m_pivotX;
}
//-------------------------------------------------------------------
int StructureFootprint::getPivotZ () const
{
return m_pivotZ;
}
//-------------------------------------------------------------------
LotType StructureFootprint::getLotType (int x, int z) const
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE (0, x, m_width);
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE (0, z, m_height);
return m_data [m_width * z + x];
}
//-------------------------------------------------------------------
float StructureFootprint::getHardReservationTolerance () const
{
return m_hardReservationTolerance;
}
//-------------------------------------------------------------------
float StructureFootprint::getStructureReservationTolerance () const
{
return m_structureReservationTolerance;
}
//-------------------------------------------------------------------
int StructureFootprint::getNumberOfReservations () const
{
return m_numberOfReservations;
}
//-------------------------------------------------------------------
int StructureFootprint::getNumberOfHardReservations () const
{
return m_numberOfHardReservations;
}
//-------------------------------------------------------------------
int StructureFootprint::getNumberOfStructureReservations () const
{
return m_numberOfStructureReservations;
}
//-------------------------------------------------------------------
void StructureFootprint::getBorder (int x, int z, bool& top, bool& bottom, bool& left, bool& right) const
{
top = false;
bottom = false;
left = false;
right = false;
const bool center = getLotType (x, z) == LT_structure;
const bool outOfRangeTop = z < 0 + 1;
const bool outOfRangeBottom = z >= m_height - 1;
const bool outOfRangeLeft = x < 0 + 1;
const bool outOfRangeRight = x >= m_width - 1;
if (center)
{
top = outOfRangeTop || (!outOfRangeTop && getLotType (x, z - 1) != LT_structure);
bottom = outOfRangeBottom || (!outOfRangeBottom && getLotType (x, z + 1) != LT_structure);
left = outOfRangeLeft || (!outOfRangeLeft && getLotType (x - 1, z ) != LT_structure);
right = outOfRangeRight || (!outOfRangeRight && getLotType (x + 1, z ) != LT_structure);
}
}
//===================================================================
// PRIVATE StructureFootprint
//===================================================================
void StructureFootprint::load (Iff& iff)
{
iff.enterForm (TAG_FOOT);
switch (iff.getCurrentName ())
{
case TAG_0000:
load_0000 (iff);
break;
default:
{
char tagBuffer [5];
ConvertTagToString (iff.getCurrentName (), tagBuffer);
char buffer [128];
iff.formatLocation (buffer, sizeof (buffer));
DEBUG_FATAL (true, ("StructureFootprint::load - unknown version %s/%s", buffer, tagBuffer));
}
break;
}
iff.exitForm (TAG_FOOT);
}
//-------------------------------------------------------------------
void StructureFootprint::load_0000 (Iff& iff)
{
iff.enterForm (TAG_0000);
//--
iff.enterChunk (TAG_INFO);
m_width = iff.read_int32 ();
DEBUG_FATAL (m_width == 0, ("width == 0"));
m_height = iff.read_int32 ();
DEBUG_FATAL (m_height == 0, ("height == 0"));
m_pivotX = iff.read_int32 ();
m_pivotZ = iff.read_int32 ();
m_hardReservationTolerance = iff.read_float ();
m_structureReservationTolerance = iff.read_float ();
iff.exitChunk (TAG_INFO);
m_boxTestRect.x0 = m_boxTestRect.y0 = 0.0f;
m_boxTestRect.x1 = static_cast<float>(m_width);
m_boxTestRect.y1 = static_cast<float>(m_height);
if (iff.enterChunk(TAG_DATA, true))
{
m_boxTestRect.x0 = static_cast<float>(iff.read_int32());
m_boxTestRect.y0 = static_cast<float>(iff.read_int32());
m_boxTestRect.x1 = static_cast<float>(iff.read_int32());
m_boxTestRect.y1 = static_cast<float>(iff.read_int32());
iff.exitChunk(TAG_DATA);
}
//--
iff.enterChunk (TAG_PRNT);
std::string footprint;
int i;
for (i = 0; i < m_height; ++i)
{
DEBUG_FATAL (iff.getChunkLengthLeft () == 0, ("StructureFootprintLoader::load_0000 [%s]: height mismatch", iff.getFileName ()));
char* buffer = iff.read_string ();
DEBUG_FATAL (istrlen (buffer) != m_width, ("StructureFootprintLoader::load_0000 [%s]: width mismatch", iff.getFileName ()));
const std::string tempFootprint = footprint + buffer;
footprint = tempFootprint;
delete [] buffer;
}
iff.exitChunk (TAG_PRNT);
//-- allocate footprint
IS_NULL (m_data);
m_data = new LotType [static_cast<size_t> (m_width * m_height)];
NOT_NULL (m_data);
//-- convert string to footprint
const char* const buffer = footprint.c_str ();
m_numberOfReservations = 0;
m_numberOfHardReservations = 0;
m_numberOfStructureReservations = 0;
const int n = m_width * m_height;
for (i = 0; i < n; ++i)
{
switch (buffer [i])
{
case 'F':
case 'f':
m_data [i] = LT_structure;
++m_numberOfReservations;
++m_numberOfStructureReservations;
break;
case 'H':
case 'h':
m_data [i] = LT_hard;
++m_numberOfReservations;
++m_numberOfHardReservations;
break;
case '.':
m_data [i] = LT_nothing;
break;
default:
m_data [i] = LT_hard;
++m_numberOfReservations;
++m_numberOfHardReservations;
DEBUG_WARNING (true, ("StructureFootprintLoader::load [%s] - unknown lot type %c", iff.getFileName (), buffer [i]));
break;
}
}
iff.exitForm (TAG_0000);
}
//===================================================================
@@ -0,0 +1,73 @@
//===================================================================
//
// StructureFootprint.h
// asommers
//
// copyright 2002, sony online entertainment
//
//===================================================================
#ifndef INCLUDED_StructureFootprint_H
#define INCLUDED_StructureFootprint_H
//===================================================================
#include "sharedObject/LotType.h"
#include "sharedMath/Rectangle2d.h"
class Iff;
//===================================================================
class StructureFootprint
{
public:
StructureFootprint ();
~StructureFootprint ();
void load (const char* filename);
int getWidth () const;
int getHeight () const;
Rectangle2d const & getBoxTestRect () const;
int getPivotX () const;
int getPivotZ () const;
LotType getLotType (int x, int z) const;
float getHardReservationTolerance () const;
float getStructureReservationTolerance () const;
int getNumberOfReservations () const;
int getNumberOfHardReservations () const;
int getNumberOfStructureReservations () const;
void getBorder (int x, int z, bool& top, bool& bottom, bool& left, bool& right) const;
private:
void load (Iff& iff);
void load_0000 (Iff& iff);
private:
StructureFootprint (const StructureFootprint&);
StructureFootprint& operator= (const StructureFootprint&);
private:
int m_width;
int m_height;
Rectangle2d m_boxTestRect;
int m_pivotX;
int m_pivotZ;
LotType* m_data;
float m_hardReservationTolerance;
float m_structureReservationTolerance;
int m_numberOfReservations;
int m_numberOfHardReservations;
int m_numberOfStructureReservations;
};
//===================================================================
#endif
@@ -0,0 +1,493 @@
// ======================================================================
//
// MovementTable.cpp
// Copyright 2002-2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/MovementTable.h"
#include "sharedUtility/DataTable.h"
#include "sharedUtility/DataTableManager.h"
#include "swgSharedUtility/Postures.h"
#include "swgSharedUtility/States.h"
#include <map>
// ======================================================================
namespace MovementTableNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef std::map<States::Enumerator, float> StateFloatMap;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
char const *const cs_stateRateModifierFilename = "datatables/movement/state_rate_modifiers.iff";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StateFloatMap s_stateMovementRateModifiers;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline bool hasState(uint64 flags, States::Enumerator state)
{
return (flags & States::getStateMask(state)) != 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
using namespace MovementTableNamespace;
// ======================================================================
struct MovementTable::rates
{
Locomotions::Enumerator stationary;
Locomotions::Enumerator slow;
Locomotions::Enumerator fast;
float move;
float accel;
float turn;
float canSeeHeightMod;
};
// ======================================================================
bool MovementTable::ms_installed;
MovementTable::eLocomotionSpeed MovementTable::ms_stateMoveLimit[States::NumberOfStates];
// ======================================================================
// class MovementTable: PUBLIC STATIC
// ======================================================================
void MovementTable::install(const std::string &stateFileName)
{
DEBUG_FATAL(ms_installed, ("MovementTable already installed"));
//-- Process state locomotion speed limit file.
{
DataTable *table = DataTableManager::getTable(stateFileName, true);
FATAL(!table, ("Couldn't open movement state datatable [%s]", stateFileName.c_str()));
int i;
for (i = 0; i < States::NumberOfStates; ++i)
ms_stateMoveLimit[i] = kFast;
int const rowCount = table->getNumRows();
for (i = 0; i < rowCount; ++i)
{
States::Enumerator state = static_cast<States::Enumerator>(table->getIntValue("state", i));
ms_stateMoveLimit[state] = static_cast<eLocomotionSpeed>(table->getIntValue("maxSpeedCategory", i));
}
DataTableManager::close(stateFileName);
}
//-- Process state movement rate modifiers file.
{
s_stateMovementRateModifiers.clear();
// @todo -TRF- get filename from caller.
char const *filename = cs_stateRateModifierFilename;
DataTable *table = DataTableManager::getTable(filename, true);
FATAL(!table, ("Couldn't open state movement rate modifier datatable [%s].", filename));
int const rowCount = table->getNumRows();
for (int i = 0; i < rowCount; ++i)
{
States::Enumerator const state = static_cast<States::Enumerator>(table->getIntValue("state", i));
float const rateModifier = table->getFloatValue("movementRateModifier", i);
IGNORE_RETURN(s_stateMovementRateModifiers.insert(StateFloatMap::value_type(state, rateModifier)));
}
DataTableManager::close(filename);
}
ms_installed = true;
}
// ======================================================================
// class MovementTable: PUBLIC
// ======================================================================
MovementTable::MovementTable (const std::string &filename, const std::string &templateName) :
m_postures(new PostureMap)
{
DataTable * table = DataTableManager::getTable(filename, true);
UNREF(templateName);
FATAL(!table, ("Couldn't open movement datatable [%s] for template [%s]", filename.c_str(), templateName.c_str()));
int x;
for (x=0; x<Locomotions::NumberOfLocomotions; ++x)
{
m_locomotionPostures[x] = Postures::Invalid;
}
for (x=0; x<table->getNumRows(); ++x)
{
Postures::Enumerator posture = static_cast<Postures::Enumerator>(table->getIntValue("posture", x));
rates temp;
temp.stationary = static_cast<Locomotions::Enumerator>(table->getIntValue("stationary", x));
temp.slow = static_cast<Locomotions::Enumerator>(table->getIntValue("slow", x));
temp.fast = static_cast<Locomotions::Enumerator>(table->getIntValue("fast", x));
temp.move = table->getFloatValue("movementScale", x);
temp.accel = table->getFloatValue("accelerationScale", x);
temp.turn = table->getFloatValue("turnScale", x);
temp.canSeeHeightMod = table->getFloatValue("canSeeHeightMod", x);
(*m_postures)[posture] = temp;
if (temp.stationary != Locomotions::Invalid)
m_locomotionPostures[temp.stationary] = posture;
if (temp.slow != Locomotions::Invalid)
m_locomotionPostures[temp.slow] = posture;
if (temp.fast != Locomotions::Invalid)
m_locomotionPostures[temp.fast] = posture;
}
table = 0;
}
// ----------------------------------------------------------------------
MovementTable::~MovementTable (void)
{
delete m_postures;
}
// ----------------------------------------------------------------------
MovementTable::eLocomotionSpeed MovementTable::getLocomotionData(Locomotions::Enumerator locomotion, Postures::Enumerator &o_posture) const
{
if (locomotion < 0 || locomotion >= Locomotions::NumberOfLocomotions)
return kInvalid;
o_posture = m_locomotionPostures[locomotion];
if (o_posture == Postures::Invalid)
return kInvalid;
return getPostureSpeed(o_posture, locomotion);
}
// ----------------------------------------------------------------------
MovementTable::eLocomotionSpeed MovementTable::getPostureSpeed(Postures::Enumerator i_posture, Locomotions::Enumerator i_locomotion) const
{
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return kInvalid;
const rates &rate = m_postures->find(i_posture)->second;
if (rate.fast == i_locomotion)
return kFast;
if (rate.slow == i_locomotion)
return kSlow;
DEBUG_FATAL(rate.stationary != i_locomotion, ("Bad movement rate setup. See a programmer"));
return kStationary;
}
// ----------------------------------------------------------------------
Locomotions::Enumerator MovementTable::getLocomotion(Postures::Enumerator i_posture, uint64 i_states, MovementTable::eLocomotionSpeed i_speed) const
{
//-- Validate posture arg.
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return Locomotions::Invalid;
//-- Lookup base rates for posture.
PostureMap::const_iterator f = m_postures->find(i_posture);
if (f == m_postures->end())
return Locomotions::Invalid;
const rates &rate = f->second;
//-- Adjust locomotion speed for the prevailing states.
eLocomotionSpeed speed = adjustSpeedForStates(i_speed, i_states);
//-- Return the appropriate rate based on locomotion speed.
Locomotions::Enumerator locomotion = Locomotions::Invalid;
switch (i_speed)
{
case kInvalid:
locomotion = Locomotions::Invalid;
break;
case kStationary:
locomotion = rate.stationary;
break;
case kSlow:
if (speed >= kSlow)
locomotion = rate.slow;
break;
case kFast:
if (speed >= kFast)
locomotion = rate.fast;
break;
}
return locomotion;
}
// ----------------------------------------------------------------------
void MovementTable::getAllLocomotions(Postures::Enumerator i_posture, uint64 i_states, Locomotions::Enumerator &fastLocomotion, Locomotions::Enumerator &slowLocomotion, Locomotions::Enumerator &stationaryLocomotion) const
{
//-- Initialize to invalid.
fastLocomotion = Locomotions::Invalid;
slowLocomotion = Locomotions::Invalid;
stationaryLocomotion = Locomotions::Invalid;
//-- Validate posture arg.
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return;
//-- Lookup base rates for posture.
PostureMap::const_iterator f = m_postures->find(i_posture);
if (f == m_postures->end())
return;
const rates &rate = f->second;
//-- Retrieve locomotion for each rate if that rate is supported.
if (adjustSpeedForStates(kFast, i_states) >= kFast)
fastLocomotion = rate.fast;
if (adjustSpeedForStates(kSlow, i_states) >= kSlow)
slowLocomotion = rate.slow;
stationaryLocomotion = rate.stationary;
}
// ----------------------------------------------------------------------
bool MovementTable::getRates(Postures::Enumerator i_posture, float &o_moveScale, float &o_accelScale, float &o_turnScale) const
{
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return false;
PostureMap::const_iterator f = m_postures->find(i_posture);
if (f == m_postures->end())
return false;
const rates &rate = f->second;
o_moveScale = rate.move;
o_turnScale = rate.turn;
o_accelScale = rate.accel;
return true;
}
// ----------------------------------------------------------------------
bool MovementTable::hasMovingLocomotion(Postures::Enumerator i_posture, uint64 i_states) const
{
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return false;
if (adjustSpeedForStates(kFast, i_states) == kStationary)
return false;
const rates &rate = m_postures->find(i_posture)->second;
return (rate.fast != Locomotions::Invalid) || (rate.slow != Locomotions::Invalid);
}
// ----------------------------------------------------------------------
float MovementTable::getSlowMoveRate(Postures::Enumerator i_posture, uint64 i_states) const
{
//-- Validate posture arg.
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return 0.0f;
//-- Check if state speed adjustment causes us to stop moving.
if (adjustSpeedForStates(kSlow, i_states) < kSlow)
return 0.0f;
//-- Lookup rate table for posture.
PostureMap::iterator findIt = m_postures->find(i_posture);
if (findIt == m_postures->end())
{
DEBUG_WARNING(true, ("MovementTable::getSlowMoveRate(): failed to find rate table entry for posture id=[%s],name=[%s], will return 0 rate.", i_posture, Postures::getPostureName(i_posture)));
return 0.0f;
}
const rates &rate = findIt->second;
//-- Start with the fast movement rate.
float const baseRate = (rate.slow != Locomotions::Invalid) ? rate.move : 0.0f;
//-- Retrieve state rate modifiers.
float const stateRateModifier = getMovementRateModifierForStates(i_states);
float const finalRate = baseRate * stateRateModifier;
return finalRate;
}
// ----------------------------------------------------------------------
float MovementTable::getFastMoveRate(Postures::Enumerator i_posture, uint64 i_states) const
{
//-- Validate posture arg.
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return 0.0f;
//-- Check if state speed adjustment causes us to stop moving.
if (adjustSpeedForStates(kFast, i_states) <= kSlow)
return 0.0f;
//-- Lookup rate table for posture.
PostureMap::iterator findIt = m_postures->find(i_posture);
if (findIt == m_postures->end())
{
DEBUG_WARNING(true, ("MovementTable::getFastMoveRate(): failed to find rate table entry for posture id=[%s],name=[%s], will return 0 rate.", i_posture, Postures::getPostureName(i_posture)));
return 0.0f;
}
const rates &rate = findIt->second;
//-- Start with the fast movement rate.
float const baseRate = (rate.fast != Locomotions::Invalid) ? rate.move : 0.0f;
//-- Retrieve state rate modifiers.
float const stateRateModifier = getMovementRateModifierForStates(i_states);
float const finalRate = baseRate * stateRateModifier;
return finalRate;
}
// ----------------------------------------------------------------------
void MovementTable::getAllMovementRateScales(Postures::Enumerator posture, uint64 states, float &slowMoveRateScale, float &fastMoveRateScale, float &accelerationScale, float &turnScale) const
{
//-- Lookup rate table for posture.
PostureMap::iterator findIt = m_postures->find(posture);
if (findIt == m_postures->end())
{
slowMoveRateScale = 0.0f;
fastMoveRateScale = 0.0f;
accelerationScale = 0.0f;
turnScale = 0.0f;
DEBUG_WARNING(true, ("MovementTable::getSlowAndFastMoveRates(): failed to find rate table entry for posture id=[%i],name=[%s], will return 0 rate.", posture, Postures::getPostureName(posture)));
return;
}
const rates &rate = findIt->second;
//-- Retrieve accel/turn rate modifiers.
accelerationScale = rate.accel;
turnScale = rate.turn;
//-- Apply posture's movement rate.
slowMoveRateScale = (rate.slow != Locomotions::Invalid) ? rate.move : 0.0f;
fastMoveRateScale = (rate.fast != Locomotions::Invalid) ? rate.move : 0.0f;
//-- Check if a state's max speed causes us to stop moving.
eLocomotionSpeed slowSpeed = kSlow;
eLocomotionSpeed fastSpeed = kFast;
adjustTwoSpeedsForStates(states, slowSpeed, fastSpeed);
slowMoveRateScale *= (slowSpeed >= kSlow) ? 1.0f : 0.0f;
fastMoveRateScale *= (fastSpeed >= kFast) ? 1.0f : 0.0f;
//-- Retrieve and apply state movement rate modifiers.
float const stateRateModifier = getMovementRateModifierForStates(states);
slowMoveRateScale *= stateRateModifier;
fastMoveRateScale *= stateRateModifier;
}
// ----------------------------------------------------------------------
float MovementTable::getCanSeeHeightMod(Postures::Enumerator i_posture, uint64 i_states) const
{
UNREF(i_states);
if (i_posture < 0 || i_posture >= Postures::NumberOfPostures)
return 1.0f;
const rates &rate = m_postures->find(i_posture)->second;
return rate.canSeeHeightMod;
}
// ----------------------------------------------------------------------
float MovementTable::getMovementRateModifierForStates(uint64 stateFlags) const
{
DEBUG_FATAL(!ms_installed, ("MovementTable not installed."));
//-- Start with base rate modifier of multiplicative identity.
float rateModifier = 1.0f;
if (stateFlags)
{
//-- Apply each state, one at a time.
for (States::Enumerator i = 0; i < States::NumberOfStates; ++i)
{
// Check if this state is present.
if (hasState(stateFlags, i))
{
// Check if we have an entry for this state.
StateFloatMap::iterator const findIt = s_stateMovementRateModifiers.find(i);
if (findIt != s_stateMovementRateModifiers.end())
{
// This state is present and we have a movement rate modifier for it. Apply the movement rate modifier.
rateModifier *= findIt->second;
}
}
}
}
return rateModifier;
}
// ======================================================================
// class MovementTable: PRIVATE
// ======================================================================
MovementTable::eLocomotionSpeed MovementTable::adjustSpeedForStates(eLocomotionSpeed i_speed, uint64 i_states) const
{
if (i_states)
for (States::Enumerator i = 0; i < States::NumberOfStates; ++i)
if (hasState(i_states, i) && ms_stateMoveLimit[i] < i_speed)
i_speed = ms_stateMoveLimit[i];
return i_speed;
}
// ----------------------------------------------------------------------
void MovementTable::adjustTwoSpeedsForStates(uint64 states, eLocomotionSpeed &speed1, eLocomotionSpeed &speed2) const
{
if (states)
{
for (States::Enumerator i = 0; i < States::NumberOfStates; ++i)
{
if (hasState(states, i))
{
eLocomotionSpeed const maxSpeed = ms_stateMoveLimit[i];
if (speed1 > maxSpeed)
speed1 = maxSpeed;
if (speed2 > maxSpeed)
speed2 = maxSpeed;
}
}
}
}
// ======================================================================
@@ -0,0 +1,87 @@
// ======================================================================
//
// MovementTable.h
// Copyright 2002-2003 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_MovementTable_H
#define INCLUDED_MovementTable_H
//===================================================================
#include "swgSharedUtility/Locomotions.def"
#include "swgSharedUtility/Postures.def"
#include "swgSharedUtility/States.def"
//===================================================================
class MovementTable
{
public:
enum eLocomotionSpeed
{
kInvalid = -1,
kStationary,
kSlow,
kFast
};
public:
static void install(const std::string &stateFileName);
public:
MovementTable (const std::string &fileName, const std::string &templateName); // templateName is used for error messages
virtual ~MovementTable ();
eLocomotionSpeed getLocomotionData(Locomotions::Enumerator locomotion, Postures::Enumerator &o_posture) const;
eLocomotionSpeed getPostureSpeed(Postures::Enumerator o_posture, Locomotions::Enumerator locomotion) const;
Locomotions::Enumerator getLocomotion(Postures::Enumerator i_posture, uint64 i_states, eLocomotionSpeed speed) const;
void getAllLocomotions(Postures::Enumerator i_posture, uint64 i_states, Locomotions::Enumerator &fastLocomotion, Locomotions::Enumerator &slowLocomotion, Locomotions::Enumerator &stationaryLocomotion) const;
bool getRates(Postures::Enumerator i_posture, float &moveScale, float &accelScale, float &turnScale) const;
bool hasMovingLocomotion(Postures::Enumerator i_posture, uint64 i_states) const;
float getSlowMoveRate(Postures::Enumerator i_posture, uint64 i_states) const;
float getFastMoveRate(Postures::Enumerator i_posture, uint64 i_states) const;
void getAllMovementRateScales(Postures::Enumerator posture, uint64 states, float &slowMoveRateScale, float &fastMoveRateScale, float &accelerationScale, float &turnScale) const;
float getCanSeeHeightMod(Postures::Enumerator i_posture, uint64 i_states) const;
float getMovementRateModifierForStates(uint64 stateFlags) const;
private:
struct rates;
typedef stdmap<Postures::Enumerator, rates>::fwd PostureMap;
private:
eLocomotionSpeed adjustSpeedForStates(eLocomotionSpeed i_speed, uint64 i_states) const;
void adjustTwoSpeedsForStates(uint64 states, eLocomotionSpeed &speed1, eLocomotionSpeed &speed2) const;
// Disabled.
MovementTable();
MovementTable(const MovementTable&);
MovementTable& operator=(const MovementTable&);
private:
static bool ms_installed;
static eLocomotionSpeed ms_stateMoveLimit[States::NumberOfStates];
private:
PostureMap* const m_postures;
Postures::Enumerator m_locomotionPostures[Locomotions::NumberOfLocomotions];
};
//===================================================================
#endif
@@ -0,0 +1,53 @@
// ======================================================================
//
// AlterResult.cpp
// Copyright 2002 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedObject/FirstSharedObject.h"
#include "sharedObject/AlterResult.h"
#include <algorithm>
#include <limits>
// ======================================================================
/*
Note these constants are organized so that an object can return the
minimum value of all of its subcomponents/children and basically do
the right thing. If any subcomponent wants to be altered next frame,
the min of alter return values will be cms_alterNextFrame. If
no subcomponents care to be altered but at least one still wants to
live and specifies cms_keepNoAlter, then the object will return
cms_keepNoAlter. Finally, if all subcomponents want to be killed,
the object will return cms_kill.
With the above in mind: DON'T CHANGE THESE VALUES (unless you think this
through and chek all the code that handles alter return values).
*/
float const AlterResult::cms_alterNextFrame = 0.0f;
float const AlterResult::cms_alterQuickly = 0.5f;
float const AlterResult::cms_keepNoAlter = 3.3e38f;
float const AlterResult::cms_kill = 3.4e38f;
// ======================================================================
void AlterResult::formatTime(char *buffer, int bufferLength, float time)
{
DEBUG_FATAL(bufferLength < 6, ("buffer length must be at least 5"));
if (time == cms_alterNextFrame)
strcpy(buffer, "next ");
else
if (time == cms_keepNoAlter)
strcpy(buffer, "none ");
else
if (time == cms_kill)
strcpy(buffer, "kill ");
else
snprintf(buffer, bufferLength, "%5.2f", time);
}
// ======================================================================

Some files were not shown because too many files have changed in this diff Show More