xoreos  0.0.5
talkman.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/scopedptr.h"
26 #include "src/common/error.h"
27 #include "src/common/ustring.h"
28 #include "src/common/readstream.h"
29 #include "src/common/uuid.h"
30 #include "src/common/encoding.h"
31 
32 #include "src/aurora/talkman.h"
33 #include "src/aurora/resman.h"
34 #include "src/aurora/talktable.h"
35 
37 
38 namespace Aurora {
39 
41 }
42 
44  clear();
45 }
46 
48  for (Tables::iterator t = _tablesMain.begin(); t != _tablesMain.end(); ++t)
49  deleteTable(*t);
50  for (Tables::iterator t = _tablesAlt.begin(); t != _tablesAlt.end(); ++t)
51  deleteTable(*t);
52 
53  _tablesMain.clear();
54  _tablesAlt.clear();
55 }
56 
57 static TalkTable *loadTable(const Common::UString &name, Common::Encoding encoding) {
58  if (name.empty())
59  return 0;
60 
61  Common::SeekableReadStream *tlk = ResMan.getResource(name, kFileTypeTLK);
62  if (!tlk)
63  return 0;
64 
65  return TalkTable::load(tlk, encoding);
66 }
67 
68 static void loadTables(const Common::UString &nameM, const Common::UString &nameF,
69  TalkTable *&tableM, TalkTable *&tableF, Common::Encoding encoding) {
70 
71  Common::ScopedPtr<TalkTable> m(loadTable(nameM, encoding));
72  Common::ScopedPtr<TalkTable> f(loadTable(nameF, encoding));
73 
74  tableM = m.release();
75  tableF = f.release();
76 }
77 
78 void TalkManager::addTable(const Common::UString &nameMale, const Common::UString &nameFemale,
79  bool isAlt, uint32 priority, Common::ChangeID *changeID) {
80 
81  TalkTable *tableMale = 0, *tableFemale = 0;
82  loadTables(nameMale, nameFemale, tableMale, tableFemale, LangMan.getCurrentEncoding());
83 
84  if (!tableMale && !tableFemale)
85  throw Common::Exception("No such talk table \"%s\"/\"%s\"", nameMale.c_str(), nameFemale.c_str());
86 
87  Tables *tables = &_tablesMain;
88  if (isAlt)
89  tables = &_tablesAlt;
90 
91  const uint32 id = Common::generateIDNumber();
92 
93  tables->push_back(Table(tableMale, tableFemale, priority, id));
94  tables->sort();
95 
96  if (changeID)
97  changeID->setContent(new Change(id, isAlt));
98 }
99 
101  delete table.tableMale;
102  delete table.tableFemale;
103 
104  table.tableMale = 0;
105  table.tableFemale = 0;
106 }
107 
109  Change *change = dynamic_cast<Change *>(changeID.getContent());
110  if (!change)
111  return;
112 
113  Tables *tables = &_tablesMain;
114  if (change->_isAlt)
115  tables = &_tablesAlt;
116 
117  for (Tables::iterator t = tables->begin(); t != tables->end(); ++t) {
118  if (t->id == change->_id) {
119  deleteTable(*t);
120 
121  tables->erase(t);
122  break;
123  }
124  }
125 
126  changeID.clear();
127 }
128 
129 static const Common::UString kEmptyString = "";
131  if (gender == kLanguageGenderCurrent)
132  gender = LangMan.getCurrentGender();
133 
134  if (strRef == kStrRefInvalid)
135  return kEmptyString;
136 
137  const TalkTable *table = find(strRef, gender);
138  if (!table)
139  return kEmptyString;
140 
141  return table->getString(strRef);
142 }
143 
145  if (gender == kLanguageGenderCurrent)
146  gender = LangMan.getCurrentGender();
147 
148  if (strRef == kStrRefInvalid)
149  return kEmptyString;
150 
151  const TalkTable *table = find(strRef, gender);
152  if (!table)
153  return kEmptyString;
154 
155  return table->getSoundResRef(strRef);
156 }
157 
158 const TalkTable *TalkManager::find(const Tables &tables, uint32 strRef, LanguageGender gender) const {
159  /* Look for the strRef in decreasing priority.
160  *
161  * Only look through the female table if a female gendered string was requested,
162  * but fall back on the male table in either case.
163  */
164 
165  for (Tables::const_reverse_iterator t = tables.rbegin(); t != tables.rend(); ++t) {
166  if (gender == kLanguageGenderFemale)
167  if (t->tableFemale && t->tableFemale->hasEntry(strRef))
168  return t->tableFemale;
169 
170  if (t->tableMale && t->tableMale->hasEntry(strRef))
171  return t->tableMale;
172  }
173 
174  return 0;
175 }
176 
177 const TalkTable *TalkManager::find(uint32 strRef, LanguageGender gender) const {
178  bool isAlt = (strRef & 0xFF000000) != 0;
179 
180  strRef &= 0x00FFFFFF;
181 
182  const TalkTable *table = 0;
183 
184  /* If the flag for "use alternate tables" is set, search through those.
185  * If the flag is not set, or the strRef was not found, search in the main tables.
186  */
187 
188  if (isAlt)
189  if ((table = find(_tablesAlt, strRef & 0x00FFFFFF, gender)) != 0)
190  return table;
191 
192  // If the flag is not set, or the strRef was not found, look in the main tables
193  if ((table = find(_tablesMain, strRef, gender)) != 0)
194  return table;
195 
196  return 0;
197 }
198 
199 } // End of namespace Aurora
LanguageGender
Definition: language.h:67
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
const TalkTable * find(uint32 strRef, LanguageGender gender) const
Definition: talkman.cpp:177
TalkTable * tableMale
Definition: talkman.h:71
static TalkTable * loadTable(const Common::UString &name, Common::Encoding encoding)
Definition: talkman.cpp:57
A class holding an UTF-8 string.
Definition: ustring.h:48
const Common::UString & getString(uint32 strRef, LanguageGender gender=kLanguageGenderCurrent)
Definition: talkman.cpp:130
The global Aurora talk manager, holding the current talk tables.
Definition: talkman.h:42
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
Definition: scopedptr.h:103
Base class for BioWare&#39;s talk tables.
Definition: talktable.h:52
Utility functions for generating unique IDs.
virtual const Common::UString & getString(uint32 strRef) const =0
Tables _tablesMain
Definition: talkman.h:98
ChangeContent * getContent() const
Definition: changeid.cpp:56
static void loadTables(const Common::UString &nameM, const Common::UString &nameF, TalkTable *&tableM, TalkTable *&tableF, Common::Encoding encoding)
Definition: talkman.cpp:68
A simple scoped smart pointer template.
Basic exceptions to throw.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
void addTable(const Common::UString &nameMale, const Common::UString &nameFemale, bool isAlt, uint32 priority, Common::ChangeID *changeID=0)
Add a talk table to the talk manager.
Definition: talkman.cpp:78
virtual const Common::UString & getSoundResRef(uint32 strRef) const =0
const Common::UString & getSoundResRef(uint32 strRef, LanguageGender gender=kLanguageGenderCurrent)
Definition: talkman.cpp:144
static TalkTable * load(Common::SeekableReadStream *tlk, Common::Encoding encoding)
Take over this stream and read a talk table (of either format) out of it.
Definition: talktable.cpp:45
#define DECLARE_SINGLETON(T)
Note that you need to use this macro from the global namespace.
Definition: singleton.h:122
static const uint32 kStrRefInvalid
Definition: types.h:444
Utility functions for working with differing string encodings.
Encoding
Definition: encoding.h:37
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
Base class for BioWare&#39;s talk tables.
void setContent(ChangeContent *content)
Definition: changeid.cpp:60
StackException Exception
Definition: error.h:59
A scoped plain pointer, allowing pointer-y access and normal deletion.
Definition: scopedptr.h:120
Talk table.
Definition: types.h:87
void deleteTable(Table &table)
Definition: talkman.cpp:100
void removeTable(Common::ChangeID &changeID)
Remove a talk table from the talk manager again.
Definition: talkman.cpp:108
Basic reading stream interfaces.
Unicode string handling.
Pseudo value that means the current language gender.
Definition: language.h:72
TalkTable * tableFemale
Definition: talkman.h:72
#define LangMan
Shortcut for accessing the language manager.
Definition: language.h:275
A class representing an undoable change.
Definition: changeid.h:35
uint32_t uint32
Definition: types.h:204
The global talk manager for Aurora strings.
std::list< Table > Tables
Definition: talkman.h:95
static const Common::UString kEmptyString
Definition: talkman.cpp:129
Interface for a seekable & readable data stream.
Definition: readstream.h:265
Tables _tablesAlt
Definition: talkman.h:99
The global resource manager for Aurora resources.
uint32 generateIDNumber()
Definition: uuid.cpp:46