Skip to content

Commit 76348d9

Browse files
committed
copy color as tmp tag, css rgb, hsl
1 parent d4e689d commit 76348d9

8 files changed

Lines changed: 141 additions & 64 deletions

File tree

freesprite/FileIO.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2436,7 +2436,7 @@ void g_setupIO() {
24362436
;
24372437

24382438
io_registerVSP();
2439-
g_fileExporters.push_back(exORA = FileExporter::sessionExporter("OpenRaster", ".ora", "", &writeOpenRaster));
2439+
g_fileExporters.push_back(exORA = FileExporter::sessionExporter("OpenRaster", ".ora", TL("vsp.export.ora"), &writeOpenRaster));
24402440
g_fileExporters.push_back(exPixelStudioPSP = FileExporter::sessionExporter("Pixel Studio PSP", ".psp", "", &writePixelStudioPSP));
24412441
g_fileExporters.push_back(exPixelStudioPSX = FileExporter::sessionExporter("Pixel Studio (compressed) PSX", ".psx", "", &writePixelStudioPSX));
24422442
g_fileExporters.push_back(exLPE = FileExporter::sessionExporter("Lospec Pixel Editor", ".lpe", "", &writeLPE));

freesprite/UIColorPicker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ UIColorPicker::UIColorPicker()
270270

271271
//widgets outside of tabs
272272

273-
colorTextField = new UITextField();
274-
colorTextField->isColorField = true;
273+
colorTextField = new UIColorTextField();
274+
colorTextField->linkedToColorPicker = this;
275275
colorTextField->position = XY{ 60, 350 };
276276
colorTextField->wxWidth = 140;
277277
colorTextField->tooltip = TL("vsp.maineditor.panel.colorpicker.colorinput.tooltip");

freesprite/UIColorPicker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class UIColorPicker : public Panel, public EventCallbackListener
5656
UIHueWheel* hueWheel = NULL;
5757
UIHueSlider* hueSlider = NULL;
5858
UISVPicker* satValSlider = NULL;
59-
UITextField* colorTextField = NULL;
59+
UIColorTextField* colorTextField = NULL;
6060

6161
//todo: change these sliders to work based off the color models system
6262
UINumberInputField* txtR = NULL, *txtG = NULL, *txtB = NULL;

freesprite/UITextField.cpp

Lines changed: 106 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "TooltipsLayer.h"
55
#include "Notification.h"
66
#include "PopupContextMenu.h"
7+
#include "UIColorPicker.h"
78
#include "multiwindow.h"
89

910
void UITextField::render(XY pos)
@@ -203,6 +204,25 @@ bool UITextField::inputChar(char c) {
203204
return false;
204205
}
205206

207+
void UITextField::renderTextFieldText(XY at)
208+
{
209+
XY textEP = g_fnt->RenderString(text + ((focused && numericFieldCurrentOperation == '\0') ? "_" : ""),
210+
at.x + 2, at.y + 2,
211+
SDL_Color{ textColor.r,textColor.g,textColor.b,(u8)(focused ? 0xff : 0xa0) }, fontsize);
212+
213+
if (numericFieldCurrentOperation != '\0') {
214+
textEP.x += 10;
215+
double separatorAnimTimer = XM1PW3P1(numericFieldOperationTimer.percentElapsedTime(400));
216+
SDL_SetRenderDrawColor(g_rd, 255, 255, 255, 255);
217+
drawLine({ textEP.x + 2, at.y }, { textEP.x + 2, at.y + wxHeight }, separatorAnimTimer);
218+
219+
textEP.x += 10;
220+
221+
textEP = g_fnt->RenderString(frmt("{} ", numericFieldCurrentOperation), textEP.x, textEP.y);
222+
g_fnt->RenderString(frmt("{}_", numericFieldOperationBuffer), textEP.x, textEP.y, { 255,255,255,0xa0 });
223+
}
224+
}
225+
206226
void UITextField::renderTextField(XY at)
207227
{
208228
SDL_Rect drawrect = { at.x, at.y, wxWidth, wxHeight };
@@ -253,46 +273,7 @@ void UITextField::renderTextField(XY at)
253273
}
254274
#endif
255275

256-
if (!isColorField || !isValidOrPartialColor() || text.empty()) {
257-
XY textEP = g_fnt->RenderString(text + ((focused && numericFieldCurrentOperation == '\0') ? "_" : ""), at.x + 2, at.y + 2, SDL_Color{ textColor.r,textColor.g,textColor.b,(unsigned char)(focused ? 0xff : 0xa0) }, fontsize);
258-
259-
if (numericFieldCurrentOperation != '\0') {
260-
textEP.x += 10;
261-
double separatorAnimTimer = XM1PW3P1(numericFieldOperationTimer.percentElapsedTime(400));
262-
SDL_SetRenderDrawColor(g_rd, 255,255,255,255);
263-
drawLine({textEP.x+2, at.y}, {textEP.x+2, at.y+wxHeight}, separatorAnimTimer);
264-
265-
textEP.x += 10;
266-
267-
textEP = g_fnt->RenderString(frmt("{} ", numericFieldCurrentOperation), textEP.x, textEP.y);
268-
g_fnt->RenderString(frmt("{}_", numericFieldOperationBuffer), textEP.x, textEP.y, {255,255,255,0xa0});
269-
}
270-
}
271-
else {
272-
int textPtr = 0;
273-
XY origin = xyAdd(at, { 2,2 });
274-
if (text[0] == '#') {
275-
origin = g_fnt->RenderString("#", origin.x, origin.y, SDL_Color{ 0x80,0x80,0x80,255 });
276-
textPtr++;
277-
}
278-
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 255,0x32,0x32,255 }, fontsize);
279-
textPtr += 2;
280-
if (textPtr < text.size()) {
281-
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 0x50,255,0x50,255 }, fontsize);
282-
textPtr += 2;
283-
}
284-
if (textPtr < text.size()) {
285-
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 0x18,0x9A,255,255 }, fontsize);
286-
textPtr += 2;
287-
}
288-
if (textPtr < text.size()) {
289-
origin = g_fnt->RenderString(text.substr(textPtr), origin.x, origin.y, {255,255,255,255}, fontsize);
290-
}
291-
if (focused) {
292-
g_fnt->RenderString("_", origin.x, origin.y, {255,255,255,255}, fontsize);
293-
294-
}
295-
}
276+
renderTextFieldText(at);
296277
}
297278

298279
void UITextField::renderOnScreenTextField()
@@ -312,25 +293,9 @@ void UITextField::renderOnScreenTextField()
312293
//g_popClip();
313294
}
314295

315-
bool UITextField::isValidOrPartialColor()
316-
{
317-
for (int x = 0; x < text.size(); x++) {
318-
char c = tolower(text[x]);
319-
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c == '#' && x == 0))) {
320-
return false;
321-
}
322-
}
323-
return true;
324-
}
325-
326296
void UITextField::copyToClipboard()
327297
{
328-
if (SDL_SetClipboardText(text.c_str())) {
329-
g_addNotification(SuccessShortNotification(TL("vsp.cmn.copiedtoclipboard"), ""));
330-
}
331-
else {
332-
g_addNotification(ErrorNotification(TL("vsp.cmn.error.clipboardcopy"), ""));
333-
}
298+
g_copyStringToClipboard(text);
334299
}
335300

336301
void UITextField::pasteFromClipboard()
@@ -354,6 +319,90 @@ void UITextField::pasteFromClipboard()
354319
}
355320
}
356321

322+
bool UIColorTextField::isValidOrPartialColor()
323+
{
324+
for (int x = 0; x < text.size(); x++) {
325+
char c = tolower(text[x]);
326+
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c == '#' && x == 0))) {
327+
return false;
328+
}
329+
}
330+
return true;
331+
}
332+
333+
void UIColorTextField::copyUnityTMP()
334+
{
335+
if (linkedToColorPicker != NULL) {
336+
u32 col = linkedToColorPicker->colorNowU32 & 0xFFFFFF;
337+
g_copyStringToClipboard(frmt("<#{:06X}>", col));
338+
}
339+
}
340+
341+
void UIColorTextField::copyCSSRGB()
342+
{
343+
if (linkedToColorPicker != NULL) {
344+
SDL_Color col = uint32ToSDLColor(linkedToColorPicker->colorNowU32);
345+
g_copyStringToClipboard(frmt("rgb({} {} {})", col.r, col.g, col.b));
346+
}
347+
}
348+
349+
void UIColorTextField::copyCSSHSL()
350+
{
351+
if (linkedToColorPicker != NULL) {
352+
auto hsl = g_colorModels["HSL"]->fromRGB(linkedToColorPicker->colorNowU32);
353+
g_copyStringToClipboard(frmt("hsl({:.1f} {:.1f}% {:.1f}%)", hsl["H"], hsl["S"]*100, hsl["L"]*100));
354+
}
355+
}
356+
357+
void UIColorTextField::renderTextFieldText(XY at)
358+
{
359+
if (!isValidOrPartialColor() || text.empty()) {
360+
UITextField::renderTextFieldText(at);
361+
}
362+
else {
363+
int textPtr = 0;
364+
XY origin = xyAdd(at, { 2,2 });
365+
if (text[0] == '#') {
366+
origin = g_fnt->RenderString("#", origin.x, origin.y, SDL_Color{ 0x80,0x80,0x80,255 });
367+
textPtr++;
368+
}
369+
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 255,0x32,0x32,255 }, fontsize);
370+
textPtr += 2;
371+
if (textPtr < text.size()) {
372+
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 0x50,255,0x50,255 }, fontsize);
373+
textPtr += 2;
374+
}
375+
if (textPtr < text.size()) {
376+
origin = g_fnt->RenderString(text.substr(textPtr, ixmin(2, text.size() - textPtr)), origin.x, origin.y, SDL_Color{ 0x18,0x9A,255,255 }, fontsize);
377+
textPtr += 2;
378+
}
379+
if (textPtr < text.size()) {
380+
origin = g_fnt->RenderString(text.substr(textPtr), origin.x, origin.y, { 255,255,255,255 }, fontsize);
381+
}
382+
if (focused) {
383+
g_fnt->RenderString("_", origin.x, origin.y, { 255,255,255,255 }, fontsize);
384+
385+
}
386+
}
387+
}
388+
389+
void UIColorTextField::openActionsMenu()
390+
{
391+
if (linkedToColorPicker == NULL) {
392+
UITextField::openActionsMenu();
393+
}
394+
else {
395+
g_openContextMenu({
396+
{ TL("vsp.cmn.copy"), [this]() { copyToClipboard(); } },
397+
{ "Copy as TextMeshPro tag", [this]() { copyUnityTMP(); }},
398+
{ "Copy as CSS rgb()", [this]() { copyCSSRGB(); }},
399+
{ "Copy as CSS hsl()", [this]() { copyCSSHSL(); }},
400+
{ TL("vsp.cmn.paste"), [this]() { pasteFromClipboard(); } },
401+
{ TL("vsp.cmn.erase"), [this]() { clearText(); } },
402+
});
403+
}
404+
}
405+
357406
void UITextField::runNumericOperation() {
358407
if (isNumericField && numericFieldCurrentOperation != '\0') {
359408
try {

freesprite/UITextField.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class UITextField : public Drawable
1212
int fontsize = 18;
1313
std::string tooltip = "";
1414
std::string placeholderText = "";
15-
bool isColorField = false;
1615
int insertPosition = 0;
1716
int wxWidth = 250, wxHeight = 30;
1817
Fill bgFill = Fill::Solid(0xFF000000);
@@ -71,6 +70,7 @@ class UITextField : public Drawable
7170
bool focusableWithTab() override { return true; }
7271
XY getDimensions() override { return { wxWidth, wxHeight }; }
7372

73+
virtual void renderTextFieldText(XY at);
7474
void renderTextField(XY at);
7575
void renderOnScreenTextField();
7676

@@ -89,7 +89,6 @@ class UITextField : public Drawable
8989
}
9090
void removeLastUTF8Char();
9191
bool inputChar(char c);
92-
bool isValidOrPartialColor();
9392
void copyToClipboard();
9493
void pasteFromClipboard();
9594
void clearText();
@@ -98,6 +97,20 @@ class UITextField : public Drawable
9897
void runNumericOperation();
9998
};
10099

100+
class UIColorTextField : public UITextField {
101+
public:
102+
UIColorPicker* linkedToColorPicker = NULL;
103+
104+
void renderTextFieldText(XY at) override;
105+
void openActionsMenu() override;
106+
107+
bool isValidOrPartialColor();
108+
109+
void copyUnityTMP();
110+
void copyCSSRGB();
111+
void copyCSSHSL();
112+
};
113+
101114
class UINumberInputField : public UITextField
102115
{
103116
protected:

freesprite/globals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ class UILabel;
251251
class UISlider;
252252
class UIColorSlider;
253253
class UITextField;
254+
class UIColorTextField;
254255
class UINumberInputField;
255256
class UICheckbox;
256257
class UIDropdown;
@@ -364,6 +365,7 @@ void g_pushRenderTarget(SDL_Texture* tex);
364365
void g_popRenderTarget();
365366

366367
void g_reloadFonts();
368+
void g_copyStringToClipboard(std::string text);
367369

368370
SDL_Texture* IMGLoadToTexture(std::string path);
369371
SDL_Surface* IMGLoadAssetToSurface(std::string path, SDL_Renderer* rd = NULL);

freesprite/localization/localization_english.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@
5858
{"vsp.export.html", "Export the image as a PNG encoded into Base64 for an inline <img> tag for HTML."},
5959
{"vsp.export.pgm", "Simple, easily adaptable format for grayscale images.\n"
6060
"In RGB mode, pixels will be converted to grayscale.\n"
61-
"In indexed mode, raw palette indexes will be written."},
61+
"In indexed mode, raw palette indexes will be written."},
62+
{"vsp.export.avif", "Modern image format that uses AV1 video compression.\n"
63+
"Compatible with most modern browsers. Supports transparency and animation."},
64+
{"vsp.export.ora", "Universal project format for graphics editors.\n"
65+
"Saves the full layer stack and can be loaded by programs such as GIMP or Krita."},
6266

6367
{"vsp.export.palette.voidplt", "Native palette format of voidsprite."},
6468
{"vsp.export.palette.hex", "Text file with colors in hex (RRGGBB) format, separated by newlines."},

freesprite/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ void g_reloadFonts() {
120120
currentWd->thisWindowsTurn();
121121
}
122122

123+
void g_copyStringToClipboard(std::string text) {
124+
if (SDL_SetClipboardText(text.c_str())) {
125+
g_addNotification(SuccessShortNotification(TL("vsp.cmn.copiedtoclipboard"), ""));
126+
}
127+
else {
128+
g_addNotification(ErrorNotification(TL("vsp.cmn.error.clipboardcopy"), ""));
129+
}
130+
}
131+
123132
std::vector<SDL_Rect> clips;
124133
void g_pushClip(SDL_Rect r) {
125134
if (!clips.empty()

0 commit comments

Comments
 (0)