Make font editor more convenient
This commit is contained in:
parent
dd93bbdeb3
commit
6607b7e845
@ -873,7 +873,7 @@ int main(int argc, char * argv[])
|
||||
|
||||
#else // FONTEDITOR
|
||||
if(argc <= 1)
|
||||
throw std::runtime_error("Not enough arguments");
|
||||
throw std::runtime_error("Usage: " + ByteString(argv[0]) + " ./data/font.cpp");
|
||||
engine->ShowWindow(new FontEditor(argv[1]));
|
||||
#endif
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "gui/interface/Button.h"
|
||||
#include "gui/interface/Mouse.h"
|
||||
#include "gui/interface/Keys.h"
|
||||
#include "gui/interface/ScrollPanel.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
#ifdef FONTEDITOR
|
||||
@ -254,6 +255,26 @@ void FontEditor::PackData(
|
||||
fontRanges.push_back({0, 0});
|
||||
}
|
||||
|
||||
class StretchLabel: public ui::Label
|
||||
{
|
||||
using Label::Label;
|
||||
public:
|
||||
int WrappedLines() const
|
||||
{
|
||||
return displayTextWrapper.WrappedLines();
|
||||
}
|
||||
};
|
||||
|
||||
class StretchTextbox: public ui::Textbox
|
||||
{
|
||||
using Textbox::Textbox;
|
||||
public:
|
||||
int WrappedLines() const
|
||||
{
|
||||
return displayTextWrapper.WrappedLines();
|
||||
}
|
||||
};
|
||||
|
||||
#define FONT_SCALE 16
|
||||
FontEditor::FontEditor(ByteString _header):
|
||||
ui::Window(ui::Point(0, 0), ui::Point(WINDOWW, WINDOWH)),
|
||||
@ -339,8 +360,8 @@ FontEditor::FontEditor(ByteString _header):
|
||||
currentX += 33;
|
||||
showRulers->SetTogglable(true);
|
||||
showRulers->SetToggleState(rulers);
|
||||
showRulers->SetActionCallback({ [this, showGrid] {
|
||||
rulers = showGrid->GetToggleState();
|
||||
showRulers->SetActionCallback({ [this, showRulers] {
|
||||
rulers = showRulers->GetToggleState();
|
||||
} });
|
||||
AddComponent(showRulers);
|
||||
|
||||
@ -375,29 +396,41 @@ FontEditor::FontEditor(ByteString _header):
|
||||
|
||||
baseline += 18;
|
||||
|
||||
outputPreview = new ui::Label(ui::Point(0, baseline + (Size.Y - baseline) * 3 / 5), ui::Point(Size.X, (Size.Y - baseline) * 2 / 5), "");
|
||||
ui::ScrollPanel *outputPanel = new ui::ScrollPanel(ui::Point(Size.X / 2, baseline), ui::Point(Size.X / 2, Size.Y - baseline));
|
||||
AddComponent(outputPanel);
|
||||
StretchLabel *outputPreview = new StretchLabel(ui::Point(0, 0), ui::Point(Size.X / 2, 0), "");
|
||||
outputPreview->SetMultiline(true);
|
||||
outputPreview->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
outputPreview->Appearance.VerticalAlign = ui::Appearance::AlignTop;
|
||||
AddComponent(outputPreview);
|
||||
outputPanel->AddChild(outputPreview);
|
||||
|
||||
ui::Textbox *inputPreview = new ui::Textbox(ui::Point(0, baseline), ui::Point(Size.X, (Size.Y - baseline) * 3 / 5));
|
||||
ui::ScrollPanel *inputPanel = new ui::ScrollPanel(ui::Point(0, baseline), ui::Point(Size.X / 2, Size.Y - baseline));
|
||||
AddComponent(inputPanel);
|
||||
StretchTextbox *inputPreview = new StretchTextbox(ui::Point(0, 0), ui::Point(Size.X / 2, 0));
|
||||
inputPreview->SetMultiline(true);
|
||||
inputPreview->SetInputType(ui::Textbox::Multiline);
|
||||
inputPreview->Appearance.HorizontalAlign = ui::Appearance::AlignLeft;
|
||||
inputPreview->Appearance.VerticalAlign = ui::Appearance::AlignTop;
|
||||
auto textChangedCallback = [this, inputPreview] {
|
||||
auto textChangedCallback = [outputPreview, outputPanel, inputPreview, inputPanel] {
|
||||
String str = inputPreview->GetText();
|
||||
size_t at = 0;
|
||||
StringBuilder text;
|
||||
while(at < str.size())
|
||||
{
|
||||
unsigned int ch;
|
||||
unsigned int ch1, ch2;
|
||||
if(str[at] != ' ')
|
||||
if(String::Split split = str.SplitNumber(ch, Format::Hex(), at))
|
||||
if(String::Split split1 = str.SplitNumber(ch1, Format::Hex(), at))
|
||||
{
|
||||
text << String::value_type(ch);
|
||||
at = split.PositionAfter();
|
||||
if(str[split1.PositionAfter()] == ':')
|
||||
if(String::Split split2 = str.SplitNumber(ch2, Format::Hex(), split1.PositionAfter() + 1))
|
||||
{
|
||||
for(unsigned int ch = ch1; ch <= ch2; ch++)
|
||||
text << String::value_type(ch);
|
||||
at = split2.PositionAfter();
|
||||
continue;
|
||||
}
|
||||
text << String::value_type(ch1);
|
||||
at = split1.PositionAfter();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -407,16 +440,21 @@ FontEditor::FontEditor(ByteString _header):
|
||||
at++;
|
||||
}
|
||||
outputPreview->SetText(text.Build());
|
||||
outputPanel->InnerSize.Y = outputPreview->Size.Y = std::max(outputPreview->WrappedLines(), 1) * FONT_H + 2;
|
||||
inputPanel->InnerSize.Y = inputPreview->Size.Y = std::max(inputPreview->WrappedLines(), 1) * FONT_H + 2;
|
||||
};
|
||||
inputPreview->SetActionCallback({ textChangedCallback });
|
||||
inputPanel->AddChild(inputPreview);
|
||||
|
||||
StringBuilder input;
|
||||
input << Format::Hex() << Format::Width(2);
|
||||
for(unsigned int ch = 0x20; ch <= 0xFF; ch++)
|
||||
for(unsigned int ch = 0x20; ch <= 0xFF; ch += 0x10)
|
||||
{
|
||||
if(!(ch & 0x3F))
|
||||
input << 0x20 << " ";
|
||||
input << ch << " ";
|
||||
if(ch == 0x80)
|
||||
input << "\n";
|
||||
else if(ch != 0x20)
|
||||
input << " 0a ";
|
||||
input << ch << ":" << (ch + 0x0F);
|
||||
}
|
||||
inputPreview->SetText(input.Build());
|
||||
textChangedCallback();
|
||||
@ -478,16 +516,43 @@ void FontEditor::OnMouseDown(int x, int y, unsigned button)
|
||||
}
|
||||
}
|
||||
|
||||
void FontEditor::Translate(std::array<std::array<char, MAX_WIDTH>, FONT_H> &pixels, int dx, int dy)
|
||||
{
|
||||
std::array<std::array<char, MAX_WIDTH>, FONT_H> old = pixels;
|
||||
for(int j = 0; j < FONT_H; j++)
|
||||
for(int i = 0; i < MAX_WIDTH; i++)
|
||||
if(i - dx >= 0 && i - dx + 1 < MAX_WIDTH && j - dy >= 0 && j - dy + 1 < FONT_H)
|
||||
pixels[j][i] = old[j - dy][i - dx];
|
||||
else
|
||||
pixels[j][i] = 0;
|
||||
}
|
||||
|
||||
void FontEditor::OnKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
||||
{
|
||||
if (IsFocused(NULL))
|
||||
{
|
||||
switch(scan)
|
||||
{
|
||||
case SDL_SCANCODE_UP:
|
||||
if(shift)
|
||||
Translate(fontPixels[currentChar], 0, -1);
|
||||
break;
|
||||
case SDL_SCANCODE_DOWN:
|
||||
if(shift)
|
||||
Translate(fontPixels[currentChar], 0, 1);
|
||||
break;
|
||||
case SDL_SCANCODE_LEFT:
|
||||
PrevChar(); break;
|
||||
if(shift)
|
||||
Translate(fontPixels[currentChar], -1, 0);
|
||||
else
|
||||
PrevChar();
|
||||
break;
|
||||
case SDL_SCANCODE_RIGHT:
|
||||
PrevChar(); break;
|
||||
if(shift)
|
||||
Translate(fontPixels[currentChar], 1, 0);
|
||||
else
|
||||
NextChar();
|
||||
break;
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
case SDL_SCANCODE_Q:
|
||||
if(savedButton->GetToggleState())
|
||||
|
@ -50,7 +50,6 @@ private:
|
||||
|
||||
ui::Textbox *currentCharTextbox;
|
||||
ui::Button *savedButton;
|
||||
ui::Label *outputPreview;
|
||||
|
||||
String::value_type currentChar;
|
||||
int fgR, fgG, fgB;
|
||||
@ -69,6 +68,7 @@ private:
|
||||
void GrowChar();
|
||||
void Render();
|
||||
void Save();
|
||||
void Translate(std::array<std::array<char, MAX_WIDTH>, FONT_H> &, int dx, int dy);
|
||||
|
||||
public:
|
||||
FontEditor(ByteString header);
|
||||
|
@ -41,6 +41,11 @@ namespace ui
|
||||
return wrapped_text;
|
||||
}
|
||||
|
||||
int WrappedLines() const
|
||||
{
|
||||
return wrapped_lines;
|
||||
}
|
||||
|
||||
Index IndexBegin() const
|
||||
{
|
||||
return Index{ 0, 0, 0 };
|
||||
|
Loading…
Reference in New Issue
Block a user