#include <sstream>
#include <vector>
+#include "Clock.h"
#include "Game.h"
+#include "Timer.h"
#include "../gfx/ColorRGB.h"
#include "../pango/Layout.h"
, w(w), h(h), x(0), y(0)
, step_size(1)
, color_intensity(9)
+ , brush{ 0, 0, 0 }
, pos{ 760, 100 }
, font_color{ 1, 1, 1 }
, cursor_font("DejaVu Sans 16px")
, cursor_layout(ctx.CreateLayout())
- , text_dirty(true) {
+ , text_dirty(true)
+ , draw_timer(150) {
+ cursor_layout.SetFont(cursor_font);
cells.resize(w * h, base_color);
}
public:
+ virtual void Handle(const twitch::IRCMessage &msg) {
+ std::string text = msg.GetText();
+ if (!text.empty()) {
+ QueueCommands(text);
+ }
+ }
+
virtual void Update(cairo::Context &ctx, const Clock &now) {
- if (!command_queue.empty()) {
+ int amount = draw_timer.ActivationsBetween(last_update, now);
+ while (amount > 0 && !command_queue.empty()) {
const char c = command_queue.back();
command_queue.pop_back();
if (!command_queue.empty()) {
} else {
InterpretCharacter(c);
}
+ --amount;
}
if (text_dirty) {
UpdateText(ctx);
}
+ last_update = now;
}
virtual void Render(cairo::Context &ctx) const {
ctx.DrawLayout(cursor_layout);
gfx::Rectangle r{ 0, 0, 10, 10 };
+ r.x = pos.x + (w - 1) * r.w;
+ r.y = pos.y + 30 - 2 * r.h;
+ ctx.SetSourceColor(brush);
+ ctx.Rectangle(r);
+ ctx.Fill();
+ ctx.SetSourceColor({ 0.5, 0.5, 0.5 });
+ ctx.SetLineWidth(1);
+ ctx.Rectangle(r);
+ ctx.Stroke();
+
for (int cy = 0; cy < h; ++cy) {
for (int cx = 0; cx < w; ++cx) {
r.x = pos.x + cx * r.w;
case '5': case '6': case '7': case '8': case '9':
if (IsMovementCharacter(next)) {
SetStepSize(c - '0');
- } else {
+ } else if (IsColorCharacter(next)) {
SetColorIntensity(c - '0');
}
break;
- case 'u': case 'U':
- case 'n': case 'N':
+ case 'w': case 'W':
+ case 'i': case 'I':
MoveUp();
break;
- case 'd': case 'D':
case 's': case 'S':
+ case 'k': case 'K':
MoveDown();
break;
- case 'l': case 'L':
- case 'w': case 'W':
+ case 'a': case 'A':
+ case 'j': case 'J':
MoveLeft();
break;
- case 'r': case 'R':
- case 'e': case 'E':
+ case 'd': case 'D':
+ case 'l': case 'L':
MoveRight();
break;
- case 'a': case 'A':
+ case 'r': case 'R':
SetRed();
break;
- case 'b': case 'B':
+ case 'g': case 'G':
SetGreen();
break;
- case 'c': case 'C':
+ case 'b': case 'B':
SetBlue();
break;
- case 'f': case 'F':
- ClearRed();
- break;
- case 'g': case 'G':
- ClearGreen();
- break;
- case 'h': case 'H':
- ClearBlue();
- break;
- case 'i': case 'I':
- SetYellow();
- break;
- case 'j': case 'J':
+ case 'c': case 'C':
SetCyan();
break;
- case 'k': case 'K':
- SetMagenta();
- break;
case 'm': case 'M':
- ClearYellow();
- break;
- case 'o': case 'O':
- ClearCyan();
+ SetMagenta();
break;
- case 'p': case 'P':
- ClearMagenta();
+ case 'y': case 'Y':
+ SetYellow();
break;
case 'q': case 'Q':
- InvertRed();
+ Pick();
break;
+ case 'e': case 'E':
+ case 'f': case 'F':
+ case 'h': case 'H':
+ case 'n': case 'N':
+ case 'o': case 'O':
+ case 'p': case 'P':
case 't': case 'T':
- InvertGreen();
- break;
+ case 'u': case 'U':
case 'v': case 'V':
- InvertBlue();
+ Paste();
break;
case 'x': case 'X':
- InvertColor();
- break;
- case 'y': case 'Y':
- SetColor({ 1, 1, 1 });
- break;
case 'z': case 'Z':
- SetColor({ 0, 0, 0 });
+ InvertColor();
break;
default:
break;
}
}
+ bool IsColorCharacter(char c) const {
+ switch (c) {
+ case 'r': case 'R':
+ case 'g': case 'G':
+ case 'b': case 'B':
+ case 'c': case 'C':
+ case 'm': case 'M':
+ case 'y': case 'Y':
+ return true;
+ }
+ return false;
+ }
+
bool IsMovementCharacter(char c) const {
switch (c) {
- case 'u': case 'U':
- case 'n': case 'N':
- case 'd': case 'D':
+ case 'w': case 'W':
+ case 'a': case 'A':
case 's': case 'S':
+ case 'd': case 'D':
+ case 'i': case 'I':
+ case 'j': case 'J':
+ case 'k': case 'K':
case 'l': case 'L':
- case 'w': case 'W':
- case 'r': case 'R':
- case 'e': case 'E':
return true;
}
return false;
}
void SetRed() {
- cells[y * w + x].r = double(color_intensity) / 9.0;
+ brush.r = double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
void SetGreen() {
- cells[y * w + x].g = double(color_intensity) / 9.0;
+ brush.g = double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
void SetBlue() {
- cells[y * w + x].b = double(color_intensity) / 9.0;
- }
-
- void ClearRed() {
- cells[y * w + x].r = 0;
- }
-
- void ClearGreen() {
- cells[y * w + x].g = 0;
- }
-
- void ClearBlue() {
- cells[y * w + x].b = 0;
- }
-
- void SetYellow() {
- cells[y * w + x].r = double(color_intensity) / 9.0;
- cells[y * w + x].g = double(color_intensity) / 9.0;
+ brush.b = double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
void SetCyan() {
- cells[y * w + x].g = double(color_intensity) / 9.0;
- cells[y * w + x].b = double(color_intensity) / 9.0;
+ brush.r = 1.0 - double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
void SetMagenta() {
- cells[y * w + x].r = double(color_intensity) / 9.0;
- cells[y * w + x].b = double(color_intensity) / 9.0;
- }
-
- void ClearYellow() {
- cells[y * w + x].r = 0;
- cells[y * w + x].g = 0;
- }
-
- void ClearCyan() {
- cells[y * w + x].g = 0;
- cells[y * w + x].b = 0;
+ brush.g = 1.0 - double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
- void ClearMagenta() {
- cells[y * w + x].r = 0;
- cells[y * w + x].b = 0;
- }
-
- void InvertRed() {
- cells[y * w + x].r = 1.0 - cells[y * w + x].r;
+ void SetYellow() {
+ brush.b = 1.0 - double(color_intensity) / 9.0;
+ SetColorIntensity(9);
}
- void InvertGreen() {
- cells[y * w + x].g = 1.0 - cells[y * w + x].g;
+ void Pick() {
+ brush = CurrentCell();
}
- void InvertBlue() {
- cells[y * w + x].b = 1.0 - cells[y * w + x].b;
+ void Paste() {
+ CurrentCell() = brush;
}
void InvertColor() {
- cells[y * w + x].r = 1.0 - cells[y * w + x].r;
- cells[y * w + x].g = 1.0 - cells[y * w + x].g;
- cells[y * w + x].b = 1.0 - cells[y * w + x].b;
+ brush.r = 1.0 - brush.r;
+ brush.g = 1.0 - brush.g;
+ brush.b = 1.0 - brush.b;
}
void SetColorIntensity(int m) {
- int new_intensity = std::max(0, std::min(9, m));
- text_dirty = new_intensity != color_intensity;
- color_intensity = new_intensity;
+ color_intensity = std::max(0, std::min(9, m));
}
void SetStepSize(int m) {
- int new_size = std::max(0, std::min(9, m));
- text_dirty = new_size != step_size;
- step_size = new_size;
+ step_size = std::max(0, std::min(9, m));
+ }
+
+ gfx::ColorRGB &CurrentCell() {
+ return cells[y * w + x];
}
private:
void UpdateText(cairo::Context &ctx) {
if (!text_dirty) return;
std::stringstream out;
- out << "Cursor: " << x << ", " << y;
- out << " Schrittgröße: " << step_size;
- out << " Deckkraft: " << color_intensity;
+ out << "Cursor: " << (x + 1) << ", " << (y + 1);
cursor_layout.SetText(out.str());
ctx.UpdateLayout(cursor_layout);
text_dirty = false;
int w, h, x, y;
int step_size;
int color_intensity;
+ gfx::ColorRGB brush;
std::string command_queue;
pango::Layout cursor_layout;
bool text_dirty;
+ Clock last_update;
+ Timer draw_timer;
+
};
}