mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Removes the old component code and moves the IProcessInput interface file into platform/input/ directory.
This commit is contained in:
parent
7c7c799b57
commit
95ae0b9863
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 © )
|
||||
{
|
||||
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
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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_
|
||||
|
|
@ -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");
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue