123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- // SuperTux Path
- // Copyright (C) 2005 Philipp <balinor@pnxs.de>
- // Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
- // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
- //
- // 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/path.hpp"
- #include "editor/bezier_marker.hpp"
- #include "editor/node_marker.hpp"
- #include "math/easing.hpp"
- #include "supertux/sector.hpp"
- #include "util/reader_mapping.hpp"
- #include "util/writer.hpp"
- #include "util/log.hpp"
- WalkMode
- string_to_walk_mode(const std::string& mode_string)
- {
- if (mode_string == "oneshot")
- return WalkMode::ONE_SHOT;
- else if (mode_string == "pingpong")
- return WalkMode::PING_PONG;
- else if (mode_string == "circular")
- return WalkMode::CIRCULAR;
- else {
- log_warning << "Unknown path mode '" << mode_string << "' found. Using oneshot instead." << std::endl;
- return WalkMode::ONE_SHOT;
- }
- }
- std::string
- walk_mode_to_string(WalkMode walk_mode)
- {
- if (walk_mode == WalkMode::ONE_SHOT)
- return "oneshot";
- else if (walk_mode == WalkMode::PING_PONG)
- return "pingpong";
- else if (walk_mode == WalkMode::CIRCULAR)
- return "circular";
- else {
- log_warning << "Unknown path mode found. Using oneshot instead." << std::endl;
- return "oneshot";
- }
- }
- Path::Path(PathGameObject& parent) :
- m_parent_gameobject(parent),
- m_nodes(),
- m_mode(WalkMode::CIRCULAR),
- m_adapt_speed()
- {
- }
- Path::Path(const Vector& pos, PathGameObject& parent) :
- m_parent_gameobject(parent),
- m_nodes(),
- m_mode(),
- m_adapt_speed()
- {
- Node first_node(this);
- first_node.position = pos;
- first_node.bezier_before = pos;
- first_node.bezier_after = pos;
- first_node.time = 1;
- first_node.speed = 0;
- first_node.easing = EaseNone;
- m_nodes.push_back(first_node);
- }
- void
- Path::read(const ReaderMapping& reader)
- {
- auto iter = reader.get_iter();
- m_mode = WalkMode::CIRCULAR;
- while (iter.next()) {
- if (iter.get_key() == "mode") {
- std::string mode_string;
- iter.get(mode_string);
- m_mode = string_to_walk_mode(mode_string);
- } else if (iter.get_key() == "adapt_speed") {
- iter.get(m_adapt_speed);
- } else if (iter.get_key() == "node") {
- ReaderMapping node_mapping = iter.as_mapping();
- // each new node will inherit all values from the last one
- Node node(this);
- node.time = 1;
- node.speed = 0;
- node.easing = EaseNone;
- if (!node_mapping.get("x", node.position.x) ||
- !node_mapping.get("y", node.position.y))
- throw std::runtime_error("Path node without x and y coordinate specified");
- if (!node_mapping.get("bezier_before_x", node.bezier_before.x) ||
- !node_mapping.get("bezier_before_y", node.bezier_before.y))
- node.bezier_before = node.position;
- if (!node_mapping.get("bezier_after_x", node.bezier_after.x) ||
- !node_mapping.get("bezier_after_y", node.bezier_after.y))
- node.bezier_after = node.position;
- node_mapping.get("time", node.time);
- node_mapping.get("speed", node.speed);
- node_mapping.get_custom("easing", node.easing, EasingMode_from_string);
- if (node.time <= 0)
- throw std::runtime_error("Path node with non-positive time");
- m_nodes.push_back(node);
- } else {
- log_warning << "unknown token '" << iter.get_key() << "' in Path nodes list. Ignored." << std::endl;
- }
- }
- if (m_nodes.empty())
- throw std::runtime_error("Path with zero nodes");
- }
- void
- Path::save(Writer& writer)
- {
- if (!is_valid()) return;
- writer.start_list("path");
- if (m_mode != WalkMode::CIRCULAR) {
- writer.write("mode", walk_mode_to_string(m_mode), false);
- }
- writer.write("adapt_speed", m_adapt_speed);
- for (auto& nod : m_nodes) {
- writer.start_list("node");
- writer.write("x", nod.position.x);
- writer.write("y", nod.position.y);
- if (nod.bezier_before.x != nod.position.x || nod.bezier_before.y != nod.position.y)
- {
- writer.write("bezier_before_x", nod.bezier_before.x);
- writer.write("bezier_before_y", nod.bezier_before.y);
- }
- if (nod.bezier_after.x != nod.position.x || nod.bezier_after.y != nod.position.y)
- {
- writer.write("bezier_after_x", nod.bezier_after.x);
- writer.write("bezier_after_y", nod.bezier_after.y);
- }
- if (nod.time != 1.0f) {
- writer.write("time", nod.time);
- }
- if (nod.speed != 0.0f) {
- writer.write("speed", nod.speed);
- }
- if (nod.easing != EaseNone) {
- writer.write("easing", getEasingName(nod.easing));
- }
- writer.end_list("node");
- }
- writer.end_list("path");
- }
- Vector
- Path::get_base() const
- {
- if (m_nodes.empty())
- return Vector(0, 0);
- return m_nodes[0].position;
- }
- int
- Path::get_nearest_node_idx(const Vector& reference_point) const
- {
- int nearest_node_id = -1;
- float nearest_node_dist = 0;
- int id = 0;
- for (std::vector<Node>::const_iterator i = m_nodes.begin(); i != m_nodes.end(); ++i, ++id) {
- float dist = glm::distance(i->position, reference_point);
- if ((nearest_node_id == -1) || (dist < nearest_node_dist)) {
- nearest_node_id = id;
- nearest_node_dist = dist;
- }
- }
- return nearest_node_id;
- }
- int
- Path::get_farthest_node_idx(const Vector& reference_point) const
- {
- int farthest_node_id = -1;
- float farthest_node_dist = 0;
- int id = 0;
- for (std::vector<Node>::const_iterator i = m_nodes.begin(); i != m_nodes.end(); ++i, ++id)
- {
- float dist = glm::distance(i->position, reference_point);
- if ((farthest_node_id == -1) || (dist > farthest_node_dist)) {
- farthest_node_id = id;
- farthest_node_dist = dist;
- }
- }
- return farthest_node_id;
- }
- void
- Path::move_by(const Vector& shift)
- {
- for (auto& nod : m_nodes) {
- nod.position += shift;
- nod.bezier_before += shift;
- nod.bezier_after += shift;
- }
- }
- void
- Path::edit_path()
- {
- int id = 0;
- for (auto i = m_nodes.begin(); i != m_nodes.end(); ++i) {
- auto& before = Sector::get().add<BezierMarker>(&(*i), &(i->bezier_before));
- auto& after = Sector::get().add<BezierMarker>(&(*i), &(i->bezier_after));
- auto& nm = Sector::get().add<NodeMarker>(i, id, before.get_uid(), after.get_uid());
- before.set_parent(nm.get_uid());
- after.set_parent(nm.get_uid());
- id++;
- }
- }
- bool
- Path::is_valid() const
- {
- return !m_nodes.empty();
- }
- void
- Path::on_flip(float height)
- {
- for (auto& node : m_nodes) {
- node.position.y = height - node.position.y;
- node.bezier_before.y = height - node.bezier_before.y;
- node.bezier_after.y = height - node.bezier_after.y;
- }
- }
- /* EOF */
|