123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- //-----------------------------------------------------------------------------
- // 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
|