//====================================================================== // STATUS BAR //====================================================================== namespace { class Window { public: Window() {} Window (const ScreenArea &area) : m_area(area) {} const ScreenArea &get_area() const { return m_area; } private: ScreenArea m_area; }; class TextDisplay { public: TextDisplay(Rect a, Font &f); void set_text(const string &t, TextMode m); void deactivate() { active = false; } bool is_active() const { return active; } void tick(double dtime); bool has_changed() { return changedp; } void draw(px::GC &gc, const Rect &r); private: string text; bool active, changedp; TextMode mode; Rect area; double xoff; const double scrollspeed; // pixels per second std::auto_ptr textsurface; px::Font &font; double time, maxtime; }; class StatusBarImpl : public StatusBar, public Window { public: StatusBarImpl (const ScreenArea &area); ~StatusBarImpl(); bool has_changed() const { return m_changedp; } void redraw (px::GC &gc, const ScreenArea &r); void tick (double dtime); void new_world(); // Window interface. // StatusBar interface. void set_inventory (Inventory *inv); void update_inventory (Inventory *inv); void show_text (const std::string &str, TextMode m=TEXT_SCROLLING); void hide_text() { m_textview.deactivate(); } private: ScreenArea m_itemarea; ScreenArea m_textarea; vector m_models; bool m_changedp; Inventory * m_inventory; TextDisplay m_textview; double m_leveltime; bool m_showtime_p; }; } StatusBarImpl::StatusBarImpl (const ScreenArea &area) : Window(area), m_itemarea (area.x+142, area.y+area.h-64+5, area.w-147, 64-10), m_textarea (area.x+147, area.y+area.h-64+20, area.w-157, 32), m_models(), m_changedp(false), m_inventory(0), m_textview (m_textarea, *enigma::GetFont("dreamorp24")), m_leveltime (0), m_showtime_p (true) {} StatusBarImpl::~StatusBarImpl() {} void StatusBarImpl::redraw (px::GC &gc, const ScreenArea &r) { ScreenArea a = get_area(); clip(gc, intersect(a, r)); blit(gc, a.x, a.y, enigma::GetImage ("inventory")); if (m_showtime_p) { char time[8]; int minutes = static_cast(m_leveltime/60) % 100; int seconds = static_cast(m_leveltime) % 60; Font *f = enigma::GetFont ("timefont"); sprintf (time, "%02d : %02d", minutes, seconds); Surface *s = f->render (time); blit(gc, a.x + 30, a.y+13, s); delete s; } else blit(gc, a.x+5, a.y+10, enigma::GetImage ("enigma_logo2_small")); if (m_textview.is_active()) { m_textview.draw (gc, r); } else { for (unsigned i=0; idraw(gc, m_itemarea.x + 10+i*40, m_itemarea.y + 11); } } m_changedp = false; } void StatusBarImpl::set_inventory (Inventory *inv) { m_inventory = inv; update_inventory (inv); } void StatusBarImpl::update_inventory (Inventory *inv) { if (inv && inv == m_inventory) { px::delete_sequence(m_models.begin(), m_models.end()); m_models.clear(); for (int i=0; isize(); ++i) { world::Item *it = inv->get_item(i); m_models.push_back(MakeModel(it->get_inventory_model ())); } m_changedp = true; } } void StatusBarImpl::show_text (const std::string &str, TextMode m) { m_textview.set_text (str, m); } void StatusBarImpl::tick (double dtime) { // Update text display if (m_textview.is_active()) { m_textview.tick (dtime); m_changedp = m_textview.has_changed(); } double oldtime=m_leveltime; m_leveltime += dtime; if (m_showtime_p && int(m_leveltime) - int(oldtime) >= 1) m_changedp = true; // update clock } void StatusBarImpl::new_world() { m_leveltime = 0; delete_sequence(m_models.begin(), m_models.end()); m_models.clear(); m_textview.deactivate(); } //---------------------------------------- // TextDisplay //---------------------------------------- TextDisplay::TextDisplay(ScreenArea a, Font &f) : text(), active(false), changedp(false), mode(TEXT_SCROLLING), area(a), xoff(0), scrollspeed(200), textsurface(0), font(f) { time = maxtime = 0; } void TextDisplay::set_text(const string &t, TextMode m) { text = t; mode = m; textsurface.reset(font.render(text.c_str())); time = 0; maxtime = 1e20; // this should be close to ``indefinitely'' switch (mode) { case TEXT_SCROLLING: xoff = -area.w; break; case TEXT_2SECONDS: maxtime = 2.0; // 2 seconds // fall through case TEXT_STATIC: xoff = -(area.w - textsurface->width())/2; break; } changedp = active = true; } void TextDisplay::tick(double dtime) { time += dtime; if (time > maxtime) { active = false; changedp = true; } else { int oldxoff = int(xoff); if (mode == TEXT_SCROLLING) { xoff += dtime * scrollspeed; changedp = int(xoff) != oldxoff; if (xoff >= textsurface->width()) { active = false; changedp = true; } } } } void TextDisplay::draw(px::GC &gc, const ScreenArea &r) { if (active) { clip(gc, intersect(area, r)); set_color(gc, 0,0,0); box(gc, area); blit(gc, area.x-int(xoff), area.y, textsurface.get()); } }