Initial commit, includes Lua with broken Luabind as a backup for branching purposes
[terrastrategy.git] / src / gui / cursor.cpp
blobc1e9ca1d7086409e2b00be88123e448dbda55f96
1 //
2 // Copyright (C) 2008 by Martin Moracek
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /**
20 * @file cursor.cpp
22 * blahblah
25 #include <string>
27 #include "xml/tinyxml.h"
28 #include "xml/xmlutils.h"
30 #include "vfs/fstream.h"
31 #include "vfs/logfile.h"
33 #include "exception.h"
34 #include "cursor.h"
36 namespace tre {
39 * Cursor class implementation
41 void Cursor::Rescale(const Vector2f & scale, Float2Vector & verts)
43 DEBUG_ASSERT(indices);
45 verts[indices->vFrom].Set(0.0f, baseSize_.y * scale.y);
46 verts[indices->vFrom + 1].Set(baseSize_.x * scale.x, baseSize_.y * scale.y);
47 verts[indices->vFrom + 2].Set(baseSize_.x * scale.x, 0.0f);
48 verts[indices->vFrom + 3].Set(0.0f, 0.0f);
51 void Cursor::LoadFromXml(TiXmlElement & root, const Vector2f & scale,
52 Float2Vector & verts, Float2Vector & coords)
54 uint offset = verts.size();
56 TiXmlElement * elem = root.FirstChildElement("effect");
57 if(!elem)
58 throw(Exception("Missing effect information"));
60 effect = Effect::Factory().CreateInstance(CheckText(*elem));
62 elem = root.FirstChildElement("texture");
63 if(!elem)
64 throw(Exception("Missing texture information"));
66 vars.SetTexture("gui_Texture", CheckText(*elem));
68 elem = root.FirstChildElement("rect");
69 if(!elem)
70 throw(Exception("Missing rectangle information"));
72 float tex_scale = CheckFloatAttribute(*elem, "scale", false, 1.0f);
74 float left = CheckFloatAttribute(*elem, "left");
75 float right = CheckFloatAttribute(*elem, "right");
76 float bottom = CheckFloatAttribute(*elem, "bottom");
77 float top = CheckFloatAttribute(*elem, "top");
79 baseSize_.x = right - left;
80 baseSize_.y = top - bottom;
82 baseOffset_ = 0.0f;
83 elem = root.FirstChildElement("offset");
84 if(elem) {
85 baseOffset_.x = CheckFloatAttribute(*elem, "x", false, 0.0f);
86 baseOffset_.y = CheckFloatAttribute(*elem, "y", false, 0.0f);
89 left /= tex_scale;
90 right /= tex_scale;
91 top /= tex_scale;
92 bottom /= tex_scale;
94 coords.push_back(Vector2f(left, top));
95 coords.push_back(Vector2f(left, bottom));
96 coords.push_back(Vector2f(right, top));
97 coords.push_back(Vector2f(right, bottom));
99 elem = root.FirstChildElement("scale");
100 if(elem) {
101 baseSize_.x *= CheckFloatAttribute(*elem, "x", false, 1.0f);
102 baseOffset_.x *= CheckFloatAttribute(*elem, "x", false, 1.0f);
103 baseSize_.y *= CheckFloatAttribute(*elem, "y", false, 1.0f);
104 baseOffset_.y *= CheckFloatAttribute(*elem, "y", false, 1.0f);
107 indices = IndexBufPtr(IndexBuffer::Factory().CreateInstance());
108 indices->vFrom = verts.size();
110 verts.push_back(Vector2f(baseOffset_.x * scale.x,
111 baseOffset_.y * scale.y));
112 verts.push_back(Vector2f(baseOffset_.x * scale.x,
113 (baseSize_.y + baseOffset_.y) * scale.y));
114 verts.push_back(Vector2f((baseSize_.x + baseOffset_.x) * scale.x,
115 baseOffset_.y * scale.y));
116 verts.push_back(Vector2f((baseSize_.x + baseOffset_.x) * scale.x,
117 (baseSize_.y + baseOffset_.y) * scale.y));
119 indices->vTo = verts.size();
121 uint inds[] = {offset + 1, offset + 3, offset + 2,
122 offset + 1, offset + 2, offset};
124 indices->Init(6);
125 uint * ptr = indices->Lock();
126 DEBUG_ASSERT(ptr);
127 memcpy(ptr, inds, sizeof(uint) * 6);
128 indices->Unlock();
129 indices->vFrom = 0;
130 indices->vTo = 6;
134 * CursorSetFactory class implementation
136 const CursorSetPtr CursorSetFactory::CreateInstance
137 (const std::string & filename, const Vector2f & scale)
139 CursorMap::iterator pos = cursorMap_.find(filename);
141 if(pos != cursorMap_.end() && !pos->second.expired()) {
142 return pos->second.lock();
145 CursorSetPtr newset;
147 try {
148 FileIStream file(filename.c_str());
149 if(!file.is_open())
150 throw(Exception("Cannot open GUI cursor file"));
152 TiXmlDocument doc;
154 if(!(file >> doc) || doc.Error())
155 throw(Exception(doc.ErrorDesc()));
157 TiXmlElement * section = doc.RootElement();
158 DEBUG_ASSERT(section);
159 if(section->ValueTStr() != "cursorSet")
160 throw(Exception("Wrong root element"));
162 newset = CursorSetPtr(new CursorSet);
163 newset->LoadFromXml(*section, scale);
164 } catch(Exception & exc) {
165 vLog << err("Gui") << "Error loading cursor set (" << filename
166 << ")\nReason: " << exc.what() << "." << std::endl;
167 return CursorSetPtr();
170 cursorMap_[filename] = newset;
171 return newset;
174 const CursorSetPtr CursorSetFactory::CreateInstance
175 (TiXmlElement & root, const Vector2f & scale)
177 CursorSetPtr newset;
179 newset = CursorSetPtr(new CursorSet);
180 newset->LoadFromXml(root, scale);
182 return newset;
186 * CursorSet class implementation
188 const Cursor * CursorSet::GetCursor(const std::string & name) const
190 CursorVector::const_iterator pos = std::lower_bound(
191 cursors_.begin(), cursors_.end(), name);
193 if(pos == cursors_.end() || pos->first != name)
194 return NULL;
196 return &pos->second;
199 void CursorSet::OnGuiResize(const Vector2f & scale)
201 Float2Vector verts;
202 verts.resize(bufSize_);
204 for(CursorVector::iterator itr = cursors_.begin();
205 itr != cursors_.end(); ++itr) {
206 itr->second.Rescale(scale, verts);
209 if(!verts.empty())
210 attribs_->Set(atPosition, verts);
213 void CursorSet::LoadFromXml(TiXmlElement & root, const Vector2f & scale)
215 attribs_ = AttribBufPtr(AttribBufferSet::Factory().CreateInstance());
216 Float2Vector verts, coords;
218 TiXmlElement * elem = root.FirstChildElement("cursor");
219 while(elem) {
220 cursors_.push_back(std::make_pair(CheckAttribute(*elem, "id"), Cursor()));
221 cursors_.back().second.attribs = attribs_;
222 cursors_.back().second.LoadFromXml(*elem, scale, verts, coords);
224 elem = elem->NextSiblingElement("cursor");
226 std::sort(cursors_.begin(), cursors_.end());
228 bufSize_ = verts.size();
230 // if there's at least one cursor, create buffers
231 if(bufSize_) {
232 attribs_->Set(atPosition, verts);
233 attribs_->Set(atTexCoord0, coords);