⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tweaker.h

📁 游戏编程精华02-含有几十个游戏编程例子
💻 H
字号:
/* Copyright (C) Lasse Staff Jensen, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Lasse Staff Jensen, 2001"
 */
#ifndef EQX_TWEAKER_DEFINED
#define EQX_TWEAKER_DEFINED

/*!
  \file tweaker.h

  \brief Declaration of the eqx::Tweaker_c class which defines an interface 
   and functions to tweak a tweakable.

  \author Lasse.Staff.Jensen@funcom.com
*/

// disable "warning C4786: 'argument' : identifier was truncated to '255' 
// characters in the debug information"
#pragma warning( disable : 4786 )

// - Standar lib include -
#include <string>
#include <iterator>
#include <map>

// - Local includes -
#include "tweakable.h"

namespace eqx {

// I'm sorry this class is a mess, but Microsoft VS6.0 won't compile the
// template members without having the implementation directly in the header
// (and no, inlining won't work :-(((( ). Please use the docs!

//=============================================================================
//!       -== Tweaker_c class definision ==-
//----------------------------------------------------------------------------- 

class Tweaker_c {
public:
  
  // - Typedefs -
  typedef std::map<std::string, eqx::TweakableBase_c*> 
    TweakableMap_t;
  typedef TweakableMap_t::iterator
    iTweakableMap_t;
  typedef TweakableMap_t::const_iterator
    iConstTweakableMap_t;
  typedef std::pair<TweakableMap_t::iterator, bool> 
    iTweakableMap_pair_t;
  
  
  
  //! Ctor 
  Tweaker_c( const std::string& i_cName = std::string() ) { m_cName = i_cName; } 
  
  
  /*! Add a tweakable to the tweakable database.
      The given \a i_cTweakableID is an unique string to identify the given \a i_pxValue
      tweakable. <br>
      If \a i_bAddType is set to \c true then we will add type information for this tweakable. <br>
      If \a i_pfCallback is not \c null callback function will also be stored with the given
      \a i_pCallbackData data pointer.
  */
  template<class Value_x>
  void AddTweakable( Value_x* i_pxValue, std::string i_cTweakableID,
    bool i_bAddType = true, TweakableBase_c::Function_t* i_pfCallback = NULL,
    void* i_pCallbackData = NULL ) {
    iTweakableMap_pair_t cInsertResult;
	 
	  // 1. Insert the tweakable
    if( i_bAddType == true ) {
      if( i_pfCallback == NULL ) {
        cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableType_c<Value_x>( i_pxValue, TweakableBase_c::GetTypeID( *i_pxValue ) ) ) );
      } else {
         cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableCallbackType_c<Value_x>( i_pxValue, TweakableBase_c::GetTypeID( *i_pxValue ), 
            i_pfCallback, i_pCallbackData ) ) );
      }
    } else {
      if( i_pfCallback == NULL ) {
        cInsertResult = m_cTweakable_map.insert(
		      std::make_pair( i_cTweakableID, new Tweakable_c<Value_x>( i_pxValue ) ) );
      } else {
        cInsertResult = m_cTweakable_map.insert(
		      std::make_pair( i_cTweakableID, new TweakableCallback_c<Value_x>( i_pxValue, i_pfCallback, i_pCallbackData ) ) );
      }
    }

    // 2. Assert if not OK since we need it to work!
    assert( cInsertResult.second == true );
        
  } // AddTweakable


  /*! Add a tweakable to the tweakable database.
      This add method stores \a i_xMin and \a i_xMax values with the tweakable. These
      constraints are enforced by the TweakValue() method. <br>
      If \a i_bAddType is set to \c true then we will add type information for this tweakable. <br>
      If \a i_pfCallback is not \c null callback function will also be stored with the given \a
      i_pCallbackData data pointer.
  */
  template<class Value_x>
  void AddTweakable( Value_x* i_pxValue, const std::string& i_cTweakableID,
   const Value_x& i_xMin, const Value_x& i_xMax, bool i_bAddType = true, 
   TweakableBase_c::Function_t* i_pfCallback = NULL, void* i_pCallbackData = NULL ) {
        
    iTweakableMap_pair_t cInsertResult;
	    
    // 1. Insert the tweakable
    if( i_bAddType == true ) {
      if( i_pfCallback == NULL ) {
        cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableTypeRange_c<Value_x>( i_pxValue, i_xMin, i_xMax, TweakableBase_c::GetTypeID( *i_pxValue )  ) ) );
      } else {
        cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableCallbackTypeRange_c<Value_x>( i_pxValue, i_xMin, i_xMax, 
            TweakableBase_c::GetTypeID( *i_pxValue ), i_pfCallback, i_pCallbackData ) ) );
      }
    } else {
      if( i_pfCallback == NULL ) {
        cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableRange_c<Value_x>( i_pxValue, i_xMin, i_xMax ) ) );
      } else {
        cInsertResult = m_cTweakable_map.insert(
          std::make_pair( i_cTweakableID, 
          new TweakableCallbackRange_c<Value_x>( i_pxValue, i_xMin, i_xMax, i_pfCallback, i_pCallbackData ) ) );
      }
    }
	
    // 2. Assert if not OK since we need it to work!
    assert( cInsertResult.second == true );
        
  } // AddTweakable


  /*! Set the tweakable with the \a i_cID ID to the given \a i_xValue. 
      If \a i_bDoCallback = true then the callback function (if any) will be called.
      \return 
      \a e_UNKNOW_KEY   - Can't find any tweakable with the given \a i_cID <br>
      \a e_MIN_EXCEEDED - Given value less than minimum aloved <br>
      \a e_MAX_EXCEEDED - Given value larger than maximum aloved <br>
      \a e_OK           - Tweakable set equal to given value

      \note All IDs stored in the database are \b case \b sensetive!
  */
  template<class Value_x>
  TweakError_e TweakValue( const std::string& i_cID, const Value_x& i_xValue, bool i_bDoCallback = true ) {
    TweakableBase_c* pcTweakable;
	  iTweakableMap_t iSearchResult = m_cTweakable_map.find( i_cID );
    if( iSearchResult == m_cTweakable_map.end() ) { return e_UNKNOWN_KEY; }
	  pcTweakable = (*iSearchResult).second;

    // 1. Check the limits
    TweakError_e eError = pcTweakable->ConstrainValue( reinterpret_cast<const void* const>( &i_xValue ) );
    if( eError != e_OK ) { return eError; }
    // 2. Check the type
    assert( pcTweakable->TestType( TweakableBase_c::GetTypeID( i_xValue ) ) == true );
    // 3. Change the value 
    pcTweakable->ChangeValueAndDoCallback( reinterpret_cast<const void* const>( &i_xValue ), 
      this, i_cID, i_bDoCallback );

    return e_OK;
  } // TweakValue

  /*! Get the value of the tweakable with the given \a i_cID and store it at 
      the given \a o_pxValue location. 
      \return 
      \a e_UNKNOW_KEY  - Can't find any tweakable with the given \a i_cID <br>
      \a e_OK          - Value stored succesfully in \a o_pxValue 
  */
  template<class Value_x>
  TweakError_e GetValue( const std::string& i_cID, Value_x* o_pxValue ) const {
    TweakableBase_c* pcTweakable;
	  iTweakableMap_t iSearchResult = m_cTweakable_map.find( i_cID );
    if( iSearchResult == m_cTweakable_map.end() ) { return e_UNKNOWN_KEY; }
	  pcTweakable = (*iSearchResult).second;

    assert( pcTweakable->TestType( TweakableBase_c::GetTypeID( *o_pxValue ) ) == true );
  
    *o_pxValue = *(reinterpret_cast<Value_x*>( pcTweakable->m_pData ) );
    return e_OK;   
  } // GetValue

  /*! Get limits of the given tweakable and store them into \a o_pxMin and \a o_pxMax.
      \return
      \a e_UNKNOWN_KEY - Can't find any tweakable with the given \a i_cID <br> 
      \a e_NOT_STORED  - The tweakable doesn't have any limits defined <br>
      \a e_OK          - Value stored succesfully
  */
  template<class Value_x>
  TweakError_e GetLimits( const std::string& i_cID, Value_x* o_pxMin, Value_x* o_pxMax ) const {
    iTweakableMap_t iSearchResult = m_cTweakable_map.find( i_cID );
    if ( iSearchResult == m_cTweakable_map.end() ) { return e_UNKNOWN_KEY; }

    assert( iSearchResult->second->TestType( TweakableBase_c::GetTypeID( *o_pxMin ) ) == true );

    return iSearchResult->second->GetMinMax( o_pxMin, o_pxMax );
  }

  //! \return true if tweakable with the given name exists
  bool DoesTweakableExists( const std::string& i_cID ) const {
    return m_cTweakable_map.find( i_cID ) != m_cTweakable_map.end();
  }

  //! Get the name of this tweaker
  const std::string& GetName() const { return m_cName; };
  
  //! Get the number of tweakables stored in this tweaker
  unsigned int GetNoOfTweakables() const { return m_cTweakable_map.size(); }

  // Some function to ease the GUI implementation -> remove'em if you don't need it!
  const iConstTweakableMap_t begin() const { return m_cTweakable_map.begin(); }
  const iConstTweakableMap_t end() const { return m_cTweakable_map.end(); }
  const iConstTweakableMap_t find( const std::string& i_cName ) const { return m_cTweakable_map.find( i_cName ); }

private:
  //! Destructor - force user to use TweakerInstanceDB_c::DeleteInstances()
  virtual ~Tweaker_c();

  //! All the tweakables this tweaker controls
  TweakableMap_t  m_cTweakable_map;
  std::string     m_cName;

  friend class TweakerInstanceDB_c;
}; // Tweaker_c


}; // eqx 



#endif // EQX_TWEAKER_DEFINED

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -