OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4ConsoleQtNewScenario.cpp
Go to the documentation of this file.
1 /*
2 * OpenClonk, http://www.openclonk.org
3 *
4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5 * Copyright (c) 2013, The OpenClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16 
17 /* "New scenario" editor dialogue */
18 
19 #include "C4Include.h"
20 #include "script/C4Value.h"
21 #include "config/C4Config.h"
23 
24 
25 /* Definition file list model for new scenario definition selection */
26 
27 C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo(C4ConsoleQtDefinitionFileListModel::DefFileInfo *parent, const char *filename, const char *root_path)
28  : parent(parent), filename(filename), root_path(root_path), was_opened(false), is_root(false), user_selected(parent->IsUserSelected()), force_selected(parent->IsForceSelected())
29 {
30  // Delay opening of groups until information is actually requested
31  // Full names into child groups in C4S always delimeted with backslashes
32  if (parent->full_filename.getLength())
33  full_filename = parent->full_filename + "\\" + filename;
34  else
35  full_filename = filename;
36 }
37 
38 C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo()
39  : parent(nullptr), was_opened(true), is_root(true), user_selected(false), force_selected(false)
40 {
41  // Init as root: List definitions in root paths
42  // Objects.ocd is always there (even if not actually found) and always first
43  DefFileInfo *main_objects_def = new DefFileInfo(this, C4CFN_Objects, "");
44  children.emplace_back(main_objects_def);
45  bool has_default_objects_found = false;
46  for (auto & root_iter : ::Reloc)
47  {
48  const char *root = root_iter.strBuf.getData();
49  for (DirectoryIterator def_file_iter(root); *def_file_iter; ++def_file_iter)
50  {
51  const char *def_file = ::GetFilename(*def_file_iter);
52  if (WildcardMatch(C4CFN_DefFiles, def_file))
53  {
54  // Set path of main objects if found
55  if (!has_default_objects_found && !strcmp(C4CFN_Objects, def_file))
56  {
57  main_objects_def->root_path.Copy(root);
58  continue;
59  }
60  // Avoid duplicates on top level
61  bool dup = false;
62  for (auto & child : children)
63  if (!strcmp(child->GetName(), def_file))
64  {
65  dup = true; break;
66  }
67  if (dup) continue;
68  children.emplace_back(new DefFileInfo(this, def_file, root));
69  }
70  }
71  }
72 }
73 
74 void C4ConsoleQtDefinitionFileListModel::DefFileInfo::SetSelected(bool to_val, bool forced)
75 {
76  if (forced)
77  force_selected = to_val;
78  else
79  user_selected = to_val;
80  // Selection propagates to children
81  for (auto & child : children)
82  {
83  child->SetSelected(to_val, forced);
84  }
85 }
86 
87 bool C4ConsoleQtDefinitionFileListModel::DefFileInfo::OpenGroup()
88 {
89  children.clear();
90  was_opened = true; // mark as opened even if fails to prevent permanent re-loading of broken groups
91  if (parent->IsRoot())
92  {
93  if (!grp.Open((root_path + DirectorySeparator + filename).getData())) return false;
94  }
95  else
96  {
97  if (!grp.OpenAsChild(&parent->grp, filename.getData())) return false;
98  }
99  // Init child array (without loading full groups)
100  StdStrBuf child_filename;
101  children.reserve(grp.EntryCount(C4CFN_DefFiles));
102  grp.ResetSearch();
103  while (grp.FindNextEntry(C4CFN_DefFiles, &child_filename))
104  children.emplace_back(new DefFileInfo(this, child_filename.getData(), nullptr));
105  return true;
106 }
107 
108 int32_t C4ConsoleQtDefinitionFileListModel::DefFileInfo::GetChildCount()
109 {
110  if (!was_opened) OpenGroup();
111  return children.size();
112 }
113 
114 C4ConsoleQtDefinitionFileListModel::DefFileInfo *C4ConsoleQtDefinitionFileListModel::DefFileInfo::GetChild(int32_t index)
115 {
116  if (!was_opened) OpenGroup();
117  if (index >= children.size()) return nullptr;
118  return children[index].get();
119 }
120 
121 int32_t C4ConsoleQtDefinitionFileListModel::DefFileInfo::GetChildIndex(const DefFileInfo *child)
122 {
123  auto iter = std::find_if(children.begin(), children.end(),
124  [child](std::unique_ptr<DefFileInfo> & item)->bool { return item.get() == child; });
125  if (iter == children.end()) return -1; // not found
126  return int32_t(iter - children.begin());
127 }
128 
129 void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddUserSelectedDefinitions(std::list<const char *> *result) const
130 {
131  // Add parent-most selected
132  // Ignore any forced selection even if also selected by user.
133  // It may have been selected first and then forced by the scenario preset after the template has been switched)
134  if (!IsForceSelected())
135  {
136  if (IsUserSelected())
137  result->push_back(full_filename.getData());
138  else
139  for (auto &iter : children) iter->AddUserSelectedDefinitions(result);
140  }
141 }
142 
143 void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddSelectedDefinitions(std::list<const char *> *result) const
144 {
145  // Add parent-most selected
146  if (IsSelected())
147  result->push_back(full_filename.getData());
148  else
149  for (auto &iter : children) iter->AddSelectedDefinitions(result);
150 }
151 
152 void C4ConsoleQtDefinitionFileListModel::DefFileInfo::SetForcedSelection(const char *selected_def_filepath)
153 {
154  // Filenames are assumed to be case insensitive for the Windows client
155  if (SEqualNoCase(selected_def_filepath, full_filename.getData()))
156  {
157  // This is the def to be force-selected
158  SetSelected(true, true);
159  }
160  else if (is_root || (SEqual2NoCase(selected_def_filepath, full_filename.getData()) && selected_def_filepath[full_filename.getLength()] == '\\'))
161  {
162  // One of the child definitions should be force-selected
163  if (!was_opened) OpenGroup();
164  for (auto &iter : children) iter->SetForcedSelection(selected_def_filepath);
165  }
166 }
167 
168 void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddExtraDef(const char *def)
169 {
170  assert(is_root);
171  // Ignore if it was already added
172  // Could also avoid adding child definitions if they are already in the list.
173  // E.g. do not add both foo.ocs\bar.ocd and foo.ocs\bar.ocd\baz.ocd, but keep only the parent path.
174  // But it's overkill for a case that will probably never happen and would pose just a minor nuisance if it does.
175  for (auto &iter : children)
176  {
177  if (SEqualNoCase(iter->full_filename.getData(), def))
178  {
179  return;
180  }
181  }
182  // Add using user path as root (extra defs will always be in the user path because they are not used by our main system templates)
183  children.emplace_back(new DefFileInfo(this, def, ::Config.General.UserDataPath));
184 }
185 
186 
187 C4ConsoleQtDefinitionFileListModel::C4ConsoleQtDefinitionFileListModel()
188 {
189 }
190 
191 C4ConsoleQtDefinitionFileListModel::~C4ConsoleQtDefinitionFileListModel()
192 {
193 }
194 
195 void C4ConsoleQtDefinitionFileListModel::AddExtraDef(const char *def)
196 {
197  root.AddExtraDef(def);
198 }
199 
200 std::list<const char *> C4ConsoleQtDefinitionFileListModel::GetUserSelectedDefinitions() const
201 {
202  std::list<const char *> result;
203  root.AddUserSelectedDefinitions(&result);
204  return result;
205 }
206 
207 std::list<const char *> C4ConsoleQtDefinitionFileListModel::GetSelectedDefinitions() const
208 {
209  std::list<const char *> result;
210  root.AddSelectedDefinitions(&result);
211  return result;
212 }
213 
214 void C4ConsoleQtDefinitionFileListModel::SetForcedSelection(const std::list<const char *> &defs)
215 {
216  beginResetModel();
217  // Unselect previous
218  root.SetSelected(false, true);
219  // Force new selection
220  for (const char *def : defs)
221  {
222  root.SetForcedSelection(def);
223  }
224  endResetModel();
225 }
226 
227 int C4ConsoleQtDefinitionFileListModel::rowCount(const QModelIndex & parent) const
228 {
229  if (!parent.isValid()) return root.GetChildCount();
230  DefFileInfo *parent_def = static_cast<DefFileInfo *>(parent.internalPointer());
231  if (!parent_def) return 0;
232  return parent_def->GetChildCount();
233 }
234 
235 int C4ConsoleQtDefinitionFileListModel::columnCount(const QModelIndex & parent) const
236 {
237  return 1; // Name
238 }
239 
240 QVariant C4ConsoleQtDefinitionFileListModel::data(const QModelIndex & index, int role) const
241 {
242  DefFileInfo *def = static_cast<DefFileInfo *>(index.internalPointer());
243  if (!def) return QVariant();
244  // Query latest data from prop list
245  if (role == Qt::DisplayRole)
246  {
247  return QString(def->GetName());
248  }
249  else if (role == Qt::CheckStateRole)
250  {
251  return def->IsSelected() ? Qt::Checked : Qt::Unchecked;
252  }
253  // Nothing to show
254  return QVariant();
255 }
256 
257 QModelIndex C4ConsoleQtDefinitionFileListModel::index(int row, int column, const QModelIndex &parent) const
258 {
259  if (column) return QModelIndex();
260  DefFileInfo *parent_def = &root;
261  if (parent.isValid()) parent_def = static_cast<DefFileInfo *>(parent.internalPointer());
262  if (!parent_def) return QModelIndex();
263  return createIndex(row, column, parent_def->GetChild(row));
264 }
265 
266 QModelIndex C4ConsoleQtDefinitionFileListModel::parent(const QModelIndex &index) const
267 {
268  DefFileInfo *def = static_cast<DefFileInfo *>(index.internalPointer());
269  if (!def) return QModelIndex();
270  DefFileInfo *parent_def = def->GetParent();
271  if (!parent_def) return QModelIndex();
272  int32_t def_index = parent_def->GetChildIndex(def);
273  if (def_index < 0) return QModelIndex(); // can't happen
274  return createIndex(def_index, 0, parent_def);
275 }
276 
277 Qt::ItemFlags C4ConsoleQtDefinitionFileListModel::flags(const QModelIndex &index) const
278 {
279  Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
280  DefFileInfo *def = static_cast<DefFileInfo *>(index.internalPointer());
281  if (def && !def->IsDisabled()) flags |= Qt::ItemIsEnabled;
282  return flags;
283 }
284 
285 bool C4ConsoleQtDefinitionFileListModel::setData(const QModelIndex& index, const QVariant& value, int role)
286 {
287  // Adjust check-state
288  if (role == Qt::CheckStateRole)
289  {
290  DefFileInfo *def = static_cast<DefFileInfo *>(index.internalPointer());
291  if (def && !def->IsDisabled())
292  {
293  def->SetSelected(value.toBool(), false);
294  // Update changed index and all children
295  int32_t child_count = def->GetChildCount();
296  QModelIndex end_changed = index;
297  if (child_count) end_changed = createIndex(child_count - 1, 0, def->GetChild(child_count - 1));
298  emit dataChanged(index, end_changed);
299  }
300  }
301  return true;
302 }
303 
304 
305 /* New scenario dialogue */
306 
307 C4ConsoleQtNewScenarioDlg::C4ConsoleQtNewScenarioDlg(class QMainWindow *parent_window)
308  : QDialog(parent_window, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint)
309  , has_custom_filename(false)
310 {
311  ui.setupUi(this);
312  adjustSize();
313  setMinimumSize(size());
314  // Create scenario at user path by default
315  ui.filenameEdit->setText(::Config.General.UserDataPath);
316  // Fill definition file model
317  QItemSelectionModel *m = ui.definitionTreeView->selectionModel();
318  ui.definitionTreeView->setModel(&def_file_model);
319  delete m;
320  // Init scenario template list
321  InitScenarioTemplateList();
322 }
323 
324 void C4ConsoleQtNewScenarioDlg::InitScenarioTemplateList()
325 {
326  // Init template scenarios from user and system folder
327  // Clear previous
328  ui.templateComboBox->clear();
329  C4Group system_templates, user_templates;
330  system_templates.OpenAsChild(&::Application.SystemGroup, C4CFN_Template);
331  user_templates.Open(Config.AtUserDataPath(C4CFN_Template));
332  for (C4Group *template_group : { &system_templates, &user_templates })
333  {
334  if (template_group->IsOpen()) // open may have failed (e.g. if it doesn't exist)
335  {
336  // All scenarios within the template group are possible scenario templates
337  template_group->ResetSearch();
338  StdStrBuf template_filename;
339  while (template_group->FindNextEntry(C4CFN_ScenarioFiles, &template_filename))
340  {
341  bool is_default = (template_group == &system_templates) && (template_filename == C4CFN_DefaultScenarioTemplate);
342  AddScenarioTemplate(*template_group, template_filename.getData(), is_default);
343  }
344  }
345  }
346  // TODO could sort elements. But should usually be sorted within the packed groups anyway.
347 }
348 
349 void C4ConsoleQtNewScenarioDlg::AddScenarioTemplate(C4Group &parent, const char *filename, bool is_default)
350 {
351  // Load scenario information from group and add as template
352  C4Group grp;
353  if (!grp.OpenAsChild(&parent, filename)) return;
354  C4Scenario template_c4s;
355  if (!template_c4s.Load(grp)) return;
356  // Title from file or scenario core
357  C4ComponentHost title_file;
358  StdCopyStrBuf title(template_c4s.Head.Title);
360  title_file.GetLanguageString(Config.General.LanguageEx, title);
361  // Add it; remember full path as user data
362  StdStrBuf template_path(grp.GetFullName());
363  ui.templateComboBox->addItem(QString(title.getData()), QString(template_path.getData()));
364  all_template_c4s.push_back(template_c4s);
365  // Add any extra definition (e.g. pointing into a scenario) to selection model
366  // "extra" definitions are those that use non-ocd-files anywhere in their path
367  auto c4s_defs = template_c4s.Definitions.GetModulesAsList();
368  for (const char *c4s_def : c4s_defs)
369  {
370  char c4s_def_component[_MAX_PATH + 1];
371  int32_t i = 0;
372  bool is_extra_def = false;
373  while (SCopySegment(c4s_def, i++, c4s_def_component, '\\', _MAX_PATH))
374  {
375  if (!WildcardMatch(C4CFN_DefFiles, c4s_def_component))
376  {
377  is_extra_def = true;
378  break;
379  }
380  }
381  if (is_extra_def)
382  {
383  def_file_model.AddExtraDef(c4s_def);
384  }
385  }
386  // Default selection
387  if (is_default) ui.templateComboBox->setCurrentIndex(ui.templateComboBox->count()-1);
388 }
389 
390 bool C4ConsoleQtNewScenarioDlg::IsHostAsNetwork() const
391 {
392  return ui.startInNetworkCheckbox->isChecked();
393 }
394 
395 void C4ConsoleQtNewScenarioDlg::SelectedTemplateChanged(int new_selection)
396 {
397  // Update forced definition selection for template
398  if (new_selection >= 0 && new_selection < all_template_c4s.size())
399  {
400  const C4Scenario &template_c4s = all_template_c4s[new_selection];
401  def_file_model.SetForcedSelection(template_c4s.Definitions.GetModulesAsList());
402  }
403  else
404  {
405  def_file_model.SetForcedSelection(std::list<const char *>());
406  }
407 }
408 
409 bool C4ConsoleQtNewScenarioDlg::CreateScenario()
410 {
411  // Try to create scenario from template. Unpack if necessery.
412  QVariant tmpl_data = ui.templateComboBox->currentData();
413  LogF(tmpl_data.toString().toUtf8());
414  StdStrBuf template_filename;
415  template_filename.Copy(tmpl_data.toString().toUtf8());
416  if (DirectoryExists(template_filename.getData()))
417  {
418  if (!CopyDirectory(template_filename.getData(), filename.getData(), true))
419  {
420  return false;
421  }
422  }
423  else
424  {
425  if (!C4Group_CopyItem(template_filename.getData(), filename.getData(), true, true))
426  {
427  return false;
428  }
429  if (!C4Group_UnpackDirectory(filename.getData()))
430  {
431  return false;
432  }
433  }
434  C4Group grp;
435  if (!grp.Open(filename.getData()))
436  {
437  return false;
438  }
439  // Remove localized title file to ensure it's loaded from the scenario core
441  // Update scenario core with settings from dialogue
442  C4Scenario c4s;
443  if (!c4s.Load(grp)) return false;
444  // Take over settings
445  c4s.Landscape.MapWdt.SetConstant(ui.mapWidthSpinBox->value());
446  c4s.Landscape.MapHgt.SetConstant(ui.mapHeightSpinBox->value());
447  c4s.Landscape.MapZoom.SetConstant(ui.mapZoomSpinBox->value());
448  c4s.Head.Title = ui.titleEdit->text().toStdString();
449  c4s.Game.Mode.Copy(ui.gameModeComboBox->currentText().toUtf8());
450  if (c4s.Game.Mode == "Undefined") c4s.Game.Mode.Clear();
451  filename.Copy(ui.filenameEdit->text().toUtf8());
452  std::list<const char *> definitions = def_file_model.GetUserSelectedDefinitions();
453  StdStrBuf forced_definitions;
454  c4s.Definitions.GetModules(&forced_definitions);
455  const char *forced_definitions_c = forced_definitions.getData();
456  std::ostringstream definitions_join(forced_definitions_c ? forced_definitions_c : nullptr, std::ostringstream::ate);
457  if (definitions.size())
458  {
459  // definitions_join = definitions.join(";")
460  if (forced_definitions.getLength())
461  {
462  // Combine both forced and user-selected definitions
463  definitions_join << ";";
464  }
465  auto iter_end = definitions.end();
466  std::copy(definitions.begin(), --iter_end, std::ostream_iterator<std::string>(definitions_join, ";"));
467  definitions_join << *iter_end;
468  }
469  c4s.Definitions.SetModules(definitions_join.str().c_str());
470  if (!c4s.Save(grp))
471  {
472  return false;
473  }
474  // Group saving not needed because it's unpacked.
475  //if (!grp.Save()) return false;
476  return true;
477 }
478 
479 void C4ConsoleQtNewScenarioDlg::CreatePressed()
480 {
481  // Check validity of settings
482  if (!ui.titleEdit->text().length())
483  {
484  DoError(::LoadResStr("IDS_ERR_ENTERTITLE"));
485  ui.titleEdit->setFocus();
486  return;
487  }
488  if (ItemExists(filename.getData()))
489  {
490  DoError(::LoadResStr("IDS_ERR_NEWSCENARIOFILEEXISTS"));
491  ui.titleEdit->setFocus();
492  return;
493  }
494  std::list<const char *> definitions = def_file_model.GetSelectedDefinitions();
495  if (definitions.size() > C4S_MaxDefinitions)
496  {
497  DoError(FormatString(::LoadResStr("IDS_ERR_TOOMANYDEFINITIONS"), (int)definitions.size(), (int)C4S_MaxDefinitions).getData());
498  ui.definitionTreeView->setFocus();
499  return;
500  }
501  if (!CreateScenario())
502  {
503  EraseItem(filename.getData());
504  DoError(::LoadResStr("IDS_ERR_CREATESCENARIO"));
505  ui.titleEdit->setFocus();
506  return;
507  }
508  // Close dialogue with OK
509  accept();
510 }
511 
512 // Filter for allowed characters in filename
513 // (Also replace space, because spaces in filenames suk)
514 static char ReplaceSpecialFilenameChars(char c)
515 {
516  const char *special_chars = "\\/:<>|$?\" ";
517  return strchr(special_chars, c) ? '_' : c;
518 }
519 
520 void C4ConsoleQtNewScenarioDlg::TitleChanged(const QString &new_title)
521 {
522  if (!has_custom_filename)
523  {
524  // Default filename by title
525  std::string filename = new_title.toStdString();
526  std::transform(filename.begin(), filename.end(), filename.begin(), ReplaceSpecialFilenameChars);
527  filename += (C4CFN_ScenarioFiles+1);
528  const char *filename_full = Config.AtUserDataPath(filename.c_str());
529  ui.filenameEdit->setText(filename_full);
530  this->filename.Copy(filename_full);
531 
532  }
533 }
534 
535 void C4ConsoleQtNewScenarioDlg::DoError(const char *msg)
536 {
537  QMessageBox::critical(this, ::LoadResStr("IDS_ERR_TITLE"), QString(msg));
538 }
539 
540 void C4ConsoleQtNewScenarioDlg::BrowsePressed()
541 {
542  // Browse for new filename to be used instead of the filename generated from the title
543  QString new_file;
544  for (;;)
545  {
546  new_file = QFileDialog::getSaveFileName(this, LoadResStr("IDS_CNS_NEWSCENARIO"), Config.General.UserDataPath, QString("%1 (%2)").arg(LoadResStr("IDS_CNS_SCENARIOFILE")).arg(C4CFN_ScenarioFiles), nullptr, QFileDialog::DontConfirmOverwrite);
547  if (!new_file.size()) return;
548  // Extension must be .ocs
549  if (!new_file.endsWith(C4CFN_ScenarioFiles + 1)) new_file += (C4CFN_ScenarioFiles + 1);
550  if (!ItemExists(new_file.toUtf8())) break;
551  // Overwriting of existing scenarios not supported
552  QMessageBox::critical(this, ::LoadResStr("IDS_ERR_TITLE"), ::LoadResStr("IDS_ERR_NEWSCENARIOFILEEXISTS"));
553  }
554  filename.Copy(new_file.toUtf8());
555  ui.filenameEdit->setText(filename.getData()); // set from converted filename just in case weird stuff happened in toUtf8
556  // After setting a new filename, it no longer changes when changing the title
557  has_custom_filename = true;
558 }
char * GetFilename(char *szPath)
Definition: StdFile.cpp:55
const char * getData() const
Definition: StdBuf.h:450
StdCopyStrBuf Mode
Definition: C4Scenario.h:121
#define C4CFN_WriteTitle
Definition: C4Components.h:83
C4Config Config
Definition: C4Config.cpp:837
C4SDefinitions Definitions
Definition: C4Scenario.h:231
bool Save(C4Group &hGroup, bool fSaveSection=false)
Definition: C4Scenario.cpp:114
#define C4CFN_Objects
Definition: C4Components.h:40
void Clear()
Definition: StdBuf.h:474
C4ConfigGeneral General
Definition: C4Config.h:252
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:250
C4SLandscape Landscape
Definition: C4Scenario.h:234
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:184
std::string Title
Definition: C4Scenario.h:64
C4SVal MapWdt
Definition: C4Scenario.h:176
bool C4Group_UnpackDirectory(const char *szFilename)
Definition: C4Group.cpp:306
bool GetModules(StdStrBuf *psOutModules) const
Definition: C4Scenario.cpp:420
#define _MAX_PATH
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool GetLanguageString(const char *szLanguage, StdStrBuf &rTarget)
static bool LoadComponentHost(C4ComponentHost *host, C4Group &hGroup, const char *szFilename, const char *szLanguage)
Definition: C4Language.cpp:235
#define C4CFN_Title
Definition: C4Components.h:82
C4SVal MapZoom
Definition: C4Scenario.h:176
char UserDataPath[CFG_MaxString+1]
Definition: C4Config.h:55
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2078
bool Open(const char *szGroupName, bool fCreate=false)
Definition: C4Group.cpp:514
bool Load(C4Group &hGroup, bool fLoadSection=false, bool suppress_errors=false)
Definition: C4Scenario.cpp:92
bool C4Group_CopyItem(const char *szSource, const char *szTarget1, bool fNoSort, bool fResetAttributes)
Definition: C4Group.cpp:100
bool CopyDirectory(const char *szSource, const char *szTarget, bool fResetAttributes)
Definition: StdFile.cpp:723
char LanguageEx[CFG_MaxString+1]
Definition: C4Config.h:38
std::list< const char * > GetModulesAsList() const
Definition: C4Scenario.cpp:444
C4Reloc Reloc
Definition: C4Reloc.cpp:22
bool DeleteEntry(const char *szFilename, bool fRecycle=false)
Definition: C4Group.cpp:1384
bool DirectoryExists(const char *szFilename)
Definition: StdFile.cpp:694
#define C4CFN_Template
Definition: C4Components.h:33
C4SVal MapHgt
Definition: C4Scenario.h:176
bool EraseItem(const char *szItemName)
Definition: StdFile.cpp:819
const char * AtUserDataPath(const char *szFilename)
Definition: C4Config.cpp:530
void SetModules(const char *szList, const char *szRelativeToPath=nullptr, const char *szRelativeToPath2=nullptr)
Definition: C4Scenario.cpp:462
bool WildcardMatch(const char *szWildcard, const char *szString)
Definition: StdFile.cpp:384
C4SGame Game
Definition: C4Scenario.h:232
bool SEqual2NoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:197
#define C4CFN_ScenarioFiles
Definition: C4Components.h:174
#define C4CFN_DefFiles
Definition: C4Components.h:166
size_t getLength() const
Definition: StdBuf.h:453
void SetConstant(int32_t val)
Definition: C4Scenario.cpp:41
C4SHead Head
Definition: C4Scenario.h:230
bool ItemExists(const char *szItemName)
Definition: StdFile.h:75
#define DirectorySeparator
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
void Copy()
Definition: StdBuf.h:475
const int32_t C4S_MaxDefinitions
Definition: C4Scenario.h:87
C4Group SystemGroup
Definition: C4Application.h:40
C4Application Application
Definition: C4Globals.cpp:44
bool OpenAsChild(C4Group *pMother, const char *szEntryName, bool fExclusive=false, bool fCreate=false)
Definition: C4Group.cpp:1585
#define C4CFN_DefaultScenarioTemplate
Definition: C4Components.h:149
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277