This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
The-Powder-Toy/src/gui/game/SignTool.cpp
Tamás Bálint Misius 9d92b77163
Clean up sign-related code a bit
Also draw search signs with purple text and thread signs with red.
2019-04-12 17:09:34 +02:00

299 lines
9.0 KiB
C++

#include <iostream>
#include "gui/Style.h"
#include "simulation/Simulation.h"
#include "Tool.h"
#include "gui/interface/Window.h"
#include "gui/interface/Button.h"
#include "gui/interface/Label.h"
#include "gui/interface/Textbox.h"
#include "gui/interface/DropDown.h"
#include "gui/game/GameModel.h"
class SignWindow: public ui::Window
{
public:
ui::DropDown * justification;
ui::Textbox * textField;
SignTool * tool;
sign * movingSign;
bool signMoving;
Simulation * sim;
int signID;
ui::Point signPosition;
SignWindow(SignTool * tool_, Simulation * sim_, int signID_, ui::Point position_);
void OnDraw() override;
void DoDraw() override;
void DoMouseMove(int x, int y, int dx, int dy) override;
void DoMouseDown(int x, int y, unsigned button) override;
void DoMouseUp(int x, int y, unsigned button) override
{
if(!signMoving)
ui::Window::DoMouseUp(x, y, button);
}
void DoMouseWheel(int x, int y, int d) override
{
if(!signMoving)
ui::Window::DoMouseWheel(x, y, d);
}
void DoKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override
{
if(!signMoving)
ui::Window::DoKeyPress(key, scan, repeat, shift, ctrl, alt);
}
void DoKeyRelease(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt) override
{
if(!signMoving)
ui::Window::DoKeyRelease(key, scan, repeat, shift, ctrl, alt);
}
virtual ~SignWindow() {}
void OnTryExit(ui::Window::ExitMethod method) override;
class OkayAction: public ui::ButtonAction
{
public:
SignWindow * prompt;
OkayAction(SignWindow * prompt_) { prompt = prompt_; }
void ActionCallback(ui::Button * sender) override
{
prompt->CloseActiveWindow();
if(prompt->signID==-1 && prompt->textField->GetText().length())
{
prompt->sim->signs.push_back(sign(prompt->textField->GetText(), prompt->signPosition.X, prompt->signPosition.Y, (sign::Justification)prompt->justification->GetOption().second));
}
else if(prompt->signID!=-1 && prompt->textField->GetText().length())
{
prompt->sim->signs[prompt->signID] = sign(sign(prompt->textField->GetText(), prompt->signPosition.X, prompt->signPosition.Y, (sign::Justification)prompt->justification->GetOption().second));
}
prompt->SelfDestruct();
}
};
class DeleteAction: public ui::ButtonAction
{
public:
SignWindow * prompt;
DeleteAction(SignWindow * prompt_) { prompt = prompt_; }
void ActionCallback(ui::Button * sender) override
{
prompt->CloseActiveWindow();
if(prompt->signID!=-1)
{
prompt->sim->signs.erase(prompt->sim->signs.begin()+prompt->signID);
}
prompt->SelfDestruct();
}
};
class SignTextAction: public ui::TextboxAction
{
public:
SignWindow * prompt;
SignTextAction(SignWindow * prompt_) { prompt = prompt_; }
void TextChangedCallback(ui::Textbox * sender) override
{
if(prompt->signID!=-1)
{
prompt->sim->signs[prompt->signID].text = sender->GetText();
prompt->sim->signs[prompt->signID].ju = (sign::Justification)prompt->justification->GetOption().second;
}
}
};
class MoveAction: public ui::ButtonAction
{
public:
SignWindow * prompt;
MoveAction(SignWindow * prompt_) { prompt = prompt_; }
void ActionCallback(ui::Button * sender) override
{
if(prompt->signID!=-1)
{
prompt->movingSign = &prompt->sim->signs[prompt->signID];
prompt->sim->signs[prompt->signID].ju = (sign::Justification)prompt->justification->GetOption().second;
prompt->signMoving = true;
}
}
};
};
SignWindow::SignWindow(SignTool * tool_, Simulation * sim_, int signID_, ui::Point position_):
ui::Window(ui::Point(-1, -1), ui::Point(250, 87)),
tool(tool_),
movingSign(NULL),
signMoving(false),
sim(sim_),
signID(signID_),
signPosition(position_)
{
ui::Label * messageLabel = new ui::Label(ui::Point(4, 5), ui::Point(Size.X-8, 15), "New sign");
messageLabel->SetTextColour(style::Colour::InformationTitle);
messageLabel->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
messageLabel->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(messageLabel);
ui::Button * okayButton = new ui::Button(ui::Point(0, Size.Y-16), ui::Point(Size.X, 16), "OK");
okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
okayButton->Appearance.BorderInactive = (ui::Colour(200, 200, 200));
okayButton->SetActionCallback(new OkayAction(this));
AddComponent(okayButton);
SetOkayButton(okayButton);
ui::Label * tempLabel = new ui::Label(ui::Point(8, 48), ui::Point(40, 15), "Pointer:");
okayButton->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
okayButton->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
AddComponent(tempLabel);
justification = new ui::DropDown(ui::Point(52, 48), ui::Point(50, 16));
AddComponent(justification);
justification->AddOption(std::pair<String, int>(0xE020 + String(" Left"), (int)sign::Left));
justification->AddOption(std::pair<String, int>(0xE01E + String(" Middle"), (int)sign::Middle));
justification->AddOption(std::pair<String, int>(0xE01F + String(" Right"), (int)sign::Right));
justification->AddOption(std::pair<String, int>(0xE01D + String(" None"), (int)sign::None));
justification->SetOption(1);
justification->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
textField = new ui::Textbox(ui::Point(8, 25), ui::Point(Size.X-16, 17), "", "[message]");
textField->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
textField->Appearance.VerticalAlign = ui::Appearance::AlignMiddle;
textField->SetLimit(45);
textField->SetActionCallback(new SignTextAction(this));
AddComponent(textField);
FocusComponent(textField);
if(signID!=-1)
{
messageLabel->SetText("Edit sign");
textField->SetText(sim->signs[signID].text);
justification->SetOption(sim->signs[signID].ju);
ui::Point position = ui::Point(justification->Position.X+justification->Size.X+3, 48);
ui::Button * moveButton = new ui::Button(position, ui::Point(((Size.X-position.X-8)/2)-2, 16), "Move");
moveButton->SetActionCallback(new MoveAction(this));
AddComponent(moveButton);
position = ui::Point(justification->Position.X+justification->Size.X+3, 48)+ui::Point(moveButton->Size.X+3, 0);
ui::Button * deleteButton = new ui::Button(position, ui::Point((Size.X-position.X-8)-1, 16), "Delete");
//deleteButton->SetIcon(IconDelete);
deleteButton->SetActionCallback(new DeleteAction(this));
signPosition.X = sim->signs[signID].x;
signPosition.Y = sim->signs[signID].y;
AddComponent(deleteButton);
}
MakeActiveWindow();
}
void SignWindow::OnTryExit(ui::Window::ExitMethod method)
{
CloseActiveWindow();
SelfDestruct();
}
void SignWindow::DoDraw()
{
for (auto &currentSign : sim->signs)
{
int x, y, w, h, dx, dy;
Graphics * g = GetGraphics();
String text = currentSign.getDisplayText(sim, x, y, w, h);
g->clearrect(x, y, w+1, h);
g->drawrect(x, y, w+1, h, 192, 192, 192, 255);
g->drawtext(x+3, y+3, text, 255, 255, 255, 255);
if (currentSign.ju != sign::None)
{
x = currentSign.x;
y = currentSign.y;
dx = 1 - currentSign.ju;
dy = (currentSign.y > 18) ? -1 : 1;
#ifdef OGLR
glBegin(GL_LINES);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glVertex2i(x, y);
glVertex2i(x+(dx*4), y+(dy*4));
glEnd();
#else
for (int j=0; j<4; j++)
{
g->blendpixel(x, y, 192, 192, 192, 255);
x+=dx;
y+=dy;
}
#endif
}
}
if(!signMoving)
{
ui::Window::DoDraw();
}
}
void SignWindow::DoMouseMove(int x, int y, int dx, int dy) {
if(!signMoving)
ui::Window::DoMouseMove(x, y, dx, dy);
else
{
ui::Point pos = tool->gameModel->AdjustZoomCoords(ui::Point(x, y));
if(pos.X < XRES && pos.Y < YRES)
{
movingSign->x = pos.X;
movingSign->y = pos.Y;
signPosition.X = pos.X;
signPosition.Y = pos.Y;
}
}
}
void SignWindow::DoMouseDown(int x, int y, unsigned button)
{
if(!signMoving)
ui::Window::DoMouseDown(x, y, button);
else
{
signMoving = false;
}
}
void SignWindow::OnDraw()
{
Graphics * g = GetGraphics();
g->clearrect(Position.X-2, Position.Y-2, Size.X+3, Size.Y+3);
g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 200, 200, 200, 255);
}
VideoBuffer * SignTool::GetIcon(int toolID, int width, int height)
{
VideoBuffer * newTexture = new VideoBuffer(width, height);
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
pixel pc = x==0||x==width-1||y==0||y==height-1 ? PIXPACK(0xA0A0A0) : PIXPACK(0x000000);
newTexture->SetPixel(x, y, PIXR(pc), PIXG(pc), PIXB(pc), 255);
}
}
newTexture->AddCharacter((width/2)-5, (height/2)-5, 0xE021, 32, 64, 128, 255);
newTexture->BlendCharacter((width/2)-5, (height/2)-5, 0xE020, 255, 255, 255, 255);
return newTexture;
}
void SignTool::Click(Simulation * sim, Brush * brush, ui::Point position)
{
int signX, signY, signW, signH, signIndex = -1;
for (size_t i = 0; i < sim->signs.size(); i++)
{
sim->signs[i].getDisplayText(sim, signX, signY, signW, signH);
if (position.X > signX && position.X < signX+signW && position.Y > signY && position.Y < signY+signH)
{
signIndex = i;
break;
}
}
if (signIndex != -1 || sim->signs.size() < MAXSIGNS)
new SignWindow(this, sim, signIndex, position);
}