Factor out the game toolbars into a class.
This includes the following related or incidental changes: * Remove the win_from_rects global variable. With one minor exception, they were all equal to the relevant render texture's size anyway. * Split out time advancement from the handle_action function into a separate function * Split out each individual button action into its own function * Thanks to the above two, button actions triggered from the keyboard (and menu spells) no longer pass thru handle_action * Side-effect: keyboard shortcuts and menu spells no longer trigger the button press animation * Button presses now behave like proper buttons * Button clicks are now grouped by effect in the handling code, rather than by index * Removed a variable that mysteriously caused dialogue to become blank
This commit is contained in:
@@ -117,6 +117,7 @@
|
||||
<ClInclude Include="..\..\..\src\game\boe.text.hpp" />
|
||||
<ClInclude Include="..\..\..\src\game\boe.town.hpp" />
|
||||
<ClInclude Include="..\..\..\src\game\boe.townspec.hpp" />
|
||||
<ClInclude Include="..\..\..\src\game\boe.ui.hpp" />
|
||||
<ClInclude Include="..\..\..\rsrc\menus\boeresource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -142,6 +143,7 @@
|
||||
<ClCompile Include="..\..\..\src\game\boe.text.cpp" />
|
||||
<ClCompile Include="..\..\..\src\game\boe.town.cpp" />
|
||||
<ClCompile Include="..\..\..\src\game\boe.townspec.cpp" />
|
||||
<ClCompile Include="..\..\..\src\game\boe.ui.cpp" />
|
||||
<ClCompile Include="..\..\..\src\pcedit\pc.editors.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@@ -81,6 +81,9 @@
|
||||
<ClInclude Include="..\..\..\src\game\boe.actions.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\game\boe.ui.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\..\src\game\boe.actions.cpp">
|
||||
@@ -140,6 +143,9 @@
|
||||
<ClCompile Include="..\..\..\src\game\boe.townspec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\game\boe.ui.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\pcedit\pc.editors.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@@ -299,6 +299,7 @@
|
||||
91FCC8D818FE28CC007026CE /* pcedit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 91FCC8D718FE28CC007026CE /* pcedit.xib */; };
|
||||
91FCC8DC18FE2CE8007026CE /* pc.menus.mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91FCC8DB18FE2CE8007026CE /* pc.menus.mac.mm */; };
|
||||
91FCC8F418FF0866007026CE /* pc.appleevents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91FCC8F318FF069A007026CE /* pc.appleevents.mm */; };
|
||||
91FD417423DFC9D4003D5B8A /* boe.ui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91FD417223DFC5C1003D5B8A /* boe.ui.cpp */; };
|
||||
DCCA42001A8C467000E6A9A5 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; };
|
||||
DCCA42021A8C467800E6A9A5 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCCA42011A8C467800E6A9A5 /* libz.dylib */; };
|
||||
DCCA42031A8C469400E6A9A5 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DCCA42011A8C467800E6A9A5 /* libz.dylib */; };
|
||||
@@ -814,6 +815,8 @@
|
||||
91FCC8DA18FE2CCA007026CE /* pc.menus.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = pc.menus.hpp; sourceTree = "<group>"; };
|
||||
91FCC8DB18FE2CE8007026CE /* pc.menus.mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = pc.menus.mac.mm; sourceTree = "<group>"; };
|
||||
91FCC8F318FF069A007026CE /* pc.appleevents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = pc.appleevents.mm; sourceTree = "<group>"; };
|
||||
91FD417223DFC5C1003D5B8A /* boe.ui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = boe.ui.cpp; sourceTree = "<group>"; };
|
||||
91FD417323DFC5C1003D5B8A /* boe.ui.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = boe.ui.hpp; sourceTree = "<group>"; };
|
||||
91FDB5771A4E71A900DE5983 /* shop.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = shop.hpp; sourceTree = "<group>"; };
|
||||
91FDB5791A4E774E00DE5983 /* shop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shop.cpp; sourceTree = "<group>"; };
|
||||
DCCA42011A8C467800E6A9A5 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
|
||||
@@ -1458,6 +1461,7 @@
|
||||
2BF04B070BF51924006C0831 /* boe.text.cpp */,
|
||||
2BF04B090BF51924006C0831 /* boe.town.cpp */,
|
||||
2BF04AD50BF51923006C0831 /* boe.townspec.cpp */,
|
||||
91FD417223DFC5C1003D5B8A /* boe.ui.cpp */,
|
||||
);
|
||||
name = src;
|
||||
sourceTree = "<group>";
|
||||
@@ -1485,6 +1489,7 @@
|
||||
2BF04B080BF51924006C0831 /* boe.text.hpp */,
|
||||
2BF04B0A0BF51924006C0831 /* boe.town.hpp */,
|
||||
2BF04AD60BF51923006C0831 /* boe.townspec.hpp */,
|
||||
91FD417323DFC5C1003D5B8A /* boe.ui.hpp */,
|
||||
);
|
||||
name = headers;
|
||||
sourceTree = "<group>";
|
||||
@@ -1849,6 +1854,7 @@
|
||||
919145FC18E3AB1B005CF3A4 /* boe.appleevents.mm in Sources */,
|
||||
915325171A2E1DF0000A9A1C /* oldstructs.cpp in Sources */,
|
||||
91B0D5D11E3442FE002BE4DA /* view_dialogs.cpp in Sources */,
|
||||
91FD417423DFC9D4003D5B8A /* boe.ui.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "sounds.hpp"
|
||||
#include "boe.infodlg.hpp"
|
||||
#include "boe.main.hpp"
|
||||
#include "boe.ui.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "fileio.hpp"
|
||||
#include "choicedlog.hpp"
|
||||
@@ -37,7 +38,6 @@
|
||||
#include "render_shapes.hpp"
|
||||
#include "enum_map.hpp"
|
||||
|
||||
rectangle bottom_buttons[14];
|
||||
rectangle item_screen_button_rects[9] = {
|
||||
{125,10,141,28},{125,40,141,58},{125,68,141,86},{125,98,141,116},{125,126,141,144},{125,156,141,174},
|
||||
{126,176,141,211},
|
||||
@@ -123,6 +123,8 @@ std::queue<pending_special_type> special_queue;
|
||||
bool end_scenario = false;
|
||||
bool current_bash_is_bash = false;
|
||||
|
||||
static void advance_time(bool did_something, bool need_redraw, bool need_reprint);
|
||||
|
||||
// This is defined in pc.editors.cpp since the PC editor also uses it
|
||||
extern void edit_stuff_done();
|
||||
|
||||
@@ -294,6 +296,51 @@ static void handle_spellcast(eSkill which_type, bool& did_something, bool& need_
|
||||
put_item_screen(stat_window);
|
||||
}
|
||||
|
||||
static void handle_begin_look(bool& need_redraw) {
|
||||
if(overall_mode == MODE_OUTDOORS) overall_mode = MODE_LOOK_OUTDOORS;
|
||||
if(overall_mode == MODE_TOWN) overall_mode = MODE_LOOK_TOWN;
|
||||
if(overall_mode == MODE_COMBAT) overall_mode = MODE_LOOK_COMBAT;
|
||||
add_string_to_buf("Look: Select a space. You can also right click to look.", 2);
|
||||
need_redraw = true;
|
||||
}
|
||||
|
||||
static void handle_begin_talk(bool& need_reprint) {
|
||||
overall_mode = MODE_TALK_TOWN;
|
||||
add_string_to_buf("Talk: Select someone.");
|
||||
need_reprint = true;
|
||||
}
|
||||
|
||||
static void handle_stand_ready(bool& need_redraw, bool& need_reprint) {
|
||||
need_reprint = true;
|
||||
need_redraw = true;
|
||||
//draw_terrain();
|
||||
//pause(2);
|
||||
univ.cur_pc++;
|
||||
combat_next_step();
|
||||
set_stat_window_for_pc(univ.cur_pc);
|
||||
put_pc_screen();
|
||||
}
|
||||
|
||||
static void handle_parry(bool& did_something, bool& need_redraw, bool& need_reprint) {
|
||||
add_string_to_buf("Parry.");
|
||||
char_parry();
|
||||
did_something = true;
|
||||
need_reprint = true;
|
||||
need_redraw = true;
|
||||
}
|
||||
|
||||
static void handle_toggle_active(bool& need_reprint) {
|
||||
if(combat_active_pc == 6) {
|
||||
add_string_to_buf("This PC now active.");
|
||||
combat_active_pc = univ.cur_pc;
|
||||
} else {
|
||||
add_string_to_buf("All PC's now active.");
|
||||
univ.cur_pc = combat_active_pc;
|
||||
combat_active_pc = 6;
|
||||
}
|
||||
need_reprint = true;
|
||||
}
|
||||
|
||||
static void handle_rest(bool& need_redraw, bool& need_reprint) {
|
||||
sf::Event dummy_evt;
|
||||
int i = 0;
|
||||
@@ -969,56 +1016,27 @@ static void handle_party_death() {
|
||||
}
|
||||
|
||||
bool handle_action(const sf::Event& event) {
|
||||
short s1,s2,s3;
|
||||
long item_hit;
|
||||
bool are_done = false;
|
||||
bool need_redraw = false, did_something = false, need_reprint = false;
|
||||
bool pc_delayed = false;
|
||||
location cur_loc,loc_in_sec,cur_direction;
|
||||
short button_hit = 12;
|
||||
location loc_in_sec,cur_direction;
|
||||
bool right_button = event.mouseButton.button == sf::Mouse::Right;
|
||||
eGameMode previous_mode;
|
||||
rectangle world_screen = win_to_rects[WINRECT_TERVIEW];
|
||||
world_screen.inset(13, 13);
|
||||
|
||||
std::ostringstream str;
|
||||
location the_point,point_in_area;
|
||||
location point_in_area;
|
||||
|
||||
the_point = location(event.mouseButton.x, event.mouseButton.y);
|
||||
location the_point(event.mouseButton.x, event.mouseButton.y);
|
||||
the_point = mainPtr.mapPixelToCoords(the_point, mainView);
|
||||
end_scenario = false;
|
||||
|
||||
// MARK: First, figure out where party is
|
||||
switch(overall_mode) {
|
||||
case MODE_OUTDOORS: case MODE_LOOK_OUTDOORS:
|
||||
cur_loc = univ.party.out_loc;
|
||||
for(int i = 0; i < 14; i++)
|
||||
if(the_point.in(bottom_buttons[i])) {
|
||||
button_hit = i;
|
||||
if(!spell_forced)
|
||||
main_button_click(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_TOWN: case MODE_TALK_TOWN: case MODE_TOWN_TARGET: case MODE_USE_TOWN: case MODE_LOOK_TOWN:
|
||||
case MODE_DROP_TOWN: case MODE_BASH_TOWN:
|
||||
case MODE_COMBAT: case MODE_SPELL_TARGET: case MODE_FIRING: case MODE_THROWING:
|
||||
case MODE_FANCY_TARGET: case MODE_DROP_COMBAT: case MODE_LOOK_COMBAT:
|
||||
cur_loc = center;
|
||||
for(int i = 0; i < 14; i++)
|
||||
if(the_point.in(bottom_buttons[i])) {
|
||||
button_hit = i;
|
||||
if(!spell_forced)
|
||||
main_button_click(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_TALKING: case MODE_SHOPPING: break;
|
||||
|
||||
case MODE_STARTUP: case MODE_RESTING: case MODE_CUTSCENE:
|
||||
// If we get here during these modes, something is probably not right, so bail out
|
||||
add_string_to_buf("Unexpected game state!");
|
||||
return are_done;
|
||||
if(overall_mode == MODE_STARTUP || overall_mode == MODE_RESTING || overall_mode == MODE_CUTSCENE) {
|
||||
// If we get here during these modes, something is probably not right, so bail out
|
||||
add_string_to_buf("Unexpected game state!");
|
||||
return are_done;
|
||||
}
|
||||
|
||||
// Now split off the extra stuff, like talking and shopping.
|
||||
@@ -1033,52 +1051,60 @@ bool handle_action(const sf::Event& event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise they're in a terrain view mode
|
||||
location cur_loc = is_out() ? univ.party.out_loc : center;
|
||||
auto button_hit = UI::toolbar.button_hit(mainPtr, the_point);
|
||||
|
||||
// MARK: Then, handle a button being hit.
|
||||
if(button_hit != 12)
|
||||
switch(button_hit) {
|
||||
case 0: case 1:
|
||||
handle_spellcast(button_hit == 0 ? eSkill::MAGE_SPELLS : eSkill::PRIEST_SPELLS, did_something, need_redraw, need_reprint);
|
||||
case TOOLBAR_NONE: break;
|
||||
case TOOLBAR_MAGE: case TOOLBAR_PRIEST:
|
||||
handle_spellcast(button_hit == TOOLBAR_MAGE ? eSkill::MAGE_SPELLS : eSkill::PRIEST_SPELLS, did_something, need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(overall_mode == MODE_OUTDOORS) overall_mode = MODE_LOOK_OUTDOORS;
|
||||
if(overall_mode == MODE_TOWN) overall_mode = MODE_LOOK_TOWN;
|
||||
if(overall_mode == MODE_COMBAT) overall_mode = MODE_LOOK_COMBAT;
|
||||
add_string_to_buf("Look: Select a space. You can also right click to look.", 2);
|
||||
need_redraw = true;
|
||||
case TOOLBAR_LOOK:
|
||||
handle_begin_look(need_redraw);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
add_string_to_buf("Parry.");
|
||||
char_parry();
|
||||
did_something = true;
|
||||
need_reprint = true;
|
||||
need_redraw = true;
|
||||
} else if(overall_mode == MODE_TOWN) {
|
||||
overall_mode = MODE_TALK_TOWN;
|
||||
add_string_to_buf("Talk: Select someone.");
|
||||
need_reprint = true;
|
||||
} else if(overall_mode == MODE_OUTDOORS)
|
||||
case TOOLBAR_SHIELD:
|
||||
if(overall_mode == MODE_COMBAT)
|
||||
handle_parry(did_something, need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case TOOLBAR_TALK:
|
||||
if(overall_mode == MODE_TOWN)
|
||||
handle_begin_talk(need_reprint);
|
||||
break;
|
||||
|
||||
case TOOLBAR_CAMP:
|
||||
if(overall_mode == MODE_OUTDOORS)
|
||||
handle_rest(need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if(overall_mode == MODE_OUTDOORS) {
|
||||
case TOOLBAR_SCROLL: case TOOLBAR_MAP:
|
||||
if(overall_mode == MODE_OUTDOORS || overall_mode == MODE_TOWN) {
|
||||
give_help(62,0);
|
||||
display_map();
|
||||
set_cursor(sword_curs);
|
||||
} else if(overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT)
|
||||
}
|
||||
break;
|
||||
|
||||
case TOOLBAR_BAG: case TOOLBAR_HAND:
|
||||
if(overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT)
|
||||
handle_get_items(did_something, need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case TOOLBAR_SAVE:
|
||||
if(overall_mode == MODE_OUTDOORS) {
|
||||
save_party(univ.file, univ);
|
||||
need_redraw = true;
|
||||
current_switch = 6;
|
||||
break;
|
||||
} else if(overall_mode == MODE_TOWN) {
|
||||
}
|
||||
break;
|
||||
|
||||
case TOOLBAR_USE:
|
||||
if(overall_mode == MODE_TOWN) {
|
||||
add_string_to_buf("Use: Select a space or item.");
|
||||
add_string_to_buf(" (Hit button again to cancel.)");
|
||||
need_reprint = true;
|
||||
@@ -1087,39 +1113,32 @@ bool handle_action(const sf::Event& event) {
|
||||
overall_mode = MODE_TOWN;
|
||||
need_reprint = true;
|
||||
add_string_to_buf(" Cancelled.");
|
||||
} else if(overall_mode == MODE_COMBAT) {
|
||||
need_reprint = true;
|
||||
need_redraw = true;
|
||||
pc_delayed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case TOOLBAR_WAIT:
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
handle_stand_ready(need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case TOOLBAR_LOAD:
|
||||
if(overall_mode == MODE_OUTDOORS)
|
||||
do_load();
|
||||
else if(overall_mode == MODE_TOWN) {
|
||||
give_help(62,0);
|
||||
display_map();
|
||||
set_cursor(sword_curs);
|
||||
} else handle_missile(need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case TOOLBAR_SHOOT:
|
||||
if(overall_mode == MODE_COMBAT || overall_mode == MODE_FIRING || overall_mode == MODE_THROWING)
|
||||
handle_missile(need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case TOOLBAR_SWORD: case TOOLBAR_END:
|
||||
handle_combat_switch(did_something, need_redraw, need_reprint);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case TOOLBAR_ACT:
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
if(combat_active_pc == 6) {
|
||||
add_string_to_buf("This PC now active.");
|
||||
combat_active_pc = univ.cur_pc;
|
||||
} else {
|
||||
add_string_to_buf("All PC's now active.");
|
||||
univ.cur_pc = combat_active_pc;
|
||||
combat_active_pc = 6;
|
||||
}
|
||||
need_reprint = true;
|
||||
handle_toggle_active(need_reprint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1389,20 +1408,17 @@ bool handle_action(const sf::Event& event) {
|
||||
need_reprint = true;
|
||||
}
|
||||
|
||||
// MARK: If in combat and pc delayed, jump forward a step
|
||||
if(pc_delayed) {
|
||||
draw_terrain();
|
||||
//pause(2);
|
||||
univ.cur_pc++;
|
||||
combat_next_step();
|
||||
set_stat_window_for_pc(univ.cur_pc);
|
||||
put_pc_screen();
|
||||
}
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
|
||||
are_done = All_Done;
|
||||
return are_done;
|
||||
}
|
||||
|
||||
static void advance_time(bool did_something, bool need_redraw, bool need_reprint) {
|
||||
// MARK: At this point, see if any specials have been queued up, and deal with them
|
||||
// Note: We just check once here instead of looping because run_special also pulls from the queue.
|
||||
if(!special_queue.empty()) {
|
||||
s3 = 0;
|
||||
short s1 = 0, s2 = 0, s3 = 0;
|
||||
pending_special_type pending = special_queue.front();
|
||||
special_queue.pop();
|
||||
run_special(pending, &s1, &s2, &s3);
|
||||
@@ -1428,9 +1444,6 @@ bool handle_action(const sf::Event& event) {
|
||||
handle_party_death();
|
||||
else if(end_scenario)
|
||||
handle_victory();
|
||||
|
||||
are_done = All_Done;
|
||||
return are_done;
|
||||
}
|
||||
|
||||
void handle_monster_actions(bool& need_redraw, bool& need_reprint) {
|
||||
@@ -1522,26 +1535,10 @@ void handle_menu_spell(eSpell spell_picked) {
|
||||
if((store_spell_target = char_select_pc((*spell_picked).need_select == SELECT_ANY ? 1 : 0,"Cast spell on who?")) == 6)
|
||||
return;
|
||||
}
|
||||
/* if((is_combat()) && (((spell_type == 0) && (refer_mage[spell_picked] > 0)) ||
|
||||
((spell_type == 1) && (refer_priest[spell_picked] > 0)))){
|
||||
if((spell_type == 0) && (mage_need_select[spell_picked] > 0))
|
||||
store_spell_target = char_select_pc(2 - mage_need_select[spell_picked],0,"Cast spell on who?");
|
||||
else if((spell_type == 1) && (priest_need_select[spell_picked] > 0))
|
||||
store_spell_target = char_select_pc(2 - priest_need_select[spell_picked],0,"Cast spell on who?");
|
||||
}
|
||||
else {
|
||||
} */
|
||||
if(spell_type == eSkill::MAGE_SPELLS) {
|
||||
pass_point.x = bottom_buttons[0].left + 5;
|
||||
pass_point.y = bottom_buttons[0].top + 5;
|
||||
} else {
|
||||
pass_point.x = bottom_buttons[1].left + 5;
|
||||
pass_point.y = bottom_buttons[1].top + 5;
|
||||
}
|
||||
pass_point = mainPtr.mapCoordsToPixel(pass_point, mainView);
|
||||
event.mouseButton.x = pass_point.x;
|
||||
event.mouseButton.y = pass_point.y;
|
||||
handle_action(event);
|
||||
|
||||
bool did_something = false, need_redraw = false, need_reprint = false;
|
||||
handle_spellcast(spell_type, did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
|
||||
void initiate_outdoor_combat(short i) {
|
||||
@@ -1687,6 +1684,8 @@ bool handle_keystroke(const sf::Event& event){
|
||||
}
|
||||
}
|
||||
|
||||
bool did_something = false, need_redraw = false, need_reprint = false;
|
||||
|
||||
char chr = keyToChar(chr2, event.key.shift);
|
||||
// F1 should bring up help.
|
||||
// TODO: So should the help key, if it exists (but SFML doesn't support the help key)
|
||||
@@ -2074,80 +2073,99 @@ bool handle_keystroke(const sf::Event& event){
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': case 'x': case 'e':
|
||||
case 'm': case 'p': case 'l': case 'r': case 'w': case 't': case 'd': case 'g': case 'f':
|
||||
case 'M': case 'P':
|
||||
int btn = 50;
|
||||
if(overall_mode == MODE_SPELL_TARGET || overall_mode == MODE_FANCY_TARGET || overall_mode == MODE_TOWN_TARGET) { // cancel spell
|
||||
if(chr == 'm') btn = 0;
|
||||
else if(chr == 'p') btn = 1;
|
||||
// Spells (cast/cancel)
|
||||
case 'M': spell_forced = true;
|
||||
case 'm':
|
||||
if(overall_mode == MODE_SPELL_TARGET || overall_mode == MODE_FANCY_TARGET || overall_mode == MODE_TOWN_TARGET || overall_mode == MODE_OUTDOORS || overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) {
|
||||
handle_spellcast(eSkill::MAGE_SPELLS, did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P': spell_forced = true;
|
||||
case 'p':
|
||||
if(overall_mode == MODE_SPELL_TARGET || overall_mode == MODE_FANCY_TARGET || overall_mode == MODE_TOWN_TARGET || overall_mode == MODE_OUTDOORS || overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) {
|
||||
handle_spellcast(eSkill::PRIEST_SPELLS, did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l': // Look
|
||||
if((overall_mode == MODE_OUTDOORS) || (overall_mode == MODE_TOWN) || (overall_mode == MODE_COMBAT)) {
|
||||
switch(chr) {
|
||||
// Spells
|
||||
case 'M': spell_forced = true; btn = 0; break;
|
||||
case 'm': btn = 0; break;
|
||||
case 'P': spell_forced = true; btn = 1; break;
|
||||
case 'p': btn = 1; break;
|
||||
// Look
|
||||
case 'l': btn = 2; break;
|
||||
case 'r': // Rest
|
||||
if(overall_mode != MODE_OUTDOORS) return false;
|
||||
btn = 3;
|
||||
break;
|
||||
case 't': // Talk
|
||||
if(overall_mode != MODE_TOWN) return false;
|
||||
btn = 3;
|
||||
break;
|
||||
case 'w': // Wait (town), delay action (combat)
|
||||
if(overall_mode == MODE_COMBAT)
|
||||
btn = 5;
|
||||
else if(overall_mode == MODE_TOWN) {
|
||||
pass_point = mainPtr.mapCoordsToPixel({1001, 0}, mainView);
|
||||
pass_event.mouseButton.x = pass_point.x;
|
||||
pass_event.mouseButton.y = pass_point.y;
|
||||
are_done = handle_action(pass_event);
|
||||
}
|
||||
else {
|
||||
add_string_to_buf("Wait: In town only.");
|
||||
print_buf();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'd': // Parry
|
||||
if(overall_mode != MODE_COMBAT) return false;
|
||||
btn = 3;
|
||||
break;
|
||||
case 'g': // Get
|
||||
if(overall_mode == MODE_OUTDOORS) return false;
|
||||
btn = 4;
|
||||
break;
|
||||
case 's': // Shoot
|
||||
if(overall_mode != MODE_COMBAT) return false;
|
||||
btn = 6;
|
||||
break;
|
||||
case 'x': // Toggle active
|
||||
if(overall_mode != MODE_COMBAT) return false;
|
||||
btn = 8;
|
||||
break;
|
||||
case 'e': // End combat
|
||||
if(overall_mode != MODE_COMBAT) return false;
|
||||
btn = 7;
|
||||
break;
|
||||
case 'f': // Fight (toggle combat)
|
||||
if(overall_mode != MODE_TOWN && overall_mode != MODE_COMBAT) return false;
|
||||
btn = 7;
|
||||
break;
|
||||
}
|
||||
} else if(chr == 's' && (overall_mode == MODE_FIRING || overall_mode == MODE_THROWING))
|
||||
btn = 6;
|
||||
if(btn < 50) {
|
||||
pass_point.x = bottom_buttons[btn].left + 5;
|
||||
pass_point.y = bottom_buttons[btn].top + 5;
|
||||
pass_point = mainPtr.mapCoordsToPixel(pass_point, mainView);
|
||||
handle_begin_look(need_redraw);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r': // Rest (outdoors)
|
||||
if(overall_mode == MODE_OUTDOORS) {
|
||||
handle_rest(need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': // Talk
|
||||
if(overall_mode == MODE_TOWN) {
|
||||
handle_begin_talk(need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w': // Wait / delay
|
||||
if(overall_mode == MODE_TOWN) {
|
||||
pass_point = mainPtr.mapCoordsToPixel({1001, 0}, mainView);
|
||||
pass_event.mouseButton.x = pass_point.x;
|
||||
pass_event.mouseButton.y = pass_point.y;
|
||||
are_done = handle_action(pass_event);
|
||||
} else if(overall_mode == MODE_COMBAT) {
|
||||
handle_stand_ready(need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
} else if(overall_mode == MODE_OUTDOORS) {
|
||||
add_string_to_buf("Wait: In town only.");
|
||||
print_buf();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': // Parry
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
handle_parry(did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g': // Get items
|
||||
if(overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) {
|
||||
handle_get_items(did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's': // Shoot
|
||||
if(overall_mode == MODE_COMBAT || overall_mode == MODE_FIRING || overall_mode == MODE_THROWING) {
|
||||
handle_missile(need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x': // Toggle active
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
handle_toggle_active(need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'e': // End combat
|
||||
if(overall_mode == MODE_COMBAT) {
|
||||
handle_combat_switch(did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': // Toggle combat
|
||||
if(overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) {
|
||||
handle_combat_switch(did_something, need_redraw, need_reprint);
|
||||
advance_time(did_something, need_redraw, need_reprint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2214,7 +2232,7 @@ void post_load() {
|
||||
set_stat_window(ITEM_WIN_PC1);
|
||||
put_pc_screen();
|
||||
draw_terrain();
|
||||
draw_buttons(0);
|
||||
UI::toolbar.draw(mainPtr);
|
||||
draw_text_bar();
|
||||
|
||||
print_buf();
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "boe.specials.hpp"
|
||||
#include "boe.graphutil.hpp"
|
||||
#include "boe.main.hpp"
|
||||
#include "boe.ui.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "choicedlog.hpp"
|
||||
#include "boe.menus.hpp"
|
||||
@@ -360,7 +361,7 @@ void start_outdoor_combat(cOutdoors::cCreature encounter,location where,short nu
|
||||
set_pc_moves();
|
||||
pick_next_pc();
|
||||
center = univ.current_pc().combat_pos;
|
||||
draw_buttons(0);
|
||||
UI::toolbar.draw(mainPtr);
|
||||
put_pc_screen();
|
||||
set_stat_window_for_pc(univ.cur_pc);
|
||||
|
||||
@@ -4656,7 +4657,7 @@ void end_combat() {
|
||||
if(univ.current_pc().main_status != eMainStatus::ALIVE)
|
||||
univ.cur_pc = first_active_pc();
|
||||
put_item_screen(stat_window);
|
||||
draw_buttons(0);
|
||||
UI::toolbar.draw(mainPtr);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -544,7 +544,6 @@ void set_up_shop_array() {
|
||||
|
||||
void start_talk_mode(short m_num,short personality,mon_num_t monst_type,short store_face_pic) {
|
||||
rectangle area_rect;
|
||||
std::string place_string1;
|
||||
|
||||
store_personality = personality;
|
||||
|
||||
@@ -570,10 +569,11 @@ void start_talk_mode(short m_num,short personality,mon_num_t monst_type,short st
|
||||
current_talk_node = TALK_LOOK;
|
||||
|
||||
// Bring up and place first strings.
|
||||
place_string1 = univ.town.cur_talk().people[personality % 10].look;
|
||||
save_talk_str1 = univ.town.cur_talk().people[personality % 10].look;
|
||||
save_talk_str2 = "";
|
||||
can_save_talk = true;
|
||||
|
||||
place_talk_str(place_string1, "", 0, dummy_rect);
|
||||
place_talk_str(save_talk_str1, "", 0, dummy_rect);
|
||||
|
||||
put_item_screen(stat_window);
|
||||
give_help(5,6);
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "boe.items.hpp"
|
||||
#include "boe.dlgutil.hpp"
|
||||
#include "boe.infodlg.hpp"
|
||||
#include "boe.ui.hpp"
|
||||
|
||||
#include "scrollbar.hpp"
|
||||
|
||||
@@ -74,10 +75,7 @@ sf::View mainView;
|
||||
|
||||
long anim_ticks = 0;
|
||||
|
||||
// 0 - terrain 1 - buttons 2 - pc stats
|
||||
// 3 - item stats 4 - text bar 5 - text area (not right)
|
||||
enum_map(eGuiArea, rectangle) win_from_rects = {{0,0,350,278},{0,0,37,258},{0,0,115,288},{0,0,143,288},{0,0,21,279},{0,0,0,288}};
|
||||
enum_map(eGuiArea, rectangle) win_to_rects = {{7,19,358,298},{385,19,423,285},{7,305,123,576},{132,305,276,576},{360,19,381,298},{285,305,423,561}};
|
||||
extern enum_map(eGuiArea, rectangle) win_to_rects;
|
||||
|
||||
// 0 - title 1 - button 2 - credits 3 - base button
|
||||
rectangle startup_from[4] = {{0,0,274,602},{274,0,322,301},{0,301,67,579},{274,301,314,341}};
|
||||
@@ -446,17 +444,6 @@ void draw_start_button(eStartButton which_position,short which_button) {
|
||||
win_draw_string(mainPtr,to_rect,button_labels[which_position],eTextMode::CENTRE,style);
|
||||
}
|
||||
|
||||
void main_button_click(int which_button) {
|
||||
mainPtr.setActive();
|
||||
// TODO: Mini-event loop so that the click doesn't happen until releasing the mouse button
|
||||
|
||||
draw_buttons(which_button);
|
||||
mainPtr.display();
|
||||
play_sound(37, time_in_ticks(5));
|
||||
draw_buttons(-1);
|
||||
undo_clip(mainPtr);
|
||||
}
|
||||
|
||||
void arrow_button_click(rectangle button_rect) {
|
||||
mainPtr.setActive();
|
||||
clip_rect(mainPtr, button_rect);
|
||||
@@ -539,7 +526,7 @@ void redraw_screen(int refresh) {
|
||||
if(refresh & REFRESH_BAR)
|
||||
draw_text_bar();
|
||||
refresh_text_bar();
|
||||
draw_buttons(-1);
|
||||
UI::toolbar.draw(mainPtr);
|
||||
break;
|
||||
}
|
||||
if(overall_mode == MODE_COMBAT)
|
||||
@@ -595,81 +582,6 @@ void put_background() {
|
||||
tileImage(mainPtr, rectangle(mainPtr), bg_pict);
|
||||
}
|
||||
|
||||
// mode; -1 - all buttons, normal; otherwise draw this button pressed
|
||||
void draw_buttons(short mode) {
|
||||
rectangle lg_rect = {0,0,38,38}, sm_rect[2] = {{0,38,19,76}, {19,38,38,76}}, dest_rec;
|
||||
static const int MAX_TOOLBAR_BUTTONS = 14;
|
||||
static const location null_loc(-1,-1);
|
||||
static const location out_buttons[MAX_TOOLBAR_BUTTONS] = {
|
||||
{0,0}, {1,0}, {2,0}, {3,0}, {4,0}, {5,0}, {5,1}, null_loc, null_loc, null_loc, null_loc, null_loc, null_loc, null_loc
|
||||
};
|
||||
static const location town_buttons[MAX_TOOLBAR_BUTTONS] = {
|
||||
{0,0}, {1,0}, {2,0}, {2,1}, {3,1}, {4,2}, {5,2}, {4,1}, null_loc, null_loc, null_loc, null_loc, null_loc, null_loc
|
||||
};
|
||||
static const location combat_buttons[MAX_TOOLBAR_BUTTONS] = {
|
||||
{0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {0,2}, {2,2}, {1,2}, {3,2}, null_loc, null_loc, null_loc, null_loc, null_loc
|
||||
};
|
||||
extern rectangle bottom_buttons[MAX_TOOLBAR_BUTTONS];
|
||||
|
||||
const location* toolbar = is_combat() ? combat_buttons : (is_town() ? town_buttons : out_buttons);
|
||||
|
||||
static bool inited = false;
|
||||
static sf::RenderTexture button_gw;
|
||||
if(!inited) {
|
||||
inited = true;
|
||||
button_gw.create(266,38);
|
||||
}
|
||||
|
||||
sf::Texture& buttons_gworld = *ResMgr::graphics.get("buttons");
|
||||
dest_rec = lg_rect;
|
||||
|
||||
bool bottom_half = false;
|
||||
std::fill_n(bottom_buttons, MAX_TOOLBAR_BUTTONS, rectangle());
|
||||
for(int i = 0; i < MAX_TOOLBAR_BUTTONS && toolbar[i] != null_loc; i++) {
|
||||
rectangle source_rect = {0, 0, 32, 32};
|
||||
rectangle to_rect = dest_rec, btn_rect, icon_rect;
|
||||
source_rect.offset(32 * toolbar[i].x, 38 + 32 * toolbar[i].y);
|
||||
if(toolbar[i].y == 2) {
|
||||
// Small button
|
||||
btn_rect = sm_rect[bottom_half];
|
||||
source_rect.height() = 13;
|
||||
to_rect.height() = 19;
|
||||
if(bottom_half) {
|
||||
to_rect.offset(0,19);
|
||||
bottom_half = false;
|
||||
} else bottom_half = true;
|
||||
icon_rect = {3,3,13,13};
|
||||
} else {
|
||||
// Large button
|
||||
btn_rect = lg_rect;
|
||||
if(bottom_half) {
|
||||
dest_rec.offset(38,0);
|
||||
bottom_half = false;
|
||||
}
|
||||
icon_rect = {3,3,32,32};
|
||||
}
|
||||
if(mode == -1) {
|
||||
rect_draw_some_item(buttons_gworld, btn_rect, button_gw, to_rect);
|
||||
to_rect.inset(3,3);
|
||||
rect_draw_some_item(buttons_gworld, source_rect, button_gw, to_rect, sf::BlendAlpha);
|
||||
to_rect.inset(-3,-3);
|
||||
}
|
||||
to_rect.offset(win_to_rects[WINRECT_ACTBTNS].topLeft());
|
||||
if(i == mode)
|
||||
fill_rect(mainPtr, to_rect, sf::Color::Blue);
|
||||
else fill_rect(mainPtr, to_rect, sf::Color::Black);
|
||||
bottom_buttons[i] = to_rect;
|
||||
if(toolbar[i].y != 2 || !bottom_half) {
|
||||
dest_rec.offset(38,0);
|
||||
bottom_half = false;
|
||||
}
|
||||
}
|
||||
button_gw.display();
|
||||
|
||||
dest_rec = win_to_rects[WINRECT_ACTBTNS];
|
||||
rect_draw_some_item(button_gw.getTexture(), rectangle(button_gw), mainPtr, dest_rec, sf::BlendAdd);
|
||||
}
|
||||
|
||||
void draw_text_bar() {
|
||||
location loc;
|
||||
|
||||
@@ -713,7 +625,8 @@ void draw_text_bar() {
|
||||
|
||||
void put_text_bar(std::string str) {
|
||||
text_bar_gworld.setActive();
|
||||
rect_draw_some_item(*ResMgr::graphics.get("textbar"), win_from_rects[WINRECT_STATUS], text_bar_gworld, win_from_rects[WINRECT_STATUS]);
|
||||
auto& bar_gw = *ResMgr::graphics.get("textbar");
|
||||
rect_draw_some_item(bar_gw, rectangle(bar_gw), text_bar_gworld, rectangle(bar_gw));
|
||||
TextStyle style;
|
||||
style.colour = sf::Color::White;
|
||||
style.font = FONT_BOLD;
|
||||
@@ -753,7 +666,7 @@ void put_text_bar(std::string str) {
|
||||
|
||||
void refresh_text_bar() {
|
||||
mainPtr.setActive();
|
||||
rect_draw_some_item(text_bar_gworld.getTexture(), win_from_rects[WINRECT_STATUS], mainPtr, win_to_rects[WINRECT_STATUS]);
|
||||
rect_draw_some_item(text_bar_gworld.getTexture(), rectangle(text_bar_gworld), mainPtr, win_to_rects[WINRECT_STATUS]);
|
||||
}
|
||||
|
||||
// this is used for determinign whether to round off walkway corners
|
||||
@@ -1555,10 +1468,9 @@ void draw_pointing_arrows() {
|
||||
}
|
||||
|
||||
void redraw_terrain() {
|
||||
rectangle to_rect;
|
||||
|
||||
to_rect = win_to_rects[WINRECT_TERVIEW];
|
||||
rect_draw_some_item(terrain_screen_gworld.getTexture(), win_from_rects[WINRECT_TERVIEW], mainPtr, to_rect);
|
||||
rectangle to_rect = win_to_rects[WINRECT_TERVIEW], from_rect(terrain_screen_gworld);
|
||||
from_rect.bottom -= 10; // Clip off the little arrows TODO: Maybe move them to another sheet?
|
||||
rect_draw_some_item(terrain_screen_gworld.getTexture(), from_rect, mainPtr, to_rect);
|
||||
apply_light_mask(true);
|
||||
|
||||
|
||||
|
@@ -24,13 +24,11 @@ void draw_startup(short but_type);
|
||||
void draw_anim();
|
||||
void place_anim();
|
||||
void draw_start_button(eStartButton which_position,short which_button);
|
||||
void main_button_click(int which_button);
|
||||
void arrow_button_click(rectangle button_rect);
|
||||
void end_startup();
|
||||
void load_main_screen();
|
||||
void redraw_screen(int refresh);
|
||||
void put_background();
|
||||
void draw_buttons(short mode);
|
||||
void draw_text_bar();
|
||||
void refresh_text_bar();
|
||||
void put_text_bar(std::string str);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "boe.locutils.hpp"
|
||||
#include "boe.specials.hpp"
|
||||
#include "boe.infodlg.hpp"
|
||||
#include "boe.ui.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "render_image.hpp"
|
||||
#include "render_shapes.hpp"
|
||||
@@ -703,7 +704,7 @@ void start_town_combat(eDirection direction) {
|
||||
set_pc_moves();
|
||||
pick_next_pc();
|
||||
center = univ.current_pc().combat_pos;
|
||||
draw_buttons(0);
|
||||
UI::toolbar.draw(mainPtr);
|
||||
put_pc_screen();
|
||||
set_stat_window_for_pc(univ.cur_pc);
|
||||
give_help(48,49);
|
||||
|
176
src/game/boe.ui.cpp
Normal file
176
src/game/boe.ui.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
//
|
||||
// boe.ui.cpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 20-01-27.
|
||||
//
|
||||
//
|
||||
|
||||
#include "boe.ui.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include "enum_map.hpp"
|
||||
#include "boe.consts.hpp"
|
||||
#include "boe.locutils.hpp"
|
||||
#include "boe.graphics.hpp"
|
||||
#include "render_shapes.hpp"
|
||||
#include "render_image.hpp"
|
||||
#include "res_image.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "sounds.hpp"
|
||||
|
||||
namespace UI {
|
||||
cToolbar toolbar;
|
||||
}
|
||||
|
||||
// The location of each UI area
|
||||
enum_map(eGuiArea, rectangle) win_to_rects = {{7,19,358,298},{385,19,423,285},{7,305,123,576},{132,305,276,576},{360,19,381,298},{285,305,423,561}};
|
||||
|
||||
// Get the location of the button icon in buttons.png.
|
||||
static location btn_pos(eToolbarButton icon) {
|
||||
location pos;
|
||||
pos.x = icon % 6;
|
||||
pos.y = icon / 6;
|
||||
return pos;
|
||||
}
|
||||
|
||||
// The list of buttons for each mode
|
||||
std::vector<eToolbarButton> cToolbar::out_buttons = {TOOLBAR_MAGE, TOOLBAR_PRIEST, TOOLBAR_LOOK, TOOLBAR_CAMP, TOOLBAR_SCROLL, TOOLBAR_SAVE, TOOLBAR_LOAD};
|
||||
std::vector<eToolbarButton> cToolbar::town_buttons = {TOOLBAR_MAGE, TOOLBAR_PRIEST, TOOLBAR_LOOK, TOOLBAR_TALK, TOOLBAR_HAND, TOOLBAR_USE, TOOLBAR_MAP, TOOLBAR_SWORD};
|
||||
std::vector<eToolbarButton> cToolbar::fight_buttons = {TOOLBAR_MAGE, TOOLBAR_PRIEST, TOOLBAR_LOOK, TOOLBAR_SHIELD, TOOLBAR_BAG, TOOLBAR_WAIT, TOOLBAR_SHOOT, TOOLBAR_END, TOOLBAR_ACT};
|
||||
|
||||
// Source rects for each button type in buttons.png.
|
||||
static rectangle btn_src_rects[] = {{0,0,38,38}, {0,38,19,76}, {19,38,38,76}};
|
||||
|
||||
eToolbarButton cToolbar::button_hit(sf::RenderWindow& win, location click) {
|
||||
rectangle dest_rect = win_to_rects[WINRECT_ACTBTNS];
|
||||
click.x -= dest_rect.left;
|
||||
click.y -= dest_rect.top;
|
||||
if(click.in(total_rect)) {
|
||||
for(int i = 0; i < toolbar.size(); i++) {
|
||||
if(click.in(toolbar[i].bounds)) {
|
||||
sf::Event e;
|
||||
bool done = false, clicked = false;
|
||||
win.setActive();
|
||||
active = i;
|
||||
while(!done){
|
||||
redraw_screen(REFRESH_NONE);
|
||||
while(win.pollEvent(e)) {
|
||||
if(e.type == sf::Event::MouseButtonReleased){
|
||||
done = true;
|
||||
location clickPos(e.mouseButton.x, e.mouseButton.y);
|
||||
clickPos = win.mapPixelToCoords(clickPos);
|
||||
clickPos.x -= dest_rect.left;
|
||||
clickPos.y -= dest_rect.top;
|
||||
clicked = toolbar[i].bounds.contains(clickPos);
|
||||
active = -1;
|
||||
} else if(e.type == sf::Event::MouseMoved){
|
||||
location toPos(e.mouseMove.x, e.mouseMove.y);
|
||||
toPos = win.mapPixelToCoords(toPos);
|
||||
toPos.x -= dest_rect.left;
|
||||
toPos.y -= dest_rect.top;
|
||||
active = toolbar[i].bounds.contains(toPos) ? i : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
play_sound(37, time_in_ticks(5));
|
||||
redraw_screen(REFRESH_NONE);
|
||||
if(clicked) return toolbar[i].btn;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TOOLBAR_NONE;
|
||||
}
|
||||
|
||||
cToolbar::eMode cToolbar::get_mode() {
|
||||
if(is_combat()) return COMBAT;
|
||||
if(is_town()) return TOWN;
|
||||
return OUTDOORS;
|
||||
}
|
||||
|
||||
void cToolbar::init() {
|
||||
eMode mode = get_mode();
|
||||
if(mode == cur_mode) return;
|
||||
cur_mode = mode;
|
||||
// Step 1: Select the correct toolbar
|
||||
std::vector<eToolbarButton>* src;
|
||||
switch(mode) {
|
||||
case UNKNOWN: case OUTDOORS:
|
||||
src = &out_buttons;
|
||||
break;
|
||||
case TOWN:
|
||||
src = &town_buttons;
|
||||
break;
|
||||
case COMBAT:
|
||||
src = &fight_buttons;
|
||||
break;
|
||||
}
|
||||
// Step 2: calculate the positions of the toolbar buttons
|
||||
toolbar.clear();
|
||||
int offset = 0;
|
||||
bool bottom_half = false;
|
||||
for(eToolbarButton btn : *src) {
|
||||
location slot = btn_pos(btn);
|
||||
cButton btn_info;
|
||||
btn_info.btn = btn;
|
||||
if(slot.y == 2) {
|
||||
// Small button (3rd row)
|
||||
btn_info.type = bottom_half ? BTN_SM_LO : BTN_SM_HI;
|
||||
btn_info.bounds = {0,0,19,38};
|
||||
if(bottom_half) {
|
||||
btn_info.bounds.offset(0,19);
|
||||
bottom_half = false;
|
||||
} else bottom_half = true;
|
||||
} else {
|
||||
// Large button (1st & 2nd rows)
|
||||
btn_info.type = BTN_LG;
|
||||
btn_info.bounds = {0,0,38,38};
|
||||
}
|
||||
btn_info.bounds.offset(offset, 0);
|
||||
if(btn_info.type != BTN_SM_HI) offset += 38;
|
||||
toolbar.push_back(btn_info);
|
||||
}
|
||||
// Step 3: draw the buttons into the cache
|
||||
static bool inited = false;
|
||||
if(!inited) {
|
||||
inited = true;
|
||||
cache.create(266,38);
|
||||
cache.clear(sf::Color::Black);
|
||||
}
|
||||
sf::Texture& buttons_gworld = *ResMgr::graphics.get("buttons");
|
||||
for(const auto& btn : toolbar) {
|
||||
rectangle icon_rect = {0, 0, 32, 32}, to_rect = btn.bounds;
|
||||
location slot = btn_pos(btn.btn);
|
||||
if(btn.type != BTN_LG) icon_rect.bottom = 16;
|
||||
icon_rect.offset(32 * slot.x, 38 + 32 * slot.y);
|
||||
rect_draw_some_item(buttons_gworld, btn_src_rects[btn.type], cache, to_rect);
|
||||
to_rect.inset(3,3);
|
||||
if(btn.type != BTN_LG) to_rect.bottom += 3;
|
||||
rect_draw_some_item(buttons_gworld, icon_rect, cache, to_rect, sf::BlendAlpha);
|
||||
}
|
||||
cache.display();
|
||||
// Step 4: Calculate total bounds
|
||||
if(toolbar.empty()) return;
|
||||
total_rect = std::accumulate(toolbar.begin() + 1, toolbar.end(), toolbar[0].bounds, [](const rectangle& accum, const cButton& next) {
|
||||
return rectunion(accum, next.bounds);
|
||||
});
|
||||
}
|
||||
|
||||
void cToolbar::draw(sf::RenderTarget& targ) {
|
||||
init();
|
||||
|
||||
// Determine actual rect
|
||||
rectangle to = win_to_rects[WINRECT_ACTBTNS];
|
||||
to.width() = total_rect.width();
|
||||
|
||||
// Prepare background for additive blending
|
||||
fill_rect(targ, to, sf::Color::Black);
|
||||
if(active >= 0 && active < toolbar.size()) {
|
||||
rectangle press_rect = toolbar[active].bounds;
|
||||
press_rect.offset(win_to_rects[WINRECT_ACTBTNS].topLeft());
|
||||
fill_rect(targ, press_rect, sf::Color::Blue);
|
||||
}
|
||||
|
||||
// Add the cached toolbar over the background
|
||||
rect_draw_some_item(cache.getTexture(), rectangle(cache), targ, to, sf::BlendAdd);
|
||||
}
|
50
src/game/boe.ui.hpp
Normal file
50
src/game/boe.ui.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// boe.ui.hpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 20-01-27.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef BOE_GAME_UI_H
|
||||
#define BOE_GAME_UI_H
|
||||
|
||||
#include <vector>
|
||||
#include "location.hpp"
|
||||
|
||||
// These correspond to the icons in buttons.png
|
||||
enum eToolbarButton {
|
||||
TOOLBAR_MAGE, TOOLBAR_PRIEST, TOOLBAR_LOOK, TOOLBAR_CAMP, TOOLBAR_SCROLL, TOOLBAR_SAVE,
|
||||
TOOLBAR_SHIELD, TOOLBAR_BAG, TOOLBAR_TALK, TOOLBAR_HAND, TOOLBAR_SWORD, TOOLBAR_LOAD,
|
||||
TOOLBAR_WAIT, TOOLBAR_END, TOOLBAR_SHOOT, TOOLBAR_ACT, TOOLBAR_USE, TOOLBAR_MAP,
|
||||
TOOLBAR_NONE = -1 // Keep this last
|
||||
};
|
||||
|
||||
class cToolbar {
|
||||
// These correspond to the button frames in buttons.png (top row)
|
||||
enum eButtonType {BTN_LG, BTN_SM_HI, BTN_SM_LO};
|
||||
|
||||
static std::vector<eToolbarButton> out_buttons, town_buttons, fight_buttons;
|
||||
struct cButton {
|
||||
eToolbarButton btn;
|
||||
eButtonType type;
|
||||
rectangle bounds;
|
||||
};
|
||||
|
||||
sf::RenderTexture cache;
|
||||
std::vector<cButton> toolbar;
|
||||
rectangle total_rect;
|
||||
enum eMode {UNKNOWN, OUTDOORS, TOWN, COMBAT};
|
||||
eMode cur_mode = UNKNOWN, get_mode();
|
||||
int active = -1;
|
||||
void init();
|
||||
public:
|
||||
void draw(sf::RenderTarget& targ);
|
||||
eToolbarButton button_hit(sf::RenderWindow& win, location click);
|
||||
};
|
||||
|
||||
namespace UI {
|
||||
extern cToolbar toolbar;
|
||||
}
|
||||
|
||||
#endif /* defined(BOE_GAME_UI_H) */
|
Reference in New Issue
Block a user