2 // Copyright (C) 2008 by Martin Moracek
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.
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
27 #include "xml/tinyxml.h"
28 #include "xml/xmlutils.h"
30 #include "vfs/fstream.h"
31 #include "vfs/logfile.h"
33 #include "exception.h"
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");
58 throw(Exception("Missing effect information"));
60 effect
= Effect::Factory().CreateInstance(CheckText(*elem
));
62 elem
= root
.FirstChildElement("texture");
64 throw(Exception("Missing texture information"));
66 vars
.SetTexture("gui_Texture", CheckText(*elem
));
68 elem
= root
.FirstChildElement("rect");
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
;
83 elem
= root
.FirstChildElement("offset");
85 baseOffset_
.x
= CheckFloatAttribute(*elem
, "x", false, 0.0f
);
86 baseOffset_
.y
= CheckFloatAttribute(*elem
, "y", false, 0.0f
);
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");
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
};
125 uint
* ptr
= indices
->Lock();
127 memcpy(ptr
, inds
, sizeof(uint
) * 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();
148 FileIStream
file(filename
.c_str());
150 throw(Exception("Cannot open GUI cursor file"));
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
;
174 const CursorSetPtr
CursorSetFactory::CreateInstance
175 (TiXmlElement
& root
, const Vector2f
& scale
)
179 newset
= CursorSetPtr(new CursorSet
);
180 newset
->LoadFromXml(root
, scale
);
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
)
199 void CursorSet::OnGuiResize(const Vector2f
& scale
)
202 verts
.resize(bufSize_
);
204 for(CursorVector::iterator itr
= cursors_
.begin();
205 itr
!= cursors_
.end(); ++itr
) {
206 itr
->second
.Rescale(scale
, verts
);
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");
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
232 attribs_
->Set(atPosition
, verts
);
233 attribs_
->Set(atTexCoord0
, coords
);