home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 February / maximum-cd-2009-02.iso / DiscContents / SMC_1.6_win32.exe / src / objects / sprite.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-25  |  36.2 KB  |  1,722 lines

  1. /***************************************************************************
  2.  * sprite.cpp  -  basic sprite class
  3.  *
  4.  * Copyright (C) 2003 - 2008 Florian Richter
  5.  ***************************************************************************/
  6. /*
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  14. */
  15.  
  16. #include "../objects/sprite.h"
  17. #include "../objects/movingsprite.h"
  18. #include "../core/game_core.h"
  19. #include "../level/level.h"
  20. #include "../core/camera.h"
  21. #include "../core/framerate.h"
  22. #include "../player/player.h"
  23. #include "../gui/hud.h"
  24. #include "../video/gl_surface.h"
  25. #include "../video/renderer.h"
  26. #include "../core/sprite_manager.h"
  27.  
  28. cEditor_Object_Settings_Item :: cEditor_Object_Settings_Item( void )
  29. {
  30.     window_name = NULL;
  31.     window_setting = NULL;
  32.     advance_row = 1;
  33. }
  34.  
  35. cEditor_Object_Settings_Item :: ~cEditor_Object_Settings_Item( void )
  36. {
  37.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  38.  
  39.     wmgr.destroyWindow( window_name );
  40.     wmgr.destroyWindow( window_setting );
  41. }
  42.  
  43.  
  44. /* *** *** *** *** *** *** *** *** cCollidingSprite *** *** *** *** *** *** *** *** *** */
  45.  
  46. cCollidingSprite :: cCollidingSprite( void )
  47. {
  48.  
  49. }
  50.  
  51. cCollidingSprite :: ~cCollidingSprite( void )
  52. {
  53.  
  54. }
  55.  
  56. void cCollidingSprite :: Parse_Collisions( void )
  57. {
  58.     // get collision list
  59.     ObjectCollisionList col_list;
  60.     collisions.swap( col_list );
  61.  
  62.     // parse the found collisions
  63.     for( ObjectCollisionList::iterator itr = col_list.begin(), itr_end = col_list.end(); itr != itr_end; ++itr )
  64.     {
  65.         // get object pointer
  66.         cObjectCollision *col = (*itr);
  67.  
  68.         // handle
  69.         Handle_Collision( col );
  70.     }
  71. }
  72.  
  73. void cCollidingSprite :: Handle_Collisions( void )
  74. {
  75.     // parse
  76.     Parse_Collisions();
  77.     // clear
  78.     Collisions_Clear();
  79. }
  80.  
  81. bool cCollidingSprite :: Collision_Add( cSprite *base, cSprite *col, unsigned int col_id /* = 0 */, ObjectCollisionType col_type /* = CO_NOTHING */, bool add_if_new /* = 0 */ )
  82. {
  83.     // invalid base
  84.     if( !base )
  85.     {
  86.         return 0;
  87.     }
  88.  
  89.     // create
  90.     cObjectCollision *collision = new cObjectCollision();
  91.  
  92.     // type
  93.     collision->type = col_type;
  94.     // identifier
  95.     collision->number = col_id;
  96.  
  97.     // if col object is available
  98.     if( col )
  99.     {
  100.         // direction 
  101.         collision->Set_Direction( base, col );
  102.     }
  103.  
  104.     // add
  105.     return Collision_Add( collision, add_if_new );
  106. }
  107.  
  108. bool cCollidingSprite :: Collision_Add( cObjectCollision *collision, bool add_if_new /* = 0 */ )
  109. {
  110.     // invalid collision data
  111.     if( !collision )
  112.     {
  113.         return 0;
  114.     }
  115.  
  116.     // check if collision data is new
  117.     if( add_if_new )
  118.     {
  119.         // check found collisions list
  120.         for( ObjectCollisionList::iterator itr = collisions.begin(), itr_end = collisions.end(); itr != itr_end; ++itr )
  121.         {
  122.             // get object pointer
  123.             cObjectCollision *col = (*itr);
  124.  
  125.             // already in list
  126.             if( col->number == collision->number )
  127.             {
  128.                 delete collision;
  129.                 return 0;
  130.             }
  131.         }
  132.     }
  133.  
  134.     collisions.push_back( collision );
  135.  
  136.     return 1;
  137. }
  138.  
  139. void cCollidingSprite :: Collision_Delete( cObjectCollision *collision )
  140. {
  141.     if( !collision )
  142.     {
  143.         return;
  144.     }
  145.  
  146.     for( ObjectCollisionList::iterator itr = collisions.begin(), itr_end = collisions.end(); itr != itr_end; ++itr )
  147.     {
  148.         // get object pointer
  149.         cObjectCollision *col = (*itr);
  150.  
  151.         if( col == collision )
  152.         {
  153.             delete collision;
  154.             collisions.erase( itr );
  155.             break;
  156.         }
  157.     }
  158. }
  159.  
  160. void cCollidingSprite :: Collision_Delete_last( void )
  161. {
  162.     if( collisions.empty() )
  163.     {
  164.         return;
  165.     }
  166.     
  167.     delete collisions[collisions.size() - 1];
  168.     collisions.erase( collisions.begin() + collisions.size() - 1 );
  169. }
  170.  
  171. int cCollidingSprite :: Collision_Check_Direction( ObjectDirection dir )
  172. {
  173.     for( unsigned int i = 0; i < collisions.size(); i++ )
  174.     {
  175.         if( collisions[i]->direction == dir )
  176.         {
  177.             return i;
  178.         }
  179.     }
  180.  
  181.     return -1;
  182. }
  183.  
  184. cObjectCollision *cCollidingSprite :: Collision_Get_first( void )
  185. {
  186.     // no collision available
  187.     if( collisions.empty() )
  188.     {
  189.         return NULL;    
  190.     }
  191.  
  192.     return collisions[0];
  193. }
  194.  
  195. cObjectCollision *cCollidingSprite :: Collision_Get_last( bool only_blocking /* = 0 */ )
  196. {
  197.     // no collisions available
  198.     if( collisions.empty() )
  199.     {
  200.         return NULL;
  201.     }
  202.  
  203.     if( only_blocking )
  204.     {
  205.         for( ObjectCollisionList::reverse_iterator itr = collisions.rbegin(), itr_end = collisions.rend(); itr != itr_end; ++itr )
  206.         {
  207.             // get object pointer
  208.             cObjectCollision *col = (*itr);
  209.  
  210.             cSprite *col_obj = pActive_Sprite_Manager->Get_Pointer( col->number );
  211.  
  212.             // ignore passive
  213.             if( col_obj->massivetype == MASS_PASSIVE )
  214.             {
  215.                 continue;
  216.             }
  217.             // if active check if not climbable
  218.             else if( col->type == CO_ACTIVE )
  219.             {
  220.                 // not a valid object
  221.                 if( col_obj->massivetype == MASS_CLIMBABLE )
  222.                 {
  223.                     continue;
  224.                 }
  225.  
  226.             }
  227.  
  228.             // is blocking
  229.             return col;
  230.         }
  231.  
  232.         // not found
  233.         return NULL;
  234.     }
  235.  
  236.     return collisions[collisions.size() - 1];
  237. }
  238.  
  239. void cCollidingSprite :: Collisions_Clear( void )
  240. {
  241.     for( ObjectCollisionList::iterator itr = collisions.begin(), itr_end = collisions.end(); itr != itr_end; ++itr )
  242.     {
  243.         delete *itr;
  244.     }
  245.  
  246.     collisions.clear();
  247. }
  248.  
  249. void cCollidingSprite :: Handle_Collision( cObjectCollision *collision )
  250. {
  251.     // player
  252.     if( collision->type == CO_PLAYER )
  253.     {
  254.         Handle_Collision_Player( collision );
  255.     }
  256.     // enemy
  257.     else if( collision->type == CO_ENEMY )
  258.     {
  259.         Handle_Collision_Enemy( collision );
  260.     }
  261.     // massive
  262.     else if( collision->type == CO_MASSIVE || collision->type == CO_ACTIVE )
  263.     {
  264.         Handle_Collision_Massive( collision );
  265.     }
  266. }
  267.  
  268. void cCollidingSprite :: Handle_Collision_Player( cObjectCollision *collision )
  269. {
  270.     // virtual
  271. }
  272.  
  273. void cCollidingSprite :: Handle_Collision_Enemy( cObjectCollision *collision )
  274. {
  275.     // virtual
  276. }
  277.  
  278. void cCollidingSprite :: Handle_Collision_Massive( cObjectCollision *collision )
  279. {
  280.     // virtual
  281. }
  282.  
  283. void cCollidingSprite :: Handle_Collision_Box( ObjectDirection direction, GL_rect *r2 )
  284. {
  285.     // virtual
  286. }
  287.  
  288. /* *** *** *** *** *** *** *** cSprite *** *** *** *** *** *** *** *** *** *** */
  289.  
  290. cSprite :: cSprite( GL_Surface *new_image /* = NULL */, float x /* = 0 */, float y /* = 0 */, bool del_img /* = 0 */ )
  291. {
  292.     cSprite::Init();
  293.  
  294.     if( new_image )
  295.     {
  296.         Set_Image( new_image, 0, del_img );
  297.     }
  298.  
  299.     Set_Pos( x, y );
  300. }
  301.  
  302. cSprite :: cSprite( CEGUI::XMLAttributes &attributes )
  303. {
  304.     cSprite::Init();
  305.     cSprite::Create_from_Stream( attributes );
  306. }
  307.  
  308. cSprite :: ~cSprite( void )
  309. {
  310.     if( delete_image && image )
  311.     {
  312.         delete image;
  313.     }
  314. }
  315.  
  316. void cSprite :: Init( void )
  317. {
  318.     // undefined
  319.     type = TYPE_UNDEFINED;
  320.     sprite_array = ARRAY_UNDEFINED;
  321.  
  322.     // collision data
  323.     col_pos.x = 0;
  324.     col_pos.y = 0;
  325.     col_rect.x = 0;
  326.     col_rect.y = 0;
  327.     col_rect.w = 0;
  328.     col_rect.h = 0;
  329.     // image data
  330.     rect.x = 0;
  331.     rect.y = 0;
  332.     rect.w = 0;
  333.     rect.h = 0;
  334.     start_rect.clear();
  335.  
  336.     startposx = 0;
  337.     startposy = 0;
  338.  
  339.     start_image = NULL;
  340.     image = NULL;
  341.     destroy = 0;
  342.     delete_image = 0;
  343.     shadow_pos = 0;
  344.     shadow_color = black;
  345.     no_camera = 0;
  346.  
  347.     color = static_cast<Uint8>(255);
  348.  
  349.     combine_type = 0;
  350.     combine_col[0] = 0;
  351.     combine_col[1] = 0;
  352.     combine_col[2] = 0;
  353.  
  354.     posx = 0;
  355.     posy = 0;
  356.     posz = 0;
  357.     editor_posz = 0;
  358.  
  359.     massivetype = MASS_PASSIVE;
  360.     visible = 1;
  361.     spawned = 0;
  362.     player_range = 1000;
  363.     can_be_ground = 0;
  364.  
  365.     // rotation
  366.     rotation_affects_rect = 0;
  367.     start_rotx = 0;
  368.     start_roty = 0;
  369.     start_rotz = 0;
  370.     rotx = 0;
  371.     roty = 0;
  372.     rotz = 0;
  373.     // scale
  374.     scale_affects_rect = 0;
  375.     scale_up = 0;
  376.     scale_down = 1;
  377.     scale_left = 0;
  378.     scale_right = 1;
  379.     start_scalex = 1;
  380.     start_scaley = 1;
  381.     scalex = 1;
  382.     scaley = 1;
  383.  
  384.     valid_draw = 1;
  385.     valid_update = 1;
  386.  
  387.     editor_window_name_width = 0;
  388. }
  389.  
  390. cSprite *cSprite :: Copy( void )
  391. {
  392.     cSprite *basic_sprite = new cSprite( start_image, startposx, startposy );
  393.  
  394.     basic_sprite->type = type;
  395.     basic_sprite->sprite_array = sprite_array;
  396.     basic_sprite->Set_Massive_Type( massivetype );
  397.     basic_sprite->can_be_ground = can_be_ground;
  398.     basic_sprite->Set_Rotation_affects_Rect( rotation_affects_rect );
  399.     basic_sprite->Set_Scale_affects_Rect( scale_affects_rect );
  400.     basic_sprite->Set_Scale_Directions( scale_up, scale_down, scale_left, scale_right );
  401.     basic_sprite->Set_Ignore_Camera( no_camera );
  402.     basic_sprite->Set_Shadow_Pos( shadow_pos );
  403.     basic_sprite->Set_Shadow_Color( shadow_color );
  404.     basic_sprite->spawned = spawned;
  405.  
  406.     return basic_sprite;
  407. }
  408.  
  409. void cSprite :: Create_from_Stream( CEGUI::XMLAttributes &attributes )
  410. {
  411.     // position
  412.     Set_Pos( static_cast<float>(attributes.getValueAsInteger( "posx" )), static_cast<float>(attributes.getValueAsInteger( "posy" )), 1 );
  413.     // image
  414.     Set_Image( pVideo->Get_Surface( attributes.getValueAsString( "image" ).c_str() ), 1 ) ;
  415.     // type
  416.     Set_Sprite_Type( Get_Sprite_Type_Id( attributes.getValueAsString( "type" ).c_str() ) );
  417. }
  418.  
  419. void cSprite :: Save_to_Stream( ofstream &file )
  420. {
  421.     // begin sprite
  422.     file << "\t<sprite>" << std::endl;
  423.  
  424.     // position
  425.     file << "\t\t<Property name=\"posx\" value=\"" << static_cast<int>(startposx) << "\" />" << std::endl;
  426.     file << "\t\t<Property name=\"posy\" value=\"" << static_cast<int>(startposy) << "\" />" << std::endl;
  427.     // image
  428.     string img_filename;
  429.  
  430.     if( start_image )
  431.     {
  432.         img_filename = start_image->filename;
  433.     }
  434.     else if( image )
  435.     {
  436.         img_filename = image->filename;
  437.     }
  438.     else
  439.     {
  440.         printf( "Warning: cSprite::Save_to_Stream no image from type %d\n", type );
  441.     }
  442.  
  443.     // remove pixmaps directory from string
  444.     if( img_filename.find( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) == 0 )
  445.     {
  446.         img_filename.erase( 0, strlen( DATA_DIR "/" GAME_PIXMAPS_DIR "/" ) );
  447.     }
  448.     file << "\t\t<Property name=\"image\" value=\"" << img_filename << "\" />" << std::endl;
  449.     // type
  450.     file << "\t\t<Property name=\"type\" value=\"" << Get_Sprite_Type_String() << "\" />" << std::endl;
  451.  
  452.     // end sprite
  453.     file << "\t</sprite>" << std::endl;
  454. }
  455.  
  456. void cSprite :: Load_from_Savegame( cSave_Level_Object *save_object )
  457. {
  458.     // virtual
  459. }
  460.  
  461. cSave_Level_Object *cSprite :: Save_to_Savegame( void )
  462. {
  463.     return NULL;
  464. }
  465.  
  466. void cSprite :: Set_Image( GL_Surface *new_image, bool new_start_image /* = 0 */, bool del_img /* = 0 */ )
  467. {
  468.     if( delete_image )
  469.     {
  470.         if( image )
  471.         {
  472.             // if same image reset start_image
  473.             if( start_image == image )
  474.             {
  475.                 start_image = NULL;
  476.             }
  477.  
  478.             delete image;
  479.             image = NULL;
  480.         }
  481.  
  482.         delete_image = 0;
  483.     }
  484.  
  485.     image = new_image;
  486.  
  487.     if( image )
  488.     {
  489.         // collision data
  490.         col_pos = image->col_pos;
  491.         // scale affects the rect
  492.         if( scale_affects_rect )
  493.         {
  494.             col_rect.w = image->col_w * scalex;
  495.             col_rect.h = image->col_h * scaley;
  496.             // image data
  497.             rect.w = image->w * scalex;
  498.             rect.h = image->h * scaley;
  499.         }
  500.         // scale does not affect the rect
  501.         else
  502.         {
  503.             col_rect.w = image->col_w;
  504.             col_rect.h = image->col_h;
  505.             // image data
  506.             rect.w = image->w;
  507.             rect.h = image->h;
  508.         }
  509.         // rotation affects the rect
  510.         if( rotation_affects_rect )
  511.         {
  512.             Update_Rect_Rotation();
  513.         }
  514.  
  515.         delete_image = del_img;
  516.  
  517.         // if no name is set use the first image name
  518.         if( !name.length() )
  519.         {
  520.             name = image->name;
  521.         }
  522.         // if no editor tags are set use the first image editor tags
  523.         if( !editor_tags.length() )
  524.         {
  525.             editor_tags = image->editor_tags;
  526.         }
  527.     }
  528.     else
  529.     {
  530.         // clear image data
  531.         col_pos.x = 0;
  532.         col_pos.y = 0;
  533.         col_rect.w = 0;
  534.         col_rect.h = 0;
  535.         rect.w = 0;
  536.         rect.h = 0;
  537.     }
  538.  
  539.     if( !start_image || new_start_image )
  540.     {
  541.         start_image = new_image;
  542.  
  543.         if( new_image )
  544.         {
  545.             start_rect.w = new_image->w;
  546.             start_rect.h = new_image->h;
  547.         }
  548.         else
  549.         {
  550.             start_rect.w = 0;
  551.             start_rect.h = 0;
  552.         }
  553.     }
  554.     
  555.     // because col_pos could have changed
  556.     Update_Position_Rect();
  557. }
  558.  
  559. void cSprite :: Set_Sprite_Type( SpriteType ntype )
  560. {
  561.     // set first because of massivetype z calculation
  562.     type = ntype;
  563.  
  564.     if( ntype == TYPE_MASSIVE )
  565.     {
  566.         sprite_array = ARRAY_MASSIVE;
  567.         Set_Massive_Type( MASS_MASSIVE );
  568.         can_be_ground = 1;
  569.     }
  570.     else if( ntype == TYPE_PASSIVE )
  571.     {
  572.         sprite_array = ARRAY_PASSIVE;
  573.         Set_Massive_Type( MASS_PASSIVE );
  574.         can_be_ground = 0;
  575.     }
  576.     else if( ntype == TYPE_FRONT_PASSIVE )
  577.     {
  578.         sprite_array = ARRAY_FRONT_PASSIVE;
  579.         Set_Massive_Type( MASS_PASSIVE );
  580.         can_be_ground = 0;
  581.     }
  582.     else if( ntype == TYPE_HALFMASSIVE )
  583.     {
  584.         sprite_array = ARRAY_ACTIVE;
  585.         Set_Massive_Type( MASS_HALFMASSIVE );
  586.         can_be_ground = 1;
  587.     }
  588.     else if( ntype == TYPE_CLIMBABLE )
  589.     {
  590.         sprite_array = ARRAY_ACTIVE;
  591.         Set_Massive_Type( MASS_CLIMBABLE );
  592.         can_be_ground = 0;
  593.     }
  594. }
  595.  
  596. string cSprite :: Get_Sprite_Type_String( void )
  597. {
  598.     if( sprite_array == ARRAY_PASSIVE )
  599.     {
  600.         return "passive";
  601.     }
  602.     else if( sprite_array == ARRAY_FRONT_PASSIVE )
  603.     {
  604.         return "front_passive";
  605.     }
  606.     else if( sprite_array == ARRAY_ACTIVE )
  607.     {
  608.         if( type == TYPE_HALFMASSIVE )
  609.         {
  610.             return "halfmassive";
  611.         }
  612.         else if( type == TYPE_CLIMBABLE )
  613.         {
  614.             return "climbable";
  615.         }
  616.         else
  617.         {
  618.             printf( "Warning : Sprite array set as active but unknown type %d\n", type );
  619.         }
  620.     }
  621.     else if( sprite_array == ARRAY_MASSIVE )
  622.     {
  623.         return "massive";
  624.     }
  625.     else
  626.     {
  627.         printf( "Warning : Sprite unknown array %d\n", sprite_array );
  628.     }
  629.  
  630.     return "";
  631. }
  632.  
  633. void cSprite :: Set_Ignore_Camera( bool enable /* = 0 */ )
  634. {
  635.     // already set
  636.     if( no_camera == enable )
  637.     {
  638.         return;
  639.     }
  640.  
  641.     no_camera = enable;
  642.  
  643.     Update_Valid_Draw();
  644. }
  645.  
  646. void cSprite :: Set_Pos( float x, float y, bool new_startpos /* = 0 */ )
  647. {
  648.     posx = x;
  649.     posy = y;
  650.  
  651.     if( new_startpos || ( startposx == 0 && startposy == 0 ) )
  652.     {
  653.         startposx = x;
  654.         startposy = y;
  655.     }
  656.  
  657.     Update_Position_Rect();
  658. }
  659.  
  660. void cSprite :: Set_Pos_X( float x, bool new_startpos /* = 0 */ )
  661. {
  662.     posx = x;
  663.  
  664.     if( new_startpos )
  665.     {
  666.         startposx = x;
  667.     }
  668.  
  669.     Update_Position_Rect();
  670. }
  671.  
  672. void cSprite :: Set_Pos_Y( float y, bool new_startpos /* = 0 */ )
  673. {
  674.     posy = y;
  675.  
  676.     if( new_startpos )
  677.     {
  678.         startposy = y;
  679.     }
  680.  
  681.     Update_Position_Rect();
  682. }
  683.  
  684. void cSprite :: Set_Visible( bool enabled )
  685. {
  686.     // already set
  687.     if( visible == enabled )
  688.     {
  689.         return;
  690.     }
  691.  
  692.     visible = enabled;
  693.  
  694.     Update_Valid_Draw();
  695.     Update_Valid_Update();
  696. }
  697.  
  698. void cSprite :: Set_Shadow( Color shadow, float pos )
  699. {
  700.     Set_Shadow_Pos( pos );
  701.     Set_Shadow_Color( shadow );
  702. }
  703.  
  704. void cSprite :: Set_Shadow_Pos( float pos )
  705. {
  706.     shadow_pos = pos;
  707. }
  708.  
  709. void cSprite :: Set_Shadow_Color( Color shadow )
  710. {
  711.     shadow_color = shadow;
  712. }
  713.  
  714. void cSprite :: Set_Color( Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha /* = 255 */ )
  715. {
  716.     color.red = red;
  717.     color.green = green;
  718.     color.blue = blue;
  719.     color.alpha = alpha;
  720. }
  721.  
  722. void cSprite :: Set_Color( Color col )
  723. {
  724.     color = col;
  725. }
  726.  
  727. void cSprite :: Set_Color_Combine( float red, float green, float blue, GLint com_type )
  728. {
  729.     combine_type = com_type;
  730.     combine_col[0] = red;
  731.     combine_col[1] = green;
  732.     combine_col[2] = blue;
  733.  
  734.     // red limits
  735.     if( combine_col[0] > 1 )
  736.     {
  737.         combine_col[0] = 1;
  738.     }
  739.     else if( combine_col[0] <= 0 )
  740.     {
  741.         combine_col[0] = 0.000001f;
  742.     }
  743.     // green limits
  744.     if( combine_col[1] > 1 )
  745.     {
  746.         combine_col[1] = 1;
  747.     }
  748.     else if( combine_col[1] <= 0 )
  749.     {
  750.         combine_col[1] = 0.000001f;
  751.     }
  752.     // blue limits
  753.     if( combine_col[2] > 1 )
  754.     {
  755.         combine_col[2] = 1;
  756.     }
  757.     else if( combine_col[2] <= 0 )
  758.     {
  759.         combine_col[2] = 0.000001f;
  760.     }
  761. }
  762.  
  763. void cSprite :: Set_Rotation_affects_Rect( bool enable /* = 0 */ )
  764. {
  765.     rotation_affects_rect = enable;
  766. }
  767.  
  768. void cSprite :: Update_Rect_Rotation( void )
  769. {
  770.     // Z must be first for correct rotation ( see Eato )
  771.     Update_Rect_Rotation_Z();
  772.     Update_Rect_Rotation_X();
  773.     Update_Rect_Rotation_Y();
  774. }
  775.  
  776. void cSprite :: Update_Rect_Rotation_X( void )
  777. {
  778.     // mirror
  779.     if( rotx >= 180 )
  780.     {
  781.         col_pos.y = rect.h - ( col_rect.h + col_pos.y );
  782.     }
  783. }
  784.  
  785. void cSprite :: Update_Rect_Rotation_Y( void )
  786. {
  787.     // mirror
  788.     if( roty >= 180 )
  789.     {
  790.         col_pos.x = rect.w - ( col_rect.w + col_pos.x );
  791.     }
  792. }
  793.  
  794. void cSprite :: Update_Rect_Rotation_Z( void )
  795. {
  796.     // rotate 270░
  797.     if( rotz >= 270 )
  798.     {
  799.         // rotate collision position
  800.         float orig_x = col_pos.x;
  801.         col_pos.x = col_pos.y;
  802.         col_pos.y = orig_x;
  803.  
  804.         // switch width and height
  805.         float orig_w = rect.w;
  806.         rect.w = rect.h;
  807.         rect.h = orig_w;
  808.         // switch collision width and height
  809.         float orig_col_w = col_rect.w;
  810.         col_rect.w = col_rect.h;
  811.         col_rect.h = orig_col_w;
  812.     }
  813.     // mirror
  814.     else if( rotz >= 180 )
  815.     {
  816.         col_pos.y = rect.h - ( col_rect.h + col_pos.y );
  817.     }
  818.     // rotate 90░
  819.     else if( rotz >= 0.00001f )
  820.     {
  821.         // rotate collision position
  822.         float orig_x = col_pos.x;
  823.         col_pos.x = rect.h - ( col_rect.h + col_pos.y );
  824.         col_pos.y = orig_x;
  825.  
  826.         // switch width and height
  827.         float orig_w = rect.w;
  828.         rect.w = rect.h;
  829.         rect.h = orig_w;
  830.         // switch collision width and height
  831.         float orig_col_w = col_rect.w;
  832.         col_rect.w = col_rect.h;
  833.         col_rect.h = orig_col_w;
  834.     }
  835. }
  836.  
  837. void cSprite :: Set_Rotation_X( float rot, bool new_start_rot /* = 0 */ )
  838. {
  839.     rotx = fmod( rot, 360 );
  840.  
  841.     if( new_start_rot )
  842.     {
  843.         start_rotx = rotx;
  844.     }
  845.  
  846.     if( rotation_affects_rect )
  847.     {
  848.         Update_Rect_Rotation_X();
  849.     }
  850. }
  851.  
  852. void cSprite :: Set_Rotation_Y( float rot, bool new_start_rot /* = 0 */ )
  853. {
  854.     roty = fmod( rot, 360 );
  855.  
  856.     if( new_start_rot )
  857.     {
  858.         start_roty = roty;
  859.     }
  860.  
  861.     if( rotation_affects_rect )
  862.     {
  863.         Update_Rect_Rotation_Y();
  864.     }
  865. }
  866.  
  867. void cSprite :: Set_Rotation_Z( float rot, bool new_start_rot /* = 0 */ )
  868. {
  869.     rotz = fmod( rot, 360 );
  870.  
  871.     if( new_start_rot )
  872.     {
  873.         start_rotz = rotz;
  874.     }
  875.  
  876.     if( rotation_affects_rect )
  877.     {
  878.         Update_Rect_Rotation_Z();
  879.     }
  880. }
  881.  
  882. void cSprite :: Set_Rotation( float x, float y, float z, bool new_start_rot /* = 0 */ )
  883. {
  884.     Set_Rotation_X( x, new_start_rot );
  885.     Set_Rotation_Y( y, new_start_rot );
  886.     Set_Rotation_Z( z, new_start_rot );
  887. }
  888.  
  889. void cSprite :: Add_Rotation_X( float rot )
  890. {
  891.     Set_Rotation_X( rotx + rot );
  892. }
  893.  
  894. void cSprite :: Add_Rotation_Y( float rot )
  895. {
  896.     Set_Rotation_Y( roty + rot );
  897. }
  898.  
  899. void cSprite :: Add_Rotation_Z( float rot )
  900. {
  901.     Set_Rotation_Z( rotz + rot );
  902. }
  903.  
  904. void cSprite :: Add_Rotation( float x, float y, float z )
  905. {
  906.     Set_Rotation_X( rotx + x );
  907.     Set_Rotation_Y( roty + y );
  908.     Set_Rotation_Z( rotz + z );
  909. }
  910.  
  911. void cSprite :: Set_Scale_affects_Rect( bool enable /* = 0 */ )
  912. {
  913.     scale_affects_rect = enable;
  914. }
  915.  
  916. void cSprite :: Set_Scale_Directions( bool up /* = 1 */, bool down /* = 0 */, bool left /* = 1 */, bool right /* = 0 */ )
  917. {
  918.     scale_up = up;
  919.     scale_down = down;
  920.     scale_left = left;
  921.     scale_right = right;
  922. }
  923.  
  924. void cSprite :: Set_Scale_X( const float scale, const bool new_startscale /* = 0 */ )
  925. {
  926.     // invalid value
  927.     if( scale == 0 )
  928.     {
  929.         return;
  930.     }
  931.  
  932.     // undo previous scale from rect
  933.     if( scale_affects_rect && scalex != 1 )
  934.     {
  935.         col_rect.w /= scalex;
  936.         rect.w /= scalex;
  937.     }
  938.  
  939.     scalex = scale;
  940.  
  941.     // set new scale to rect
  942.     if( scale_affects_rect && scalex != 1 )
  943.     {
  944.         col_rect.w *= scalex;
  945.         rect.w *= scalex;
  946.     }
  947.  
  948.     if( new_startscale )
  949.     {
  950.         start_scalex = scalex;
  951.     }
  952. }
  953.  
  954. void cSprite :: Set_Scale_Y( const float scale, const bool new_startscale /* = 0 */ )
  955. {
  956.     // invalid value
  957.     if( scale == 0 )
  958.     {
  959.         return;
  960.     }
  961.  
  962.     // undo previous scale from rect
  963.     if( scale_affects_rect && scaley != 1 )
  964.     {
  965.         col_rect.h /= scaley;
  966.         rect.h /= scaley;
  967.     }
  968.  
  969.     scaley = scale;
  970.  
  971.     // set new scale to rect
  972.     if( scale_affects_rect && scaley != 1 )
  973.     {
  974.         col_rect.h *= scaley;
  975.         rect.h *= scaley;
  976.     }
  977.  
  978.     if( new_startscale )
  979.     {
  980.         start_scaley = scaley;
  981.     }
  982. }
  983.  
  984. void cSprite :: Set_Scale( const float scale, const bool new_startscale /* = 0 */ )
  985. {
  986.     Set_Scale_X( scale, new_startscale );
  987.     Set_Scale_Y( scale, new_startscale );
  988. }
  989.  
  990. void cSprite :: Add_Scale_X( const float val )
  991. {
  992.     Set_Scale_X( scalex + val );
  993. }
  994.  
  995. void cSprite :: Add_Scale_Y( const float val )
  996. {
  997.     Set_Scale_Y( scaley + val );
  998. }
  999.  
  1000. void cSprite :: Add_Scale( const float val )
  1001. {
  1002.     Set_Scale_X( scalex + val );
  1003.     Set_Scale_Y( scaley + val );
  1004. }
  1005.  
  1006. void cSprite :: Set_on_Top( const cSprite *sprite, bool optimize_hor_pos /* = 1 */ )
  1007. {
  1008.     // set ground position 0.1f over it
  1009.     posy = sprite->col_rect.y - col_pos.y - col_rect.h - 0.1f;
  1010.  
  1011.     // optimize the horizontal position if given
  1012.     if( optimize_hor_pos && ( posx < sprite->posx || posx > sprite->posx + sprite->col_rect.w ) )
  1013.     {
  1014.         posx = sprite->posx + sprite->col_rect.w / 3;
  1015.     }
  1016.  
  1017.     Update_Position_Rect();
  1018. }
  1019.  
  1020. void cSprite :: Move( float move_x, float move_y, const bool real /* = 0 */ )
  1021. {
  1022.     if( move_x == 0 && move_y == 0 )
  1023.     {
  1024.         return;
  1025.     }
  1026.  
  1027.     if( !real )
  1028.     {
  1029.         move_x *= pFramerate->speedfactor;
  1030.         move_y *= pFramerate->speedfactor;
  1031.     }
  1032.  
  1033.     posx += move_x;
  1034.     posy += move_y;
  1035.  
  1036.     Update_Position_Rect();
  1037. }
  1038.  
  1039. void cSprite :: Collide_Move( void )
  1040. {
  1041.     // virtual
  1042. }
  1043.  
  1044. void cSprite :: Update_Position_Rect( void )
  1045. {
  1046.     // if not editor mode
  1047.     if( !editor_enabled )
  1048.     {
  1049.         rect.x = posx;
  1050.         rect.y = posy;
  1051.         // editor rect
  1052.         start_rect.x = posx;
  1053.         start_rect.y = posy;
  1054.         // collision rect
  1055.         col_rect.x = posx + col_pos.x;
  1056.         col_rect.y = posy + col_pos.y;
  1057.     }
  1058.     // editor mode
  1059.     else
  1060.     {
  1061.         rect.x = startposx;
  1062.         rect.y = startposy;
  1063.         start_rect.x = startposx;
  1064.         start_rect.y = startposy;
  1065.         // Don't use startposx/startposy because col_rect is not the editor/start rect
  1066.         col_rect.x = posx + col_pos.x; // todo : startcol_pos ?
  1067.         col_rect.y = posy + col_pos.y;
  1068.     }
  1069.  
  1070.     Update_Valid_Draw();
  1071. }
  1072.  
  1073. void cSprite :: Update( void )
  1074. {
  1075.     // virtual
  1076. }
  1077.  
  1078. void cSprite :: Update_Valid_Draw( void )
  1079. {
  1080.     valid_draw = Is_Draw_Valid();
  1081. }
  1082.  
  1083. void cSprite :: Update_Valid_Update( void )
  1084. {
  1085.     valid_update = Is_Update_Valid();
  1086. }
  1087.  
  1088. void cSprite :: Draw( cSurfaceRequest *request /* = NULL */ )
  1089. {
  1090.     if( !valid_draw )
  1091.     {
  1092.         return;
  1093.     }
  1094.  
  1095.     Draw_Image( request );
  1096.  
  1097.     // draw debugging collision rects
  1098.     if( game_debug )
  1099.     {
  1100.         // - image rect
  1101.         // create request
  1102.         cRectRequest *rect_request = new cRectRequest();
  1103.         // draw
  1104.         pVideo->Draw_Rect( &rect, posz + 0.000002f, &lightgrey, rect_request );
  1105.         rect_request->no_camera = no_camera;
  1106.         rect_request->filled = 0;
  1107.         rect_request->blend_sfactor = GL_SRC_COLOR;
  1108.         rect_request->blend_dfactor = GL_DST_ALPHA;
  1109.         // scale
  1110.         if( !scale_affects_rect )
  1111.         {
  1112.             // scale position y
  1113.             if( scale_up )
  1114.             {
  1115.                 rect_request->rect.y += ( image->int_y * scaley ) - ( ( image->h * 0.5f ) * ( scaley - 1 ) );
  1116.             }
  1117.  
  1118.             // scale height
  1119.             if( scale_down )
  1120.             {
  1121.                 rect_request->rect.h += image->h * ( scaley - 1 );
  1122.             }
  1123.  
  1124.             // scale position x
  1125.             if( scale_left )
  1126.             {
  1127.                 rect_request->rect.x += ( image->int_x * scalex ) - ( ( image->w * 0.5f ) * ( scalex - 1 ) );
  1128.             }
  1129.  
  1130.             // scale width
  1131.             if( scale_right )
  1132.             {
  1133.                 rect_request->rect.w += image->w * ( scalex - 1 );
  1134.             }
  1135.         }
  1136.         // add request
  1137.         pRenderer->Add( rect_request );
  1138.  
  1139.         // - collision rect
  1140.         // create request
  1141.         rect_request = new cRectRequest();
  1142.         // draw
  1143.         Color sprite_color = Get_Sprite_Color( this );
  1144.         pVideo->Draw_Rect( &col_rect, posz + 0.000001f, &sprite_color, rect_request );
  1145.         rect_request->no_camera = no_camera;
  1146.         // blending
  1147.         rect_request->blend_sfactor = GL_SRC_COLOR;
  1148.         rect_request->blend_dfactor = GL_DST_ALPHA;
  1149.  
  1150.         // add request
  1151.         pRenderer->Add( rect_request );
  1152.     }
  1153.  
  1154.     // no editor drawing
  1155.     if( !editor_enabled )
  1156.     {
  1157.         // draw debug rect
  1158.         if( game_debug )
  1159.         {
  1160.             if( type == TYPE_PLAYER )
  1161.             {
  1162.                 // Get Moving Sprite
  1163.                 cMovingSprite *moving_sprite = static_cast<cMovingSprite *>(this);
  1164.  
  1165.                 // if on ground
  1166.                 if( moving_sprite->ground_object )
  1167.                 {
  1168.                     // create request
  1169.                     cRectRequest *rect_request = new cRectRequest();
  1170.                     // draw
  1171.                     pVideo->Draw_Rect( &moving_sprite->ground_object->col_rect, posz + 0.000002f, &grey, rect_request );
  1172.                     rect_request->no_camera = 0;
  1173.                     // blending
  1174.                     rect_request->blend_sfactor = GL_SRC_COLOR;
  1175.                     rect_request->blend_dfactor = GL_DST_ALPHA;
  1176.  
  1177.                     // add request
  1178.                     pRenderer->Add( rect_request );
  1179.                 }
  1180.             }
  1181.         }
  1182.     }
  1183.     // show obsolete images in editor
  1184.     else if( image && image->obsolete )
  1185.     {
  1186.         // create request
  1187.         cRectRequest *rect_request = new cRectRequest();
  1188.         // draw
  1189.         pVideo->Draw_Rect( &col_rect, posz + 0.000001f, &red, rect_request );
  1190.         rect_request->no_camera = 0;
  1191.  
  1192.         // blending
  1193.         rect_request->blend_sfactor = GL_SRC_COLOR;
  1194.         rect_request->blend_dfactor = GL_DST_ALPHA;
  1195.  
  1196.         // add request
  1197.         pRenderer->Add( rect_request );
  1198.     }
  1199. }
  1200.  
  1201. void cSprite :: Draw_Image( cSurfaceRequest *request /* = NULL */ )
  1202. {
  1203.     if( !valid_draw )
  1204.     {
  1205.         return;
  1206.     }
  1207.  
  1208.     bool create_request = 0;
  1209.  
  1210.     if( !request )
  1211.     {
  1212.         create_request = 1;
  1213.         // create request
  1214.         request = new cSurfaceRequest();
  1215.     }
  1216.  
  1217.     // editor
  1218.     if( editor_enabled )
  1219.     {
  1220.         // blit surface
  1221.         start_image->Blit_Data( request );
  1222.  
  1223.         // rotation
  1224.         request->rotx += start_rotx;
  1225.         request->roty += start_roty;
  1226.         request->rotz += start_rotz;
  1227.         // position x and
  1228.         // scalex
  1229.         if( start_scalex != 1 )
  1230.         {
  1231.             // scale to the right and left
  1232.             if( scale_right && scale_left )
  1233.             {
  1234.                 request->scale_x = start_scalex;
  1235.                 request->pos_x = startposx + ( start_image->int_x * start_scalex ) - ( ( start_image->w * 0.5f ) * ( start_scalex - 1 ) );
  1236.             }
  1237.             // scale to the right only
  1238.             else if( scale_right )
  1239.             {
  1240.                 request->scale_x = start_scalex;
  1241.                 request->pos_x = startposx + ( start_image->int_x * start_scalex );
  1242.             }
  1243.             // scale to the left only
  1244.             else if( scale_left )
  1245.             {
  1246.                 request->scale_x = start_scalex;
  1247.                 request->pos_x = startposx + ( start_image->int_x * start_scalex ) - ( ( start_image->w ) * ( start_scalex - 1 ) );
  1248.             }
  1249.             // no scaling
  1250.             else
  1251.             {
  1252.                 request->pos_x = startposx + start_image->int_x;
  1253.             }
  1254.         }
  1255.         // no scalex
  1256.         else
  1257.         {
  1258.             request->pos_x = startposx + start_image->int_x;
  1259.         }
  1260.         // position y and
  1261.         // scaley
  1262.         if( start_scaley != 1 )
  1263.         {
  1264.             // scale down and up
  1265.             if( scale_down && scale_up )
  1266.             {
  1267.                 request->scale_y = start_scaley;
  1268.                 request->pos_y = startposy + ( start_image->int_y * start_scaley ) - ( ( start_image->h * 0.5f ) * ( start_scaley - 1 ) );
  1269.             }
  1270.             // scale down only
  1271.             else if( scale_down )
  1272.             {
  1273.                 request->scale_y = start_scaley;
  1274.                 request->pos_y = startposy + ( start_image->int_y * start_scaley );
  1275.             }
  1276.             // scale up only
  1277.             else if( scale_up )
  1278.             {
  1279.                 request->scale_y = start_scaley;
  1280.                 request->pos_y = startposy + ( start_image->int_y * start_scaley ) - ( ( start_image->h ) * ( start_scaley - 1 ) );
  1281.             }
  1282.             // no scaling
  1283.             else
  1284.             {
  1285.                 request->pos_y = startposy + start_image->int_y;
  1286.             }
  1287.         }
  1288.         // no scaley
  1289.         else
  1290.         {
  1291.             request->pos_y = startposy + start_image->int_y;
  1292.         }
  1293.     
  1294.         // if editor z position is given
  1295.         if( editor_posz > 0 )
  1296.         {
  1297.             request->pos_z = editor_posz;
  1298.         }
  1299.         // normal position z
  1300.         else
  1301.         {
  1302.             request->pos_z = posz;
  1303.         }
  1304.     }
  1305.     // no editor
  1306.     else
  1307.     {
  1308.         // blit surface
  1309.         image->Blit_Data( request );
  1310.  
  1311.         // rotation
  1312.         request->rotx += rotx;
  1313.         request->roty += roty;
  1314.         request->rotz += rotz;
  1315.         // position x and
  1316.         // scalex
  1317.         if( scalex != 1 )
  1318.         {
  1319.             // scale to the right and left
  1320.             if( scale_right && scale_left )
  1321.             {
  1322.                 request->scale_x = scalex;
  1323.                 request->pos_x = posx + ( image->int_x * scalex ) - ( ( image->w * 0.5f ) * ( scalex - 1 ) );
  1324.             }
  1325.             // scale to the right only
  1326.             else if( scale_right )
  1327.             {
  1328.                 request->scale_x = scalex;
  1329.                 request->pos_x = posx + ( image->int_x * scalex );
  1330.             }
  1331.             // scale to the left only
  1332.             else if( scale_left )
  1333.             {
  1334.                 request->scale_x = scalex;
  1335.                 request->pos_x = posx + ( image->int_x * scalex ) - ( ( image->w ) * ( scalex - 1 ) );
  1336.             }
  1337.             // no scaling
  1338.             else
  1339.             {
  1340.                 request->pos_x = posx + image->int_x;
  1341.             }
  1342.         }
  1343.         // no scalex
  1344.         else
  1345.         {
  1346.             request->pos_x = posx + image->int_x;
  1347.         }
  1348.         // position y and
  1349.         // scaley
  1350.         if( scaley != 1 )
  1351.         {
  1352.             // scale down and up
  1353.             if( scale_down && scale_up )
  1354.             {
  1355.                 request->scale_y = scaley;
  1356.                 request->pos_y = posy + ( image->int_y * scaley ) - ( ( image->h * 0.5f ) * ( scaley - 1 ) );
  1357.             }
  1358.             // scale down only
  1359.             else if( scale_down )
  1360.             {
  1361.                 request->scale_y = scaley;
  1362.                 request->pos_y = posy + ( image->int_y * scaley );
  1363.             }
  1364.             // scale up only
  1365.             else if( scale_up )
  1366.             {
  1367.                 request->scale_y = scaley;
  1368.                 request->pos_y = posy + ( image->int_y * scaley ) - ( ( image->h ) * ( scaley - 1 ) );
  1369.             }
  1370.             // no scaling
  1371.             else
  1372.             {
  1373.                 request->pos_y = posy + image->int_y;
  1374.             }
  1375.         }
  1376.         // no scaley
  1377.         else
  1378.         {
  1379.             request->pos_y = posy + image->int_y;
  1380.         }
  1381.     
  1382.         // position z
  1383.         request->pos_z = posz;
  1384.     }
  1385.  
  1386.     // no camera setting
  1387.     request->no_camera = no_camera;
  1388.  
  1389.     // color
  1390.     request->color = color;
  1391.     // combine color
  1392.     if( combine_type )
  1393.     {
  1394.         request->combine_type = combine_type;
  1395.         request->combine_col[0] = combine_col[0];
  1396.         request->combine_col[1] = combine_col[1];
  1397.         request->combine_col[2] = combine_col[2];
  1398.     }
  1399.  
  1400.     // shadow
  1401.     if( shadow_pos )
  1402.     {
  1403.         request->shadow_pos = shadow_pos;
  1404.         request->shadow_color = shadow_color;
  1405.     }
  1406.  
  1407.     if( create_request )
  1408.     {
  1409.         // add request
  1410.         pRenderer->Add( request );
  1411.     }
  1412. }
  1413.  
  1414. void cSprite :: Set_Massive_Type( MassiveType mtype )
  1415. {
  1416.     // set massivetype z position
  1417.     if( mtype == MASS_MASSIVE )
  1418.     {
  1419.         posz = 0.08f;
  1420.     }
  1421.     else if( mtype == MASS_PASSIVE )
  1422.     {
  1423.         if( sprite_array == ARRAY_FRONT_PASSIVE )
  1424.         {
  1425.             posz = 0.1f;
  1426.         }
  1427.         else
  1428.         {
  1429.             posz = 0.01f;
  1430.         }
  1431.     }
  1432.     else if( mtype == MASS_CLIMBABLE || mtype == MASS_HALFMASSIVE )
  1433.     {
  1434.         posz = 0.04f;
  1435.     }
  1436.  
  1437.     massivetype = mtype;
  1438.  
  1439.     // set correct Z position
  1440.     pActive_Sprite_Manager->Set_Z( this );
  1441. }
  1442.  
  1443. bool cSprite :: Is_on_Top( const cSprite *obj )
  1444. {
  1445.     // invalid
  1446.     if( !obj )
  1447.     {
  1448.         return 0;
  1449.     }
  1450.  
  1451.     // always collide upwards because of the image size collision checking
  1452.     if( col_rect.x + col_rect.w > obj->col_rect.x && col_rect.x < obj->col_rect.x + obj->col_rect.w &&
  1453.         col_rect.y + col_rect.h < obj->col_rect.y )
  1454.     {
  1455.         return 1;
  1456.     }
  1457.  
  1458.     return 0;
  1459. }
  1460.  
  1461. bool cSprite :: Is_Visible_on_Screen( void )
  1462. {
  1463.     // camera position
  1464.     float cam_x = 0, cam_y = 0;
  1465.  
  1466.     if( !no_camera )
  1467.     {
  1468.         cam_x = pActive_Camera->x;
  1469.         cam_y = pActive_Camera->y;
  1470.     }
  1471.  
  1472.     // not visible left
  1473.     if( rect.x + rect.w < cam_x )
  1474.     {
  1475.         return 0;
  1476.     }
  1477.     // not visible right
  1478.     else if( rect.x > cam_x + game_res_w )
  1479.     {
  1480.         return 0;
  1481.     }
  1482.     // not visible down
  1483.     else if( rect.y + rect.h < cam_y )
  1484.     {
  1485.         return 0;
  1486.     }
  1487.     // not visible up
  1488.     else if( rect.y > cam_y + game_res_h )
  1489.     {
  1490.         return 0;
  1491.     }
  1492.  
  1493.     return 1;
  1494. }
  1495.  
  1496. bool cSprite :: is_Player_range( void )
  1497. {
  1498.     // no player range set
  1499.     if( player_range < 300 )
  1500.     {
  1501.         return Is_Visible_on_Screen();
  1502.     }
  1503.     // check if not in range
  1504.     else if( posx < pPlayer->posx - player_range || posy < pPlayer->posy - player_range ||
  1505.         posx > pPlayer->posx + player_range || posy > pPlayer->posy + player_range )
  1506.     {
  1507.         return 0;
  1508.     }
  1509.  
  1510.     // is in range
  1511.     return 1;
  1512. }
  1513.  
  1514. bool cSprite :: Is_Update_Valid( void )
  1515. {
  1516.     // if destroyed
  1517.     if( destroy )
  1518.     {
  1519.         return 0;
  1520.     }
  1521.  
  1522.     return 1;
  1523. }
  1524.  
  1525. bool cSprite :: Is_Draw_Valid( void )
  1526. {
  1527.     // if editor not enabled
  1528.     if( !editor_enabled )
  1529.     {
  1530.         // not visible
  1531.         if( !visible || !image )
  1532.         {
  1533.             return 0;
  1534.         }
  1535.     }
  1536.     // editor enabled
  1537.     else
  1538.     {
  1539.         // no image
  1540.         if( !start_image )
  1541.         {
  1542.             return 0;
  1543.         }
  1544.     }
  1545.  
  1546.     // not visible on the screen
  1547.     if( !Is_Visible_on_Screen() )
  1548.     {
  1549.         return 0;
  1550.     }
  1551.  
  1552.     return 1;
  1553. }
  1554.  
  1555. void cSprite :: Destroy( void )
  1556. {
  1557.     destroy = 1;
  1558.     visible = 0;
  1559.     valid_draw = 0;
  1560.     valid_update = 0;
  1561.     Set_Image( NULL, 1 );
  1562. }
  1563.  
  1564. void cSprite :: Editor_Add( const CEGUI::String name, const CEGUI::String tooltip, CEGUI::Window *window_setting, float obj_width, float obj_height /* = 28 */, bool advance_row /* = 1 */ )
  1565. {
  1566.     if( obj_height < 28 )
  1567.     {
  1568.         obj_height = 28;
  1569.     }
  1570.  
  1571.     // get gui sheet
  1572.     CEGUI::Window *guisheet = pGuiSystem->getGUISheet();
  1573.     // get window manager
  1574.     CEGUI::WindowManager &wmgr = CEGUI::WindowManager::getSingleton();
  1575.  
  1576.     // create name window
  1577.     CEGUI::Window *window_name = wmgr.createWindow( "TaharezLook/StaticText", "text_" + window_setting->getName() );
  1578.     window_name->setText( name );
  1579.     window_name->setTooltipText( tooltip );
  1580.     // get text width
  1581.     CEGUI::Font *font = CEGUI::FontManager::getSingleton().getFont( "bluebold_medium" );
  1582.     float text_width = 12 + font->getTextExtent( name ) * global_downscalex;
  1583.     // all names should have the same width
  1584.     if( text_width > editor_window_name_width )
  1585.     {
  1586.         editor_window_name_width = text_width;
  1587.     }
  1588.     // set size
  1589.     window_name->setWidth( CEGUI::UDim( 0, text_width * global_upscalex ) );
  1590.     window_name->setHeight( CEGUI::UDim( 0, 28 * global_upscaley ) );
  1591.  
  1592.     // create settings window
  1593.     cEditor_Object_Settings_Item *settings_item = new cEditor_Object_Settings_Item();
  1594.  
  1595.     // set size
  1596.     window_setting->setWidth( CEGUI::UDim( 0, obj_width * global_upscalex ) );
  1597.     window_setting->setHeight( CEGUI::UDim( 0, obj_height * global_upscaley ) );
  1598.  
  1599.     settings_item->window_name = window_name;
  1600.     settings_item->window_setting = window_setting;
  1601.     settings_item->advance_row = advance_row;
  1602.  
  1603.     editor_windows.push_back( settings_item );
  1604.  
  1605.     // add to main window
  1606.     guisheet->addChildWindow( window_name );
  1607.     guisheet->addChildWindow( window_setting );
  1608. }
  1609.  
  1610. void cSprite :: Editor_Activate( void )
  1611. {
  1612.     // virtual
  1613. }
  1614.  
  1615. void cSprite :: Editor_Deactivate( void )
  1616. {
  1617.     // remove editor controls
  1618.  
  1619.     for( Editor_Object_Settings_List::iterator itr = editor_windows.begin(), itr_end = editor_windows.end(); itr != itr_end; ++itr )
  1620.     {
  1621.         cEditor_Object_Settings_Item *obj = (*itr);
  1622.  
  1623.         delete obj;
  1624.     }
  1625.  
  1626.     editor_windows.clear();
  1627. }
  1628.  
  1629. void cSprite :: Editor_Position_Update( void )
  1630. {
  1631.     float obj_posx = 0;
  1632.     float obj_posy = 0;
  1633.     float row_height = 0;
  1634.  
  1635.     // set all positions
  1636.     for( Editor_Object_Settings_List::iterator itr = editor_windows.begin(), itr_end = editor_windows.end(); itr != itr_end; ++itr )
  1637.     {
  1638.         cEditor_Object_Settings_Item *obj = (*itr);
  1639.         CEGUI::Window *window_name = obj->window_name;
  1640.         CEGUI::Window *window_setting = obj->window_setting;
  1641.  
  1642.         // start a new row
  1643.         if( obj->advance_row )
  1644.         {
  1645.             obj_posx = 0;
  1646.             obj_posy += row_height;
  1647.             row_height = 0;
  1648.         }
  1649.  
  1650.         // get window text width
  1651.         float window_name_width = window_name->getWidth().asAbsolute( static_cast<float>(game_res_w) ) * global_downscalex;
  1652.         float window_name_height = window_name->getHeight().asAbsolute( static_cast<float>(game_res_h) ) * global_downscaley;
  1653.  
  1654.         // get window setting width
  1655.         float window_setting_width;
  1656.         float window_setting_height;
  1657.  
  1658.         // if combobox get the editbox dimension
  1659.         if( window_setting->getType() == "TaharezLook/Combobox" )
  1660.         {
  1661.             window_setting_width = static_cast<CEGUI::Combobox *>(window_setting)->getEditbox()->getWidth().asAbsolute( static_cast<float>(game_res_w) ) * global_downscalex;
  1662.             window_setting_height = static_cast<CEGUI::Combobox *>(window_setting)->getEditbox()->getHeight().asAbsolute( static_cast<float>(game_res_h) ) * global_downscaley;
  1663.         }
  1664.         // get default dimension
  1665.         else
  1666.         {
  1667.             window_setting_width = window_setting->getWidth().asAbsolute( static_cast<float>(game_res_w) ) * global_downscalex;
  1668.             window_setting_height = window_setting->getHeight().asAbsolute( static_cast<float>(game_res_h) ) * global_downscaley;
  1669.         }
  1670.  
  1671.         // update row height
  1672.         if( window_setting_height > row_height )
  1673.         {
  1674.             row_height = window_setting_height;
  1675.         }
  1676.         if( window_name_height > row_height )
  1677.         {
  1678.             row_height = window_name_height;
  1679.         }
  1680.  
  1681.         // current position
  1682.         float object_final_pos_x = startposx + rect.w + 5 + obj_posx - pActive_Camera->x;
  1683.         float object_final_pos_y = startposy + 5 + obj_posy - pActive_Camera->y;
  1684.  
  1685.         // set name position
  1686.         window_name->setXPosition( CEGUI::UDim( 0, object_final_pos_x * global_upscalex ) );
  1687.         window_name->setYPosition( CEGUI::UDim( 0, object_final_pos_y * global_upscaley ) );
  1688.         // set setting position
  1689.         window_setting->setXPosition( CEGUI::UDim( 0, ( window_name_width + object_final_pos_x ) * global_upscalex ) );
  1690.         window_setting->setYPosition( CEGUI::UDim( 0, object_final_pos_y * global_upscaley ) );
  1691.         
  1692.         // set new position x
  1693.         obj_posx += window_name_width + window_setting_width + 0.05f;
  1694.     }
  1695. }
  1696.  
  1697. void cSprite :: Editor_Init( void )
  1698. {
  1699.     // set state
  1700.     Editor_State_Update();
  1701.  
  1702.     // init
  1703.     for( Editor_Object_Settings_List::iterator itr = editor_windows.begin(), itr_end = editor_windows.end(); itr != itr_end; ++itr )
  1704.     {
  1705.         cEditor_Object_Settings_Item *obj = (*itr);
  1706.         CEGUI::Window *window_name = obj->window_name;
  1707.  
  1708.         // set first row width
  1709.         if( obj->advance_row )
  1710.         {
  1711.             window_name->setWidth( CEGUI::UDim( 0, editor_window_name_width * global_upscalex ) );
  1712.         }
  1713.     }
  1714.  
  1715.     // set position
  1716.     Editor_Position_Update();
  1717. }
  1718.  
  1719. void cSprite :: Editor_State_Update( void )
  1720. {
  1721.     // virtual
  1722. }