1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (C) 2004-2010 by The Allacrost Project
3 // All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9
10 /*!****************************************************************************
11 * \file skill_editor.h
12 * \author Daniel Steuernol, steu@allacrost.org
13 * \brief Header file for editor's skill editor dialog
14 *****************************************************************************/
15
16 #include "skill_editor.h"
17
18 using namespace std;
19
20 using namespace hoa_utils;
21
22 using namespace hoa_script;
23 using namespace hoa_global;
24 using namespace hoa_editor;
25
26
SkillEditor(QWidget * parent,const QString & name)27 SkillEditor::SkillEditor(QWidget *parent, const QString &name)
28 : QWidget(parent, static_cast<const char *>(name))
29 {
30 setCaption("Skill Editor");
31
32 _current_skill_index[GLOBAL_SKILL_ATTACK] = -1;
33 _current_skill_index[GLOBAL_SKILL_DEFEND] = -1;
34 _current_skill_index[GLOBAL_SKILL_SUPPORT] = -1;
35
36
37 _LoadSkills();
38
39 // initialize tabs
40 _tab_skill_groups = new QTabWidget();
41 _tab_skill_groups->setTabPosition(QTabWidget::North);
42 connect(_tab_skill_groups, SIGNAL(currentChanged(int)), this, SLOT(_ChangeCurrentTab(int)));
43
44 // set up the layout boxes
45 _hbox = new QHBoxLayout();
46 _hbox->addWidget(_tab_skill_groups);
47
48 // add layout to form
49 setLayout(_hbox);
50
51 _CreateTab(GLOBAL_SKILL_ATTACK, _attack_skills, "attack");
52 _CreateTab(GLOBAL_SKILL_DEFEND, _defense_skills, "defense");
53 _CreateTab(GLOBAL_SKILL_SUPPORT, _support_skills, "support");
54
55 _current_tab = GLOBAL_SKILL_ATTACK;
56 } // SkillEditor
57
~SkillEditor()58 SkillEditor::~SkillEditor()
59 {
60 for (uint32 i = 0; i < _attack_skills.size(); ++i)
61 delete _attack_skills[i];
62 for (uint32 i = 0; i < _defense_skills.size(); ++i)
63 delete _defense_skills[i];
64 for (uint32 i = 0; i < _support_skills.size(); ++i)
65 delete _support_skills[i];
66
67 _CleanupTab(GLOBAL_SKILL_ATTACK);
68 _CleanupTab(GLOBAL_SKILL_DEFEND);
69 _CleanupTab(GLOBAL_SKILL_SUPPORT);
70
71 delete _hbox;
72 delete _tab_skill_groups;
73 } // ~SkillEditor
74
_ChangeCurrentTab(int index)75 void SkillEditor::_ChangeCurrentTab(int index)
76 {
77 if (index == 0)
78 _current_tab = GLOBAL_SKILL_ATTACK;
79 else if (index == 1)
80 _current_tab = GLOBAL_SKILL_DEFEND;
81 else if (index == 2)
82 _current_tab = GLOBAL_SKILL_SUPPORT;
83 } // _ChangeCurrentTab()
84
_LeftButtonClicked()85 void SkillEditor::_LeftButtonClicked()
86 {
87 _current_skill_index[_current_tab]--;
88 if (_current_skill_index[_current_tab] < 0)
89 _current_skill_index[_current_tab] = _GetCurrentSkillList().size() - 1;
90
91 _ReloadTab();
92 } // _LeftButtonClicked()
93
_RightButtonClicked()94 void SkillEditor::_RightButtonClicked()
95 {
96 _current_skill_index[_current_tab]++;
97 if (_current_skill_index[_current_tab] >= static_cast<int32>(_GetCurrentSkillList().size()))
98 _current_skill_index[_current_tab] = 0;
99
100 _ReloadTab();
101 } // _RightButtonClicked()
102
_LoadSkills()103 void SkillEditor::_LoadSkills()
104 {
105 string path = string("dat/skills/");
106 ReadScriptDescriptor script;
107 script.OpenFile(path + "defense.lua", true);
108 script.CloseFile();
109 script.OpenFile(path + "support.lua", true);
110 script.CloseFile();
111 vector<GlobalSkill *> skills;
112 if (script.OpenFile(path + "attack.lua", true) != false)
113 _LoadSkills(script, skills, GLOBAL_SKILL_ATTACK);
114 // Now clean up the skills script (due to the way we're storing the scripts in lua, they're all actually in one big table in lua
115 // regardless of the file split on disk
116 vector<GlobalSkill *>::iterator i = skills.begin();
117 for (; i != skills.end(); ++i)
118 {
119 if ((*i)->GetType() == GLOBAL_SKILL_ATTACK)
120 _attack_skills.push_back(*i);
121 else if ((*i)->GetType() == GLOBAL_SKILL_DEFEND)
122 _defense_skills.push_back(*i);
123 else if ((*i)->GetType() == GLOBAL_SKILL_SUPPORT)
124 _support_skills.push_back(*i);
125 }
126 if (_attack_skills.size() > 0)
127 _current_skill_index[GLOBAL_SKILL_ATTACK] = 0;
128 if (_defense_skills.size() > 0)
129 _current_skill_index[GLOBAL_SKILL_DEFEND] = 0;
130 if (_support_skills.size() > 0)
131 _current_skill_index[GLOBAL_SKILL_SUPPORT] = 0;
132
133 } // _LoadSkills()
134
_LoadSkills(ReadScriptDescriptor & script,vector<GlobalSkill * > & skills,GLOBAL_SKILL type)135 void SkillEditor::_LoadSkills(ReadScriptDescriptor &script, vector<GlobalSkill *> &skills, GLOBAL_SKILL type)
136 {
137 script.OpenTable("skills");
138 vector<uint32> keys;
139 script.ReadTableKeys(keys);
140 for (uint32 i = 0; i < keys.size(); ++i)
141 skills.push_back(new GlobalSkill(keys[i]));
142 script.CloseAllTables();
143 script.CloseFile();
144
145 } // _LoadSkills(ReadScriptDescriptor, vector<GlobalSkill *>)
146
_CreateTab(GLOBAL_SKILL type,vector<GlobalSkill * > skills,QString tab_name)147 void SkillEditor::_CreateTab(GLOBAL_SKILL type, vector<GlobalSkill *>skills, QString tab_name)
148 {
149 _gl_layouts[type] = new QGridLayout();
150 // add the labels for the different parts of the skill
151 _lbl_skill_names[type] = new QLabel();
152 _lbl_skill_names[type]->setText("Skill Name:");
153 _gl_layouts[type]->addWidget(_lbl_skill_names[type], 0, 0);
154
155 _lbl_description[type] = new QLabel();
156 _lbl_description[type]->setText("Description:");
157 _gl_layouts[type]->addWidget(_lbl_description[type], 1, 0);
158
159 _lbl_sp_required[type] = new QLabel();
160 _lbl_sp_required[type]->setText("SP Required:");
161 _gl_layouts[type]->addWidget(_lbl_sp_required[type], 2, 0);
162
163 _lbl_warmup_time[type] = new QLabel();
164 _lbl_warmup_time[type]->setText("Warmup Time:");
165 _gl_layouts[type]->addWidget(_lbl_warmup_time[type], 2, 2);
166
167 _lbl_cooldown_time[type] = new QLabel();
168 _lbl_cooldown_time[type]->setText("Cooldown Time:");
169 _gl_layouts[type]->addWidget(_lbl_cooldown_time[type], 3, 0);
170
171 _lbl_target_type[type] = new QLabel();
172 _lbl_target_type[type]->setText("Target Type:");
173 _gl_layouts[type]->addWidget(_lbl_target_type[type], 4, 0);
174
175 // add the line edits for the skill
176 _le_skill_names[type] = new QLineEdit();
177 _le_description[type] = new QLineEdit();
178 _le_sp_required[type] = new QLineEdit();
179 _le_warmup_time[type] = new QLineEdit();
180 _le_cooldown_time[type] = new QLineEdit();
181 _cb_target_type[type] = new QComboBox();
182
183 if (_current_skill_index[type] != -1)
184 {
185 GlobalSkill *skill = skills[_current_skill_index[type]];
186 // this skill is enabled so set the text
187 string text = MakeStandardString(skill->GetName());
188 // get the char array from the standard string, because otherwise the QString ends up with
189 // some gibberish text at the beginning of it
190 _le_skill_names[type]->setText(QString(text.c_str()));
191
192 text = MakeStandardString(skill->GetDescription());
193 _le_description[type]->setText(QString(text.c_str()));
194
195 text = NumberToString<uint32>(skill->GetSPRequired());
196 _le_sp_required[type]->setText(QString(text.c_str()));
197
198 text = NumberToString<uint32>(skill->GetWarmupTime());
199 _le_warmup_time[type]->setText(QString(text.c_str()));
200
201 text = NumberToString<uint32>(skill->GetCooldownTime());
202 _le_cooldown_time[type]->setText(QString(text.c_str()));
203
204 _cb_target_type[type]->insertItem("Attack Point");
205 _cb_target_type[type]->insertItem("Actor");
206 _cb_target_type[type]->insertItem("Party");
207 _cb_target_type[type]->setCurrentIndex(static_cast<int32>(skill->GetTargetType()));
208 }
209 else
210 {
211 // disable the line edits (no skills for this group)
212 _le_skill_names[type]->setDisabled(true);
213 _le_description[type]->setDisabled(true);
214 _le_sp_required[type]->setDisabled(true);
215 _le_warmup_time[type]->setDisabled(true);
216 _le_cooldown_time[type]->setDisabled(true);
217 _cb_target_type[type]->setDisabled(true);
218 _rb_target_ally_false[type]->setDisabled(true);
219 _rb_target_ally_true[type]->setDisabled(true);
220 }
221
222 // add above widgets to grid layout
223 _gl_layouts[type]->addWidget(_le_skill_names[type], 0, 1, 1, 3);
224 _gl_layouts[type]->addWidget(_le_description[type], 1, 1, 1, 3);
225 _gl_layouts[type]->addWidget(_le_sp_required[type], 2, 1);
226 _gl_layouts[type]->addWidget(_le_warmup_time[type], 2, 3);
227 _gl_layouts[type]->addWidget(_le_cooldown_time[type], 3, 1);
228 _gl_layouts[type]->addWidget(_cb_target_type[type], 4, 1);
229 _hbox_target_ally[type] = new QHBoxLayout();
230 _hbox_target_ally[type]->addWidget(_rb_target_ally_true[type]);
231 _hbox_target_ally[type]->addWidget(_rb_target_ally_false[type]);
232 _target_ally_spacers[type] = new QSpacerItem(10, 5, QSizePolicy::Expanding);
233 _hbox_target_ally[type]->addItem(_target_ally_spacers[type]);
234 _gl_layouts[type]->addLayout(_hbox_target_ally[type], 3, 3);
235
236 // create the vertical layout for the tab
237 _tab_vboxes[type] = new QVBoxLayout();
238 _tab_vboxes[type]->addLayout(_gl_layouts[type]);
239
240 // add a spacer to the vbox to push up the grid layout
241 _tab_spacers[type] = new QSpacerItem(10,5, QSizePolicy::Minimum, QSizePolicy::Expanding);
242 _tab_vboxes[type]->addItem(_tab_spacers[type]);
243
244 // create the horizontal layout underneath the grid in the tab
245 _tab_bottom_hboxes[type] = new QHBoxLayout();
246
247 _CreateTabBottomButtons(type);
248
249 _tab_vboxes[type]->addLayout(_tab_bottom_hboxes[type]);
250
251 _tab_pages[type] = new QWidget();
252 _tab_pages[type]->setLayout(_tab_vboxes[type]);
253 _tab_skill_groups->addTab(_tab_pages[type], tab_name);
254 } // _CreateTab(GLOBAL_SKILL)
255
_CreateTabBottomButtons(GLOBAL_SKILL type)256 void SkillEditor::_CreateTabBottomButtons(GLOBAL_SKILL type)
257 {
258 // add all the buttons
259 _new_buttons[type] = new QPushButton();
260 _new_buttons[type]->setText("Create New Skill");
261 _new_buttons[type]->setDisabled(true);
262 _new_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
263 _tab_bottom_hboxes[type]->addWidget(_new_buttons[type]);
264
265 _save_buttons[type] = new QPushButton();
266 _save_buttons[type]->setText("Save Changes");
267 _save_buttons[type]->setDisabled(true);
268 _save_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
269 _tab_bottom_hboxes[type]->addWidget(_save_buttons[type]);
270
271 // this spacer pushes the nav buttons to the right, and the other 2 buttons to the left
272 _button_spacers[type] = new QSpacerItem(30, 10, QSizePolicy::Expanding);
273 _tab_bottom_hboxes[type]->addItem(_button_spacers[type]);
274
275 _left_buttons[type] = new QPushButton();
276 _left_buttons[type]->setIcon(QIcon("img/misc/editor-tools/arrow-left.png"));
277 _left_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
278 connect(_left_buttons[type], SIGNAL(clicked()), this, SLOT(_LeftButtonClicked()));
279 _tab_bottom_hboxes[type]->addWidget(_left_buttons[type]);
280
281 _right_buttons[type] = new QPushButton();
282 _right_buttons[type]->setIcon(QIcon("img/misc/editor-tools/arrow-right.png"));
283 _right_buttons[type]->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
284 connect(_right_buttons[type], SIGNAL(clicked()), this, SLOT(_RightButtonClicked()));
285 _tab_bottom_hboxes[type]->addWidget(_right_buttons[type]);
286 }
287
_CleanupTab(GLOBAL_SKILL type)288 void SkillEditor::_CleanupTab(GLOBAL_SKILL type)
289 {
290 delete _tab_vboxes[type];
291 delete _tab_bottom_hboxes[type];
292 delete _gl_layouts[type];
293 delete _tab_pages[type];
294 delete _left_buttons[type];
295 delete _right_buttons[type];
296 delete _save_buttons[type];
297 delete _button_spacers[type];
298 delete _tab_spacers[type];
299 delete _lbl_skill_names[type];
300 delete _lbl_description[type];
301 delete _lbl_sp_required[type];
302 delete _lbl_warmup_time[type];
303 delete _lbl_cooldown_time[type];
304 delete _lbl_target_type[type];
305 delete _le_skill_names[type];
306 delete _le_description[type];
307 delete _le_sp_required[type];
308 delete _le_warmup_time[type];
309 delete _le_cooldown_time[type];
310 delete _cb_target_type[type];
311 delete _bg_target_ally[type];
312 delete _rb_target_ally_true[type];
313 delete _rb_target_ally_false[type];
314 delete _hbox_target_ally[type];
315 delete _target_ally_spacers[type];
316 } // _CleanupTab(GLOBAL_SKILL)
317
_GetCurrentSkillList()318 vector<GlobalSkill *> &SkillEditor::_GetCurrentSkillList()
319 {
320 if (_current_tab == GLOBAL_SKILL_ATTACK)
321 return _attack_skills;
322 else if (_current_tab == GLOBAL_SKILL_DEFEND)
323 return _defense_skills;
324 return _support_skills;
325 } // _GetCurrentSkillList
326
_ReloadTab()327 void SkillEditor::_ReloadTab()
328 {
329
330 if (_GetCurrentSkillList().empty()) {
331 return;
332 }
333
334 GlobalSkill *skill = _GetCurrentSkillList()[_current_skill_index[_current_tab]];
335
336 string text = MakeStandardString(skill->GetName());
337 _le_skill_names[_current_tab]->setText(QString(text.c_str()));
338
339 text = MakeStandardString(skill->GetDescription());
340 _le_description[_current_tab]->setText(QString(text.c_str()));
341
342 text = NumberToString<uint32>(skill->GetSPRequired());
343 _le_sp_required[_current_tab]->setText(QString(text.c_str()));
344
345 text = NumberToString<uint32>(skill->GetWarmupTime());
346 _le_warmup_time[_current_tab]->setText(QString(text.c_str()));
347
348 text = NumberToString<uint32>(skill->GetCooldownTime());
349 _le_cooldown_time[_current_tab]->setText(QString(text.c_str()));
350
351 _cb_target_type[_current_tab]->setCurrentIndex(static_cast<int32>(skill->GetTargetType()));
352
353 // TODO: as more controls are added to the tab, reload them here.
354 }
355
356