Removes the old component code and moves the IProcessInput interface file into platform/input/ directory.

This commit is contained in:
Areloch 2016-05-12 23:31:15 -05:00
parent 7c7c799b57
commit 95ae0b9863
16 changed files with 2 additions and 1977 deletions

View file

@ -1,82 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "component/simComponent.h"
#include "component/componentInterface.h"
#include "core/strings/findMatch.h"
#include "core/stringTable.h"
bool ComponentInterfaceCache::add( const char *type, const char *name, const SimComponent *owner, ComponentInterface *cinterface )
{
if( ( mInterfaceList.size() == 0 ) || ( enumerate( NULL, type, name, owner ) == 0 ) )
{
mInterfaceList.increment();
// CodeReview [tom, 3/9/2007] Seems silly to keep calling last(), why not cache the var? Yes, I know I am pedantic.
mInterfaceList.last().type = ( type == NULL ? NULL : StringTable->insert( type ) );
mInterfaceList.last().name = ( name == NULL ? NULL : StringTable->insert( name ) );
mInterfaceList.last().owner = owner;
mInterfaceList.last().iface = cinterface;
return true;
}
return false;
}
//------------------------------------------------------------------------------
void ComponentInterfaceCache::clear()
{
mInterfaceList.clear();
}
//------------------------------------------------------------------------------
U32 ComponentInterfaceCache::enumerate( ComponentInterfaceList *list, const char *type /* = NULL */,
const char *name /* = NULL */, const SimComponent *owner /* = NULL */, bool notOwner /* = false */ ) const
{
U32 numMatches = 0;
for( _InterfaceEntryItr i = mInterfaceList.begin(); i != mInterfaceList.end(); i++ )
{
// Early out if limiting results by component owner
if( owner != NULL && (
( (*i).owner == owner && notOwner ) ||
( (*i).owner != owner && !notOwner ) ) )
continue;
// Match the type, short circuit if type == NULL
if( type == NULL || FindMatch::isMatch( type, (*i).type ) )
{
// Match the name
if( name == NULL || FindMatch::isMatch( name, (*i).name ) )
{
numMatches++;
if( list != NULL )
list->push_back( (*i).iface );
}
}
}
return numMatches;
}

View file

@ -1,234 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _COMPONENTINTERFACE_H_
#define _COMPONENTINTERFACE_H_
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _SIMOBJECT_H_
#include "console/simObject.h"
#endif
#include "core/util/safeDelete.h"
class SimComponent;
// CodeReview [patw, 2, 13, 2007] The issue I have not addressed in this class is
// interface locking. I think that we want to do this, for sure, but I also want
// to keep it as light-weight as possible. For the most part, there should only
// ever be one thing doing something with a component at one time, but I can see
// many situations where this wouldn't be the case. When we decide to address
// the issues of locking, I believe it should be done here, at the ComponentInterface
// level. I would like lock functionality to be as centralized as possible, and
// so this is the place for it. The functionality is critical for safe useage of
// the ComponentProperty class, so implementation here would also be ideal.
// CodeReview [patw, 2, 14, 2007] This really should be a ref-counted object
class ComponentInterface
{
friend class SimComponent;
private:
SimObjectPtr<SimComponent> mOwner; ///< SimComponent will directly modify this value
public:
/// Default constructor
ComponentInterface() : mOwner(NULL) {};
/// Destructor
virtual ~ComponentInterface()
{
mOwner = NULL;
}
/// This will return true if the interface is valid
virtual bool isValid() const
{
return mOwner != NULL;
}
/// Get the owner of this interface
SimComponent *getOwner() { return mOwner; }
const SimComponent *getOwner() const { return mOwner; }
};
typedef VectorPtr<ComponentInterface *> ComponentInterfaceList;
typedef VectorPtr<ComponentInterface *>::iterator ComponentInterfaceListIterator;
// These two asserts I found myself wanting a lot when doing interface methods
#ifdef TORQUE_ENABLE_ASSERTS
# define VALID_INTERFACE_ASSERT(OwningClassType) \
AssertFatal( isValid(), "Interface validity check failed." ); \
AssertFatal( dynamic_cast<const OwningClassType *>( getOwner() ) != NULL, avar( "Owner is not an instance of %s", #OwningClassType ) )
#else
# define VALID_INTERFACE_ASSERT(OwningClassType)
#endif
/// This class is designed to wrap an existing class or type easily to allow
/// a SimComponent to expose a property with custom processing code in an efficient
/// and safe way. Specialized templates could be written which include validation
/// on sets, and processing on gets.
///
/// This class has a lot of "blow your leg off" potential, if you have bad aim.
/// I think that a lot of very intuitive functionality can be gained from using
/// this properly, however when implementing a specialized template, be mindful
/// of what you are doing, and
// CodeReview [patw, 2, 13, 2007] I am very interested in making this as thin as
// possible. I really like the possibilities that it exposes as far as exposing
// "properties" to other components. I want it to be performant, however, so
// if anyone has notes on this, mark up the source, e-mail me, whatever.
template<class T>
class ComponentProperty : public ComponentInterface
{
typedef ComponentInterface Parent;
protected:
T *mValuePtr;
// ComponentInterface Overrides
public:
// Override this to add a check for valid memory.
virtual bool isValid() const
{
return ( mValuePtr != NULL ) && Parent::isValid();
}
// Operator overloads
public:
/// Dereferencing a value interface will allow get to do any processing and
/// return the reference to that
const T &operator*()
{
return get();
}
/// Assignment operator will invoke set.
const T &operator=( const T &lval )
{
return set( lval );
}
// Constructors/Destructors, specialize these if needed
public:
/// Default Constructor.
ComponentProperty() : mValuePtr( NULL )
{
mValuePtr = new T;
}
/// Copy constructor
ComponentProperty( const T &copy )
{
ComponentProperty();
// CodeReview [patw, 2, 13, 2007] So, the reasoning here is that I want to
// use the functionality that a specialized template implements in the set
// method. See the notes on the set method implementation.
set( copy );
}
/// Destructor, destroy memory
virtual ~ComponentProperty()
{
SAFE_DELETE( mValuePtr );
}
// This is the ComponentProperty interface that specializations of the class
// will be interested in.
public:
/// Get the value associated with this interface. Processing code can be done
/// here for specialized implementations.
virtual const T &get() // 'const' is intentionally not used as a modifier here
{
return *mValuePtr;
}
/// Set the value associated with this interface. Validation/processing code
/// can be done here. The copy-constructor uses the set method to do it's copy
/// so be mindful of that, or specialize the copy-constructor.
virtual const T &set( const T &t )
{
// CodeReview [patw, 2, 13, 2007] So I am using the = operator here. Do you
// guys think that this should be the default behavior? I am trying to keep
// everything as object friendly as possible, so I figured I'd use this.
*mValuePtr = t;
return *mValuePtr;
}
};
/// This class is just designed to isolate the functionality of querying for, and
/// managing interfaces.
class ComponentInterfaceCache
{
// CodeReview [patw, 2, 14, 2007] When we move this whole system to Juggernaught
// we may want to consider making safe pointers for ComponentInterfaces. Not
// sure why I put this note here.
private:
struct _InterfaceEntry
{
ComponentInterface *iface;
StringTableEntry type;
StringTableEntry name;
const SimComponent *owner;
};
Vector<_InterfaceEntry> mInterfaceList;
typedef Vector<_InterfaceEntry>::const_iterator _InterfaceEntryItr;
public:
/// Add an interface to the cache. This function will return true if the interface
/// is added successfully. An interface will not be added successfully if an entry
/// in the list with the same values for 'type' and 'name' is present in the list.
///
/// @param type Type of the interface being added. If NULL is passed, it will match any type string queried.
/// @param name Name of interface being added. If NULL is passed, it will match any name string queried.
/// @param owner The owner of the ComponentInterface being cached
/// @param cinterface The ComponentInterface being cached
virtual bool add( const char *type, const char *name, const SimComponent *owner, ComponentInterface *cinterface );
/// Clear the interface cache. This does not perform any operations on the contents
/// of the list.
virtual void clear();
/// Query the list for all of the interfaces it stores references to that match
/// the 'type' and 'name' parameters. The results of the query will be appended
/// to the list specified. Pattern matching is done using core/findMatch.h; for
/// more information on matching, see that code/header pair. Passing NULL for
/// one of these fields will match all values for that field. The return value
/// for the method will be the number of interfaces which match the query.
///
/// @param list The list that this method will append search results on to. It is possible to pass NULL here and just receive the return value.
/// @param type An expression which the 'type' field on an added object must match to be included in results
/// @param name An expression which the 'name' field on an added object must match to be included in results
/// @param owner Limit results to components owned/not-owned by this SimComponent (see next param)
/// @param notOwner If set to true, this will enumerate only interfaces NOT owned by 'owner'
virtual U32 enumerate( ComponentInterfaceList *list, const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false ) const;
};
#endif

View file

@ -1,209 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "component/dynamicConsoleMethodComponent.h"
#include "console/stringStack.h"
extern StringStack STR;
extern ConsoleValueStack CSTK;
IMPLEMENT_CO_NETOBJECT_V1(DynamicConsoleMethodComponent);
ConsoleDocClass( DynamicConsoleMethodComponent,
"@brief Console object used for calling methods defined in script, from within other classes.\n\n"
"Not intended for game development, for editors or internal use only.\n\n "
"@internal");
//-----------------------------------------------------------
// Function name: SimComponent::handlesConsoleMethod
// Summary:
//-----------------------------------------------------------
bool DynamicConsoleMethodComponent::handlesConsoleMethod( const char *fname, S32 *routingId )
{
// CodeReview: Host object is now given priority over components for method
// redirection. [6/23/2007 Pat]
// On this object?
if( isMethod( fname ) )
{
*routingId = -1; // -1 denotes method on object
#ifdef TORQUE_DEBUG
// Inject Method.
injectMethodCall( fname );
#endif
return true;
}
// on this objects components?
S32 nI = 0;
VectorPtr<SimComponent*> &componentList = lockComponentList();
for( SimComponentIterator nItr = componentList.begin(); nItr != componentList.end(); nItr++, nI++ )
{
SimObject *pComponent = dynamic_cast<SimObject*>(*nItr);
if( pComponent != NULL && pComponent->isMethod( fname ) )
{
*routingId = -2; // -2 denotes method on component
unlockComponentList();
#ifdef TORQUE_DEBUG
// Inject Method.
injectMethodCall( fname );
#endif
return true;
}
}
unlockComponentList();
return false;
}
const char *DynamicConsoleMethodComponent::callMethod( S32 argc, const char* methodName, ... )
{
const char *argv[128];
methodName = StringTable->insert( methodName );
argc++;
va_list args;
va_start(args, methodName);
for(S32 i = 0; i < argc; i++)
argv[i+2] = va_arg(args, const char *);
va_end(args);
// FIXME: the following seems a little excessive. I wonder why it's needed?
argv[0] = methodName;
argv[1] = methodName;
argv[2] = methodName;
StringStackConsoleWrapper argsw(argc, argv);
return callMethodArgList( argsw.count() , argsw );
}
#ifdef TORQUE_DEBUG
/// Inject Method Call.
void DynamicConsoleMethodComponent::injectMethodCall( const char* method )
{
// Get Call Method.
StringTableEntry callMethod = StringTable->insert( method );
// Find Call Method Metric.
callMethodMetricType::Iterator itr = mCallMethodMetrics.find( callMethod );
// Did we find the method?
if ( itr == mCallMethodMetrics.end() )
{
// No, so set the call count to initially be 1.
itr = mCallMethodMetrics.insert( callMethod, 1 );
}
else
{
// Increment Call Count.
itr->value++;
}
}
#endif
const char* DynamicConsoleMethodComponent::callMethodArgList( U32 argc, ConsoleValueRef argv[], bool callThis /* = true */ )
{
#ifdef TORQUE_DEBUG
injectMethodCall( argv[0] );
#endif
return _callMethod( argc, argv, callThis );
}
// Call all components that implement methodName giving them a chance to operate
// Components are called in reverse order of addition
const char *DynamicConsoleMethodComponent::_callMethod( U32 argc, ConsoleValueRef argv[], bool callThis /* = true */ )
{
// Set Owner
SimObject *pThis = dynamic_cast<SimObject *>( this );
AssertFatal( pThis, "DynamicConsoleMethodComponent::callMethod : this should always exist!" );
const char *cbName = StringTable->insert(argv[0]);
if( getComponentCount() > 0 )
{
lockComponentList();
for( S32 i = getComponentCount() - 1; i >= 0; i-- )
//for( SimComponentIterator nItr = componentList.end(); nItr != componentList.begin(); nItr-- )
{
argv[0] = cbName;
SimComponent *pComponent = dynamic_cast<SimComponent *>( getComponent( i ) );
AssertFatal( pComponent, "DynamicConsoleMethodComponent::callMethod - NULL component in list!" );
DynamicConsoleMethodComponent *pThisComponent = dynamic_cast<DynamicConsoleMethodComponent*>( pComponent );
AssertFatal( pThisComponent, "DynamicConsoleMethodComponent::callMethod - Non DynamicConsoleMethodComponent component attempting to callback!");
// Prevent stack corruption
STR.pushFrame();
CSTK.pushFrame();
// --
// Only call on first depth components
// Should isMethod check these calls? [11/22/2006 justind]
if(pComponent->isEnabled())
Con::execute( pThisComponent, argc, argv );
// Prevent stack corruption
STR.popFrame();
CSTK.popFrame();
// --
// Bail if this was the first element
//if( nItr == componentList.begin() )
// break;
}
unlockComponentList();
}
// Prevent stack corruption
STR.pushFrame();
CSTK.pushFrame();
// --
// Set Owner Field
const char* result = "";
if(callThis)
result = Con::execute( pThis, argc, argv, true ); // true - exec method onThisOnly, not on DCMCs
// Prevent stack corruption
STR.popFrame();
CSTK.popFrame();
// --
return result;
}
ConsoleMethod( DynamicConsoleMethodComponent, callMethod, void, 3, 64 , "(methodName, argi) Calls script defined method\n"
"@param methodName The method's name as a string\n"
"@param argi Any arguments to pass to the method\n"
"@return No return value"
"@note %obj.callMethod( %methodName, %arg1, %arg2, ... );\n")
{
object->callMethodArgList( argc - 1, argv + 2 );
}
//////////////////////////////////////////////////////////////////////////

View file

@ -1,89 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _DYNAMIC_CONSOLEMETHOD_COMPONENT_H_
#define _DYNAMIC_CONSOLEMETHOD_COMPONENT_H_
#ifndef _SIMCOMPONENT_H_
#include "component/simComponent.h"
#endif
#ifndef _CONSOLEINTERNAL_H_
#include "console/consoleInternal.h"
#endif
#ifndef _ICALLMETHOD_H_
#include "console/ICallMethod.h"
#endif
#ifdef TORQUE_DEBUG
#ifndef _TDICTIONARY_H_
#include "core/util/tDictionary.h"
#endif
#endif
//-----------------------------------------------------------------------------
class DynamicConsoleMethodComponent : public SimComponent, public ICallMethod
{
#ifdef TORQUE_DEBUG
public:
typedef Map<StringTableEntry, S32> callMethodMetricType;
#endif
private:
typedef SimComponent Parent;
#ifdef TORQUE_DEBUG
// Call Method Debug Stat.
callMethodMetricType mCallMethodMetrics;
#endif
protected:
/// Internal callMethod : Actually does component notification and script method execution
/// @attention This method does some magic to the argc argv to make Con::execute act properly
/// as such it's internal and should not be exposed or used except by this class
virtual const char* _callMethod( U32 argc, ConsoleValueRef argv[], bool callThis = true );
public:
#ifdef TORQUE_DEBUG
/// Call Method Metrics.
const callMethodMetricType& getCallMethodMetrics( void ) const { return mCallMethodMetrics; };
/// Inject Method Call.
void injectMethodCall( const char* method );
#endif
/// Call Method
virtual const char* callMethodArgList( U32 argc, ConsoleValueRef argv[], bool callThis = true );
/// Call Method format string
const char* callMethod( S32 argc, const char* methodName, ... );
// query for console method data
virtual bool handlesConsoleMethod(const char * fname, S32 * routingId);
DECLARE_CONOBJECT(DynamicConsoleMethodComponent);
};
#endif

View file

@ -1,60 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "component/moreAdvancedComponent.h"
// unitTest_runTests("Component/MoreAdvancedComponent");
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_CONOBJECT(MoreAdvancedComponent);
ConsoleDocClass( MoreAdvancedComponent,
"@brief This is a slightly more advanced component which will be used to demonstrate "
"components which are dependent on other components.\n\n"
"Not intended for game development, for editors or internal use only.\n\n "
"@internal");
bool MoreAdvancedComponent::onComponentRegister( SimComponent *owner )
{
if( !Parent::onComponentRegister( owner ) )
return false;
// This will return the first interface of type SimpleComponent that is cached
// on the parent object.
mSCInterface = owner->getInterface<SimpleComponentInterface>();
// If we can't find this interface, our component can't function, so false
// will be returned, and this will signify, to the top-level component, that it
// should fail the onAdd call.
return ( mSCInterface != NULL );
}
bool MoreAdvancedComponent::testDependentInterface()
{
// These two requirements must be met in order for the test to proceed, so
// lets check them.
if( mSCInterface == NULL || !mSCInterface->isValid() )
return false;
return mSCInterface->isFortyTwo( 42 );
}

View file

@ -1,55 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _MOREADVANCEDCOMPONENT_H_
#define _MOREADVANCEDCOMPONENT_H_
#ifndef _SIMPLECOMPONENT_H_
#include "component/simpleComponent.h"
#endif
/// This is a slightly more advanced component which will be used to demonstrate
/// components which are dependent on other components.
class MoreAdvancedComponent : public SimComponent
{
typedef SimComponent Parent;
protected:
// This component is going to be dependent on a SimpleComponentInterface being
// queried off of it's parent object. This will store that interface that
// will get queried during onComponentRegister()
SimpleComponentInterface *mSCInterface;
public:
DECLARE_CONOBJECT(MoreAdvancedComponent);
// Firstly, take a look at the documentation for this function in simComponent.h.
// We will be overloading this method to query the component heirarchy for our
// dependent interface, as noted above.
virtual bool onComponentRegister( SimComponent *owner );
// This function will try to execute a function through the interface that this
// component is dependent on.
virtual bool testDependentInterface();
};
#endif

View file

@ -1,452 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/simObject.h"
#include "console/consoleTypes.h"
#include "component/simComponent.h"
#include "core/stream/stream.h"
#include "console/engineAPI.h"
SimComponent::SimComponent() : mOwner( NULL )
{
mComponentList.clear();
mMutex = Mutex::createMutex();
mEnabled = true;
mTemplate = false;
}
SimComponent::~SimComponent()
{
Mutex::destroyMutex( mMutex );
mMutex = NULL;
}
IMPLEMENT_CO_NETOBJECT_V1(SimComponent);
ConsoleDocClass( SimComponent,
"@brief Legacy component system, soon to be deprecated.\n\n"
"Not intended for game development, for editors or internal use only.\n\n "
"@internal");
bool SimComponent::onAdd()
{
if( !Parent::onAdd() )
return false;
// Register
_registerInterfaces( this );
if( !_registerComponents( this ) )
return false;
//Con::executef( this, 1, "onAdd" );
return true;
}
void SimComponent::_registerInterfaces( SimComponent *owner )
{
// First call this to expose the interfaces that this component will cache
// before examining the list of subcomponents
registerInterfaces( owner );
// Early out to avoid mutex lock and such
if( !hasComponents() )
return;
VectorPtr<SimComponent *> &components = lockComponentList();
for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
{
(*i)->mOwner = owner;
// Tell the component itself to register it's interfaces
(*i)->registerInterfaces( owner );
(*i)->mOwner = NULL; // This tests to see if the object's onComponentRegister call will call up to the parent.
// Recurse
(*i)->_registerInterfaces( owner );
}
unlockComponentList();
}
bool SimComponent::_registerComponents( SimComponent *owner )
{
// This method will return true if the object contains no components. See the
// documentation for SimComponent::onComponentRegister for more information
// on this behavior.
bool ret = true;
// If this doesn't contain components, don't even lock the list.
if( hasComponents() )
{
VectorPtr<SimComponent *> &components = lockComponentList();
for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
{
if( !(*i)->onComponentRegister( owner ) )
{
ret = false;
break;
}
AssertFatal( (*i)->mOwner == owner, "Component failed to call parent onComponentRegister!" );
// Recurse
if( !(*i)->_registerComponents( owner ) )
{
ret = false;
break;
}
}
unlockComponentList();
}
return ret;
}
void SimComponent::_unregisterComponents()
{
if( !hasComponents() )
return;
VectorPtr<SimComponent *> &components = lockComponentList();
for( SimComponentIterator i = components.begin(); i != components.end(); i++ )
{
(*i)->onComponentUnRegister();
AssertFatal( (*i)->mOwner == NULL, "Component failed to call parent onUnRegister" );
// Recurse
(*i)->_unregisterComponents();
}
unlockComponentList();
}
void SimComponent::onRemove()
{
//Con::executef(this, 1, "onRemove");
_unregisterComponents();
// Delete all components
VectorPtr<SimComponent *>&componentList = lockComponentList();
while(componentList.size() > 0)
{
SimComponent *c = componentList[0];
componentList.erase( componentList.begin() );
if( c->isProperlyAdded() )
c->deleteObject();
else if( !c->isRemoved() && !c->isDeleted() )
delete c;
// else, something else is deleting this, don't mess with it
}
unlockComponentList();
Parent::onRemove();
}
//////////////////////////////////////////////////////////////////////////
bool SimComponent::processArguments(S32 argc, ConsoleValueRef *argv)
{
for(S32 i = 0; i < argc; i++)
{
SimComponent *obj = dynamic_cast<SimComponent*> (Sim::findObject(argv[i]) );
if(obj)
addComponent(obj);
else
Con::printf("SimComponent::processArguments - Invalid Component Object \"%s\"", (const char*)argv[i]);
}
return true;
}
//////////////////////////////////////////////////////////////////////////
void SimComponent::initPersistFields()
{
addGroup("Component");
addProtectedField( "Template", TypeBool, Offset(mTemplate, SimComponent),
&setIsTemplate, &defaultProtectedGetFn,
"Places the object in a component set for later use in new levels." );
endGroup("Component");
// Call Parent.
Parent::initPersistFields();
}
//------------------------------------------------------------------------------
bool SimComponent::getInterfaces( ComponentInterfaceList *list, const char *type /* = NULL */, const char *name /* = NULL */,
const SimComponent *owner /* = NULL */, bool notOwner /* = false */ )
{
AssertFatal( list != NULL, "Passing NULL for a list is not supported functionality for SimComponents." );
return ( mInterfaceCache.enumerate( list, type, name, owner, notOwner ) > 0 );
}
bool SimComponent::registerCachedInterface( const char *type, const char *name, SimComponent *interfaceOwner, ComponentInterface *cinterface )
{
if( mInterfaceCache.add( type, name, interfaceOwner, cinterface ) )
{
cinterface->mOwner = interfaceOwner;
// Recurse
if( mOwner != NULL )
return mOwner->registerCachedInterface( type, name, interfaceOwner, cinterface );
return true;
}
// So this is not a good assert, because it will get triggered due to the recursive
// nature of interface caching. I want to keep it here, though, just so nobody
// else thinks, "Oh I'll add an assert here."
//
//AssertFatal( false, avar( "registerCachedInterface failed, probably because interface with type '%s', name '%s' and owner with SimObjectId '%d' already exists",
// type, name, interfaceOwner->getId() ) );
return false;
}
//////////////////////////////////////////////////////////////////////////
// Component Management
//////////////////////////////////////////////////////////////////////////
bool SimComponent::addComponentFromField( void* obj, const char* data )
{
SimComponent *pComponent = dynamic_cast<SimComponent*>( Sim::findObject( data ) );
if( pComponent != NULL )
static_cast<SimComponent*>(obj)->addComponent( pComponent );
return false;
}
// Add Component to this one
bool SimComponent::addComponent( SimComponent *component )
{
AssertFatal( dynamic_cast<SimObject*>(component), "SimComponent - Cannot add non SimObject derived components!" );
MutexHandle mh;
if( mh.lock( mMutex, true ) )
{
for( SimComponentIterator nItr = mComponentList.begin(); nItr != mComponentList.end(); nItr++ )
{
SimComponent *pComponent = dynamic_cast<SimComponent*>(*nItr);
AssertFatal( pComponent, "SimComponent::addComponent - NULL component in list!" );
if( pComponent == component )
return true;
}
if(component->onComponentAdd(this))
{
component->mOwner = this;
mComponentList.push_back( component );
return true;
}
}
return false;
}
// Remove Component from this one
bool SimComponent::removeComponent( SimComponent *component )
{
MutexHandle mh;
if( mh.lock( mMutex, true ) )
{
for( SimComponentIterator nItr = mComponentList.begin(); nItr != mComponentList.end(); nItr++ )
{
SimComponent *pComponent = dynamic_cast<SimComponent*>(*nItr);
AssertFatal( pComponent, "SimComponent::removeComponent - NULL component in list!" );
if( pComponent == component )
{
AssertFatal( component->mOwner == this, "Somehow we contain a component who doesn't think we are it's owner." );
(*nItr)->onComponentRemove(this);
component->mOwner = NULL;
mComponentList.erase( nItr );
return true;
}
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool SimComponent::onComponentAdd(SimComponent *target)
{
Con::executef(this, "onComponentAdd", Con::getIntArg(target->getId()));
return true;
}
void SimComponent::onComponentRemove(SimComponent *target)
{
Con::executef(this, "onComponentRemove", Con::getIntArg(target->getId()));
}
//////////////////////////////////////////////////////////////////////////
ComponentInterface *SimComponent::getInterface(const char *type /* = NULL */, const char *name /* = NULL */,
const SimComponent *owner /* = NULL */, bool notOwner /* = false */)
{
ComponentInterfaceList iLst;
if( getInterfaces( &iLst, type, name, owner, notOwner ) )
return iLst[0];
return NULL;
}
//////////////////////////////////////////////////////////////////////////
bool SimComponent::writeField(StringTableEntry fieldname, const char* value)
{
if (!Parent::writeField(fieldname, value))
return false;
if( fieldname == StringTable->insert("owner") )
return false;
return true;
}
void SimComponent::write(Stream &stream, U32 tabStop, U32 flags /* = 0 */)
{
MutexHandle handle;
handle.lock(mMutex); // When this goes out of scope, it will unlock it
// export selected only?
if((flags & SelectedOnly) && !isSelected())
{
for(U32 i = 0; i < mComponentList.size(); i++)
mComponentList[i]->write(stream, tabStop, flags);
return;
}
stream.writeTabs(tabStop);
char buffer[1024];
dSprintf(buffer, sizeof(buffer), "new %s(%s) {\r\n", getClassName(), getName() ? getName() : "");
stream.write(dStrlen(buffer), buffer);
writeFields(stream, tabStop + 1);
if(mComponentList.size())
{
stream.write(2, "\r\n");
stream.writeTabs(tabStop+1);
stream.writeLine((U8 *)"// Note: This is a list of behaviors, not arbitrary SimObjects as in a SimGroup or SimSet.\r\n");
for(U32 i = 0; i < mComponentList.size(); i++)
mComponentList[i]->write(stream, tabStop + 1, flags);
}
stream.writeTabs(tabStop);
stream.write(4, "};\r\n");
}
//////////////////////////////////////////////////////////////////////////
// Console Methods
//////////////////////////////////////////////////////////////////////////
ConsoleMethod( SimComponent, addComponents, bool, 3, 64, "%obj.addComponents( %compObjName, %compObjName2, ... );\n"
"Adds additional components to current list.\n"
"@param Up to 62 component names\n"
"@return Returns true on success, false otherwise.")
{
for(S32 i = 2; i < argc; i++)
{
SimComponent *obj = dynamic_cast<SimComponent*> (Sim::findObject(argv[i]) );
if(obj)
object->addComponent(obj);
else
Con::printf("SimComponent::addComponents - Invalid Component Object \"%s\"", (const char*)argv[i]);
}
return true;
}
ConsoleMethod( SimComponent, removeComponents, bool, 3, 64, "%obj.removeComponents( %compObjName, %compObjName2, ... );\n"
"Removes components by name from current list.\n"
"@param objNamex Up to 62 component names\n"
"@return Returns true on success, false otherwise.")
{
for(S32 i = 2; i < argc; i++)
{
SimComponent *obj = dynamic_cast<SimComponent*> (Sim::findObject(argv[i]) );
if(obj)
object->removeComponent(obj);
else
Con::printf("SimComponent::removeComponents - Invalid Component Object \"%s\"", (const char*)argv[i]);
}
return true;
}
DefineConsoleMethod( SimComponent, getComponentCount, S32, (), , "() Get the current component count\n"
"@return The number of components in the list as an integer")
{
return object->getComponentCount();
}
DefineConsoleMethod( SimComponent, getComponent, S32, (S32 idx), , "(idx) Get the component corresponding to the given index.\n"
"@param idx An integer index value corresponding to the desired component.\n"
"@return The id of the component at the given index as an integer")
{
if(idx < 0 || idx >= object->getComponentCount())
{
Con::errorf("SimComponent::getComponent - Invalid index %d", idx);
return 0;
}
SimComponent *c = object->getComponent(idx);
return c ? c->getId() : 0;
}
DefineConsoleMethod(SimComponent, setEnabled, void, (bool enabled), , "(enabled) Sets or unsets the enabled flag\n"
"@param enabled Boolean value\n"
"@return No return value")
{
object->setEnabled(enabled);
}
DefineConsoleMethod(SimComponent, isEnabled, bool, (), , "() Check whether SimComponent is currently enabled\n"
"@return true if enabled and false if not")
{
return object->isEnabled();
}
DefineConsoleMethod(SimComponent, setIsTemplate, void, (bool templateFlag), , "(template) Sets or unsets the template flag\n"
"@param template Boolean value\n"
"@return No return value")
{
object->setIsTemplate(templateFlag);
}
DefineConsoleMethod(SimComponent, getIsTemplate, bool, (), , "() Check whether SimComponent is currently a template\n"
"@return true if is a template and false if not")
{
return object->getIsTemplate();
}

View file

@ -1,256 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _SIMCOMPONENT_H_
#define _SIMCOMPONENT_H_
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
#ifndef _STRINGTABLE_H_
#include "core/stringTable.h"
#endif
#ifndef _NETOBJECT_H_
#include "sim/netObject.h"
#endif
#ifndef _COMPONENTINTERFACE_H_
#include "component/componentInterface.h"
#endif
#ifndef _PLATFORM_THREADS_MUTEX_H_
#include "platform/threads/mutex.h"
#endif
#ifndef _STRINGFUNCTIONS_H_
#include "core/strings/stringFunctions.h"
#endif
// Forward refs
class Stream;
class ComponentInterface;
class ComponentInterfaceCache;
class SimComponent : public NetObject
{
typedef NetObject Parent;
private:
VectorPtr<SimComponent *> mComponentList; ///< The Component List
void *mMutex; ///< Component List Mutex
SimObjectPtr<SimComponent> mOwner; ///< The component which owns this one.
/// This is called internally to instruct the component to iterate over it's
// list of components and recursively call _registerInterfaces on their lists
// of components.
void _registerInterfaces( SimComponent *owner );
bool _registerComponents( SimComponent *owner );
void _unregisterComponents();
protected:
ComponentInterfaceCache mInterfaceCache; ///< Stores the interfaces exposed by this component.
bool mEnabled;
bool mTemplate;
// Non-const getOwner for derived classes
SimComponent *_getOwner() { return mOwner; }
/// Returns a const reference to private mComponentList
typedef VectorPtr<SimComponent *>::iterator SimComponentIterator;
VectorPtr<SimComponent *> &lockComponentList()
{
Mutex::lockMutex( mMutex );
return mComponentList;
};
void unlockComponentList()
{
Mutex::unlockMutex( mMutex );
}
/// onComponentRegister is called on each component by it's owner. If a component
/// has no owner, onComponentRegister will not be called on it. The purpose
/// of onComponentRegister is to allow a component to check for any external
/// interfaces, or other dependencies which it needs to function. If any component
/// in a component hierarchy returns false from it's onComponentRegister call
/// the entire hierarchy is invalid, and SimObject::onAdd will fail on the
/// top-level component. To put it another way, if a component contains other
/// components, it will be registered successfully with Sim iff each subcomponent
/// returns true from onComponentRegister. If a component does not contain
/// other components, it will not receive an onComponentRegister call.
///
/// Overloads of this method must pass the call along to their parent, as is
/// shown in the example below.
///
/// @code
/// bool FooComponent::onComponentRegister( SimComponent *owner )
/// {
/// if( !Parent::onComponentRegister( owner ) )
/// return false;
/// ...
/// }
/// @endcode
virtual bool onComponentRegister( SimComponent *owner )
{
mOwner = owner;
return true;
}
/// onUnregister is called when the owner is unregistering. Your object should
/// do cleanup here, as well as pass a call up the chain to the parent.
virtual void onComponentUnRegister()
{
mOwner = NULL;
}
/// registerInterfaces is called on each component as it's owner is registering
/// it's interfaces. This is called before onComponentRegister, and should be used to
/// register all interfaces exposed by your component, as well as all callbacks
/// needed by your component.
virtual void registerInterfaces( SimComponent *owner )
{
}
public:
DECLARE_CONOBJECT(SimComponent);
/// Constructor
/// Add this component
SimComponent();
/// Destructor
/// Remove this component and destroy child references
virtual ~SimComponent();
public:
virtual bool onAdd();
virtual void onRemove();
static void initPersistFields();
virtual bool processArguments(S32 argc, ConsoleValueRef *argv);
bool isEnabled() const { return mEnabled; }
void setEnabled( bool value ) { mEnabled = value; }
/// Will return true if this object contains components.
bool hasComponents() const { return ( mComponentList.size() > 0 ); };
/// The component which owns this object
const SimComponent *getOwner() const { return mOwner; };
// Component Information
inline virtual StringTableEntry getComponentName() { return StringTable->insert( getClassName() ); };
/// Protected 'Component' Field setter that will add a component to the list.
static bool addComponentFromField(void* obj, const char* data);
/// Add Component to this one
virtual bool addComponent( SimComponent *component );
/// Remove Component from this one
virtual bool removeComponent( SimComponent *component );
/// Clear Child components of this one
virtual bool clearComponents() { mComponentList.clear(); return true; };
virtual bool onComponentAdd(SimComponent *target);
virtual void onComponentRemove(SimComponent *target);
S32 getComponentCount() { return mComponentList.size(); }
SimComponent *getComponent(S32 idx) { return mComponentList[idx]; }
SimComponentIterator find(SimComponentIterator first, SimComponentIterator last, SimComponent *value)
{
return ::find(first, last, value);
}
static bool setIsTemplate( void *object, const char *index, const char *data )
{ static_cast<SimComponent*>(object)->setIsTemplate( dAtob( data ) ); return false; };
virtual void setIsTemplate( const bool pTemplate ) { mTemplate = pTemplate; }
bool getIsTemplate() const { return mTemplate; }
virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
virtual bool writeField(StringTableEntry fieldname, const char* value);
/// getInterfaces allows the caller to enumerate the interfaces exposed by
/// this component. This method can be overwritten to expose interfaces
/// which are not cached on the object, before passing the call to the Parent.
/// This can be used delay interface creation until it is queried for, instead
/// of creating it on initialization, and caching it. Returns false if no results
/// were found
///
/// @param list The list that this method will append search results on to.
/// @param type An expression which the 'type' field on an added object must match to be included in results
/// @param name An expression which the 'name' field on an added object must match to be included in results
/// @param owner Limit results to components owned/not-owned by this SimComponent (see next param)
/// @param notOwner If set to true, this will enumerate only interfaces NOT owned by 'owner'
virtual bool getInterfaces( ComponentInterfaceList *list, const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false ); // const omission intentional
/// These two methods allow for easy query of component interfaces if you know
/// exactly what you are looking for, and don't mind being passed back the first
/// matching result.
ComponentInterface *getInterface( const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false );
template <class T>
T *getInterface( const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false );
/// Add an interface to the cache. This function will return true if the interface
/// is added successfully. An interface will not be added successfully if an entry
/// in this components cache with the same values for 'type' and 'name' is present.
///
/// @param type Type of the interface being added. If NULL is passed, it will match any type string queried.
/// @param name Name of interface being added. If NULL is passed, it will match any name string queried.
/// @param interfaceOwner The component which owns the interface being cached
/// @param cinterface The ComponentInterface being cached
bool registerCachedInterface( const char *type, const char *name, SimComponent *interfaceOwner, ComponentInterface *cinterface );
};
//////////////////////////////////////////////////////////////////////////
template <class T>
T *SimComponent::getInterface( const char *type /* = NULL */, const char *name /* = NULL */,
const SimComponent *owner /* = NULL */, bool notOwner /* = false */ )
{
ComponentInterfaceList iLst;
if( getInterfaces( &iLst, type, name, owner, notOwner ) )
{
ComponentInterfaceListIterator itr = iLst.begin();
while( dynamic_cast<T *>( *itr ) == NULL )
itr++;
if( itr != iLst.end() )
return static_cast<T *>( *itr );
}
return NULL;
}
#endif // _SIMCOMPONENT_H_

View file

@ -1,31 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "component/simpleComponent.h"
IMPLEMENT_CONOBJECT(SimpleComponent);
ConsoleDocClass( SimpleComponent,
"@brief The purpose of this component is to provide a minimalistic component that "
"exposes a simple, cached interface\n\n"
"Soon to be deprecated, internal only.\n\n "
"@internal");

View file

@ -1,159 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _SIMPLECOMPONENT_H_
#define _SIMPLECOMPONENT_H_
#ifndef _SIMCOMPONENT_H_
#include "component/simComponent.h"
#endif
#ifndef _COMPONENTINTERFACE_H_
#include "component/componentInterface.h"
#endif
/// This is a very simple interface. Interfaces provide ways for components to
/// interact with each-other, and query each-other for functionality. It makes it
/// possible for two components to be interdependent on one another, as well. An
/// interface should make accessor calls to it's owner for functionality, and
/// generally be as thin of a layer as possible.
class SimpleComponentInterface : public ComponentInterface
{
public:
bool isFortyTwo( const U32 test );
};
//////////////////////////////////////////////////////////////////////////
/// The purpose of this component is to provide a minimalistic component that
/// exposes a simple, cached interface
class SimpleComponent : public SimComponent
{
typedef SimComponent Parent;
protected:
SimpleComponentInterface mSCInterface;
public:
// Components are still SimObjects, and need to be declared and implemented
// with the standard macros
DECLARE_CONOBJECT(SimpleComponent);
//////////////////////////////////////////////////////////////////////////
// SimComponent overloads.
// This method is called on each component as it's parent is getting onAdd
// called. The purpose of overloading this method is to expose cached interfaces
// before onComponentRegister is called, so that other components can depend on the
// interfaces you expose in order to register properly. This functionality
// will be demonstrated in a more advanced example.
virtual void registerInterfaces( SimComponent *owner )
{
// While it is not imperative that we pass this call to the Parent in this
// example, if there existed a class-heirarchy of components, it would be
// critical, so for good practice, call up to the Parent.
Parent::registerInterfaces( owner );
// Now we should go ahead and register our cached interface. What we are doing
// is telling the component which contains this component (if it exists)
// all of the interfaces that we expose. When this call is made, it will
// recurse up the owner list.
//
// For example, there exists components A, B, and C.
// A owns B, and B owns C.
//
// If C exposes a cached interface, it will expose it via registerCachedInterface
// when registerInterfaces is recursively called. It will add it's interface to
// it's cache list, and then pass the register call up to it's parent. The parent
// will also cache the interface, and continue to pass the cache call up the
// child->parent chain until there exists no parent.
//
// The result is that, if C exposes an interface 'foo', and A owns B, and
// B owns C, an interface request for 'foo' given to component A will result
// in 'foo' being returned, even though A does not expose 'foo'. This makes
// it possible for a component to query it's owner for an interface, and
// not care where that interface is exposed. It also allows for game code
// to work with any SimComponent and query that component for any interface
// it wants without knowing or caring exactly where it is coming from.
//
// registerCachedInterface returns a boolean value if it was successful.
// Success results in the caching of this interface throughout the full
// child->parent chain. An interface will be added to a cache list
// successfully iff there exists no entry in that list that has matching
// values for 'type', 'name' and 'owner'.
owner->registerCachedInterface(
// The first parameter is the 'type' of the interface, this is not to be
// confused with any kind of existing console, or c++ type. It is simply
// a string which is can be set to any value
"example",
// The next parameter is the 'name' of the interface. This is also a string
// which can be set to any value
"isfortytwo",
// The owner of the interface. Note that the value being assigned here
// is this instance of SimpleComponent, and not the 'owner' argument
// of the function registerInterfaces that we are calling from.
this,
// And finally the interface; a pointer to an object with type ComponentInterface
&mSCInterface );
}
//////////////////////////////////////////////////////////////////////////
// Specific functionality
/// This is the test method, it will return true if the number provided
/// is forty two
bool isFortyTwo( const U32 test ) const
{
return ( test == 42 );
}
};
//////////////////////////////////////////////////////////////////////////
// Interface implementation
//
// Since interfaces themselves implement very little functionality, it is a good
// idea to inline them if at all possible. Interdependent components will be using
// these interfaces constantly, and so putting as thin of a layer between the
// functionality they expose, and the functionality the component implements is
// a good design practice.
inline bool SimpleComponentInterface::isFortyTwo( const U32 test )
{
// This code block will test for a valid owner in a debug build before
// performing operations on it's owner. It is worth noting that the
// ComponentInterface::isValid() method can be overridden to include
// validation specific to your interface and/or component.
AssertFatal( isValid(), "SimpleComponentInterface has not been registered properly by the component which exposes it." );
// This is a sanity check. The owner of this interface should have the type
// SimpleComponent, otherwise this won't work. (See further interface examples
// for some ways around this)
AssertFatal( dynamic_cast<SimpleComponent *>( getOwner() ) != NULL, "Owner of SimpleComponentInterface is not a SimpleComponent" );
// Component interfaces rely on being registered to set their mOwner
// field. This field is initialized to NULL, and then gets set by
// SimComponent when the interface is registered.
return static_cast<const SimpleComponent *>( getOwner() )->isFortyTwo( test );
}
#endif

View file

@ -1,68 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "component/moreAdvancedComponent.h"
TEST(MoreAdvancedComponent, MoreAdvancedComponent)
{
// Create component instances and compose them.
SimComponent *parentComponent = new SimComponent();
SimpleComponent *simpleComponent = new SimpleComponent();
MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent();
// CodeReview note that the interface pointer isn't initialized in a ctor
// on the components, so it's bad memory against which you might
// be checking in testDependentInterface [3/3/2007 justind]
parentComponent->addComponent( simpleComponent );
parentComponent->addComponent( moreAdvComponent );
simpleComponent->registerObject();
moreAdvComponent->registerObject();
// Put a break-point here, follow the onAdd call, and observe the order in
// which the SimComponent::onAdd function executes. You will see the interfaces
// get cached, and the dependent interface query being made.
parentComponent->registerObject();
// If the MoreAdvancedComponent found an interface, than the parentComponent
// should have returned true, from onAdd, and should therefore be registered
// properly with the Sim
EXPECT_TRUE( parentComponent->isProperlyAdded() )
<< "Parent component not properly added!";
// Now lets test the interface. You can step through this, as well.
EXPECT_TRUE( moreAdvComponent->testDependentInterface() )
<< "Dependent interface test failed.";
// CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind]
//
// Clean up
parentComponent->removeComponent( simpleComponent );
parentComponent->removeComponent( moreAdvComponent );
parentComponent->deleteObject();
moreAdvComponent->deleteObject();
simpleComponent->deleteObject();
};
#endif

View file

@ -1,149 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "component/simComponent.h"
class CachedInterfaceExampleComponent : public SimComponent
{
typedef SimComponent Parent;
ComponentProperty<U32> mMyId;
static U32 smNumInstances;
ComponentProperty<U32> *mpU32; // CodeReview [patw, 2, 17, 2007] Make ref objects when this is in Jugg
public:
DECLARE_CONOBJECT( CachedInterfaceExampleComponent );
CachedInterfaceExampleComponent() : mpU32( NULL )
{
mMyId = ( ( 1 << 24 ) | smNumInstances++ );
}
virtual ~CachedInterfaceExampleComponent()
{
smNumInstances--;
}
public:
//////////////////////////////////////////////////////////////////////////
virtual void registerInterfaces( SimComponent *owner )
{
// Register a cached interface for this
owner->registerCachedInterface( NULL, "aU32", this, &mMyId );
}
//////////////////////////////////////////////////////////////////////////
bool onComponentRegister( SimComponent *owner )
{
// Call up to the parent first
if( !Parent::onComponentRegister( owner ) )
return false;
// We want to get an interface from another object in our containing component
// to simulate component interdependency.
ComponentInterfaceList list;
// Enumerate the interfaces on the owner, only ignore interfaces that this object owns
if( !owner->getInterfaces( &list, NULL, "aU32", this, true ) )
return false;
// Sanity check before just assigning all willy-nilly
for( ComponentInterfaceListIterator i = list.begin(); i != list.end(); i++ )
{
mpU32 = dynamic_cast<ComponentProperty<U32> *>( (*i) );
if( mpU32 != NULL )
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
// CodeReview [patw, 2, 17, 2007] I'm going to make another lightweight interface
// for this functionality later
void unit_test()
{
EXPECT_TRUE( mpU32 != NULL )
<< "Pointer to dependent interface is NULL";
if( mpU32 )
{
EXPECT_TRUE( *(*mpU32) & ( 1 << 24 ) )
<< "Pointer to interface data is bogus.";
EXPECT_TRUE( *(*mpU32) != *mMyId )
<< "Two of me have the same ID, bad!";
}
}
};
IMPLEMENT_CONOBJECT( CachedInterfaceExampleComponent );
U32 CachedInterfaceExampleComponent::smNumInstances = 0;
ConsoleDocClass( CachedInterfaceExampleComponent,
"@brief Legacy from older component system.\n\n"
"Not intended for game development, for editors or internal use only.\n\n "
"@internal");
TEST(SimComponent, Composition)
{
SimComponent *testComponent = new SimComponent();
CachedInterfaceExampleComponent *componentA = new CachedInterfaceExampleComponent();
CachedInterfaceExampleComponent *componentB = new CachedInterfaceExampleComponent();
// Register sub-components
EXPECT_TRUE( componentA->registerObject() )
<< "Failed to register componentA";
EXPECT_TRUE( componentB->registerObject() )
<< "Failed to register componentB";
// Add the components
EXPECT_TRUE( testComponent->addComponent( componentA ) )
<< "Failed to add component a to testComponent";
EXPECT_TRUE( testComponent->addComponent( componentB ) )
<< "Failed to add component b to testComponent";
EXPECT_EQ( componentA->getOwner(), testComponent )
<< "testComponent did not properly set the mOwner field of componentA to NULL.";
EXPECT_EQ( componentB->getOwner(), testComponent )
<< "testComponent did not properly set the mOwner field of componentB to NULL.";
// Register the object with the simulation, kicking off the interface registration
ASSERT_TRUE( testComponent->registerObject() )
<< "Failed to register testComponent";
{
SCOPED_TRACE("componentA");
componentA->unit_test();
}
{
SCOPED_TRACE("componentB");
componentB->unit_test();
}
testComponent->deleteObject();
};
#endif

View file

@ -1,131 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifdef TORQUE_TESTS_ENABLED
#include "testing/unitTesting.h"
#include "component/simpleComponent.h"
TEST(SimpleComponent, SimpleComponent)
{
// When instantiating, and working with a SimObject in C++ code, such as
// a unit test, you *may not* allocate a SimObject off of the stack.
//
// For example:
// SimpleComponent sc;
// is a stack allocation. This memory is allocated off of the program stack
// when the function is called. SimObject deletion is done via SimObject::deleteObject()
// and the last command of this method is 'delete this;' That command will
// cause an assert if it is called on stack-allocated memory. Therefor, when
// instantiating SimObjects in C++ code, it is imperitive that you keep in
// mind that if any script calls 'delete()' on that SimObject, or any other
// C++ code calls 'deleteObject()' on that SimObject, it will crash.
SimpleComponent *sc = new SimpleComponent();
// SimObject::registerObject must be called on a SimObject before it is
// fully 'hooked in' to the engine.
//
// Tracing execution of this function will let you see onAdd get called on
// the component, and you will see it cache the interface we exposed.
sc->registerObject();
// It is *not* required that a component always be owned by a component (obviously)
// however I am using an owner so that you can trace execution of recursive
// calls to cache interfaces and such.
SimComponent *testOwner = new SimComponent();
// Add the test component to it's owner. This will set the 'mOwner' field
// of 'sc' to the address of 'testOwner'
testOwner->addComponent( sc );
// If you step-into this registerObject the same way as the previous one,
// you will be able to see the recursive caching of the exposed interface.
testOwner->registerObject();
// Now to prove that object composition is working properly, lets ask
// both of these components for their interface lists...
// The ComponentInterfaceList is a typedef for type 'VectorPtr<ComponentInterface *>'
// and it will be used by getInterfaces() to store the results of the interface
// query. This is the "complete" way to obtain an interface, and it is too
// heavy-weight for most cases. A simplified query will be performed next,
// to demonstrate the usage of both.
ComponentInterfaceList iLst;
// This query requests all interfaces, on all components, regardless of name
// or owner.
sc->getInterfaces( &iLst,
// This is the type field. I am passing NULL here to signify that the query
// should match all values of 'type' in the list.
NULL,
// The name field, let's pass NULL again just so when you trace execution
// you can see how queries work in the simple case, first.
NULL );
// Lets process the list that we've gotten back, and find the interface that
// we want.
SimpleComponentInterface *scQueriedInterface = NULL;
for( ComponentInterfaceListIterator i = iLst.begin(); i != iLst.end(); i++ )
{
scQueriedInterface = dynamic_cast<SimpleComponentInterface *>( *i );
if( scQueriedInterface != NULL )
break;
}
AssertFatal( scQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
// Lets do it again, only we will execute the query on the parent instead,
// in a simplified way. Remember the parent component doesn't expose any
// interfaces at all, so the success of this behavior is entirely dependent
// on the recursive registration that occurs in registerInterfaces()
SimpleComponentInterface *ownerQueriedInterface = testOwner->getInterface<SimpleComponentInterface>();
AssertFatal( ownerQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
// We should now have two pointers to the same interface obtained by querying
// different components.
EXPECT_EQ( ownerQueriedInterface, scQueriedInterface )
<< "This really shouldn't be possible to fail given the setup of the test";
// Lets call the method that was exposed on the component via the interface.
// Trace the execution of this function, if you wish.
EXPECT_TRUE( ownerQueriedInterface->isFortyTwo( 42 ) )
<< "Don't panic, but it's a bad day in the component system.";
EXPECT_TRUE( scQueriedInterface->isFortyTwo( 42 ) )
<< "Don't panic, but it's a bad day in the component system.";
// So there you have it. Writing a simple component that exposes a cached
// interface, and testing it. It's time to clean up.
testOwner->removeComponent( sc );
sc->deleteObject();
testOwner->deleteObject();
// Interfaces do not need to be freed. In Juggernaught, these will be ref-counted
// for more robust behavior. Right now, however, the values of our two interface
// pointers, scQueriedInterface and ownerQueriedInterface, reference invalid
// memory.
};
#endif

View file

@ -37,7 +37,7 @@
#include "core/util/tSignal.h"
#endif
#include "component/interfaces/IProcessInput.h"
#include "platform/input/IProcessInput.h"
#include "windowManager/platformWindowMgr.h"
#include "gfx/gfxFence.h"

View file

@ -23,7 +23,7 @@
#include "windowManager/windowInputGenerator.h"
#include "windowManager/platformWindow.h"
#include "sim/actionMap.h"
#include "component/interfaces/IProcessInput.h"
#include "platform/input/IProcessInput.h"
extern InputModifiers convertModifierBits(const U32 in);