Move IW4 menu dumping logic to separate class and constants to common scope

This commit is contained in:
Jan
2021-10-24 14:59:43 +02:00
parent 4e5e6d05bd
commit 805c00539b
10 changed files with 1384 additions and 1260 deletions

View File

@ -0,0 +1,250 @@
#include "AbstractMenuDumper.h"
#include <algorithm>
#include <sstream>
#include <cmath>
#include "Parsing/Impl/ParserInputStream.h"
#include "Parsing/Simple/SimpleLexer.h"
AbstractMenuDumper::AbstractMenuDumper(std::ostream& stream)
: m_stream(stream),
m_indent(0u)
{
}
void AbstractMenuDumper::IncIndent()
{
m_indent++;
}
void AbstractMenuDumper::DecIndent()
{
if (m_indent > 0)
m_indent--;
}
void AbstractMenuDumper::Indent() const
{
for (auto i = 0u; i < m_indent; i++)
m_stream << " ";
}
void AbstractMenuDumper::StartScope(const std::string& scopeName)
{
Indent();
m_stream << scopeName << "\n";
Indent();
m_stream << "{\n";
IncIndent();
}
void AbstractMenuDumper::StartMenuDefScope()
{
StartScope("menuDef");
}
void AbstractMenuDumper::StartItemDefScope()
{
StartScope("itemDef");
}
void AbstractMenuDumper::StartFunctionDefScope()
{
StartScope("functionDef");
}
void AbstractMenuDumper::EndScope()
{
DecIndent();
Indent();
m_stream << "}\n";
}
std::vector<std::string> AbstractMenuDumper::CreateScriptTokenList(const char* script)
{
const std::string scriptString(script);
std::istringstream stringStream(scriptString);
ParserInputStream inputStream(stringStream, "MenuScript");
SimpleLexer lexer(&inputStream, SimpleLexer::Config{false, true, false});
std::vector<std::string> result;
auto hasLexerTokens = true;
while (hasLexerTokens)
{
const auto& token = lexer.GetToken(0);
switch (token.m_type)
{
case SimpleParserValueType::IDENTIFIER:
result.emplace_back(token.IdentifierValue());
break;
case SimpleParserValueType::STRING:
result.emplace_back(token.StringValue());
break;
case SimpleParserValueType::CHARACTER:
result.emplace_back(1, token.CharacterValue());
break;
case SimpleParserValueType::INVALID:
case SimpleParserValueType::END_OF_FILE:
hasLexerTokens = false;
break;
default:
assert(false);
break;
}
lexer.PopTokens(1);
}
return result;
}
bool AbstractMenuDumper::DoesTokenNeedQuotationMarks(const std::string& token)
{
const auto hasAlNumCharacter = std::any_of(token.begin(), token.end(), [](const char& c)
{
return isalnum(c);
});
if (!hasAlNumCharacter)
return false;
const auto hasNonIdentifierCharacter = std::any_of(token.begin(), token.end(), [](const char& c)
{
return !isalnum(c) && c != '_';
});
return hasNonIdentifierCharacter;
}
const std::string& AbstractMenuDumper::BoolValue(const bool value)
{
return value ? BOOL_VALUE_TRUE : BOOL_VALUE_FALSE;
}
void AbstractMenuDumper::WriteKey(const std::string& keyName) const
{
m_stream << keyName;
if (keyName.size() < MENU_KEY_SPACING)
{
const auto spacingLength = MENU_KEY_SPACING - keyName.size();
for (auto i = 0u; i < spacingLength; i++)
m_stream << " ";
}
}
void AbstractMenuDumper::WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const
{
if (propertyValue.empty())
return;
Indent();
WriteKey(propertyKey);
m_stream << "\"" << propertyValue << "\"\n";
}
void AbstractMenuDumper::WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const
{
if (propertyValue == nullptr || propertyValue[0] == '\0')
return;
Indent();
WriteKey(propertyKey);
m_stream << "\"" << propertyValue << "\"\n";
}
void AbstractMenuDumper::WriteBoolProperty(const std::string& propertyKey, const bool propertyValue, const bool defaultValue) const
{
if (propertyValue == defaultValue)
return;
Indent();
WriteKey(propertyKey);
m_stream << BoolValue(propertyValue) << "\n";
}
void AbstractMenuDumper::WriteIntProperty(const std::string& propertyKey, const int propertyValue, const int defaultValue) const
{
if (propertyValue == defaultValue)
return;
Indent();
WriteKey(propertyKey);
m_stream << propertyValue << "\n";
}
void AbstractMenuDumper::WriteFloatProperty(const std::string& propertyKey, const float propertyValue, const float defaultValue) const
{
if (std::fabs(propertyValue - defaultValue) < std::numeric_limits<float>::epsilon())
return;
Indent();
WriteKey(propertyKey);
m_stream << propertyValue << "\n";
}
void AbstractMenuDumper::WriteColorProperty(const std::string& propertyKey, const float (&propertyValue)[4], const float (&defaultValue)[4]) const
{
if (std::fabs(propertyValue[0] - defaultValue[0]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[1] - defaultValue[1]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[2] - defaultValue[2]) < std::numeric_limits<float>::epsilon()
&& std::fabs(propertyValue[3] - defaultValue[3]) < std::numeric_limits<float>::epsilon())
{
return;
}
Indent();
WriteKey(propertyKey);
m_stream << propertyValue[0] << " " << propertyValue[1] << " " << propertyValue[2] << " " << propertyValue[3] << "\n";
}
void AbstractMenuDumper::WriteKeywordProperty(const std::string& propertyKey, const bool shouldWrite) const
{
if (!shouldWrite)
return;
Indent();
WriteKey(propertyKey);
m_stream << "\n";
}
void AbstractMenuDumper::WriteFlagsProperty(const std::string& propertyKey, const int flagsValue) const
{
for (auto i = 0u; i < sizeof(flagsValue) * 8; i++)
{
if (flagsValue & (1 << i))
{
Indent();
WriteKey(propertyKey);
m_stream << i << "\n";
}
}
}
void AbstractMenuDumper::Start()
{
Indent();
m_stream << "{\n";
IncIndent();
}
void AbstractMenuDumper::End()
{
for (auto i = 0u; i < m_indent; i++)
{
DecIndent();
Indent();
m_stream << "}\n";
}
}
void AbstractMenuDumper::IncludeMenu(const std::string& menuPath) const
{
Indent();
m_stream << "loadMenu { \"" << menuPath << "\" }\n";
}

View File

@ -0,0 +1,51 @@
#pragma once
#include <string>
#include <cstddef>
#include <ostream>
#include <vector>
class AbstractMenuDumper
{
protected:
static constexpr auto MENU_KEY_SPACING = 28u;
static const inline std::string BOOL_VALUE_TRUE = "1";
static const inline std::string BOOL_VALUE_FALSE = "0";
static constexpr inline float COLOR_0000[4]{ 0.0f, 0.0f, 0.0f, 0.0f };
static constexpr inline float COLOR_1111[4]{ 1.0f, 1.0f, 1.0f, 1.0f };
std::ostream& m_stream;
size_t m_indent;
void IncIndent();
void DecIndent();
void Indent() const;
void StartScope(const std::string& scopeName);
void StartMenuDefScope();
void StartItemDefScope();
void StartFunctionDefScope();
void EndScope();
static std::vector<std::string> CreateScriptTokenList(const char* script);
static bool DoesTokenNeedQuotationMarks(const std::string& token);
static const std::string& BoolValue(bool value);
void WriteKey(const std::string& keyName) const;
void WriteStringProperty(const std::string& propertyKey, const std::string& propertyValue) const;
void WriteStringProperty(const std::string& propertyKey, const char* propertyValue) const;
void WriteBoolProperty(const std::string& propertyKey, bool propertyValue, bool defaultValue) const;
void WriteIntProperty(const std::string& propertyKey, int propertyValue, int defaultValue) const;
void WriteFloatProperty(const std::string& propertyKey, float propertyValue, float defaultValue) const;
void WriteColorProperty(const std::string& propertyKey, const float(&propertyValue)[4], const float(&defaultValue)[4]) const;
void WriteKeywordProperty(const std::string& propertyKey, bool shouldWrite) const;
void WriteFlagsProperty(const std::string& propertyKey, int flagsValue) const;
explicit AbstractMenuDumper(std::ostream& stream);
public:
void Start();
void End();
void IncludeMenu(const std::string& menuPath) const;
};

View File

@ -1,47 +0,0 @@
#include "MenuDumper.h"
MenuDumper::MenuDumper(std::ostream& stream)
: m_stream(stream),
m_indent(0u)
{
}
void MenuDumper::IncIndent()
{
m_indent++;
}
void MenuDumper::DecIndent()
{
if (m_indent > 0)
m_indent--;
}
void MenuDumper::Indent() const
{
for (auto i = 0u; i < m_indent; i++)
m_stream << " ";
}
void MenuDumper::Start()
{
Indent();
m_stream << "{\n";
IncIndent();
}
void MenuDumper::End()
{
for (auto i = 0u; i < m_indent; i++)
{
DecIndent();
Indent();
m_stream << "}\n";
}
}
void MenuDumper::IncludeMenu(const std::string& menuPath) const
{
Indent();
m_stream << "loadMenu { \"" << menuPath << "\" }\n";
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <string>
#include <ostream>
class MenuDumper
{
protected:
std::ostream& m_stream;
size_t m_indent;
void IncIndent();
void DecIndent();
void Indent() const;
public:
explicit MenuDumper(std::ostream& stream);
void Start();
void End();
void IncludeMenu(const std::string& menuPath) const;
};