123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- // SuperTux
- // Copyright (C) 2018 Nir <goproducti@gmail.com>
- //
- // 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 3 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 <http://www.gnu.org/licenses/>.
- #include "object/text_array_object.hpp"
- #include <simplesquirrel/class.hpp>
- #include <simplesquirrel/vm.hpp>
- #include "control/input_manager.hpp"
- #include "supertux/sector.hpp"
- TextArrayObject::TextArrayObject(const std::string& name) :
- LayerObject(name),
- m_finished(false),
- m_is_auto(false),
- m_keep_visible(false),
- m_fade_transition(true),
- m_fadetime(1.0),
- m_texts(),
- m_curTextIndex(0),
- m_lastTextIndex(0),
- m_waiting()
- {
- }
- void
- TextArrayObject::clear()
- {
- m_texts.clear();
- reset_automation();
- }
- void
- TextArrayObject::add_text(const std::string& text)
- {
- add_text_duration(text, 3.f);
- }
- void
- TextArrayObject::add_text_duration(const std::string& text, float duration)
- {
- auto pText = std::make_unique<TextArrayItem>();
- assert(pText);
- pText->duration = duration;
- pText->text_object.set_text(text);
- m_texts.push_back(std::move(pText));
- }
- void
- TextArrayObject::set_text_index(ta_index index)
- {
- if (index < m_texts.size())
- m_curTextIndex = index;
- }
- void
- TextArrayObject::next_text()
- {
- if (m_finished)
- return;
- if (m_curTextIndex + 1 >= m_texts.size()) {
- m_finished = true;
- return;
- }
- m_lastTextIndex = m_curTextIndex++;
- override_properties();
- reset_automation();
- }
- void
- TextArrayObject::prev_text()
- {
- if (m_finished)
- return;
- if (m_curTextIndex == 0)
- return;
- m_lastTextIndex = m_curTextIndex--;
- override_properties();
- reset_automation();
- }
- TextArrayItem*
- TextArrayObject::get_text_item(ta_index index) const
- {
- auto vecSize = m_texts.size();
- if (vecSize == 0 || index >= vecSize)
- return nullptr;
- return m_texts.at(index).get();
- }
- TextArrayItem*
- TextArrayObject::get_current_text_item() const
- {
- return get_text_item(m_curTextIndex);
- }
- TextArrayItem*
- TextArrayObject::get_last_text_item() const
- {
- return get_text_item(m_lastTextIndex);
- }
- void
- TextArrayObject::set_auto(bool is_auto)
- {
- m_is_auto = is_auto;
- reset_automation();
- }
- void
- TextArrayObject::update(float dt_sec)
- {
- if (m_finished)
- return;
- // make sure there's anything to update
- if (m_texts.size() == 0)
- return;
- // detect change request
- handle_input_requests();
- // check if if should update auto narration
- if (m_is_auto && m_waiting.check()) {
- next_text();
- }
- // update current
- auto* curTextItem = get_current_text_item();
- if (curTextItem)
- curTextItem->text_object.update(dt_sec);
- // update last (if transition is enabled)
- if (should_fade()) {
- auto* lastTextItem = get_last_text_item();
- if (lastTextItem)
- lastTextItem->text_object.update(dt_sec);
- }
- }
- void
- TextArrayObject::draw(DrawingContext& context)
- {
- if (m_finished)
- return;
- auto* curTextItem = get_current_text_item();
- if (!curTextItem)
- return;
- // draw last if transition enabled
- if (should_fade()) {
- auto* lastTextItem = get_last_text_item();
- if (lastTextItem)
- lastTextItem->text_object.draw(context);
- }
- // draw current
- curTextItem->text_object.draw(context);
- }
- void
- TextArrayObject::override_properties()
- {
- if (!(should_fade() || m_keep_visible))
- return;
- auto* curTextItem = get_current_text_item();
- if (!curTextItem)
- return;
- // apply overrides
- if (should_fade()) { // make fade transition
- auto* lastTextItem = get_last_text_item();
- if (lastTextItem) {
- lastTextItem->text_object.fade_out(m_fadetime);
- curTextItem->text_object.fade_in(m_fadetime);
- }
- } else if (m_keep_visible) { // keep visible
- curTextItem->text_object.set_visible(true);
- }
- }
- void
- TextArrayObject::reset_automation()
- {
- m_waiting.stop();
- if (m_is_auto) {
- auto* text = get_current_text_item();
- if (text)
- m_waiting.start(text->duration);
- }
- }
- void
- TextArrayObject::handle_input_requests()
- {
- const Controller& controller = InputManager::current()->get_controller();
- if (controller.pressed(Control::MENU_SELECT)) {
- m_is_auto = false;
- next_text();
- } else if (controller.pressed(Control::REMOVE)) {
- m_is_auto = false;
- prev_text();
- }
- }
- bool
- TextArrayObject::should_fade() const
- {
- return m_fade_transition && (m_curTextIndex != m_lastTextIndex);
- }
- /** TextObject functions */
- #define TEXT_OBJECT_FUNCTION_VOID(F) \
- TextArrayItem* item = get_current_text_item(); \
- if (item) { \
- item->text_object.F; \
- return; \
- }
- #define TEXT_OBJECT_FUNCTION_RETURN(F) \
- TextArrayItem* item = get_current_text_item(); \
- if (item) \
- return item->text_object.F;
- #define TEXT_OBJECT_FUNCTION_VOID_THROW(F) \
- TEXT_OBJECT_FUNCTION_VOID(F) \
- throw std::runtime_error("No current TextObject in TextArrayObject!");
- #define TEXT_OBJECT_FUNCTION_RETURN_THROW(F) \
- TEXT_OBJECT_FUNCTION_RETURN(F) \
- throw std::runtime_error("No current TextObject in TextArrayObject!");
- void
- TextArrayObject::set_text(const std::string& text)
- {
- TEXT_OBJECT_FUNCTION_VOID(set_text(text))
- add_text(text);
- }
- const std::string&
- TextArrayObject::get_text() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_text())
- }
- void
- TextArrayObject::set_font(const std::string& fontname)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_font(fontname))
- }
- void
- TextArrayObject::fade_in(float fadetime)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(fade_in(fadetime))
- }
- void
- TextArrayObject::fade_out(float fadetime)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(fade_out(fadetime))
- }
- void
- TextArrayObject::grow_in(float fadetime)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(grow_in(fadetime))
- }
- void
- TextArrayObject::grow_out(float fadetime)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(grow_out(fadetime))
- }
- void
- TextArrayObject::set_visible(bool visible)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_visible(visible))
- }
- bool
- TextArrayObject::get_visible() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_visible())
- }
- void
- TextArrayObject::set_centered(bool centered)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_centered(centered))
- }
- bool
- TextArrayObject::get_centered() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_centered())
- }
- void
- TextArrayObject::set_pos(float x, float y)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_pos(Vector(x, y)))
- }
- float
- TextArrayObject::get_x() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_pos().x)
- }
- float
- TextArrayObject::get_y() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_pos().y)
- }
- void
- TextArrayObject::set_anchor_point(int anchor)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_anchor_point(static_cast<AnchorPoint>(anchor)))
- }
- int
- TextArrayObject::get_anchor_point() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_anchor_point())
- }
- void
- TextArrayObject::set_anchor_offset(float x, float y)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_anchor_offset(x, y))
- }
- float
- TextArrayObject::get_wrap_width() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_wrap_width())
- }
- void
- TextArrayObject::set_wrap_width(float width)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_wrap_width(width))
- }
- void
- TextArrayObject::set_front_fill_color(float red, float green, float blue, float alpha)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_front_fill_color(red, green, blue, alpha))
- }
- void
- TextArrayObject::set_back_fill_color(float red, float green, float blue, float alpha)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_back_fill_color(red, green, blue, alpha))
- }
- void
- TextArrayObject::set_text_color(float red, float green, float blue, float alpha)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_text_color(red, green, blue, alpha))
- }
- void
- TextArrayObject::set_roundness(float roundness)
- {
- TEXT_OBJECT_FUNCTION_VOID_THROW(set_roundness(roundness))
- }
- float
- TextArrayObject::get_roundness() const
- {
- TEXT_OBJECT_FUNCTION_RETURN_THROW(get_roundness())
- }
- #undef TEXT_OBJECT_FUNCTION_VOID
- #undef TEXT_OBJECT_FUNCTION_RETURN
- #undef TEXT_OBJECT_FUNCTION_VOID_THROW
- #undef TEXT_OBJECT_FUNCTION_RETURN_THROW
- void
- TextArrayObject::register_class(ssq::VM& vm)
- {
- ssq::Class cls = vm.addClass("TextArrayObject", []()
- {
- if (!Sector::current())
- throw std::runtime_error("Tried to create 'TextArrayObject' without an active sector.");
- return &Sector::get().add<TextArrayObject>();
- },
- {},
- false /* Do not free pointer from Squirrel */,
- vm.findClass("GameObject"));
- cls.addFunc("clear", &TextArrayObject::clear);
- cls.addFunc("add_text", &TextArrayObject::add_text);
- cls.addFunc("add_text_duration", &TextArrayObject::add_text_duration);
- cls.addFunc("set_text_index", &TextArrayObject::set_text_index);
- cls.addFunc("set_keep_visible", &TextArrayObject::set_keep_visible);
- cls.addFunc("set_fade_transition", &TextArrayObject::set_fade_transition);
- cls.addFunc("set_fade_time", &TextArrayObject::set_fade_time);
- cls.addFunc("set_done", &TextArrayObject::set_done);
- cls.addFunc("set_auto", &TextArrayObject::set_auto);
- cls.addFunc("next_text", &TextArrayObject::next_text);
- cls.addFunc("prev_text", &TextArrayObject::prev_text);
- cls.addVar("keep_visible", &TextArrayObject::m_keep_visible);
- cls.addVar("fade_transition", &TextArrayObject::m_fade_transition);
- cls.addVar("finished", &TextArrayObject::m_finished);
- /* TextObject API related */
- cls.addFunc("set_text", &TextArrayObject::set_text);
- cls.addFunc("get_text", &TextArrayObject::get_text);
- cls.addFunc("set_font", &TextArrayObject::set_font);
- cls.addFunc("fade_in", &TextArrayObject::fade_in);
- cls.addFunc("fade_out", &TextArrayObject::fade_out);
- cls.addFunc("grow_in", &TextArrayObject::grow_in);
- cls.addFunc("grow_out", &TextArrayObject::grow_out);
- cls.addFunc("set_visible", &TextArrayObject::set_visible);
- cls.addFunc("get_visible", &TextArrayObject::get_visible);
- cls.addFunc("set_centered", &TextArrayObject::set_centered);
- cls.addFunc("get_centered", &TextArrayObject::get_centered);
- cls.addFunc("set_pos", &TextArrayObject::set_pos);
- cls.addFunc("get_x", &TextArrayObject::get_x);
- cls.addFunc("get_y", &TextArrayObject::get_y);
- cls.addFunc("get_pos_x", &TextArrayObject::get_x); // Deprecated
- cls.addFunc("get_pos_y", &TextArrayObject::get_y); // Deprecated
- cls.addFunc("set_anchor_point", &TextArrayObject::set_anchor_point);
- cls.addFunc("get_anchor_point", &TextArrayObject::get_anchor_point);
- cls.addFunc("set_anchor_offset", &TextArrayObject::set_anchor_offset);
- cls.addFunc("get_wrap_width", &TextArrayObject::get_wrap_width);
- cls.addFunc("set_wrap_width", &TextArrayObject::set_wrap_width);
- cls.addFunc("set_front_fill_color", &TextArrayObject::set_front_fill_color);
- cls.addFunc("set_back_fill_color", &TextArrayObject::set_back_fill_color);
- cls.addFunc("set_text_color", &TextArrayObject::set_text_color);
- cls.addFunc("set_roundness", &TextArrayObject::set_roundness);
- cls.addFunc("get_roundness", &TextArrayObject::set_roundness);
- cls.addVar("text", &TextArrayObject::get_text, &TextArrayObject::set_text);
- cls.addVar("visible", &TextArrayObject::get_visible, &TextArrayObject::set_visible);
- cls.addVar("centered", &TextArrayObject::get_centered, &TextArrayObject::set_centered);
- cls.addVar("anchor_point", &TextArrayObject::get_anchor_point, &TextArrayObject::set_anchor_point);
- cls.addVar("wrap_width", &TextArrayObject::get_wrap_width, &TextArrayObject::set_wrap_width);
- cls.addVar("roundness", &TextArrayObject::get_roundness, &TextArrayObject::set_roundness);
- }
- /* EOF */
|