minimize some #includes and replace with forward decls
[supertux.git] / src / object / path.cpp
1 //  $Id$
2 //
3 //  SuperTux Path
4 //  Copyright (C) 2005 Philipp <balinor@pnxs.de>
5 //  Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
6 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; either version 2
11 //  of the License, or (at your option) any later version.
12 //
13 //  This program is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 //  GNU General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 //  02111-1307, USA.
22 #include <config.h>
23
24 #include "path.hpp"
25
26 #include "lisp/writer.hpp"
27 #include "lisp/lisp.hpp"
28 #include "lisp/list_iterator.hpp"
29 #include "object_factory.hpp"
30 #include "log.hpp"
31
32 #include <assert.h>
33 #include <iostream>
34 #include <stdexcept>
35 #include <sstream>
36
37 Path::Path()
38 {
39 }
40
41 Path::~Path()
42 {
43 }
44
45 void
46 Path::read(const lisp::Lisp& reader)
47 {
48   lisp::ListIterator iter(&reader);
49
50   mode = CIRCULAR;
51   while(iter.next()) {
52     if(iter.item() == "mode") {
53       std::string mode_string;
54       if(!iter.value()->get(mode_string))
55         throw std::runtime_error("Pathmode not a string");
56
57       if(mode_string == "oneshot")
58         mode = ONE_SHOT;
59       else if(mode_string == "pingpong")
60         mode = PING_PONG;
61       else if(mode_string == "circular")
62         mode = CIRCULAR;
63       else {
64         std::ostringstream msg;
65         msg << "Unknown pathmode '" << mode_string << "' found";
66         throw std::runtime_error(msg.str());
67       }
68       continue;
69     }
70
71     if(iter.item() != "node") {
72       log_warning << "unknown token '" << iter.item() << "' in Path nodes list. Ignored." << std::endl;
73       continue;
74     }
75     const lisp::Lisp* node_lisp = iter.lisp();
76
77     // each new node will inherit all values from the last one
78     Node node;
79     node.time = 1;
80     if( (!node_lisp->get("x", node.position.x) ||
81           !node_lisp->get("y", node.position.y)))
82       throw std::runtime_error("Path node without x and y coordinate specified");
83     node_lisp->get("time", node.time);
84
85     if(node.time <= 0)
86       throw std::runtime_error("Path node with non-positive time");
87
88     nodes.push_back(node);
89   }
90
91   if (nodes.empty())
92     throw std::runtime_error("Path with zero nodes");
93 }
94
95 void
96 Path::write(lisp::Writer& writer)
97 {
98   writer.start_list("path");
99
100   switch(mode) {
101     case ONE_SHOT:
102       writer.write_string("mode", "oneshot");
103       break;
104     case PING_PONG:
105       writer.write_string("mode", "pingpong");
106       break;
107     case CIRCULAR:
108       writer.write_string("mode", "circular");
109       break;
110     default:
111       log_warning << "Don't know how to write mode " << (int) mode << " ?!?" << std::endl;
112       break;
113   }
114
115   for (size_t i=0; i < nodes.size(); i++) {
116     const Node& node = nodes[i];
117
118     writer.start_list("node");
119     writer.write_float("x", node.position.x);
120     writer.write_float("y", node.position.y);
121     writer.write_float("time", node.time);
122
123     writer.end_list("node");
124   }
125
126   writer.end_list("path");
127 }
128
129 Vector
130 Path::get_base() const
131 {
132   if(nodes.empty())
133     return Vector(0, 0);
134
135   return nodes[0].position;
136 }