Skip to content

Commit

Permalink
Add DarkmodTxt object and parsing code. Parsing darkmod.txt is horrib…
Browse files Browse the repository at this point in the history
…ly fragile text splitting, based on the actual parsing code in the game.
  • Loading branch information
codereader committed Nov 4, 2017
1 parent ea51070 commit 7cb9536
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 204 deletions.
179 changes: 4 additions & 175 deletions install/ui/missioninfoeditdialog.fbp

Large diffs are not rendered by default.

25 changes: 3 additions & 22 deletions install/ui/missioninfoeditdialog.xrc
Expand Up @@ -25,7 +25,7 @@
<flag>wxEXPAND|wxLEFT</flag>
<border>12</border>
<object class="wxFlexGridSizer">
<rows>5</rows>
<rows>4</rows>
<cols>2</cols>
<vgap>0</vgap>
<hgap>12</hgap>
Expand Down Expand Up @@ -80,30 +80,10 @@
<border>6</border>
<object class="wxTextCtrl" name="MissionInfoEditDialogDescriptionEntry">
<style>wxTE_MULTILINE|wxTE_WORDWRAP</style>
<size>-1,80</size>
<value></value>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALIGN_CENTER_VERTICAL|wxALL</flag>
<border>0</border>
<object class="wxStaticText" name="m_staticText811">
<label>Version:</label>
<wrap>-1</wrap>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALL</flag>
<border>6</border>
<object class="wxSpinCtrl" name="MissionInfoEditDialogVersionEntry">
<style>wxSP_ARROW_KEYS</style>
<size>60,-1</size>
<value>0</value>
<min>1</min>
<max>999</max>
</object>
</object>
<object class="sizeritem">
<option>0</option>
<flag>wxALIGN_CENTER_VERTICAL</flag>
Expand All @@ -124,6 +104,7 @@
<flag>wxALL</flag>
<border>6</border>
<object class="wxTextCtrl" name="MissionInfoEditDialogReqTdmVersionEntry">
<size>60,-1</size>
<value></value>
</object>
</object>
Expand Down
129 changes: 129 additions & 0 deletions plugins/dm.editing/DarkmodTxt.cpp
@@ -0,0 +1,129 @@
#include "DarkmodTxt.h"

#include "iarchive.h"
#include "itextstream.h"
#include "ifilesystem.h"
#include "igame.h"
#include "os/fs.h"
#include "string/trim.h"
#include "string/convert.h"
#include "string/case_conv.h"

namespace map
{

const std::string& DarkmodTxt::getTitle()
{
return _title;
}

const std::string& DarkmodTxt::getAuthor()
{
return _author;
}

const std::string& DarkmodTxt::getDescription()
{
return _description;
}

const std::string& DarkmodTxt::getReqTdmVersion()
{
return _reqTdmVersion;
}

void DarkmodTxt::ParseMissionTitles(std::vector<std::string>& titleList, const std::string& source)
{
// TODO
}

DarkmodTxtPtr DarkmodTxt::CreateFromString(const std::string& contents)
{
DarkmodTxtPtr info(new DarkmodTxt);

// The positions need to be searched case-insensitively
std::string contentsLower = string::to_lower_copy(contents);
std::size_t titlePos = contentsLower.find("title:");
std::size_t descPos = contentsLower.find("description:");
std::size_t authorPos = contentsLower.find("author:");
std::size_t versionPos = contentsLower.find("required tdm version:");
std::size_t missionTitlesPos = contentsLower.find("mission 1 title:");

std::size_t len = contents.size();

if (titlePos != std::string::npos)
{
info->_title = contents.substr(titlePos, (missionTitlesPos != std::string::npos) ?
descPos - missionTitlesPos : (descPos != std::string::npos) ? descPos - titlePos : len - titlePos);
string::trim_left(info->_title, "Title:");
string::trim(info->_title);
}

info->_missionTitles.clear();
info->_missionTitles.push_back(info->_title); // [0] is the title

if (missionTitlesPos != std::string::npos)
{
std::string missionTitles = contents.substr(missionTitlesPos, (descPos != std::string::npos) ? missionTitlesPos - descPos : len - missionTitlesPos);
ParseMissionTitles(info->_missionTitles, missionTitles);
}

if (descPos != std::string::npos)
{
info->_description = contents.substr(descPos, (authorPos != std::string::npos) ? authorPos - descPos : len - descPos);
string::trim_left(info->_description, "Description:");
string::trim(info->_description);
}

if (authorPos != std::string::npos)
{
info->_author = contents.substr(authorPos, (versionPos != std::string::npos) ? versionPos - authorPos : len - authorPos);
string::trim_left(info->_author, "Author:");
string::trim(info->_author);
}

if (versionPos != std::string::npos)
{
info->_reqTdmVersion = contents.substr(versionPos, len - versionPos);

string::trim_left(info->_reqTdmVersion, "Required TDM Version:");
string::trim_left(info->_reqTdmVersion, "v");
string::trim(info->_reqTdmVersion);
}

return info;
}

DarkmodTxtPtr DarkmodTxt::CreateFromStream(std::istream& stream)
{
// Read all the stream contents into a string
std::string str(std::istreambuf_iterator<char>(stream), {});
return CreateFromString(str);
}

DarkmodTxtPtr DarkmodTxt::LoadForCurrentMod()
{
std::string modPath = GlobalGameManager().getModPath();

if (modPath.empty())
{
rMessage() << "Mod path empty, falling back to mod base path..." << std::endl;
modPath = GlobalGameManager().getModBasePath();
}

fs::path darkmodTxtPath = fs::path(modPath) / NAME();

rMessage() << "Trying to open file " << darkmodTxtPath << std::endl;

ArchiveTextFilePtr file = GlobalFileSystem().openTextFileInAbsolutePath(darkmodTxtPath.string());

if (file)
{
std::istream stream(&(file->getInputStream()));
return CreateFromStream(stream);
}

return std::make_shared<DarkmodTxt>();
}

}
51 changes: 51 additions & 0 deletions plugins/dm.editing/DarkmodTxt.h
@@ -0,0 +1,51 @@
#pragma once

#include <string>
#include <memory>
#include <vector>

namespace map
{

class DarkmodTxt;
typedef std::shared_ptr<DarkmodTxt> DarkmodTxtPtr;

/**
* An object representing the darkmod.txt file as found in the
* mission folder's root directory. It contains information shown
* in the "New Mission" section in TDM's main menu.
*/
class DarkmodTxt
{
private:
std::string _title;
std::string _author;
std::string _description;
std::string _reqTdmVersion;

std::vector<std::string> _missionTitles;

public:
static const char* NAME()
{
return "darkmod.txt";
}

const std::string& getTitle();
const std::string& getAuthor();
const std::string& getDescription();
const std::string& getReqTdmVersion();

// Named constructor parsing the given string into a DarkmodTxt instance
static DarkmodTxtPtr CreateFromString(const std::string& contents);

// Named constructor parsing the given stream into a DarkmodTxt instance
static DarkmodTxtPtr CreateFromStream(std::istream& stream);

static DarkmodTxtPtr LoadForCurrentMod();

private:
static void ParseMissionTitles(std::vector<std::string>& titleList, const std::string& source);
};

}
22 changes: 22 additions & 0 deletions plugins/dm.editing/MissionInfoEditDialog.cpp
Expand Up @@ -4,6 +4,7 @@
#include <sigc++/functors/mem_fun.h>

#include <wx/button.h>
#include <wx/textctrl.h>

namespace ui
{
Expand All @@ -17,6 +18,27 @@ MissionInfoEditDialog::MissionInfoEditDialog(wxWindow* parent) :
DialogBase(_(WINDOW_TITLE), parent)
{
populateWindow();

_darkmodTxt = map::DarkmodTxt::LoadForCurrentMod();
updateValuesFromDarkmodTxt();
}

void MissionInfoEditDialog::updateValuesFromDarkmodTxt()
{
if (!_darkmodTxt)
{
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogTitleEntry")->SetValue("");
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogAuthorEntry")->SetValue("");
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogDescriptionEntry")->SetValue("");
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogReqTdmVersionEntry")->SetValue("");

return;
}

findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogTitleEntry")->SetValue(_darkmodTxt->getTitle());
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogAuthorEntry")->SetValue(_darkmodTxt->getAuthor());
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogDescriptionEntry")->SetValue(_darkmodTxt->getDescription());
findNamedObject<wxTextCtrl>(this, "MissionInfoEditDialogReqTdmVersionEntry")->SetValue(_darkmodTxt->getReqTdmVersion());
}

void MissionInfoEditDialog::populateWindow()
Expand Down
14 changes: 7 additions & 7 deletions plugins/dm.editing/MissionInfoEditDialog.h
Expand Up @@ -5,31 +5,31 @@
#include "wxutil/dialog/DialogBase.h"
#include "wxutil/XmlResourceBasedWidget.h"

#include "DarkmodTxt.h"

namespace ui
{

class MissionInfoEditDialog :
public wxutil::DialogBase,
private wxutil::XmlResourceBasedWidget
{
private:
// The file we're editing
map::DarkmodTxtPtr _darkmodTxt;

public:
// Constructor
MissionInfoEditDialog(wxWindow* parent = nullptr);

static void ShowDialog(const cmd::ArgumentList& args);

protected:
bool _onDeleteEvent() override;

private:
void populateWindow();
void updateValuesFromDarkmodTxt();

void onSave(wxCommandEvent& ev);
void onCancel(wxCommandEvent& ev);
void onFormatSelection(wxCommandEvent& ev);

void saveOptionsToRegistry();
void handleFormatSelectionChange();
};

}
11 changes: 11 additions & 0 deletions plugins/dm.editing/plugin.cpp
Expand Up @@ -15,6 +15,7 @@
#include "AIVocalSetPropertyEditor.h"
#include "FixupMapDialog.h"
#include "AIEditingPanel.h"
#include "MissionInfoEditDialog.h"

class EditingModule :
public RegisterableModule
Expand Down Expand Up @@ -66,6 +67,16 @@ class EditingModule :
"FixupMapDialog"
);

GlobalCommandSystem().addCommand("MissionInfoEditDialog", ui::MissionInfoEditDialog::ShowDialog);
GlobalEventManager().addCommand("MissionInfoEditDialog", "MissionInfoEditDialog");

GlobalUIManager().getMenuManager().add("main/map",
"MissionInfoEditDialog", ui::menuItem,
_("Edit Mission Info..."), // caption
"", // icon
"MissionInfoEditDialog"
);

GlobalRadiant().signal_radiantStarted().connect(
sigc::ptr_fun(ui::AIEditingPanel::onRadiantStartup)
);
Expand Down
2 changes: 2 additions & 0 deletions tools/msvc/dm.editing.vcxproj
Expand Up @@ -317,6 +317,7 @@
<ClCompile Include="..\..\plugins\dm.editing\AIVocalSetChooserDialog.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\AIVocalSetPreview.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\AIVocalSetPropertyEditor.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\DarkmodTxt.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\FixupMap.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\FixupMapDialog.cpp" />
<ClCompile Include="..\..\plugins\dm.editing\MissionInfoEditDialog.cpp" />
Expand All @@ -329,6 +330,7 @@
<ClInclude Include="..\..\plugins\dm.editing\AIVocalSetChooserDialog.h" />
<ClInclude Include="..\..\plugins\dm.editing\AIVocalSetPreview.h" />
<ClInclude Include="..\..\plugins\dm.editing\AIVocalSetPropertyEditor.h" />
<ClInclude Include="..\..\plugins\dm.editing\DarkmodTxt.h" />
<ClInclude Include="..\..\plugins\dm.editing\DeprecatedEclassCollector.h" />
<ClInclude Include="..\..\plugins\dm.editing\FixupMap.h" />
<ClInclude Include="..\..\plugins\dm.editing\FixupMapDialog.h" />
Expand Down
6 changes: 6 additions & 0 deletions tools/msvc/dm.editing.vcxproj.filters
Expand Up @@ -37,6 +37,9 @@
<ClCompile Include="..\..\plugins\dm.editing\MissionInfoEditDialog.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\plugins\dm.editing\DarkmodTxt.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\plugins\dm.editing\AIHeadChooserDialog.h">
Expand Down Expand Up @@ -81,5 +84,8 @@
<ClInclude Include="..\..\plugins\dm.editing\MissionInfoEditDialog.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\plugins\dm.editing\DarkmodTxt.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
</Project>

0 comments on commit 7cb9536

Please sign in to comment.