/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OMOUSECR.CPP //Description : Object Cursor Resource #include #include #include #include #include #include #include //---------- define constant ------------// #define CURSOR_DBF DIR_RES"CURSOR.RES" //---------- Begin of function MouseCursor::MouseCursor --------// MouseCursor::MouseCursor() { memset( this, 0, sizeof(MouseCursor) ); } //----------- End of function MouseCursor::MouseCursor ------// //---------- Begin of function MouseCursor::~MouseCursor --------// MouseCursor::~MouseCursor() { deinit(); } //----------- End of function MouseCursor::~MouseCursor ------// //---------- Begin of function MouseCursor::init --------// // void MouseCursor::init() { //----- open plant material bitmap resource file -------// String str; str = DIR_RES; str += "I_CURSOR.RES"; res_bitmap.init_imported(str,1); // 1-read all into buffer //------- load database information --------// load_cursor_info(); init_flag=1; } //----------- End of function MouseCursor::init ------// //---------- Begin of function MouseCursor::deinit --------// void MouseCursor::deinit() { if( init_flag ) { mem_del(cursor_info_array); if( save_scr ) { mem_del( save_scr ); save_scr = NULL; } if( save_back_scr ) { mem_del( save_back_scr ); save_back_scr = NULL; } if( merge_buf ) // buffer for merging save screen from the front and back buffers { mem_del( merge_buf ); merge_buf = NULL; } init_flag = 0; icon_ptr = NULL; // ###### begin Gilbert 18/8 #####// cur_icon = 0; // ###### end Gilbert 18/8 #####// } } //----------- End of function MouseCursor::deinit ------// //------- Begin of function MouseCursor::load_cursor_info -------// // void MouseCursor::load_cursor_info() { CursorRec *cursorRec; CursorInfo *cursorInfo; int i; long bitmapOffset; Database dbCursor(CURSOR_DBF, 1); // 1-read all into the buffer cursor_count = (short) dbCursor.rec_count(); cursor_info_array = (CursorInfo*) mem_add( sizeof(CursorInfo)*cursor_count ); //-------- read in PLANTBMP.DBF -------// memset( cursor_info_array, 0, sizeof(CursorInfo) * cursor_count ); for( i=0 ; ibitmap_ptr, sizeof(long) ); cursorInfo->bitmap_ptr = res_bitmap.read_imported(bitmapOffset); cursorInfo->hot_spot_x = m.atoi( cursorRec->hot_spot_x, cursorRec->HOT_SPOT_LEN ); cursorInfo->hot_spot_y = m.atoi( cursorRec->hot_spot_y, cursorRec->HOT_SPOT_LEN ); } } //--------- End of function MouseCursor::load_cursor_info ---------// //--------- Begin of function MouseCursor::set_icon ------------// // // Set the bitmap of the mouse cursor // // cursorId = id. of the cursor // void MouseCursor::set_icon(int cursorId) { if( !init_flag ) return; //-------- hide the cursor first ----------// int hideAllFlag = hide_all_flag; if( !hideAllFlag ) // if the mouse has been hiden before, don't hide and show it mouse.hide(); //------------ set cursor icon ------------// CursorInfo* cursorInfo = cursor_info_array+cursorId-1; icon_ptr = cursorInfo->bitmap_ptr; hot_spot_x = cursorInfo->hot_spot_x; hot_spot_y = cursorInfo->hot_spot_y; err_when( !icon_ptr ); icon_width = *((short*)icon_ptr); icon_height = *((short*)icon_ptr+1); // ###### begin Gilbert 18/8 #####// cur_icon = cursorId; // ###### end Gilbert 18/8 #####// //------- allocate buffer for screen saving ------// save_scr = mem_resize( save_scr , icon_width*icon_height+sizeof(short)*2 ); // sizeof(short)*2 is the header for storing width and height info save_back_scr = mem_resize( save_back_scr, icon_width*icon_height+sizeof(short)*2 ); // sizeof(short)*2 is the header for storing width and height info merge_buf = mem_resize( merge_buf , icon_width*icon_height+sizeof(short)*2 ); // sizeof(short)*2 is the header for storing width and height info //------------ redisplay cursor -----------// if( !hideAllFlag ) mouse.show(); } //----------- End of function MouseCursor::set_icon -------------// //----------- Begin of function MouseCursor::set_frame --------// // // frameFlag - frame flag // [char] buildTrack - treat the frame as a line for building track, // also align the frame's position to locations. // (default:0) // void MouseCursor::set_frame(char frameFlag, char buildTrack) { if( frame_flag == frameFlag ) return; frame_flag = frameFlag; frame_shown = 0; } //----------- End of function MouseCursor::set_frame -------// //----------- Begin of function MouseCursor::set_frame_border --------// void MouseCursor::set_frame_border(int borderX1, int borderY1, int borderX2, int borderY2) { frame_border_x1 = borderX1; frame_border_y1 = borderY1; frame_border_x2 = borderX2; frame_border_y2 = borderY2; } //----------- End of function MouseCursor::set_frame_border -------// //----------- Begin of function MouseCursor::process --------// void MouseCursor::process(int curX, int curY) { if( processing_flag || !icon_ptr) // it is being nested call by interrupt return; // when another instance of process is // being run. processing_flag = 1; // Prevent nested call //---------- store screen area ------------// if( cursor_shown ) { // restore screen previously saved int save_x1, save_x2, save_y1, save_y2; save_x1 = max(cur_x1, 0); save_y1 = max(cur_y1, 0); save_x2 = min(cur_x2, VGA_WIDTH-1); save_y2 = min(cur_y2, VGA_HEIGHT-1); if ( save_x1 < save_x2 && save_y1 < save_y2 ) { vga_front.put_bitmap_area_trans( save_x1, save_y1, save_scr, save_x1-cur_x1, save_y1-cur_y1, save_x2-cur_x1, save_y2-cur_y1 ); } } //---- only the zoom map can be framed, limit the frame inside that area ----// if( frame_flag ) { curX = max(curX, ZOOM_X1); curY = max(curY, ZOOM_Y1); curX = min(curX, ZOOM_X2); curY = min(curY, ZOOM_Y2); process_frame(curX, curY); } //------- update cursor postions ----------// cur_x1 = curX - hot_spot_x; // handle the offset of the hot site cur_y1 = curY - hot_spot_y; cur_x2 = cur_x1 + icon_width - 1; cur_y2 = cur_y1 + icon_height - 1; //------- save screen and put cursor -------// if( hide_all_flag || ( hide_area_flag && is_touch( hide_x1, hide_y1, hide_x2, hide_y2 ) ) ) { cursor_shown = 0; } else { /* Save the screen underneath the cursor * where it will be drawn. */ int save_x1, save_x2, save_y1, save_y2; save_x1 = max(cur_x1, 0); save_y1 = max(cur_y1, 0); save_x2 = min(cur_x2, VGA_WIDTH-1); save_y2 = min(cur_y2, VGA_HEIGHT-1); if ( save_x1 < save_x2 && save_y1 < save_y2 ) { vga_front.read_bitmap( save_x1, save_y1, save_x2, save_y2, save_scr ); vga_front.put_bitmap_area_trans( save_x1, save_y1, icon_ptr, save_x1-cur_x1, save_y1-cur_y1, save_x2-cur_x1, save_y2-cur_y1 ); cursor_shown = 1; } } //------------------------------------------// processing_flag = 0; // cancel prevention of nested call } //----------- End of function MouseCursor::process -------// //-------- Begin of function MouseCursor::process_frame --------// void MouseCursor::process_frame(int curX, int curY) { //---- restore the screen area overwritten by the last frame ---// if( frame_shown ) { vga_front.fast_put_bitmap( frame_x1, frame_y1, frame_top_save_scr ); vga_front.fast_put_bitmap( frame_x1, frame_y2, frame_bottom_save_scr ); vga_front.fast_put_bitmap( frame_x1, frame_y1, frame_left_save_scr ); vga_front.fast_put_bitmap( frame_x2, frame_y1, frame_right_save_scr ); } //---------- update frame position ----------// if( !frame_shown ) // a new frame { frame_origin_x = curX; frame_origin_y = curY; frame_x1 = curX; frame_y1 = curY; frame_x2 = curX; frame_y2 = curY; } else // update the postion of the existing frame { //---------- update frame position ----------// if( curX > frame_origin_x ) { if( curY > frame_origin_y ) // stretching towards the lower right end { frame_x1 = frame_origin_x; frame_y1 = frame_origin_y; frame_x2 = curX; frame_y2 = curY; } else // stretching towards the upper right end { frame_x1 = frame_origin_x; frame_y1 = curY; frame_x2 = curX; frame_y2 = frame_origin_y; } } else { if( curY > frame_origin_y ) // stretching towards the lower left end { frame_x1 = curX; frame_y1 = frame_origin_y; frame_x2 = frame_origin_x; frame_y2 = curY; } else // stretching towards the upper left end { frame_x1 = curX; frame_y1 = curY; frame_x2 = frame_origin_x; frame_y2 = frame_origin_y; } } } //------- save the screen area and display the frame ------// disp_frame(&vga_front); } //----------- End of function MouseCursor::process_frame -------// //----------- Begin of function MouseCursor::disp_frame --------// void MouseCursor::disp_frame(VgaBuf* vgaBufPtr) { //------- save the screen area that will be overwriteen -------// vgaBufPtr->read_bitmap( frame_x1, frame_y1, frame_x2, frame_y1, frame_top_save_scr ); vgaBufPtr->read_bitmap( frame_x1, frame_y2, frame_x2, frame_y2, frame_bottom_save_scr ); vgaBufPtr->read_bitmap( frame_x1, frame_y1, frame_x1, frame_y2, frame_left_save_scr ); vgaBufPtr->read_bitmap( frame_x2, frame_y1, frame_x2, frame_y2, frame_right_save_scr ); //---------- draw the rectagular frame now -----------// vgaBufPtr->rect( frame_x1, frame_y1, frame_x2, frame_y2, 1, OWN_SELECT_FRAME_COLOR ); //---------- set frame flag ----------// frame_shown = 1; } //----------- End of function MouseCursor::disp_frame -------// //----------- Begin of function MouseCursor::disp_back_buf --------// // // Display the mouse cursor on the back buffer. // void MouseCursor::disp_back_buf(int bltX1, int bltY1, int bltX2, int bltY2) { if( !icon_ptr ) return; //-------- display frame on the back buffer ----// if( frame_flag ) disp_frame(&vga_back); //----- display mouse cursor on the back buffer ----// if( is_touch(bltX1, bltY1, bltX2, bltY2) ) { //--- save the front buffer area which will be overwritten ---// int x1 = max(cur_x1,bltX1); int y1 = max(cur_y1,bltY1); int x2 = min(cur_x2,bltX2); int y2 = min(cur_y2,bltY2); vga_back.read_bitmap( x1, y1, x2, y2, save_back_scr ); //--- merge the save area of the back buf with the front buf's save area ---// // save_scr width : min(cur_x2,VGA_WIDTH-1) -max(cur_x1,0)+1; // save_scr height : min(cur_y2,VGA_HEIGHT-1)-max(cur_y1,0)+1; IMGblt( save_scr+4, min(cur_x2,VGA_WIDTH-1) -max(cur_x1,0)+1, x1-max(cur_x1,0), y1-max(cur_y1,0), save_back_scr ); // +4 is the width & height info //--------- display the mouse cursor now -----------// if( cur_x1 < bltX1 || cur_x2 > bltX2 || cur_y1 < bltY1 || cur_y2 > bltY2 ) { vga_back.put_bitmap_area_trans( cur_x1, cur_y1, icon_ptr, max(bltX1,cur_x1)-cur_x1, max(bltY1,cur_y1)-cur_y1, min(bltX2,cur_x2)-cur_x1, min(bltY2,cur_y2)-cur_y1 ); } //---- the whole sprite is inside the view area ------// else { vga_back.put_bitmap_trans(cur_x1, cur_y1, icon_ptr); } cursor_shown = 1; } } //----------- End of function MouseCursor::disp_back_buf -------// //--------- Begin of function MouseCursor::is_touch ------------// // // Check if the given area touch the area defined by cur_??. // // Return : 1 or 0 // int MouseCursor::is_touch(int x1, int y1, int x2, int y2) { return (( cur_y1 <= y1 && cur_y2 >= y1 ) || ( y1 <= cur_y1 && y2 >= cur_y1 )) && (( cur_x1 <= x1 && cur_x2 >= x1 ) || ( x1 <= cur_x1 && x2 >= cur_x1 )); } //--------- End of function MouseCursor::is_touch -----------// // ####### begin Gilbert 18/8 ########// //--------- Begin of function MouseCursor::restore_icon ------------// void MouseCursor::restore_icon(int newCursorId) { if( newCursorId == 0) { err_here(); // should restore to invisible cursor ? if( !hide_all_flag ) mouse.hide(); cur_icon = 0; icon_ptr = NULL; } else if( cur_icon == 0 || newCursorId != cur_icon ) { set_icon(newCursorId); } } //--------- End of function MouseCursor::restore_icon ------------// // ####### end Gilbert 18/8 ########//