Skip to content

Commit

Permalink
Non-compiling, non-working WIP commit. Towards supporting math expres…
Browse files Browse the repository at this point in the history
…sions in GUI code.
  • Loading branch information
codereader committed Nov 12, 2017
1 parent 2dabb9b commit 4fa50d3
Show file tree
Hide file tree
Showing 8 changed files with 778 additions and 57 deletions.
659 changes: 659 additions & 0 deletions plugins/dm.gui/gui/GuiExpression.cpp

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions plugins/dm.gui/gui/GuiExpression.h
@@ -0,0 +1,30 @@
#pragma once

#include <memory>
#include <parser/DefTokeniser.h>

namespace gui
{

class GuiExpression;
typedef std::shared_ptr<GuiExpression> GuiExpressionPtr;

// Represents an expression found in the GUI code, which can be
// a simple float, a string, a gui variable or a complex formula.
class GuiExpression
{
private:

public:
GuiExpression();

virtual float getFloatValue() = 0;
virtual std::string getStringValue() = 0;

static GuiExpressionPtr createFromString(const std::string& exprStr);

static GuiExpressionPtr createFromTokens(parser::DefTokeniser& tokeniser);
};

}

44 changes: 25 additions & 19 deletions plugins/dm.gui/gui/GuiScript.cpp
Expand Up @@ -3,6 +3,7 @@
#include "itextstream.h"
#include "parser/DefTokeniser.h"
#include "Gui.h"
#include "GuiExpression.h"

#include "string/case_conv.h"
#include "string/trim.h"
Expand Down Expand Up @@ -74,11 +75,9 @@ void GuiScript::parseSetStatement(parser::DefTokeniser& tokeniser)
// Add all tokens up to the semicolon as arguments
while (true)
{
std::string expr = getExpression(tokeniser);
if (tokeniser.peek() == ";") break;

if (expr == ";") break;

st->args.push_back(expr); // value
st->args.push_back(getExpression(tokeniser)); // argument
}

pushStatement(st);
Expand All @@ -94,16 +93,18 @@ void GuiScript::parseTransitionStatement(parser::DefTokeniser& tokeniser)
st->args.push_back(getExpression(tokeniser)); // to
st->args.push_back(getExpression(tokeniser)); // time

std::string token = tokeniser.nextToken();

if (token != ";")
if (tokeniser.peek() != ";")
{
// no semicolon, parse optional acceleration and deceleration
st->args.push_back(token); // accel
st->args.push_back(getExpression(tokeniser)); // accel
st->args.push_back(getExpression(tokeniser)); // decel

tokeniser.assertNextToken(";");
}
else
{
tokeniser.nextToken(); // pull semicolon
}

pushStatement(st);
}
Expand Down Expand Up @@ -133,7 +134,7 @@ void GuiScript::parseResetTimeStatement(parser::DefTokeniser& tokeniser)
// Prototype: resetTime [<window>] [<time>]
StatementPtr st(new Statement(Statement::ST_RESET_TIME));

std::string token = tokeniser.nextToken();
std::string token = tokeniser.peek();

if (token != ";")
{
Expand All @@ -147,14 +148,14 @@ void GuiScript::parseResetTimeStatement(parser::DefTokeniser& tokeniser)
std::stoul(trimmed);

// Cast succeeded this is just the time for the current window
st->args.push_back(trimmed);
st->args.push_back(getExpression(tokeniser));

tokeniser.assertNextToken(";");
}
catch (std::logic_error&)
{
// Not a number, must be window plus time
st->args.push_back(token); // window
st->args.push_back(getExpression(tokeniser)); // window
st->args.push_back(getExpression(tokeniser)); // time
tokeniser.assertNextToken(";");
}
Expand Down Expand Up @@ -324,13 +325,15 @@ std::size_t GuiScript::pushStatement(const StatementPtr& statement)
return _statements.size() - 1;
}

std::string GuiScript::getExpression(parser::DefTokeniser& tokeniser)
GuiExpressionPtr GuiScript::getExpression(parser::DefTokeniser& tokeniser)
{
return tokeniser.nextToken();
return GuiExpression::createFromTokens(tokeniser);
}

std::string GuiScript::getIfExpression(parser::DefTokeniser& tokeniser)
GuiExpressionPtr GuiScript::getIfExpression(parser::DefTokeniser& tokeniser)
{
return getExpression(tokeniser);
#if 0
std::string rv;

std::size_t level = 1;
Expand All @@ -356,6 +359,7 @@ std::string GuiScript::getIfExpression(parser::DefTokeniser& tokeniser)
}

return rv;
#endif
}

const Statement& GuiScript::getStatement(std::size_t index)
Expand All @@ -364,8 +368,10 @@ const Statement& GuiScript::getStatement(std::size_t index)
return *_statements[index];
}

VariablePtr GuiScript::getVariableFromExpression(const std::string& expr)
VariablePtr GuiScript::getVariableFromExpression(const GuiExpressionPtr& expression)
{
std::string expr = expression->getStringValue();

if (string::starts_with(expr, "gui::"))
{
// Is a GUI state variable
Expand Down Expand Up @@ -404,15 +410,15 @@ VariablePtr GuiScript::getVariableFromExpression(const std::string& expr)
}
}

std::string GuiScript::getValueFromExpression(const std::string& expr)
std::string GuiScript::getValueFromExpression(const GuiExpressionPtr& expr)
{
if (string::starts_with(expr, "$gui::"))
if (string::starts_with(expr->getStringValue(), "$gui::"))
{
// This is the value of a GUI state variable
return _owner.getGui().getStateString(expr.substr(6));
return _owner.getGui().getStateString(expr->getStringValue().substr(6));
}

return expr;
return expr->getStringValue();
}

void GuiScript::execute()
Expand Down
16 changes: 7 additions & 9 deletions plugins/dm.gui/gui/GuiScript.h
@@ -1,10 +1,10 @@
#ifndef _GUI_SCRIPT_H_
#define _GUI_SCRIPT_H_
#pragma once

#include <list>
#include <vector>
#include <memory>

#include "GuiExpression.h"
#include "Variable.h"

namespace parser { class DefTokeniser; }
Expand Down Expand Up @@ -39,7 +39,7 @@ struct Statement
// The statement type
Type type;

typedef std::vector<std::string> Arguments;
typedef std::vector<GuiExpressionPtr> Arguments;
Arguments args;

// The jump destination used by ST_IF and ST_JMP
Expand Down Expand Up @@ -80,8 +80,8 @@ class GuiScript

private:
// Interprets the given string and returns the target object
VariablePtr getVariableFromExpression(const std::string& expr);
std::string getValueFromExpression(const std::string& expr);
VariablePtr getVariableFromExpression(const GuiExpressionPtr& expr);
std::string getValueFromExpression(const GuiExpressionPtr& expr);

const Statement& getStatement(std::size_t index);

Expand All @@ -91,8 +91,8 @@ class GuiScript
// Returns the current position in the code
std::size_t getCurPosition();

std::string getExpression(parser::DefTokeniser& tokeniser);
std::string getIfExpression(parser::DefTokeniser& tokeniser);
GuiExpressionPtr getExpression(parser::DefTokeniser& tokeniser);
GuiExpressionPtr getIfExpression(parser::DefTokeniser& tokeniser);

// Reads a "statement", which can be single one or a group (surrounded by curly braces)
void parseStatement(parser::DefTokeniser& tokeniser);
Expand All @@ -116,5 +116,3 @@ class GuiScript
typedef std::shared_ptr<GuiScript> GuiScriptPtr;

} // namespace

#endif /* _GUI_SCRIPT_H_ */
75 changes: 47 additions & 28 deletions plugins/dm.gui/gui/GuiWindowDef.cpp
Expand Up @@ -46,8 +46,10 @@ IGui& GuiWindowDef::getGui() const
}

// Returns a GUI expression, which can be a number, a string or a formula ("gui::objVisible" == 1).
std::string GuiWindowDef::getExpression(parser::DefTokeniser& tokeniser)
GuiExpressionPtr GuiWindowDef::getExpression(parser::DefTokeniser& tokeniser)
{
return GuiExpression::createFromTokens(tokeniser);
#if 0
std::string returnValue = tokeniser.nextToken();

if (returnValue == "(")
Expand All @@ -69,74 +71,86 @@ std::string GuiWindowDef::getExpression(parser::DefTokeniser& tokeniser)
string::trim(returnValue, "\"");

return returnValue;
#endif
}

Vector4 GuiWindowDef::parseVector4(parser::DefTokeniser& tokeniser)
{
// Collect tokens until all four components are parsed
std::vector<std::string> comp;
std::vector<GuiExpressionPtr> comp;

while (comp.size() < 4 && tokeniser.hasMoreTokens())
{
std::string token = getExpression(tokeniser);
std::string token = tokeniser.peek();

if (token == ",") continue;

if (token.find(',') != std::string::npos)
if (token == ",")
{
std::vector<std::string> parts;
string::split(parts, token, ",");

for (std::size_t i = 0; i < parts.size(); ++i)
{
comp.push_back(string::trim_copy(parts[i]));
}

tokeniser.nextToken();
continue;
}

// TODO: Catch GUI expressions
GuiExpressionPtr expr = getExpression(tokeniser);

comp.push_back(token);
comp.push_back(expr);
}

if (comp.size() != 4)
{
throw parser::ParseException("Couldn't parse Vector4, not enough components found.");
}

return Vector4(string::convert<float>(comp[0]),
string::convert<float>(comp[1]),
string::convert<float>(comp[2]),
string::convert<float>(comp[3]));
return Vector4(comp[0]->getFloatValue(),
comp[1]->getFloatValue(),
comp[2]->getFloatValue(),
comp[3]->getFloatValue());
}

float GuiWindowDef::parseFloat(parser::DefTokeniser& tokeniser)
{
// TODO: Catch GUI expressions
GuiExpressionPtr expr = getExpression(tokeniser);

return string::convert<float>(getExpression(tokeniser));
if (!expr)
{
throw parser::ParseException("Failed to parse float expression.");
}

return expr->getFloatValue();
}

int GuiWindowDef::parseInt(parser::DefTokeniser& tokeniser)
{
// TODO: Catch GUI expressions
GuiExpressionPtr expr = getExpression(tokeniser);

return string::convert<int>(getExpression(tokeniser));
if (!expr)
{
throw parser::ParseException("Failed to parse integer expression.");
}

return static_cast<int>(expr->getFloatValue());
}

std::string GuiWindowDef::parseString(parser::DefTokeniser& tokeniser)
{
// TODO: Catch GUI expressions
GuiExpressionPtr expr = getExpression(tokeniser);

return getExpression(tokeniser);
if (!expr)
{
throw parser::ParseException("Failed to parse string expression.");
}

return expr->getStringValue();
}

bool GuiWindowDef::parseBool(parser::DefTokeniser& tokeniser)
{
// TODO: Catch GUI expressions
GuiExpressionPtr expr = getExpression(tokeniser);

return string::convert<int>(getExpression(tokeniser)) != 0;
if (!expr)
{
throw parser::ParseException("Failed to parse integer expression.");
}

return expr->getFloatValue() != 0;
}

void GuiWindowDef::addWindow(const IGuiWindowDefPtr& window)
Expand All @@ -149,6 +163,11 @@ void GuiWindowDef::constructFromTokens(parser::DefTokeniser& tokeniser)
// The windowDef keyword has already been parsed, so expect a name plus an opening brace here
name = tokeniser.nextToken();

if (name == "LoadGameTextH")
{
int i = 6;
}

tokeniser.assertNextToken("{");

while (tokeniser.hasMoreTokens())
Expand Down
3 changes: 2 additions & 1 deletion plugins/dm.gui/gui/GuiWindowDef.h
Expand Up @@ -4,6 +4,7 @@
#include "ishaders.h"
#include "math/Vector4.h"

#include "GuiExpression.h"
#include "RenderableText.h"

namespace parser { class DefTokeniser; }
Expand Down Expand Up @@ -85,7 +86,7 @@ class GuiWindowDef :
std::string parseString(parser::DefTokeniser& tokeniser);
bool parseBool(parser::DefTokeniser& tokeniser);

std::string getExpression(parser::DefTokeniser& tokeniser);
GuiExpressionPtr getExpression(parser::DefTokeniser& tokeniser);
};


Expand Down
2 changes: 2 additions & 0 deletions tools/msvc/dm.gui.vcxproj
Expand Up @@ -316,6 +316,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\plugins\dm.gui\GuiSelector.cpp" />
<ClCompile Include="..\..\plugins\dm.gui\gui\GuiExpression.cpp" />
<ClCompile Include="..\..\plugins\dm.gui\plugin.cpp" />
<ClCompile Include="..\..\plugins\dm.gui\ReadableEditorDialog.cpp" />
<ClCompile Include="..\..\plugins\dm.gui\ReadableGuiView.cpp" />
Expand All @@ -333,6 +334,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\plugins\dm.gui\GuiSelector.h" />
<ClInclude Include="..\..\plugins\dm.gui\gui\GuiExpression.h" />
<ClInclude Include="..\..\plugins\dm.gui\ReadableEditorDialog.h" />
<ClInclude Include="..\..\plugins\dm.gui\ReadableGuiView.h" />
<ClInclude Include="..\..\plugins\dm.gui\ReadablePopulator.h" />
Expand Down

0 comments on commit 4fa50d3

Please sign in to comment.