Files
2026-06-01 12:46:52 +02:00

1552 lines
41 KiB
C++

#pragma once
#include <toolkit/XStringUtil.h>
//#include "KUIControl.h"
#include "KUIControlScroll.h"
#include "KUIControlGauge.h"
#include <queue>
//#include <vector>
#include "enc.h"
#include "ItemBase.h"
#include <mmo/ArType.h>
class SUIDisplayInfo;
class SUIWnd; // sonador #2.1.2.4.3 팻 조작 UI 연동
// 2010.05.11 - prodongi
class SCreatureInfo;
// 2010.06.09 - prodongi
class SInventorySlot;
// 2010.07.20 - prodongi
class KUIControlMultiIcon;
class SGameAvatarEx;
class SUIDisplayInfo;
class SSkillSlotMgr;
class SCreatureSlotMgr;
class SGameManager;
namespace sui {
namespace helper {
/// convert numeric to comma numeric...
std::string int_to_comma_numeric( __int64 number );
/// convert comma numeric to numeric...
__int64 comma_numeric_to_int( const char* number );
/// convert string to indexed string( 'abc_%d' -> 'abc_01' )
std::string indexed_id( const char* format, int index );
}
///< sequence container wiper
template< class _Ct >
inline void wipe_seq( _Ct& container )
{
typedef typename _Ct::iterator iterator;
iterator end = container.end();
for( iterator itor = container.begin(); itor != end; ++itor )
if( *itor ) delete *itor;
container.clear();
}
template< class _Ct, class _Ty >
inline void remove_seq( _Ct& container, const _Ty& value )
{
container.erase( std::remove( container.begin(), container.end(), value ), container.end() );
}
template< typename T >
struct type2type
{
typedef T type_value;
};
// sonador 7.0.25 proxy_list 정렬 타입 불일치 문제 수정
template< int T >
struct int2type
{
enum { value = T };
};
/// tree control proxy
template< class _Elem >
class proxy_tree
{
public:
typedef _Elem element_t;
struct node
{
typedef std::vector< node* > nodes_t;
node() : m_parent( 0 ), m_right( 0 ), m_depth( 0 ), m_folded_state( true )
{
}
node( const element_t& _element ) : m_element( _element ), m_parent( 0 ), m_right( 0 ), m_depth( 0 ), m_folded_state( true )
{
}
~node()
{
wipe_seq( m_children );
}
node* add( node* item )
{
if( item )
{
// setup right hand side...
if( !m_children.empty() )
{
nodes_t::reverse_iterator ri = m_children.rbegin();
assert( (*ri)->m_right == 0 );
(*ri)->m_right = item;
}
m_children.push_back( item );
item->m_parent = this;
item->on_add();
//item->m_depth = m_depth + 1;
}
return this;
}
int depth() const
{
return m_depth;
}
int size_children() const
{
return m_children.size();
}
bool empty() const
{
return m_children.empty();
}
int size() const
{
struct nodeCounter {
nodeCounter() : result( 1 ) {} // it's me =)
void operator()( const node* item ) { result += item->size(); }
int result;
};
return std::for_each( m_children.begin(), m_children.end(), nodeCounter() ).result;
}
int size_visible() const
{
struct VisibleNodeCounter {
VisibleNodeCounter() : result( 1 ) {} // it's me =)
void operator()( const node* item ) {
result += ( item->folded() ) ? 1 : item->size_visible();
}
int result;
};
return std::for_each( m_children.begin(), m_children.end(), VisibleNodeCounter() ).result;
}
void fold()
{
m_folded_state = true;
}
void unfold()
{
m_folded_state = false;
}
void toggle()
{
m_folded_state = !m_folded_state;
}
bool folded() const
{
return m_folded_state;
}
node* find( const element_t& element )
{
if( m_element == element ) return this;
if( !m_children.empty() )
{
nodes_t::iterator _i = m_children.begin(), _e = m_children.end();
for( ; _i != _e; ++_i )
{
node* _node = (*_i)->find( element );
if( _node ) return _node;
}
}
return 0;
}
const element_t& get_element() const
{
return m_element;
}
element_t& get_element()
{
return m_element;
}
typename nodes_t::iterator begin()
{
return m_children.begin();
}
typename nodes_t::iterator end()
{
return m_children.end();
}
node* next()
{
if( !m_children.empty() )
return *m_children.begin();
return next_without_children();
}
node* next_visible()
{
node* it = next();
while( it )
{
if( it->is_visible() )
return it;
it = it->next();
}
return 0;
}
node* next_visible_index( int index )
{
int loop = 0;
node* it = next_visible();
while( it )
{
if( index <= loop++ )
break;
it = it->next_visible();
}
return it;
}
private:
void on_add()
{
m_depth = m_parent->depth() + 1;
nodes_t::iterator i = m_children.begin(), e = m_children.end();
for( ; i != e; ++i )
{
(*i)->on_add();
}
}
bool is_visible() const { return m_parent ? !m_parent->folded() : false; }
node* next_without_children()
{
if( m_right )
return m_right;
if( m_parent )
return m_parent->next_without_children();
return 0;
}
element_t m_element;
int m_depth;
node* m_parent;
node* m_right;
nodes_t m_children;
bool m_folded_state;
};
proxy_tree() : m_root( 0 ), m_selected( 0 )
{
m_root = new node();
m_root->unfold();
}
~proxy_tree()
{
SAFE_DELETE( m_root );
}
node* root() { return m_root; }
const node* root() const { return m_root; }
node* operator->() { return m_root; }
const node* operator->() const { return m_root; }
node& operator*() { return *m_root; }
const node& operator*() const { return *m_root; }
private:
node* m_root;
node* m_selected;
};
class property
{
public:
enum CLASSID {
CID_NONE,
CID_BOOLEAN,
CID_CHAR,
CID_UCHAR,
CID_WORD,
CID_DWORD,
CID_INT,
CID_UINT,
CID_INT64,
CID_FLOAT,
CID_POINTER,
CID_RESOURCE,
CID_STRING,
};
struct finder
{
finder( const char* name ) : name_for_search( name ) {}
bool operator () ( const property* arg )
{
return ( ::stricmp( name_for_search, arg->get_name() ) == 0 ) ? true : false;
}
const char* name_for_search;
};
struct AbstractResource
{
virtual ~AbstractResource() {}
virtual void* get_resource() = 0;
virtual AbstractResource* clone() = 0;
};
/** 프로퍼티에 리소스를 등록하기 위한 클래스( 리소스는 값으로 취급할 수 없다... )
리소스로 등록되는 클래스는 반드시 복사 생성자를 정의하고 있어야 합니다. */
template< typename T >
struct Resource : public AbstractResource
{
Resource( T* resource ) : AbstractResource(), m_resource( new T( *resource ) )
{
}
virtual ~Resource()
{
SAFE_DELETE( m_resource );
}
virtual AbstractResource* clone()
{
return new Resource< T >( m_resource );
}
virtual void* get_resource()
{
return reinterpret_cast< void* >( m_resource );
}
T* m_resource;
};
property() : m_name( 0 ), m_class( CID_NONE )
{
m_value.int_value = 0;
}
property( const char* name ) : m_name( name ), m_class( CID_NONE )
{
m_value.int_value = 0;
}
property( const property& rhs ) : m_name( rhs.m_name ), m_class( CID_NONE )
{
m_value.int_value = 0;
copy( rhs );
}
virtual ~property()
{
wipe();
}
property& operator = ( const property& rhs )
{
copy( rhs );
return *this;
}
bool operator == ( const property& rhs ) const
{
return !::strcmp( m_name, rhs.get_name() );
}
bool is_valid() const
{
return ( m_name == 0 || m_class == CID_NONE ) ? false : true;
}
virtual void copy( const property& other )
{
wipe();
m_name = other.m_name;
if( other.m_class == CID_STRING )
{
char* buffer;
other.get_value( buffer );
set_value( buffer );
}
else if( other.m_class == CID_RESOURCE )
{
m_class = other.m_class;
AbstractResource* otherAbsResource = reinterpret_cast< AbstractResource* >( other.m_value.pointer_value );
if( otherAbsResource )
{
AbstractResource* myAbsResource = otherAbsResource->clone();
m_value.pointer_value = reinterpret_cast< void* >( myAbsResource );
}
}
else
{
m_class = other.m_class;
m_value = other.m_value;
}
}
void wipe()
{
if( m_class == CID_STRING )
{
char* buffer = reinterpret_cast< char* >( m_value.pointer_value );
SAFE_DELETE_ARRAY( buffer );
m_value.pointer_value = 0;
}
else if( m_class == CID_RESOURCE )
{
AbstractResource* resource = reinterpret_cast< AbstractResource* >( m_value.pointer_value );
SAFE_DELETE( resource );
m_value.pointer_value = 0;
}
m_class = CID_NONE;
m_value.int_value = 0;
}
const char* get_name() const
{
return m_name;
}
void set_name( const char* name )
{
m_name = name;
}
CLASSID get_class() const
{
return m_class;
}
/// setter
template< typename T >
property& set_resource( T* resource )
{
wipe();
m_class = CID_RESOURCE;
if( resource )
{
Resource< T >* res = new Resource< T >( resource );
m_value.pointer_value = reinterpret_cast< void* >( res );
}
return *this;
}
template< typename T >
property& set_value( T value )
{
wipe();
m_class = CID_POINTER;
m_value.pointer_value = reinterpret_cast< void* >( value );
return *this;
}
template< >
property& set_value< bool >( bool value )
{
wipe();
m_class = CID_BOOLEAN;
m_value.bool_value = value;
return *this;
}
template< >
property& set_value< char >( char value )
{
wipe();
m_class = CID_CHAR;
m_value.char_value = value;
return *this;
}
template< >
property& set_value< unsigned char >( unsigned char value )
{
wipe();
m_class = CID_UCHAR;
m_value.uchar_value = value;
return *this;
}
template< >
property& set_value< WORD >( WORD value )
{
wipe();
m_class = CID_WORD;
m_value.word_value = value;
return *this;
}
template< >
property& set_value< DWORD >( DWORD value )
{
wipe();
m_class = CID_DWORD;
m_value.dword_value = value;
return *this;
}
template< >
property& set_value< float >( float value )
{
wipe();
m_class = CID_FLOAT;
m_value.float_value = value;
return *this;
}
template< >
property& set_value< int >( int value )
{
wipe();
m_class = CID_INT;
m_value.int_value = value;
return *this;
}
template< >
property& set_value< unsigned int >( unsigned int value )
{
wipe();
m_class = CID_UINT;
m_value.uint_value = value;
return *this;
}
template< >
property& set_value< __int64 >( __int64 value )
{
wipe();
m_class = CID_INT64;
m_value.int64_value = value;
return *this;
}
template< >
property& set_value< const char* >( const char* value )
{
wipe();
m_class = CID_STRING;
int len = ::strlen( value );
char* buffer = new char[ len + 1 ];
::strcpy( buffer, value );
m_value.pointer_value = reinterpret_cast< void* >( buffer );
return *this;
}
template< >
property& set_value< char* >( char* value )
{
wipe();
m_class = CID_STRING;
int len = ::strlen( value );
char* buffer = new char[ len + 1 ];
::strcpy( buffer, value );
m_value.pointer_value = reinterpret_cast< void* >( buffer );
return *this;
}
/// getter
template< typename T >
void get_resource( T*& resource ) const
{
assert( m_class == CID_RESOURCE );
AbstractResource* absResource = reinterpret_cast< AbstractResource* >( m_value.pointer_value );
if( absResource )
{
resource = reinterpret_cast< T* >( absResource->get_resource() );
}
}
template< typename T >
void get_value( T& value ) const
{
assert( m_class == CID_POINTER );
value = reinterpret_cast< T >( m_value.pointer_value );
}
template< >
void get_value< bool >( bool& value ) const
{
assert( m_class == CID_BOOLEAN );
value = m_value.bool_value;
}
template< >
void get_value< char >( char& value ) const
{
assert( m_class == CID_CHAR );
value = m_value.char_value;
}
template< >
void get_value< unsigned char >( unsigned char& value ) const
{
assert( m_class == CID_UCHAR );
value = m_value.uchar_value;
}
template< >
void get_value< WORD >( WORD& value ) const
{
assert( m_class == CID_WORD );
value = m_value.word_value;
}
template< >
void get_value< DWORD >( DWORD& value ) const
{
assert( m_class == CID_DWORD );
value = m_value.dword_value;
}
template< >
void get_value< float >( float& value ) const
{
assert( m_class == CID_FLOAT );
value = m_value.float_value;
}
template< >
void get_value< int >( int& value ) const
{
assert( m_class == CID_INT );
value = m_value.int_value;
}
template< >
void get_value< unsigned int >( unsigned int& value ) const
{
assert( m_class == CID_UINT );
value = m_value.uint_value;
}
template< >
void get_value< __int64 >( __int64& value ) const
{
assert( m_class == CID_INT64 );
value = m_value.int64_value;
}
template< >
void get_value< char* >( char*& value ) const
{
assert( m_class == CID_STRING );
value = reinterpret_cast< char* >( m_value.pointer_value );
}
template< >
void get_value< std::string >( std::string& value ) const
{
assert( m_class == CID_STRING );
value = reinterpret_cast< char* >( m_value.pointer_value );
}
void* get_resource() const
{
assert( m_class == CID_RESOURCE );
AbstractResource* absResource = reinterpret_cast< AbstractResource* >( m_value.pointer_value );
if( absResource )
return absResource->get_resource();
return 0;
}
void* get_pointer_value() const
{
assert( m_class == CID_POINTER );
return m_value.pointer_value;
}
bool get_boolean_value() const
{
assert( m_class == CID_BOOLEAN );
return m_value.bool_value;
}
char get_char_value() const
{
assert( m_class == CID_CHAR );
return m_value.char_value;
}
unsigned char get_uchar_value() const
{
assert( m_class == CID_UCHAR );
return m_value.uchar_value;
}
WORD get_word_value() const
{
assert( m_class == CID_WORD );
return m_value.word_value;
}
DWORD get_dword_value() const
{
assert( m_class == CID_DWORD );
return m_value.dword_value;
}
float get_float_value() const
{
assert( m_class == CID_FLOAT );
return m_value.float_value;
}
int get_int_value() const
{
assert( m_class == CID_INT );
return m_value.int_value;
}
unsigned int get_uint_value() const
{
assert( m_class == CID_UINT );
return m_value.uint_value;
}
__int64 get_int64_value() const
{
assert( m_class == CID_INT64 );
return m_value.int64_value;
}
const char* get_string_value() const
{
assert( m_class == CID_STRING );
return reinterpret_cast< const char* >( m_value.pointer_value );
}
protected:
union value_type {
bool bool_value;
char char_value;
unsigned char uchar_value;
WORD word_value;
DWORD dword_value;
int int_value;
unsigned int uint_value;
__int64 int64_value;
float float_value;
void* pointer_value;
};
CLASSID m_class;
const char* m_name;
value_type m_value;
};
static property null_property;
/// property array
class property_array
{
public:
typedef std::vector< property* > properties_t;
typedef properties_t::iterator iterator;
typedef properties_t::const_iterator const_iterator;
property_array();
property_array( const property_array& other );
property_array& operator = ( const property_array& rhs );
virtual ~property_array();
property_array& add( property* prop );
property& get( const char* name );
property& at( int index );
property& operator[]( int index );
property& operator[]( const char* name );
int size() const;
bool empty() const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
protected:
void _copy( const property_array& other );
properties_t m_properties;
};
/// property for updatable window
class kui_window_property : public property
{
public:
kui_window_property( const char* name ) : property( name ) {}
kui_window_property( const kui_window_property& rhs ) : property( rhs ) {}
virtual ~kui_window_property() {}
virtual void on_update( property& data ) = 0;
KUIWnd* get_window()
{
return reinterpret_cast< KUIWnd* >( get_pointer_value() );
}
virtual kui_window_property& set_value( KUIWnd* value )
{
property::set_value< KUIWnd* >( value );
return *this;
}
};
// soandor #2.1.2.4.3 팻 조작 UI 연동
/// updatable widow
class kui_updatable_window
{
public:
struct finder
{
finder( const char* name ) : name_for_search( name ) {}
bool operator () ( const kui_updatable_window* arg )
{
return ( ::stricmp( name_for_search, arg->get_name() ) == 0 ) ? true : false;
}
const char* name_for_search;
};
kui_updatable_window() : m_window( 0 ), m_data( "" ) {}
kui_updatable_window( kui_window_property* window ) : m_window( window ), m_data( window->get_name() ) {}
virtual ~kui_updatable_window()
{
SAFE_DELETE( m_window );
}
virtual void update()
{
if( !m_window )
return;
m_window->on_update( m_data );
}
const char* get_name() const
{
if( !m_window )
return 0;
return m_window->get_name();
}
void set_window( kui_window_property* window )
{
SAFE_DELETE( m_window );
m_window = window;
m_data.set_name( window->get_name() );
}
KUIWnd* get_window()
{
if( !m_window )
return 0;
return m_window->get_window();
}
template< typename T >
void set_data( T data )
{
m_data.set_value( data );
}
template< typename T >
void get_data( T& data ) const
{
m_data.get_value( data );
}
template< typename T >
void set_resource( T* resource )
{
m_data.set_resource( resource );
}
template< typename T >
void get_resource( T* resource ) const
{
m_data.get_resource( T* resource );
}
protected:
kui_window_property* m_window;
property m_data;
};
static kui_updatable_window null_updatable_window;
/// updatable window array
class kui_updatable_window_array
{
public:
typedef std::vector< kui_updatable_window* > window_container_t;
typedef window_container_t::iterator iterator;
typedef window_container_t::const_iterator const_iterator;
kui_updatable_window_array();
~kui_updatable_window_array();
kui_updatable_window_array& add( kui_updatable_window* window );
kui_updatable_window& get( const char* name );
kui_updatable_window& at( int index );
kui_updatable_window& operator[]( int index );
kui_updatable_window& operator[]( const char* name );
int size() const;
bool empty() const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
void clear();
virtual void update();
protected:
window_container_t m_windows;
/// disabled...
kui_updatable_window_array( const kui_updatable_window_array& other );
kui_updatable_window_array& operator = ( const kui_updatable_window_array& rhs );
};
/// list control proxy
class proxy_list
{
public:
enum { INVALID_VALUE = -1 };
typedef property_array item_t;
typedef proxy_list this_t;
typedef std::vector< item_t* > item_container_t;
typedef std::vector< kui_window_property* > control_row_t;
typedef std::vector< control_row_t* > control_matrix_t;
typedef std::vector< KUIWnd* > selectables_t;
typedef item_container_t::iterator iterator;
// ctor and dtor
proxy_list( SUIWnd* window, const char* id, int limit, int item_offset = 0 );
~proxy_list();
// public interface
void initialize( const char* selectable_id = 0, const char* selection_mask_id = 0, const char* scroll_id = 0 );
void clear();
void update_data();
// kui method
void proc_pumpup( LPCSTR id, DWORD message, DWORD lparam, DWORD wparam );
void proc_mouse( DWORD msg, int x, int y );
void activate_mouse_proc( bool activity );
// list method
void save_state();
void load_state();
this_t& add( item_t* item );
void remove( item_t* item );
template< class _Pred >
void remove_if( _Pred pred )
{
m_items.erase( std::remove_if( begin(), end(), pred ), m_items.end() );
_update_scroll_range();
}
bool empty() const;
int size() const;
iterator begin();
iterator end();
iterator visible_begin();
iterator visible_end();
item_t* at( int item_index );
item_t* operator[ ]( int item_index );
int get_offset() const { return m_offset; } // #2.1.2.4.3
void next_page();
void prev_page();
int page_begin() const;
int page_end() const;
int page() const;
// { sonador 7.0.25 proxy_list 정렬 타입 불일치 문제 수정
template< typename _Ty, typename _Pr >
void sort( const char* column_name, _Pr pred )
{
std::sort( begin(), end(), sort_column< _Ty, _Pr, false >( column_name, pred ) );
}
template< typename _Ty, typename _Pr >
void sort_resource( const char* column_name, _Pr pred )
{
std::sort( begin(), end(), sort_column< _Ty, _Pr, true >( column_name, pred ) );
}
template< typename _Ty, typename _Pr >
void stable_sort( const char* column_name, _Pr pred )
{
std::stable_sort( begin(), end(), sort_column< _Ty, _Pr, false >( column_name, pred ) );
}
template< typename _Ty, typename _Pr >
void stable_sort_resource( const char* column_name, _Pr pred )
{
std::stable_sort( begin(), end(), sort_column< _Ty, _Pr, true >( column_name, pred ) );
}
// }
// control method
template< typename property_t >
bool add_column( const char* window_id, property_t* origin_property )
{
std::string indexed_id_orig = helper::indexed_id( window_id , 0 );
KUIWnd* wnd = m_window->GetChild( indexed_id_orig.c_str() );
if( wnd == 0 )
return false;
m_window->SetChildAsTop( indexed_id_orig.c_str() );
m_control_matrix.at( 0 )->push_back( &( origin_property->set_value( wnd ) ) );
RECT region_offset;
region_offset.left = 0;
region_offset.right = 0;
// n = 1 : our original control index ...
for( int n = 1; n < m_limit; ++n )
{
int offset = n * m_item_offset;
region_offset.top = offset;
region_offset.bottom = offset;
m_control_matrix.at( n )->push_back( &( new property_t( *origin_property ) )->set_value( m_window->CopyControl( indexed_id_orig.c_str(), helper::indexed_id( window_id, n ).c_str(), region_offset ) ) );
}
return true;
}
property* get_window_property( int row, const char* column_id );
private:
// sonador 7.0.25 proxy_list 정렬 타입 불일치 문제 수정
template< typename _Ty, typename _Pr, bool _IsRes = false >
struct sort_column {
sort_column( const char* column_name, const _Pr& pred ) : m_column_name( column_name ), m_pred( pred ) {}
bool operator () ( item_t* lhs, item_t* rhs ) const {
property& lhs_column = lhs->get( m_column_name );
property& rhs_column = rhs->get( m_column_name );
if( !rhs_column.is_valid() ) return false;
if( !lhs_column.is_valid() ) return true;
return compare_property( lhs_column, rhs_column, int2type< _IsRes >() );
}
bool compare_property( const property& lhs, const property& rhs, int2type< false > ) const {
_Ty lhs_value, rhs_value;
lhs.get_value< _Ty >( lhs_value );
rhs.get_value< _Ty >( rhs_value );
return m_pred( lhs_value, rhs_value );
}
bool compare_property( const property& lhs, const property& rhs, int2type< true > ) const {
_Ty *lhs_value, *rhs_value;
lhs.get_resource< _Ty >( lhs_value );
rhs.get_resource< _Ty >( rhs_value );
return m_pred( *lhs_value, *rhs_value );
}
const char* m_column_name;
const _Pr& m_pred;
};
void _init_scroll( const char* window_id );
void _init_selectables( const char* window_id );
void _init_selection_mask( const char* selection_mask_id );
int _normalize_offset( int offset );
bool _is_valid_index( int control_index ) const;
bool _is_visible_index( int control_index ) const;
int _get_visible_end_index() const;
int _to_item_index( int control_index ) const;
int _to_control_index( int item_index ) const;
int _mouse_to_index( int x, int y ) const;
int _change_current_index( int new_item_index );
int _get_page_from( int item_index ) const;
bool _is_valid_page( int page ) const;
void _set_offset_by( int page );
int _select_item_by( int control_index = INVALID_VALUE );
void _locate_selection_mask_at( int control_index = INVALID_VALUE );
void _update_scroll_range();
const char* m_id;
const unsigned int m_limit;
const unsigned int m_item_offset;
int m_offset;
int m_current_index;
int m_saved_offset;
int m_saved_index;
SUIWnd* m_window;
KUIControlScrollBase* m_scroll;
KUIWnd* m_selection_mask;
int m_selection_mask_origin_offset;
selectables_t m_selectables;
item_container_t m_items;
control_matrix_t m_control_matrix;
bool m_proc_mouse;
};
template< typename _Ty >
class spin_cache
{
public:
enum { INITIAL_INDEX = -1 };
typedef std::vector< _Ty > cache_t;
typedef typename cache_t::iterator iterator;
spin_cache( int maxCache ) : m_maxCache( maxCache ), m_index( INITIAL_INDEX )
{
}
void push( const _Ty& value )
{
m_cache.insert( m_cache.begin(), value );
normalizeCache();
while( overflow() )
{
m_cache.pop_back();
}
resetIndex();
}
void clear()
{
resetIndex();
m_cache.clear();
}
bool empty() const
{
return m_cache.empty();
}
iterator next()
{
normalizeIndex( ++m_index );
return isValid( m_index ) ? m_cache.begin() + m_index : m_cache.end();
}
iterator prev()
{
normalizeIndex( --m_index );
return isValid( m_index ) ? m_cache.begin() + m_index : m_cache.end();
}
iterator begin()
{
return m_cache.begin();
}
iterator end()
{
return m_cache.end();
}
void pop_front()
{
if( !m_cache.empty() )
{
m_cache.erase( m_cache.begin() );
}
}
void pop_back()
{
if( !m_cache.empty() )
{
m_cache.pop_back();
}
}
protected:
bool overflow() const { return ( m_cache.size() > m_maxCache ) ? true : false; }
void normalizeCache()
{
typedef std::vector< std::string > cache_t;
cache_t new_cache;
new_cache.reserve( m_maxCache );
cache_t::iterator i = m_cache.begin(), e = m_cache.end();
for( ; i != e; ++i )
{
cache_t::iterator i_found = std::find( new_cache.begin(), new_cache.end(), *i );
if( i_found != new_cache.end() )
continue;
new_cache.push_back( *i );
}
m_cache.clear();
m_cache.assign( new_cache.begin(), new_cache.end() );
}
void normalizeIndex( int& index )
{
if( index < 0 )
index = m_cache.size() - 1;
else if( index >= m_cache.size() )
index = 0;
}
void resetIndex()
{
m_index = INITIAL_INDEX;
}
bool isValid( int index )
{
return ( index < 0 || index >= m_cache.size() ) ? false : true;
}
std::vector< std::string > m_cache;
const int m_maxCache;
int m_index;
};
class ticker;
class tickable
{
public:
tickable() : m_ticker( 0 ) {}
virtual ~tickable() {}
// transitive methods
virtual void on_tick() = 0;
virtual void on_enter() = 0;
virtual void on_leave() = 0;
ticker* get_ticker() { return m_ticker; }
protected:
friend class ticker;
void set_ticker( ticker* _ticker );
ticker* m_ticker;
};
class ticker : public tickable
{
public:
ticker() : tickable(), m_time( 0 ), m_is_on_tick( false ), m_lock( false ) {}
virtual ~ticker() {}
virtual void on_tick() { tick( m_ticker->time() ); }
virtual void on_enter();
virtual void on_leave();
virtual void tick( DWORD time );
virtual void enter();
virtual void leave();
bool append_tickable( tickable* _tickable );
bool remove_tickable( tickable* _tickable );
DWORD time() const { return m_time; }
bool is_on_tick() const { return m_is_on_tick; }
protected:
typedef std::vector< tickable* > tickable_vector_t;
typedef std::queue< tickable* > tickable_queue_t;
tickable_vector_t m_tickables;
tickable_queue_t m_candidates;
tickable_queue_t m_garbages;
DWORD m_time;
bool m_is_on_tick;
bool m_lock;
};
class fixed_rate_ticker : public ticker
{
public:
fixed_rate_ticker( DWORD frequency ) : ticker(), m_frequency( frequency )
{
}
virtual ~fixed_rate_ticker() {}
virtual void on_tick();
virtual void on_enter();
virtual void on_leave();
DWORD frequency() const { return m_frequency; }
protected:
DWORD m_frequency;
};
class fixed_rate_one_time_ticker : public fixed_rate_ticker
{
public:
fixed_rate_one_time_ticker( DWORD frequency ) : fixed_rate_ticker( frequency )
{
}
virtual ~fixed_rate_one_time_ticker() {}
virtual void on_tick();
};
class conditional_fixed_rate_one_time_ticker : public fixed_rate_ticker
{
public:
conditional_fixed_rate_one_time_ticker( DWORD frequency ) : fixed_rate_ticker( frequency ), m_satisfaction( false )
{
}
virtual ~conditional_fixed_rate_one_time_ticker() {}
virtual void on_tick();
virtual void on_enter();
void satisfy();
bool m_satisfaction;
};
struct Action
{
virtual ~Action() {}
virtual void operator()() = 0;
};
struct ActionEnableControl : public Action
{
ActionEnableControl( KUIControl* pControl ) : Action(), m_pControl( pControl ) {}
virtual void operator()() { if( m_pControl ) m_pControl->Enable(); }
KUIControl* m_pControl;
};
struct ActionDisableControl : public Action
{
ActionDisableControl( KUIControl* pControl ) : Action(), m_pControl( pControl ) {}
void operator()() { if( m_pControl ) m_pControl->Disable(); }
KUIControl* m_pControl;
};
struct ActionShowControl : public Action
{
ActionShowControl( KUIControl* pControl ) : Action(), m_pControl( pControl ) {}
void operator()() { if( m_pControl ) m_pControl->SetShow( true ); }
KUIControl* m_pControl;
};
struct ActionHideControl : public Action
{
ActionHideControl( KUIControl* pControl ) : Action(), m_pControl( pControl ) {}
void operator()() { if( m_pControl ) m_pControl->SetShow( false ); }
KUIControl* m_pControl;
};
class ActionBinder : public tickable
{
public:
ActionBinder( Action* pOnEnter, Action* pOnTick, Action* pOnLeave )
: tickable()
, m_pOnEnterAction( pOnEnter )
, m_pOnTickAction( pOnTick )
, m_pOnLeaveAction( pOnLeave )
{
}
virtual ~ActionBinder()
{
SAFE_DELETE( m_pOnTickAction );
SAFE_DELETE( m_pOnEnterAction );
SAFE_DELETE( m_pOnLeaveAction );
}
virtual void on_tick()
{
if( m_pOnTickAction )
(*m_pOnTickAction)();
}
virtual void on_enter()
{
if( m_pOnEnterAction )
(*m_pOnEnterAction)();
}
virtual void on_leave()
{
if( m_pOnLeaveAction )
(*m_pOnLeaveAction)();
}
private:
Action* m_pOnEnterAction;
Action* m_pOnTickAction;
Action* m_pOnLeaveAction;
};
class Page
{
public:
Page() : m_nCurrentPage( 1 ), m_nEndPage( 1 ), m_pPrevButton( 0 ), m_pNextButton( 0 )
{
}
void SetButton( class KUIControl* pPrevButton, class KUIControl* pNextButton );
void Update( int nCurrentPage );
void Update( int nCurrentPage, int nEndPage );
int Current() const;
int End() const;
int Next() const;
int Prev() const;
private:
int _GetNormalizedPage( int nPage ) const;
bool _IsEnd() const;
bool _IsBegin() const;
int m_nCurrentPage;
int m_nEndPage;
class KUIControl* m_pPrevButton;
class KUIControl* m_pNextButton;
};
/// 2011.01.20 - prodongi
/// 2010.01.20 메인 프레임과 타겟 창에 쓰이는 마크 아이콘 구조체 - prodongi
struct sMarkState
{
enum eState
{
PC = 0,
FREEPASS,
PK,
PVP,
MAX
};
struct sInfo
{
bool m_show;
// 프리패스/pc방에서만 쓰인다
int m_stateCode;
AR_TIME m_endTime;
int m_stateLevel;
bool m_toggleSkill;
int m_stateValue; ///< 지속효과 관련 추가값
// pk status에만 쓰인다
int m_status;
std::string m_strMarkControlName; // 매칭 되어있는 컨트롤 마크 이름 ( 이름은 sortMarkState() 할때마다 바뀜 )
sInfo()
: m_show( false )
, m_stateCode( NULL )
, m_endTime( NULL )
, m_stateLevel( NULL )
, m_toggleSkill( NULL )
, m_stateValue( NULL )
, m_strMarkControlName( "" )
{
}
void setStateSlot( class SStateSlot const* slot );
};
void updateMarkStateList(KUIWnd* wnd, SUIDisplayInfo* displayInfo, SGameAvatarEx* avatar);
void updateMarkStatusList(KUIWnd* wnd, SUIDisplayInfo* displayInfo, int status);
void sortMarkState(KUIWnd* wnd, SUIDisplayInfo* displayInfo);
void hideAllControl(KUIWnd* wnd);
void hideAll( void );
bool IsInRectFreePass( KUIWnd* pDestWnd, const KPoint ptMouse );
void UpdateFreePassEndTimeTooltip( KUIWnd* pDestWnd, SUIDisplayInfo* pDisplayInfo );
sInfo m_info[ eState::MAX ];
};
/// 2011.12.12 마우스 영역 체크로 투명/불투명 효과를 주는 구조체 - prodongi
struct sOpacityMouseChecker
{
sOpacityMouseChecker() : m_alphaV(3.0f), m_alpha(0.0f) {}
~sOpacityMouseChecker();
void open();
void update(DWORD dwTime, int x, int y, SUIWnd* wnd);
void setAlpha(float alpha);
void addChild(SUIWnd* parent, char const* id);
void setShow(bool show);
void changeAlpha();
float m_alphaV;
float m_alpha;
std::vector<KUIWnd*> m_childList;
};
} // namespace util
/// 2012.05.02 클래스의 함수포인터를 등록해서 함수를 호출해주는 템플릿 - prodongi
template <typename T, typename KEY = std::string>
struct cClassFuncP
{
typedef void (T::*fp)();
typedef std::map<KEY, fp> map_fp;
~cClassFuncP()
{
m_funcList.clear();
}
void add(KEY const& id, fp _fp)
{
map_fp::iterator it = m_funcList.find(id);
if (it != m_funcList.end())
return ;
m_funcList[id] = _fp;
}
void del(KEY const& id)
{
map_fp::iterator it = m_funcList.find(id);
if (it == m_funcList.end())
return ;
m_funcList.erase(id);
}
void call(KEY const& id, T* owner)
{
map_fp::iterator it = m_funcList.find(id);
if (it == m_funcList.end())
return ;
fp fn = it->second;
(owner->*fn)();
}
map_fp m_funcList;
};
template <typename T, typename P, typename KEY = std::string>
struct cClassParamFuncP
{
typedef void (T::*fp)(P);
typedef std::map<KEY, fp> map_fp;
~cClassParamFuncP()
{
m_funcList.clear();
}
void add(KEY const& id, fp _fp)
{
map_fp::iterator it = m_funcList.find(id);
if (it != m_funcList.end())
return ;
m_funcList[id] = _fp;
}
void del(KEY const& id)
{
map_fp::iterator it = m_funcList.find(id);
if (it == m_funcList.end())
return ;
m_funcList.erase(id);
}
void call(KEY const& id, T* owner, P param)
{
map_fp::iterator it = m_funcList.find(id);
if (it == m_funcList.end())
return ;
fp fn = it->second;
(owner->*fn)(param);
}
map_fp m_funcList;
};
/// 2012.05.09 x, y가 m_emptyRegionControl영역에 있는지 체크하는 구조체 - prodongi
struct sEmptyControlRegionChecker
{
~sEmptyControlRegionChecker();
bool isIn(int x, int y) const;
void add(KUIWnd* control);
private:
std::list<KUIWnd*> m_controlList;
};
class EquipItemAddtionalIconSetter
{
public:
EquipItemAddtionalIconSetter( KUIControlMultiIcon* pIcon, ItemBase::ItemCode nItemCode, int nEnhance, int nEtherealDurability, XFlag<int> xFlag );
EquipItemAddtionalIconSetter( KUIControlMultiIcon* pIcon, SInventorySlot* pSlot );
private:
void SetIcon( KUIControlMultiIcon* pIcon, ItemBase::ItemCode nItemCode, int nEnhance, int nEtherealDurability, XFlag<int> xFlag );
};
// 2010.05.11 강화 크리쳐의 아이콘 이름을 구한다 - prodongi
void getEnhanceIconName(char* enhanceIconName, SCreatureInfo const* info, int enhance);
// 2010.08.31 - prodongi
void getEnhanceIconName(char* enhanceIconName, ENC_INT creatureId, int enhance);
// 2010.05.13 순수하게 아이템 이름만 뽑는다 - prodongi
std::string getItemName(int itemId);
// 2010.06.09 내구도에 따른 아이콘 이름 뽑는다 - prodongi
void getIconNameAtDurability(SInventorySlot const* slot, std::string& iconName);
// 2010.07.06 - prodongi
void getIconNameAtDurability(ItemBase::ItemCode itemCode, int enhance, int etherealDurability, std::string& iconName, int nFlag = 0, int nSummonID = 0 );
void getIconNameAtDurability(ItemBase::ItemCode itemCode, int enhance, int etherealDurability, std::string& iconName, XFlag<int> tFlag, int nSummonID = 0 );
// 2013.03.18 - gmpbigsun
void getIconNameAtDurability(SInventorySlot const* slot, int nTmep, std::string& iconName);
bool setIconNameEquipment_ENHANCE( KUIControlMultiIcon* icon, ENC_INT itemCode, const int nEnhance );
// 봉인카드 테두리아이콘 이름얻기
bool getIconNameSummonCard_BORDER( std::string& strTemp, const int nSummonID, int nEnhance = 0, int nDurability = 0 );
bool getIconNameSummonCard_BELT( std::string& strTemp, AR_HANDLE nHandle );
bool getIconNameSummonCard_FORMATION( std::string& strTemp, AR_HANDLE nHandle );
bool getIconNameSummonCard_STAGE( std::string& strTemp, const int nSummonID, const int nEnhance );
// 2010.07.14 파괴된 크리쳐 카드인지 아닌지- prodongi
bool isExhaustedSummonCard(ItemBase::ItemCode itemCode, int enhance, int etherealDurability);
// 착용 불가능한 꾸미기 아이템 인가?
bool isWearableDecoItem( const ItemBaseEx_info* pItem );
// 착용 불가능한 아이템 아이콘 설정
void setCantWearIcon(KUIControlMultiIcon* icon, ENC_INT itemCode, int nJobID, int nRace, int nLevel, XFlag<int> xFlag, SSkillSlotMgr& SkillSlotMgr );
// 2010.07.20 깨진 아이템 아이콘 설정- prodongi
void setDurabilityIcon(KUIControlMultiIcon* icon, ENC_INT itemCode, int etherealDurability);
// 강화 실패 아이템 아이콘 설정
void setEnhanceFailedIcon(KUIControlMultiIcon* icon, XFlag<int> xFlag);
// 2010.06.11 사용할려는 아이템이 동일한 타입인지 체크 - prodongi
bool checkUseEqualHairTypeItem(ItemBase const* item);
// 2010.07.27 아이템의 사용 가능 조건을 체크 - prodongi
bool checkEnableUseItem(ItemBase const* item, int itemCode, SUIDisplayInfo* displayInfo, int& msgId);
// 2010.08.20 set control gage - prodongi
void setStaticWndGage(KUIWnd* wnd, int maxSize, float percent);
// 2010.09.17 장착 카드 내구도 퍼센트 - prodongi
float getEquipCardDurPercent(SInventorySlot const* slot);
// 2010.09.17 장착 카드 내구도 퍼센트 단계- prodongi
int getEquipCardDurPercentLevel(SInventorySlot const* slot);
float getCreatureCardDurPercent(SInventorySlot const* slot, int enhance); // 2010.09.17 카드 내구도 퍼센트 - prodongi
float getCreatureCardDurPercent(int etherealDurability, int enhance); /// 2011.03.29 - prodongi
int getCreatureCardDurPercentLevel(SInventorySlot const* slot, int enhance);// 2010.09.17 장착 아이템 내구도 퍼센트 단계- prodongi
int getCreatureCardDurPercentLevel(int etherealDurability, int enhance); /// 2011.03.29 - prodongi
/// 2010.12.17 - prodongi
void setChildControlEnable(KUIWnd* parent, char const* childId, bool enable);
std::string expToString(__int64 exp);
/// 2011.02.09 - prodongi
void jpToString(__int64 jp, std::string& str);
void convertMagicTypeToString(int type, std::string& str); /// 2011.03.07 왜 속성을 magic으로 쓰고들 있나?? - prodongi
void getNpcIconAniName(std::string& str, unsigned int type = 0, unsigned int status = 0); /// 2011.03.18 npc의 아이콘 ani name을 얻어온다 - prodongi
void getDungeonGateIconAniName(std::string& str, int type); /// 2011.07.21 - prodongi
// 2012.02.03 - servantes : 백분율에 따라 게이지의 텍스처를 바꿔 준다
// int nPixelHeight : 텍스처가 4,5 .. 펙셀짜리로 여러가지가 있다. 이 중 선택한다, UI 툴 또는 UI 담당자에게 확인
bool setHPGaugeTexture(int percent, KUIControlGauge* pGauge, int nPixelHeight = 4);
bool isLastBR(char const* str); /// 2011.04.22 <br>이 str 맨 마지막 태그 안에 들어 있는지 체크
bool isFirstBR(char const* str);/// 2011.04.27 <br>이 str 맨 처음 태그 안에 들어 있는지 체크
bool setSkillCardIcon(KUIControlMultiIcon* icon, int itemCode, bool isEquip = false); /// 2011.08.03 - prodongi
// 2013. 03. 22 - gmpbigsun : 봉인카드에 대한 아이콘처리
bool setSummonCardIcon( KUIControlMultiIcon* pIcon, SInventorySlot const* pslot );
bool setSummonCardIcon( KUIControlMultiIcon* pIcon, int nItemCode, int nSummonID, int nEnhance, int nFlag, int nDurability = 0 );
bool setSummonCardIcon( KUIControlMultiIcon* pIcon, int nItemCode, int nSummonID, int nEnhance, XFlag<int> tFlag, int nDurability = 0 );
bool setSummonCardIconForPortrait( KUIControlMultiIcon* pIcon, SInventorySlot const* pSlot ); //20130409 편성창 오른쪽 초상화
void ResetMultiIcon( KUIControlMultiIcon* pIcon, const int nBegin, const int nEnd );
bool isEmptyCreatureCard(int itemCode, XFlag<int> const& xFlag); /// 2011.10.21 빈카드인지 - prodongi
// Azia Mafia ++
bool isWearableSkillCardItem(const ItemBaseEx_info* pItem, SSkillSlotMgr& SkillSlotMgr);
//
// return cost
// 0 : error
// 1 : 내구도 있음
// 2 : 내구도 없음
int refreshItemDurability(SInventorySlot* pSlot, KUIWnd* pGauge, float fGaugeWidth);
void UISendStringMessage(SGameManager* pGameManager, int nToUI, const char* pSendStr, bool bForceSend = false);