Clean up sign-related code a bit

Also draw search signs with purple text and thread signs with red.
This commit is contained in:
Tamás Bálint Misius 2019-04-12 17:09:34 +02:00
parent 59afaec70f
commit 9d92b77163
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
9 changed files with 235 additions and 244 deletions

View File

@ -58,34 +58,14 @@ int PIXELMETHODS_CLASS::drawtext(int x, int y, String str, int r, int g, int b,
if(!s[1]) break; if(!s[1]) break;
switch (s[1]) switch (s[1])
{ {
case 'w': case 'w': r = 255; g = 255; b = 255; break;
r = g = b = 255; case 'g': r = 192; g = 192; b = 192; break;
break; case 'o': r = 255; g = 216; b = 32; break;
case 'g': case 'r': r = 255; g = 0; b = 0; break;
r = g = b = 192; case 'l': r = 255; g = 75; b = 75; break;
break; case 'b': r = 0; g = 0; b = 255; break;
case 'o': case 't': b = 255; g = 170; r = 32; break;
r = 255; case 'u': r = 147; g = 83; b = 211; break;
g = 216;
b = 32;
break;
case 'r':
r = 255;
g = b = 0;
break;
case 'l':
r = 255;
g = b = 75;
break;
case 'b':
r = g = 0;
b = 255;
break;
case 't':
b = 255;
g = 170;
r = 32;
break;
} }
if(invert) if(invert)
{ {

View File

@ -981,28 +981,21 @@ void Renderer::DrawSigns()
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, partsFbo);
glTranslated(0, MENUSIZE, 0); glTranslated(0, MENUSIZE, 0);
#endif #endif
for (size_t i = 0; i < signs.size(); i++) for (auto &currentSign : signs)
if (signs[i].text.length())
{ {
String::value_type type = 0; if (currentSign.text.length())
String text = signs[i].getText(sim); {
sign::splitsign(signs[i].text, &type); String text = currentSign.getDisplayText(sim, x, y, w, h);
signs[i].pos(text, x, y, w, h);
clearrect(x, y, w+1, h); clearrect(x, y, w+1, h);
drawrect(x, y, w+1, h, 192, 192, 192, 255); drawrect(x, y, w+1, h, 192, 192, 192, 255);
if (!type)
drawtext(x+3, y+3, text, 255, 255, 255, 255); drawtext(x+3, y+3, text, 255, 255, 255, 255);
else if(type == 'b')
drawtext(x+3, y+3, text, 211, 211, 40, 255);
else
drawtext(x+3, y+3, text, 0, 191, 255, 255);
if (signs[i].ju != sign::None) if (currentSign.ju != sign::None)
{ {
int x = signs[i].x; int x = currentSign.x;
int y = signs[i].y; int y = currentSign.y;
int dx = 1 - signs[i].ju; int dx = 1 - currentSign.ju;
int dy = (signs[i].y > 18) ? -1 : 1; int dy = (currentSign.y > 18) ? -1 : 1;
#ifdef OGLR #ifdef OGLR
glBegin(GL_LINES); glBegin(GL_LINES);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
@ -1019,6 +1012,7 @@ void Renderer::DrawSigns()
#endif #endif
} }
} }
}
#ifdef OGLR #ifdef OGLR
glTranslated(0, -MENUSIZE, 0); glTranslated(0, -MENUSIZE, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);

View File

@ -311,7 +311,7 @@ int GameController::GetSignAt(int x, int y)
for (int i = sim->signs.size()-1; i >= 0; i--) for (int i = sim->signs.size()-1; i >= 0; i--)
{ {
int signx, signy, signw, signh; int signx, signy, signw, signh;
sim->signs[i].pos(sim->signs[i].getText(sim), signx, signy, signw, signh); sim->signs[i].getDisplayText(sim, signx, signy, signw, signh);
if (x>=signx && x<=signx+signw && y>=signy && y<=signy+signh) if (x>=signx && x<=signx+signw && y>=signy && y<=signy+signh)
return i; return i;
} }
@ -324,6 +324,11 @@ String GameController::GetSignText(int signID)
return gameModel->GetSimulation()->signs[signID].text; return gameModel->GetSimulation()->signs[signID].text;
} }
std::pair<int, sign::Type> GameController::GetSignSplit(int signID)
{
return gameModel->GetSimulation()->signs[signID].split();
}
void GameController::PlaceSave(ui::Point position, bool includePressure) void GameController::PlaceSave(ui::Point position, bool includePressure)
{ {
bool incPressure = Client::Ref().GetPrefBool("Simulation.LoadPressure", true); bool incPressure = Client::Ref().GetPrefBool("Simulation.LoadPressure", true);
@ -640,12 +645,13 @@ bool GameController::MouseDown(int x, int y, unsigned button)
foundSignID = GetSignAt(x, y); foundSignID = GetSignAt(x, y);
if (foundSignID != -1) if (foundSignID != -1)
{ {
sign foundSign = gameModel->GetSimulation()->signs[foundSignID]; if (gameModel->GetSimulation()->signs[foundSignID].split().first)
if (sign::splitsign(foundSign.text)) {
return false; return false;
} }
} }
} }
}
return ret; return ret;
} }
@ -665,40 +671,31 @@ bool GameController::MouseUp(int x, int y, unsigned button, char type)
int foundSignID = GetSignAt(x, y); int foundSignID = GetSignAt(x, y);
if (foundSignID != -1) if (foundSignID != -1)
{ {
sign foundSign = gameModel->GetSimulation()->signs[foundSignID]; sign &foundSign = gameModel->GetSimulation()->signs[foundSignID];
String str = foundSign.text; String str = foundSign.text;
String::value_type type; auto si = gameModel->GetSimulation()->signs[foundSignID].split();
int pos = sign::splitsign(str, &type); if (si.first)
if (pos)
{ {
ret = false; ret = false;
if (type == 'c' || type == 't' || type == 's') switch (si.second)
{ {
String link = str.Substr(3, pos-3); case sign::Type::Save:
switch (type)
{ {
case 'c': int saveID = str.Substr(3, si.first - 3).ToNumber<int>(true);
{
int saveID = link.ToNumber<int>(true);
if (saveID) if (saveID)
OpenSavePreview(saveID, 0, false); OpenSavePreview(saveID, 0, false);
}
break; break;
} case sign::Type::Thread:
case 't': Platform::OpenURI(ByteString::Build(SCHEME "powdertoy.co.uk/Discussions/Thread/View.html?Thread=", str.Substr(3, si.first - 3).ToUtf8()));
{
// buff is already confirmed to be a number by sign::splitsign
Platform::OpenURI(ByteString::Build(SCHEME "powdertoy.co.uk/Discussions/Thread/View.html?Thread=", link.ToUtf8()));
break; break;
} case sign::Type::Search:
case 's': OpenSearch(str.Substr(3, si.first - 3));
OpenSearch(link);
break; break;
} case sign::Type::Button:
} gameModel->GetSimulation()->create_part(-1, foundSign.x, foundSign.y, PT_SPRK);
else if (type == 'b') break;
{ default: break;
Simulation * sim = gameModel->GetSimulation();
sim->create_part(-1, foundSign.x, foundSign.y, PT_SPRK);
} }
} }
} }

View File

@ -59,6 +59,7 @@ public:
GameView * GetView(); GameView * GetView();
int GetSignAt(int x, int y); int GetSignAt(int x, int y);
String GetSignText(int signID); String GetSignText(int signID);
std::pair<int, sign::Type> GetSignSplit(int signID);
bool MouseMove(int x, int y, int dx, int dy); bool MouseMove(int x, int y, int dx, int dy);
bool MouseDown(int x, int y, unsigned button); bool MouseDown(int x, int y, unsigned button);

View File

@ -1726,24 +1726,25 @@ void GameView::OnTick(float dt)
if (foundSignID != -1) if (foundSignID != -1)
{ {
String str = c->GetSignText(foundSignID); String str = c->GetSignText(foundSignID);
String::value_type type = '\0'; auto si = c->GetSignSplit(foundSignID);
int pos = sign::splitsign(str, &type);
if (type == 'c' || type == 't' || type == 's')
{
String linkSign = str.Substr(3, pos-3);
StringBuilder tooltip; StringBuilder tooltip;
switch (type) switch (si.second)
{ {
case 'c': case sign::Type::Save:
tooltip << "Go to save ID:" << linkSign; tooltip << "Go to save ID:" << str.Substr(3, si.first - 3);
break; break;
case 't': case sign::Type::Thread:
tooltip << "Open forum thread " << linkSign << " in browser"; tooltip << "Open forum thread " << str.Substr(3, si.first - 3) << " in browser";
break; break;
case 's': case sign::Type::Search:
tooltip << "Search for " << linkSign; tooltip << "Search for " << str.Substr(3, si.first - 3);
break; break;
default: break;
} }
if (tooltip.Size())
{
ToolTip(ui::Point(0, Size.Y), tooltip.Build()); ToolTip(ui::Point(0, Size.Y), tooltip.Build());
} }
} }

View File

@ -193,23 +193,15 @@ void SignWindow::OnTryExit(ui::Window::ExitMethod method)
void SignWindow::DoDraw() void SignWindow::DoDraw()
{ {
for(std::vector<sign>::iterator iter = sim->signs.begin(), end = sim->signs.end(); iter != end; ++iter) for (auto &currentSign : sim->signs)
{ {
sign & currentSign = *iter;
int x, y, w, h, dx, dy; int x, y, w, h, dx, dy;
String::value_type type = 0;
Graphics * g = GetGraphics(); Graphics * g = GetGraphics();
String text = currentSign.getText(sim);
sign::splitsign(currentSign.text, &type); String text = currentSign.getDisplayText(sim, x, y, w, h);
currentSign.pos(text, x, y, w, h);
g->clearrect(x, y, w+1, h); g->clearrect(x, y, w+1, h);
g->drawrect(x, y, w+1, h, 192, 192, 192, 255); g->drawrect(x, y, w+1, h, 192, 192, 192, 255);
if (!type)
g->drawtext(x+3, y+3, text, 255, 255, 255, 255); g->drawtext(x+3, y+3, text, 255, 255, 255, 255);
else if(type == 'b')
g->drawtext(x+3, y+3, text, 211, 211, 40, 255);
else
g->drawtext(x+3, y+3, text, 0, 191, 255, 255);
if (currentSign.ju != sign::None) if (currentSign.ju != sign::None)
{ {
@ -294,7 +286,7 @@ void SignTool::Click(Simulation * sim, Brush * brush, ui::Point position)
int signX, signY, signW, signH, signIndex = -1; int signX, signY, signW, signH, signIndex = -1;
for (size_t i = 0; i < sim->signs.size(); i++) for (size_t i = 0; i < sim->signs.size(); i++)
{ {
sim->signs[i].pos(sim->signs[i].getText(sim), signX, signY, signW, signH); sim->signs[i].getDisplayText(sim, signX, signY, signW, signH);
if (position.X > signX && position.X < signX+signW && position.Y > signY && position.Y < signY+signH) if (position.X > signX && position.X < signX+signW && position.Y > signY && position.Y < signY+signH)
{ {
signIndex = i; signIndex = i;

View File

@ -564,10 +564,11 @@ int LuaScriptInterface::simulation_signIndex(lua_State *l)
return lua_pushnil(l), 1; return lua_pushnil(l), 1;
} }
int x, y, w, h;
if (!key.compare("text")) if (!key.compare("text"))
return lua_pushstring(l, luacon_sim->signs[id].text.ToUtf8().c_str()), 1; return lua_pushstring(l, luacon_sim->signs[id].text.ToUtf8().c_str()), 1;
else if (!key.compare("displayText")) else if (!key.compare("displayText"))
return lua_pushstring(l, luacon_sim->signs[id].getText(luacon_sim).ToUtf8().c_str()), 1; return lua_pushstring(l, luacon_sim->signs[id].getDisplayText(luacon_sim, x, y, w, h, false).ToUtf8().c_str()), 1;
else if (!key.compare("justification")) else if (!key.compare("justification"))
return lua_pushnumber(l, (int)luacon_sim->signs[id].ju), 1; return lua_pushnumber(l, (int)luacon_sim->signs[id].ju), 1;
else if (!key.compare("x")) else if (!key.compare("x"))
@ -576,29 +577,25 @@ int LuaScriptInterface::simulation_signIndex(lua_State *l)
return lua_pushnumber(l, luacon_sim->signs[id].y), 1; return lua_pushnumber(l, luacon_sim->signs[id].y), 1;
else if (!key.compare("screenX")) else if (!key.compare("screenX"))
{ {
int x, y, w, h; luacon_sim->signs[id].getDisplayText(luacon_sim, x, y, w, h);
luacon_sim->signs[id].pos(luacon_sim->signs[id].getText(luacon_sim), x, y, w, h);
lua_pushnumber(l, x); lua_pushnumber(l, x);
return 1; return 1;
} }
else if (!key.compare("screenY")) else if (!key.compare("screenY"))
{ {
int x, y, w, h; luacon_sim->signs[id].getDisplayText(luacon_sim, x, y, w, h);
luacon_sim->signs[id].pos(luacon_sim->signs[id].getText(luacon_sim), x, y, w, h);
lua_pushnumber(l, y); lua_pushnumber(l, y);
return 1; return 1;
} }
else if (!key.compare("width")) else if (!key.compare("width"))
{ {
int x, y, w, h; luacon_sim->signs[id].getDisplayText(luacon_sim, x, y, w, h);
luacon_sim->signs[id].pos(luacon_sim->signs[id].getText(luacon_sim), x, y, w, h);
lua_pushnumber(l, w); lua_pushnumber(l, w);
return 1; return 1;
} }
else if (!key.compare("height")) else if (!key.compare("height"))
{ {
int x, y, w, h; luacon_sim->signs[id].getDisplayText(luacon_sim, x, y, w, h);
luacon_sim->signs[id].pos(luacon_sim->signs[id].getText(luacon_sim), x, y, w, h);
lua_pushnumber(l, h); lua_pushnumber(l, h);
return 1; return 1;
} }

View File

@ -11,70 +11,23 @@ sign::sign(String text_, int x_, int y_, Justification justification_):
{ {
} }
void sign::pos(String signText, int & x0, int & y0, int & w, int & h) String sign::getDisplayText(Simulation *sim, int &x0, int &y0, int &w, int &h, bool colorize)
{
w = Graphics::textwidth(signText.c_str()) + 5;
h = 15;
x0 = (ju == Right) ? x - w :
(ju == Left) ? x : x - w/2;
y0 = (y > 18) ? y - 18 : y + 4;
}
int sign::splitsign(String str, String::value_type *type)
{
if (str[0] == '{' && (str[1] == 'c' || str[1] == 't' || str[1] == 'b' || str[1] == 's'))
{
size_t strIndex = 2;
// Signs with text arguments
if (str[1] == 's')
{
if (str[2] == ':')
{
strIndex = 3;
while (strIndex < str.length() && str[strIndex] != '|')
strIndex++;
}
else
return 0;
}
// Signs with number arguments
if (str[1] == 'c' || str[1] == 't')
{
if (str[2] == ':' && str[3] >= '0' && str[3] <= '9')
{
strIndex = 4;
while (str[strIndex] >= '0' && str[strIndex] <= '9')
strIndex++;
}
else
return 0;
}
if (str[strIndex] == '|')
{
if (str[str.length() - 1] == '}')
{
if (type)
*type = str[1];
return strIndex;
}
}
}
return 0;
}
String sign::getText(Simulation *sim)
{ {
String drawable_text;
auto si = std::make_pair(0, Type::Normal);
if (text.find('{') == text.npos) if (text.find('{') == text.npos)
{ {
return text; drawable_text = text;
} }
else
if (int pos = splitsign(text))
{ {
return text.Between(pos + 1, text.size() - 1); si = split();
if (si.first)
{
drawable_text = text.Between(si.first + 1, text.size() - 1);
} }
else
{
Particle const *part = nullptr; Particle const *part = nullptr;
float pressure = 0.0f; float pressure = 0.0f;
float aheat = 0.0f; float aheat = 0.0f;
@ -145,5 +98,66 @@ String sign::getText(Simulation *sim)
} }
} }
formatted_text << remaining_text; formatted_text << remaining_text;
return formatted_text.Build(); drawable_text = formatted_text.Build();
}
}
if (colorize)
{
switch (si.second)
{
case Normal: break;
case Save: drawable_text = "\bt" + drawable_text; break;
case Thread: drawable_text = "\bl" + drawable_text; break;
case Button: drawable_text = "\bo" + drawable_text; break;
case Search: drawable_text = "\bu" + drawable_text; break;
}
}
w = Graphics::textwidth(drawable_text.c_str()) + 5;
h = 15;
x0 = (ju == Right) ? x - w : (ju == Left) ? x : x - w/2;
y0 = (y > 18) ? y - 18 : y + 4;
return drawable_text;
}
std::pair<int, sign::Type> sign::split()
{
String::size_type pipe = 0;
if (text.size() >= 4 && text.front() == '{' && text.back() == '}')
{
switch (text[1])
{
case 'c':
case 't':
if (text[2] == ':' && (pipe = text.find('|', 4)) != text.npos)
{
for (String::size_type i = 3; i < pipe; ++i)
{
if (text[i] < '0' || text[i] > '9')
{
return std::make_pair(0, Type::Normal);
}
}
return std::make_pair(pipe, text[1] == 'c' ? Type::Save : Type::Thread);
}
break;
case 'b':
if (text[2] == '|')
{
return std::make_pair(2, Type::Button);
}
break;
case 's':
if (text[2] == ':' && (pipe = text.find('|', 3)) != text.npos)
{
return std::make_pair(pipe, Type::Search);
}
break;
}
}
return std::make_pair(0, Type::Normal);
} }

View File

@ -3,21 +3,36 @@
#include "common/String.h" #include "common/String.h"
#include <utility>
class Simulation; class Simulation;
class sign struct sign
{ {
public: enum Justification
enum Justification { Left = 0, Middle = 1, Right = 2, None = 3 }; {
sign(String text_, int x_, int y_, Justification justification_); Left = 0,
Middle = 1,
Right = 2,
None = 3
};
enum Type
{
Normal,
Save,
Thread,
Button,
Search
};
int x, y; int x, y;
Justification ju; Justification ju;
String text; String text;
String getText(Simulation *sim); sign(String text_, int x_, int y_, Justification justification_);
void pos(String signText, int & x0, int & y0, int & w, int & h); String getDisplayText(Simulation *sim, int &x, int &y, int &w, int &h, bool colorize = true);
std::pair<int, Type> split();
static int splitsign(String str, String::value_type *type = NULL);
}; };
#endif #endif