From 2872eb224e9f3ec6947542f2d7ac0ad288574cf1 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Tue, 17 May 2011 15:48:23 +0200 Subject: Added a console-like window which doesn't do anything interesting yet. --- GUI/layouts/console.layout | 15 ++++ SConstruct | 2 +- gui.cpp | 101 ++++++++++++++++++++- gui.h | 32 ++++++- main.cpp | 1 + scene.cpp | 90 ++++++++++++++----- scene.h | 1 + tool.cpp | 13 ++- tool.h | 7 +- widgets/FormattedListboxTextItem.cpp | 165 +++++++++++++++++++++++++++++++++++ widgets/FormattedListboxTextItem.h | 54 ++++++++++++ widgets/README | 1 + 12 files changed, 444 insertions(+), 38 deletions(-) create mode 100644 GUI/layouts/console.layout create mode 100644 widgets/FormattedListboxTextItem.cpp create mode 100644 widgets/FormattedListboxTextItem.h create mode 100644 widgets/README diff --git a/GUI/layouts/console.layout b/GUI/layouts/console.layout new file mode 100644 index 0000000..e6ef61b --- /dev/null +++ b/GUI/layouts/console.layout @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/SConstruct b/SConstruct index bec2ba8..c4e9247 100644 --- a/SConstruct +++ b/SConstruct @@ -24,6 +24,6 @@ if GetOption('profiling'): Export('env') -env.Program('foo', Glob('*.cpp') + ['noiseutils/noiseutils.cpp']) +env.Program('foo', Glob('*.cpp') + ['noiseutils/noiseutils.cpp'] + Glob('widgets/*.cpp')) # vim: syn=python diff --git a/gui.cpp b/gui.cpp index 72275c8..f29ee82 100644 --- a/gui.cpp +++ b/gui.cpp @@ -1,7 +1,10 @@ #include "gui.h" #include "video.h" +#include "widgets/FormattedListboxTextItem.h" + #include +#include #include using namespace CEGUI; @@ -38,6 +41,10 @@ void GUI::init() { System::getSingleton().setGUISheet(root); } +void GUI::pre_render() { + MouseCursor::getSingleton().hide(); +} + void GUI::render() { /* Disable depth testing to avoid cursor bugginess. */ glDisable(GL_DEPTH_TEST); @@ -45,6 +52,92 @@ void GUI::render() { glEnable(GL_DEPTH_TEST); } +void GUI::show() { + wnd->show(); + _showing = true; +} + +void GUI::hide() { + wnd->hide(); + _showing = false; +} + +bool GUI::showing() { + return _showing; +} + +/* ConsoleWindow */ + +ConsoleWindow::ConsoleWindow() { + WindowManager& wmgr(WindowManager::getSingleton()); + + wnd = wmgr.loadWindowLayout("console.layout"); + root->addChildWindow(wnd); + + editbox = wmgr.getWindow("console_editbox"); + editbox->subscribeEvent(Editbox::EventMouseClick, Event::Subscriber(&ConsoleWindow::clicked, this)); + editbox->subscribeEvent(Editbox::EventKeyDown, Event::Subscriber(&ConsoleWindow::keydown, this)); + + listbox = static_cast(wmgr.getWindow("console_listbox")); +} + +ConsoleWindow::~ConsoleWindow() { + WindowManager& wmgr(WindowManager::getSingleton()); + wmgr.destroyWindow(wnd); + wmgr.cleanDeadPool(); +} + +bool ConsoleWindow::clicked(const EventArgs& e) { + handle_input(); + + return true; +} + +void ConsoleWindow::erase_editbox_text() { + String s(editbox->getText()); + + if(s.size() == 0) + return; + + s.erase(s.size()-1); + editbox->setText(s); +} + +bool ConsoleWindow::keydown(const EventArgs& e) { + const KeyEventArgs& ke = static_cast(e); + switch(ke.scancode) { + // enter + case 36: + handle_input(); + break; + // backspace + case 22: + erase_editbox_text(); + break; + default: + break; + } + + return true; +} + +void ConsoleWindow::handle_input() { + std::string s = editbox->getText().c_str(); + editbox->setText(""); + boost::trim(s); + if(!s.size()) + return; + + FormattedListboxTextItem *item = new FormattedListboxTextItem(s, HTF_WORDWRAP_LEFT_ALIGNED); + listbox->addItem(item); + listbox->ensureItemIsVisible(item); +} + +void ConsoleWindow::update() { + MouseCursor::getSingleton().show(); + WindowManager::getSingleton().getWindow("console_editbox")->activate(); +} + /* RaiseWindow */ /* default values */ @@ -55,7 +148,7 @@ float RaiseWindow::strength = .3; RaiseWindow::RaiseWindow() { WindowManager& wmgr(WindowManager::getSingleton()); - wnd = static_cast(wmgr.loadWindowLayout("raisewnd.layout")); + wnd = wmgr.loadWindowLayout("raisewnd.layout"); root->addChildWindow(wnd); radius_sb = static_cast(wmgr.getWindow("radius_sb")); @@ -82,12 +175,12 @@ RaiseWindow::~RaiseWindow() { wmgr.cleanDeadPool(); } -void RaiseWindow::render() { +void RaiseWindow::update() { + MouseCursor::getSingleton().show(); + radius_sb_lbl->setText((boost::format("%.2f") % radius_sb->getScrollPosition()).str().c_str()); focus_sb_lbl->setText((boost::format("%.2f") % focus_sb->getScrollPosition()).str().c_str()); strength_sb_lbl->setText((boost::format("%.2f") % strength_sb->getScrollPosition()).str().c_str()); - - GUI::render(); } float RaiseWindow::get_radius() { diff --git a/gui.h b/gui.h index fe3bb3e..9e769f5 100644 --- a/gui.h +++ b/gui.h @@ -6,18 +6,44 @@ #include class GUI { + protected: + CEGUI::Window *wnd; + bool _showing; + public: static CEGUI::Window *root; virtual ~GUI() {}; static void init(); - virtual void render(); + static void pre_render(); + static void render(); + virtual void update() = 0; + virtual void show(); + virtual void hide(); + bool showing(); +}; + +class ConsoleWindow : public GUI { + private: + CEGUI::Window *editbox; + CEGUI::Listbox *listbox; + + bool clicked(const CEGUI::EventArgs& e); + bool keydown(const CEGUI::EventArgs& e); + + void erase_editbox_text(); + void handle_input(); + + public: + ConsoleWindow(); + virtual ~ConsoleWindow(); + + virtual void update(); }; class RaiseWindow : public GUI { private: - CEGUI::FrameWindow *wnd; CEGUI::PushButton *btn; CEGUI::Scrollbar *radius_sb; @@ -35,7 +61,7 @@ class RaiseWindow : public GUI { RaiseWindow(); virtual ~RaiseWindow(); - virtual void render(); + virtual void update(); float get_radius(); float get_focus(); float get_strength(); diff --git a/main.cpp b/main.cpp index 4d050fc..be24747 100644 --- a/main.cpp +++ b/main.cpp @@ -29,6 +29,7 @@ int main(int argc, char **argv) { Scene *scene = new Scene(); SDL_ShowCursor(SDL_DISABLE); + SDL_EnableUNICODE(1); SDL_WarpMouse(video::width/2, video::height/2); scene->last_time = SDL_GetTicks(); diff --git a/scene.cpp b/scene.cpp index f7db5c4..e179a3b 100644 --- a/scene.cpp +++ b/scene.cpp @@ -56,6 +56,9 @@ Scene::Scene() { font->FaceSize(10); GUI::init(); + + console = new ConsoleWindow(); + console->hide(); } Scene::~Scene() { @@ -64,6 +67,7 @@ Scene::~Scene() { if(terrain) delete terrain; delete font; + delete console; } void Scene::lookat() { @@ -143,11 +147,18 @@ void Scene::events() { running = false; break; case SDL_KEYDOWN: + if(console->showing() && event.key.keysym.sym != 124) { + CEGUI::System::getSingleton().injectKeyDown(event.key.keysym.scancode); + if(CEGUI::System::getSingleton().injectChar(event.key.keysym.unicode)) + break; + } switch(event.key.keysym.sym) { case SDLK_ESCAPE: if(tool) { delete tool; tool = NULL; + } else if(console->showing()) { + console->hide(); } else running = false; break; @@ -171,15 +182,35 @@ void Scene::events() { break; case SDLK_TAB: dialog = !dialog && tool; + if(tool) { + if(dialog) + tool->gui_show(); + else + tool->gui_hide(); + } break; case SDLK_1: if(tool) delete tool; tool = new RaiseTool(terrain); break; + case 124: + if(console->showing()) { + console->hide(); + dialog = false; + } else { + console->show(); + dialog = true; + } + break; default: break; } break; + case SDL_KEYUP: + if(console->showing() && event.key.keysym.sym != 124) { + CEGUI::System::getSingleton().injectKeyUp(event.key.keysym.scancode); + } + break; case SDL_MOUSEBUTTONDOWN: switch(event.button.button) { case SDL_BUTTON_LEFT: @@ -259,28 +290,30 @@ void Scene::render() { float forward = 0; float right = 0; bool moved = false; - if(keystate[SDLK_w]) { - moved = true; - forward++; - } - if(keystate[SDLK_s]) { - moved = true; - forward--; - } - if(keystate[SDLK_a]) { - moved = true; - right--; - } - if(keystate[SDLK_d]) { - moved = true; - right++; - } - if(keystate[SDLK_q]) - pos.y -= 0.002*steps*(keystate[SDLK_LSHIFT]?10:1); - if(keystate[SDLK_e]) - pos.y += 0.002*steps*(keystate[SDLK_LSHIFT]?10:1); - if(moved && (forward || right)) { - move(forward, right, steps*(keystate[SDLK_LSHIFT]?10:1)); + if(!dialog) { + if(keystate[SDLK_w]) { + moved = true; + forward++; + } + if(keystate[SDLK_s]) { + moved = true; + forward--; + } + if(keystate[SDLK_a]) { + moved = true; + right--; + } + if(keystate[SDLK_d]) { + moved = true; + right++; + } + if(keystate[SDLK_q]) + pos.y -= 0.002*steps*(keystate[SDLK_LSHIFT]?10:1); + if(keystate[SDLK_e]) + pos.y += 0.002*steps*(keystate[SDLK_LSHIFT]?10:1); + if(moved && (forward || right)) { + move(forward, right, steps*(keystate[SDLK_LSHIFT]?10:1)); + } } std::string move_str; @@ -464,8 +497,17 @@ void Scene::render() { font->Render(selected->str().c_str()); }*/ - if(dialog && tool) - tool->render_gui(); + GUI::pre_render(); + + if(tool && dialog) { + tool->gui_update(); + } + + if(console->showing()) { + console->update(); + } + + GUI::render(); SDL_GL_SwapBuffers(); } diff --git a/scene.h b/scene.h index 72bf506..89a5ec0 100644 --- a/scene.h +++ b/scene.h @@ -19,6 +19,7 @@ class Scene { FTFont *font; GUI *gui; Tool *tool; + ConsoleWindow *console; bool running; bool grid; diff --git a/tool.cpp b/tool.cpp index d96a45f..d652b16 100644 --- a/tool.cpp +++ b/tool.cpp @@ -5,13 +5,22 @@ Tool::Tool(Terrain *terrain) { this->terrain = terrain; } -void Tool::render_gui() { - gui->render(); +void Tool::gui_show() { + gui->show(); +} + +void Tool::gui_hide() { + gui->hide(); +} + +void Tool::gui_update() { + gui->update(); } /* RaiseTool */ RaiseTool::RaiseTool(Terrain *terrain) : Tool(terrain) { gui = new RaiseWindow(); + gui_hide(); } RaiseTool::~RaiseTool() { diff --git a/tool.h b/tool.h index 5ccda41..e08ecef 100644 --- a/tool.h +++ b/tool.h @@ -17,14 +17,13 @@ class Tool { virtual ~Tool() {}; virtual bool handle_event(SDL_Event& event, Vector3& selected) = 0; - virtual void render_gui(); + virtual void gui_show(); + virtual void gui_hide(); + virtual void gui_update(); virtual const char* get_name() = 0; }; class RaiseTool : public Tool { - protected: - static std::string name; - public: RaiseTool(Terrain *terrain); virtual ~RaiseTool(); diff --git a/widgets/FormattedListboxTextItem.cpp b/widgets/FormattedListboxTextItem.cpp new file mode 100644 index 0000000..b9362cc --- /dev/null +++ b/widgets/FormattedListboxTextItem.cpp @@ -0,0 +1,165 @@ +#include "FormattedListboxTextItem.h" + +namespace CEGUI +{ +//----------------------------------------------------------------------------// +FormattedListboxTextItem::FormattedListboxTextItem(const String& text, + const HorizontalTextFormatting format, + const uint item_id, + void* const item_data, + const bool disabled, + const bool auto_delete) : + // initialise base class + ListboxTextItem(text, item_id, item_data, disabled, auto_delete), + // initialise subclass fields + d_formatting(format), + d_formattedRenderedString(0) +{ +} + +//----------------------------------------------------------------------------// +FormattedListboxTextItem::~FormattedListboxTextItem() +{ + delete d_formattedRenderedString; +} + +//----------------------------------------------------------------------------// +HorizontalTextFormatting FormattedListboxTextItem::getFormatting() const +{ + return d_formatting; +} + +//----------------------------------------------------------------------------// +void FormattedListboxTextItem::setFormatting(const HorizontalTextFormatting fmt) +{ + if (fmt == d_formatting) + return; + + d_formatting = fmt; + delete d_formattedRenderedString; + d_formattedRenderedString = 0; + d_formattingAreaSize = Size(0, 0); +} + +//----------------------------------------------------------------------------// +Size FormattedListboxTextItem::getPixelSize(void) const +{ + if (!d_owner) + return Size(0, 0); + + // reparse text if we need to. + if (!d_renderedStringValid) + parseTextString(); + + // create formatter if needed + if (!d_formattedRenderedString) + setupStringFormatter(); + + // get size of render area from target window, to see if we need to reformat + const Size area_sz(static_cast(d_owner)-> + getListRenderArea().getSize()); + if (area_sz != d_formattingAreaSize) + { + d_formattedRenderedString->format(area_sz); + d_formattingAreaSize = area_sz; + } + + return Size(d_formattedRenderedString->getHorizontalExtent(), + d_formattedRenderedString->getVerticalExtent()); +} + +//----------------------------------------------------------------------------// +void FormattedListboxTextItem::draw(GeometryBuffer& buffer, + const Rect& targetRect, + float alpha, const Rect* clipper) const +{ + // reparse text if we need to. + if (!d_renderedStringValid) + parseTextString(); + + // create formatter if needed + if (!d_formattedRenderedString) + setupStringFormatter(); + + // get size of render area from target window, to see if we need to reformat + // NB: We do not use targetRect, since it may not represent the same area. + const Size area_sz(static_cast(d_owner)-> + getListRenderArea().getSize()); + if (area_sz != d_formattingAreaSize) + { + d_formattedRenderedString->format(area_sz); + d_formattingAreaSize = area_sz; + } + + // draw selection imagery + if (d_selected && d_selectBrush != 0) + d_selectBrush->draw(buffer, targetRect, clipper, + getModulateAlphaColourRect(d_selectCols, alpha)); + + // factor the window alpha into our colours. + const ColourRect final_colours( + getModulateAlphaColourRect(ColourRect(0xFFFFFFFF), alpha)); + + // draw the formatted text + d_formattedRenderedString->draw(buffer, targetRect.getPosition(), + &final_colours, clipper); +} + +//----------------------------------------------------------------------------// +void FormattedListboxTextItem::setupStringFormatter() const +{ + // delete any existing formatter + delete d_formattedRenderedString; + d_formattedRenderedString = 0; + + // create new formatter of whichever type... + switch(d_formatting) + { + case HTF_LEFT_ALIGNED: + d_formattedRenderedString = + new LeftAlignedRenderedString(d_renderedString); + break; + + case HTF_RIGHT_ALIGNED: + d_formattedRenderedString = + new RightAlignedRenderedString(d_renderedString); + break; + + case HTF_CENTRE_ALIGNED: + d_formattedRenderedString = + new CentredRenderedString(d_renderedString); + break; + + case HTF_JUSTIFIED: + d_formattedRenderedString = + new JustifiedRenderedString(d_renderedString); + break; + + case HTF_WORDWRAP_LEFT_ALIGNED: + d_formattedRenderedString = + new RenderedStringWordWrapper + (d_renderedString); + break; + + case HTF_WORDWRAP_RIGHT_ALIGNED: + d_formattedRenderedString = + new RenderedStringWordWrapper + (d_renderedString); + break; + + case HTF_WORDWRAP_CENTRE_ALIGNED: + d_formattedRenderedString = + new RenderedStringWordWrapper + (d_renderedString); + break; + + case HTF_WORDWRAP_JUSTIFIED: + d_formattedRenderedString = + new RenderedStringWordWrapper + (d_renderedString); + break; + } +} + +//----------------------------------------------------------------------------// +} diff --git a/widgets/FormattedListboxTextItem.h b/widgets/FormattedListboxTextItem.h new file mode 100644 index 0000000..efe5ff2 --- /dev/null +++ b/widgets/FormattedListboxTextItem.h @@ -0,0 +1,54 @@ +#ifndef FORMATTEDLISTBOXTEXTITEM_H +#define FORMATTEDLISTBOXTEXTITEM_H + +// TODO: Remove temporary workaround for CEGUI + GCC 4.6 +#include + +#include "CEGUI.h" + +namespace CEGUI +{ +//! A ListboxItem based class that can do horizontal text formatiing. +class FormattedListboxTextItem : public ListboxTextItem +{ +public: + //! Constructor + FormattedListboxTextItem(const String& text, + const HorizontalTextFormatting format = HTF_LEFT_ALIGNED, + const uint item_id = 0, + void* const item_data = 0, + const bool disabled = false, + const bool auto_delete = true); + + //! Destructor. + ~FormattedListboxTextItem(); + + //! Return the current formatting set. + HorizontalTextFormatting getFormatting() const; + /*! + Set the formatting. You should call Listbox::handleUpdatedItemData + after setting the formatting in order to update the listbox. We do not + do it automatically since you may wish to batch changes to multiple + items and multiple calls to handleUpdatedItemData is wasteful. + */ + void setFormatting(const HorizontalTextFormatting fmt); + + // overriden functions. + Size getPixelSize(void) const; + void draw(GeometryBuffer& buffer, const Rect& targetRect, + float alpha, const Rect* clipper) const; + +protected: + //! Helper to create a FormattedRenderedString of an appropriate type. + void setupStringFormatter() const; + //! Current formatting set + HorizontalTextFormatting d_formatting; + //! Class that renders RenderedString with some formatting. + mutable FormattedRenderedString* d_formattedRenderedString; + //! Tracks target area for rendering so we can reformat when needed + mutable Size d_formattingAreaSize; +}; + +} + +#endif diff --git a/widgets/README b/widgets/README new file mode 100644 index 0000000..3682ee3 --- /dev/null +++ b/widgets/README @@ -0,0 +1 @@ +FormattedListboxTextItem source: http://www.cegui.org.uk/phpBB2/viewtopic.php?f=10&t=4322 -- cgit v1.2.3