Merge pull request #251 from x-qq/fix_scrollbar_segfaults
fix for scrollbar segfaults * fixes #206 * fixes broken mousewheel scrolling of the scenedit palette * removed boost threads dependency * added foundation for further refactoring of the drawing and event handling code: interfaces and drawable manager with layering * removed a bunch of unneeded redraw calls * removed some repeated recalculation of effectively constant values (boe.actions) * removed recalculation of effectively constant scrollbar and button positions (boe.graphics) Closes #251
This commit is contained in:
@@ -1777,25 +1777,12 @@ void handle_keystroke(sf::Event event) {
|
||||
}
|
||||
|
||||
void handle_scroll(const sf::Event& event) {
|
||||
rectangle pal_rect = terrain_buttons_rect, right_area_rect = {0,0,RIGHT_AREA_HEIGHT,RIGHT_AREA_WIDTH};
|
||||
right_area_rect.offset(RIGHT_AREA_UL_X, RIGHT_AREA_UL_Y);
|
||||
pal_rect.offset(RIGHT_AREA_UL_X,RIGHT_AREA_UL_Y);
|
||||
pal_rect.height() = 16 * 17 + 2;
|
||||
fill_rect(mainPtr, right_area_rect, sf::Color::Magenta);
|
||||
location pos { translate_mouse_coordinates({event.mouseMove.x,event.mouseMove.y}) };
|
||||
int amount = event.mouseWheel.delta;
|
||||
if(right_sbar->isVisible() && pos.in(right_area_rect)) {
|
||||
right_sbar->setPosition(right_sbar->getPosition() - amount);
|
||||
redraw_screen();
|
||||
} else if(pal_sbar->isVisible() && pos.in(pal_rect)) {
|
||||
pal_sbar->setPosition(pal_sbar->getPosition() - amount);
|
||||
set_up_terrain_buttons(false);
|
||||
redraw_screen();
|
||||
} else if(overall_mode < MODE_MAIN_SCREEN && pos.in(terrain_rect)) {
|
||||
if(overall_mode < MODE_MAIN_SCREEN && pos.in(terrain_rect)) {
|
||||
if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) || sf::Keyboard::isKeyPressed(sf::Keyboard::RControl))
|
||||
cen_x = minmax(4, town->max_dim - 5, cen_x - amount);
|
||||
else cen_y = minmax(4, town->max_dim - 5, cen_y - amount);
|
||||
redraw_screen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,9 @@ const int RIGHT_AREA_HEIGHT = 400;
|
||||
const int TER_RECT_UL_X = 6;
|
||||
const int TER_RECT_UL_Y = 19;
|
||||
|
||||
const int UI_LAYER_DEFAULT = 1000;
|
||||
const int UI_LAYER_MENUBAR = 1200;
|
||||
|
||||
enum eScenMode {
|
||||
MODE_DRAWING = 0,
|
||||
MODE_TOGGLE_ROAD = 1,
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "scen.keydlgs.hpp"
|
||||
#include "sounds.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "drawable_manager.hpp"
|
||||
#include "cursors.hpp"
|
||||
|
||||
#include "dialog.hpp"
|
||||
@@ -38,6 +39,7 @@ void sort_specials();
|
||||
extern cOutdoors* current_terrain;
|
||||
extern sf::RenderWindow mainPtr;
|
||||
extern sf::View mainView;
|
||||
extern cDrawableManager drawable_mgr;
|
||||
extern cTown* current_town;
|
||||
extern short cen_x, cen_y,current_terrain_type,cur_town;
|
||||
extern cTown* town;
|
||||
@@ -402,7 +404,7 @@ void redraw_screen() {
|
||||
// DIRTY FIX to a problem that exist somewhere else. But where?
|
||||
undo_clip(mainPtr);
|
||||
|
||||
drawMenuBar();
|
||||
drawable_mgr.draw_all();
|
||||
|
||||
mainPtr.display();
|
||||
}
|
||||
@@ -424,14 +426,12 @@ void draw_main_screen() {
|
||||
tileImage(mainPtr,draw_rect,bg[17]);
|
||||
|
||||
draw_rb();
|
||||
right_sbar->draw();
|
||||
}
|
||||
|
||||
// draw terrain palette
|
||||
if((overall_mode < MODE_MAIN_SCREEN) || (overall_mode == MODE_EDIT_TYPES)) {
|
||||
place_location();
|
||||
set_up_terrain_buttons(false);
|
||||
pal_sbar->draw();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
|
||||
#define BOOST_NO_CXX11_NUMERIC_LIMITS // Because my libc++ is old and not quite standard-compliant, which breaks Boost.Thread
|
||||
#include <cstdio>
|
||||
#include <boost/thread.hpp>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#include "scen.global.hpp"
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "res_image.hpp"
|
||||
#include "prefs.hpp"
|
||||
#include "framerate_limiter.hpp"
|
||||
#include "event_listener.hpp"
|
||||
#include "drawable_manager.hpp"
|
||||
|
||||
/* Globals */
|
||||
bool All_Done = false;
|
||||
@@ -52,7 +54,6 @@ location cur_out;
|
||||
static void init_scened(int, char*[]);
|
||||
void handle_events();
|
||||
void handle_one_event(const sf::Event&);
|
||||
void Handle_Activate();
|
||||
void redraw_everything();
|
||||
void Mouse_Pressed(const sf::Event&);
|
||||
void close_program();
|
||||
@@ -66,6 +67,10 @@ extern rectangle terrain_buttons_rect;
|
||||
|
||||
extern void set_up_apple_events(int argc, char* argv[]);
|
||||
|
||||
// TODO: these should be members of some global entity instead of being here
|
||||
std::unordered_map <std::string, std::shared_ptr <iEventListener>> event_listeners;
|
||||
cDrawableManager drawable_mgr;
|
||||
|
||||
//Changed to ISO C specified argument and return type.
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
@@ -95,11 +100,32 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
static void init_sbar(std::shared_ptr<cScrollbar>& sbar, rectangle rect, int pgSz) {
|
||||
static void init_sbar(std::shared_ptr<cScrollbar>& sbar, std::string const name, rectangle rect, rectangle events_rect, int pgSz) {
|
||||
sbar.reset(new cScrollbar(mainPtr));
|
||||
sbar->setBounds(rect);
|
||||
sbar->set_wheel_event_rect(events_rect);
|
||||
sbar->setPageSize(pgSz);
|
||||
sbar->hide();
|
||||
|
||||
drawable_mgr.add_drawable(UI_LAYER_DEFAULT, name, sbar);
|
||||
event_listeners[name] = std::dynamic_pointer_cast <iEventListener> (sbar);
|
||||
}
|
||||
|
||||
static void init_scrollbars () {
|
||||
right_sbar_rect.top = RIGHT_AREA_UL_Y - 1;
|
||||
right_sbar_rect.left = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1 - 16;
|
||||
right_sbar_rect.bottom = RIGHT_AREA_UL_Y + RIGHT_AREA_HEIGHT + 1;
|
||||
right_sbar_rect.right = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1;
|
||||
rectangle pal_sbar_rect = terrain_buttons_rect;
|
||||
pal_sbar_rect.offset(RIGHT_AREA_UL_X,RIGHT_AREA_UL_Y);
|
||||
pal_sbar_rect.left = pal_sbar_rect.right - 16;
|
||||
pal_sbar_rect.height() = 17 * 16;
|
||||
|
||||
rectangle const right_sbar_event_rect { 5, 287, 405, 577 };
|
||||
rectangle const pal_sbar_event_rect { 5, 287, 279, 581 };
|
||||
|
||||
init_sbar(right_sbar, "right_sbar", right_sbar_rect, right_sbar_event_rect, NRSONPAGE - 1);
|
||||
init_sbar(pal_sbar, "pal_sbar", pal_sbar_rect, pal_sbar_event_rect, 16);
|
||||
}
|
||||
|
||||
sf::FloatRect compute_viewport(sf::RenderWindow const & mainPtr, float ui_scale) {
|
||||
@@ -177,17 +203,7 @@ void init_scened(int argc, char* argv[]) {
|
||||
cen_x = 18;
|
||||
cen_y = 18;
|
||||
|
||||
right_sbar_rect.top = RIGHT_AREA_UL_Y - 1;
|
||||
right_sbar_rect.left = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1 - 16;
|
||||
right_sbar_rect.bottom = RIGHT_AREA_UL_Y + RIGHT_AREA_HEIGHT + 1;
|
||||
right_sbar_rect.right = RIGHT_AREA_UL_X + RIGHT_AREA_WIDTH - 1;
|
||||
rectangle pal_sbar_rect = terrain_buttons_rect;
|
||||
pal_sbar_rect.offset(RIGHT_AREA_UL_X,RIGHT_AREA_UL_Y);
|
||||
pal_sbar_rect.left = pal_sbar_rect.right - 16;
|
||||
pal_sbar_rect.height() = 17 * 16;
|
||||
|
||||
init_sbar(right_sbar, right_sbar_rect, NRSONPAGE - 1);
|
||||
init_sbar(pal_sbar, pal_sbar_rect, 16);
|
||||
init_scrollbars();
|
||||
init_lb();
|
||||
init_rb();
|
||||
|
||||
@@ -203,7 +219,6 @@ void init_scened(int argc, char* argv[]) {
|
||||
cDialog::doAnimations = true;
|
||||
set_up_apple_events(argc, argv);
|
||||
init_fileio();
|
||||
redraw_screen();
|
||||
}
|
||||
|
||||
void handle_events() {
|
||||
@@ -225,8 +240,10 @@ void handle_events() {
|
||||
|
||||
void handle_one_event(sf::Event const & event) {
|
||||
|
||||
// Check if the menubar wants to handle this event.
|
||||
if(menuBarProcessEvent(event)) return;
|
||||
// Check if any of the event listeners want this event.
|
||||
for (auto & listener : event_listeners) {
|
||||
if(listener.second->handle_event(event)) return;
|
||||
}
|
||||
|
||||
switch(event.type) {
|
||||
case sf::Event::KeyPressed:
|
||||
@@ -609,39 +626,9 @@ void handle_menu_choice(eMenu item_hit) {
|
||||
redraw_screen();
|
||||
}
|
||||
|
||||
static void handleUpdateWhileScrolling(volatile bool& doneScrolling) {
|
||||
while(!doneScrolling) {
|
||||
sf::sleep(sf::milliseconds(10));
|
||||
// TODO: redraw_screen should probably take the argument specifying what to update
|
||||
redraw_screen(/*REFRESH_RIGHT_BAR*/);
|
||||
if(overall_mode < MODE_MAIN_SCREEN || overall_mode == MODE_EDIT_TYPES)
|
||||
set_up_terrain_buttons(false);
|
||||
}
|
||||
mainPtr.setActive(false);
|
||||
}
|
||||
|
||||
void Mouse_Pressed(sf::Event const & event) {
|
||||
|
||||
// Translate coordinates
|
||||
location mousePos { translate_mouse_coordinates({event.mouseButton.x, event.mouseButton.y}) };
|
||||
|
||||
volatile bool doneScrolling = false;
|
||||
if(right_sbar->isVisible() && mousePos.in(right_sbar->getBounds())) {
|
||||
mainPtr.setActive(false);
|
||||
boost::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling)));
|
||||
right_sbar->handleClick(mousePos);
|
||||
doneScrolling = true;
|
||||
updater.join();
|
||||
redraw_screen(/*REFRESH_RIGHT_BAR*/);
|
||||
} else if(pal_sbar->isVisible() && mousePos.in(pal_sbar->getBounds())) {
|
||||
mainPtr.setActive(false);
|
||||
boost::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling)));
|
||||
pal_sbar->handleClick(mousePos);
|
||||
doneScrolling = true;
|
||||
updater.join();
|
||||
redraw_screen(/*REFRESH_RIGHT_BAR*/);
|
||||
set_up_terrain_buttons(false);
|
||||
} else handle_action(mousePos,event);
|
||||
handle_action(mousePos,event);
|
||||
}
|
||||
|
||||
void close_program() {
|
||||
|
@@ -6,9 +6,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
OpenBoESceneditMenu::OpenBoESceneditMenu(sf::RenderWindow& window)
|
||||
: tgui { window }
|
||||
, mainPtr { window } {
|
||||
|
||||
: tgui { window } {
|
||||
// Build a menubar and store it in tgui with a known name
|
||||
this->tgui.add(this->build_menubar(), this->internal_menubar_widget_name);
|
||||
}
|
||||
@@ -17,7 +15,7 @@ tgui::MenuBar::Ptr OpenBoESceneditMenu::build_menubar() const {
|
||||
auto menubar = tgui::MenuBar::create();
|
||||
|
||||
// XXX can we get this constant magic number from somewhere?
|
||||
menubar->setSize(this->mainPtr.getSize().x, 20);
|
||||
menubar->setSize("100%", 20);
|
||||
|
||||
this->add_menu_placeholders(menubar);
|
||||
this->add_persistent_menu_items(menubar);
|
||||
|
@@ -7,14 +7,16 @@
|
||||
#include <TGUI/TGUI.hpp>
|
||||
#include <vector>
|
||||
#include "undo.hpp"
|
||||
#include "event_listener.hpp"
|
||||
#include "drawable.hpp"
|
||||
|
||||
class OpenBoESceneditMenu {
|
||||
class OpenBoESceneditMenu : public iEventListener, public iDrawable {
|
||||
public:
|
||||
|
||||
OpenBoESceneditMenu(sf::RenderWindow &);
|
||||
|
||||
bool handle_event(const sf::Event&);
|
||||
void draw();
|
||||
virtual bool handle_event(const sf::Event&) override;
|
||||
virtual void draw() override;
|
||||
void update_for_mode(short mode);
|
||||
void update_edit_menu(cUndoList const &);
|
||||
|
||||
@@ -23,7 +25,6 @@ private:
|
||||
using MenuHierarchy = std::vector<sf::String>;
|
||||
|
||||
tgui::Gui tgui;
|
||||
sf::RenderWindow& mainPtr;
|
||||
const sf::String internal_menubar_widget_name { "openboe-scenedit-menu" };
|
||||
|
||||
tgui::MenuBar::Ptr build_menubar() const;
|
||||
|
@@ -13,10 +13,6 @@ void init_menubar();
|
||||
void shut_down_menus(short mode);
|
||||
void update_edit_menu();
|
||||
|
||||
namespace sf { class Event; };
|
||||
bool menuBarProcessEvent(const sf::Event&);
|
||||
void drawMenuBar();
|
||||
|
||||
enum class eMenu {
|
||||
NONE, ABOUT, QUIT, FRILL, UNFRILL,
|
||||
FILE_NEW, FILE_OPEN, FILE_CLOSE, FILE_SAVE, FILE_SAVE_AS, FILE_REVERT,
|
||||
|
@@ -1,16 +1,26 @@
|
||||
#include "scen.global.hpp"
|
||||
#include "scen.menus.hpp"
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include "scen.menu.hpp"
|
||||
#include "undo.hpp"
|
||||
#include "event_listener.hpp"
|
||||
#include "drawable_manager.hpp"
|
||||
|
||||
extern sf::RenderWindow mainPtr;
|
||||
extern cUndoList undo_list;
|
||||
extern std::unordered_map <std::string, std::shared_ptr <iEventListener>> event_listeners;
|
||||
extern cDrawableManager drawable_mgr;
|
||||
|
||||
std::shared_ptr <OpenBoESceneditMenu> menu_ptr;
|
||||
|
||||
void init_menubar() {
|
||||
menu_ptr.reset(new OpenBoESceneditMenu(mainPtr));
|
||||
|
||||
event_listeners["menubar"] = std::dynamic_pointer_cast <iEventListener> (menu_ptr);
|
||||
drawable_mgr.add_drawable(UI_LAYER_MENUBAR, "menubar", menu_ptr);
|
||||
}
|
||||
|
||||
void shut_down_menus(short mode) {
|
||||
@@ -21,13 +31,5 @@ void update_edit_menu() {
|
||||
menu_ptr->update_edit_menu(undo_list);
|
||||
}
|
||||
|
||||
bool menuBarProcessEvent(const sf::Event& event) {
|
||||
return menu_ptr->handle_event(event);
|
||||
}
|
||||
|
||||
void drawMenuBar() {
|
||||
menu_ptr->draw();
|
||||
}
|
||||
|
||||
void set_up_apple_events(int argc, char* argv[]) {
|
||||
}
|
||||
|
@@ -164,13 +164,6 @@ void update_edit_menu() {
|
||||
}
|
||||
}
|
||||
|
||||
bool menuBarProcessEvent(const sf::Event&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void drawMenuBar() {
|
||||
}
|
||||
|
||||
@implementation MenuHandler
|
||||
-(void) menuChoice:(id) sender {
|
||||
handle_menu_choice(eMenu([[sender representedObject] intValue]));
|
||||
|
@@ -253,10 +253,3 @@ void set_up_apple_events(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool menuBarProcessEvent(const sf::Event&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void drawMenuBar() {
|
||||
}
|
||||
|
Reference in New Issue
Block a user