This commit is contained in:
Andrew Golovashevich 2024-12-25 04:11:31 +03:00
parent 0c144f992b
commit 7325fb5c63
11 changed files with 0 additions and 847 deletions

View File

@ -16,25 +16,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
endif () endif ()
endif () endif ()
add_executable(
cg1
WIN32
src/main.cpp
src/frame.hpp
src/drawing_assets.hpp
src/drawing_assets.cpp
src/painter.cpp
src/painter.hpp
src/old_main.cpp
src/ui.hpp
src/ui.cpp
)
qt5_use_modules(cg1 Widgets)
add_subdirectory(renderer-api) add_subdirectory(renderer-api)
add_subdirectory(utilities) add_subdirectory(utilities)
add_subdirectory(qt-utilities) add_subdirectory(qt-utilities)

View File

@ -1,139 +0,0 @@
#include <varargs.h>
#include "frame.hpp"
#include "drawing_assets.hpp"
void draw_circle(Frame *frame, int cx, int cy, int radius, COLOR outline) {
int x = 0, y = radius;
while (x < y) {
int D1 = x * x + y * y - radius * radius;
int D2 = x * x + (y - 1) * (y - 1) - radius * radius;
if (D1 > -D2)
y--;
frame->set_pixel(cx + x, cy + y, outline);
frame->set_pixel(cx + x, cy - y, outline);
frame->set_pixel(cx + y, cy + x, outline);
frame->set_pixel(cx + y, cy - x, outline);
frame->set_pixel(cx - x, cy + y, outline);
frame->set_pixel(cx - x, cy - y, outline);
frame->set_pixel(cx - y, cy + x, outline);
frame->set_pixel(cx - y, cy - x, outline);
x++;
}
}
void draw_line(Frame *frame, int x1, int y1, int x2, int y2, COLOR color) {
int dy = y2 - y1, dx = x2 - x1;
if (dx == 0 && dy == 0) {
frame->set_pixel(x1, y1, color);
return;
}
if (abs(dx) > abs(dy)) {
if (x2 < x1) {
std::swap(x1, x2);
std::swap(y1, y2);
dx = -dx;
dy = -dy;
}
int y, dx2 = dx / 2, p = 0;
if (dy < 0) dx2 = -dx2;
for (int x = x1; x <= x2; x++) {
y = (p + dx2) / dx + y1;
p += dy;
frame->set_pixel(x, y, color);
}
} else {
if (y2 < y1) {
std::swap(x1, x2);
std::swap(y1, y2);
dx = -dx;
dy = -dy;
}
int x, dy2 = dy / 2, p = 0;
if (dx < 0) dy2 = -dy2;
for (int y = y1; y <= y2; y++) {
x = (p + dy2) / dy + x1;
p += dx;
frame->set_pixel(x, y, color);
}
}
}
void fill_triangle(Frame *f, int x0, int y0, int x1, int y1, int x2, int y2, Shader const *shader) {
// Отсортируем точки таким образом, чтобы выполнилось условие: y0 < y1 < y2
if (y1 < y0) {
std::swap(y1, y0);
std::swap(x1, x0);
}
if (y2 < y1) {
std::swap(y2, y1);
std::swap(x2, x1);
}
if (y1 < y0) {
std::swap(y1, y0);
std::swap(x1, x0);
}
// Определяем номера строк пикселей, в которых располагаются точки треугольника
int Y0 = (int) (y0 + 0.5f);
int Y1 = (int) (y1 + 0.5f);
int Y2 = (int) (y2 + 0.5f);
// Отсечение невидимой части треугольника
if (Y0 < 0) Y0 = 0;
else if (Y0 >= f->height) Y0 = f->height;
if (Y1 < 0) Y1 = 0;
else if (Y1 >= f->height) Y1 = f->height;
if (Y2 < 0) Y2 = 0;
else if (Y2 >= f->height) Y2 = f->height;
// Рисование верхней части треугольника
for (float y = Y0 + 0.5f; y < Y1; y++) {
int X0 = (int) ((y - y0) / (y1 - y0) * (x1 - x0) + x0 + 0.5f);
int X1 = (int) ((y - y0) / (y2 - y0) * (x2 - x0) + x0 + 0.5f);
if (X0 > X1) std::swap(X0, X1);
if (X0 < 0) X0 = 0;
if (X1 > f->width) X1 = f->width;
for (int x = X0; x < X1; x++) {
f->set_pixel(x, y, shader->get_color(x + 0.5f, y));
}
}
// Рисование нижней части треугольника
for (float y = Y1 + 0.5f; y < Y2; y++) {
int X0 = (int) ((y - y1) / (y2 - y1) * (x2 - x1) + x1 + 0.5f);
int X1 = (int) ((y - y0) / (y2 - y0) * (x2 - x0) + x0 + 0.5f);
if (X0 > X1) std::swap(X0, X1);
if (X0 < 0) X0 = 0;
if (X1 > f->width) X1 = f->width;
for (int x = X0; x < X1; x++) {
f->set_pixel(x, y, shader->get_color(x + 0.5f, y));
}
}
}
COLOR ColorFromHSV(double hue, double saturation, double value) {
int hi = int(floor(hue / 60)) % 6;
double f = hue / 60 - floor(hue / 60);
value = value * 255;
const auto v = (unsigned char) (value);
const auto p = (unsigned char) (value * (1 - saturation));
const auto q = (unsigned char) (value * (1 - f * saturation));
const auto t = (unsigned char) (value * (1 - (1 - f) * saturation));
switch (hi) {
case 0:
return COLOR{v, t, p};
case 1:
return COLOR{q, v, p};
case 2:
return COLOR{p, v, t};
case 3:
return COLOR{p, q, v};
case 4:
return COLOR{t, p, v};
default:
return COLOR{v, p, q};
}
}

View File

@ -1,179 +0,0 @@
#pragma once
#include <type_traits>
#include "frame.hpp"
void draw_circle(Frame *frame, int cx, int cy, int radius, COLOR outline);
inline void draw_circle(Frame *frame, Point c, int radius, COLOR outline) {
draw_circle(frame, c.x, c.y, radius, outline);
}
void draw_line(Frame *frame, int x1, int y1, int x2, int y2, COLOR color);
inline void draw_line(Frame *frame, Point p1, Point p2, COLOR color) {
draw_line(frame, p1.x, p1.y, p2.x, p2.y, color);
}
template<class ...>
struct draw_polyline_ {
template<class ...point_t>
friend
void draw_polyline(Frame *frame, COLOR color, point_t ...points);
template<class ...>
friend
struct draw_polyline_;
private:
};
template<class p0_t, class p1_t, class ...pp_t>
struct draw_polyline_<p0_t, p1_t, pp_t...> {
template<class ...point_t>
friend
void draw_polyline(Frame *frame, COLOR color, point_t ...points);
template<class ...>
friend
struct draw_polyline_;
private:
static_assert(std::is_same_v<p0_t, Point>);
static_assert(std::is_same_v<p1_t, Point>);
static void draw(Frame *frame, COLOR color, p0_t p0, p1_t p1, pp_t ...points) {
draw_line(frame, p0, p1, color);
draw_polyline_<p1_t, pp_t...>::draw(frame, color, p1, points...);
}
static constexpr bool HAS_ANY = true;
static Point first(p0_t p0, p1_t p1, pp_t ...points) {
return p0;
}
static Point last(p0_t p0, p1_t p1, pp_t ...points) {
return draw_polyline_<p1_t, pp_t...>::last(p1, points...);
}
};
template<class p0_t>
struct draw_polyline_<p0_t> {
template<class ...point_t>
friend
void draw_polyline(Frame *frame, COLOR color, point_t ...points);
template<class ...>
friend
struct draw_polyline_;
private:
static_assert(std::is_same_v<p0_t, Point>);
static void draw(Frame *frame, COLOR color, p0_t p0) {}
static constexpr bool HAS_ANY = true;
static Point first(p0_t p0) {
return p0;
}
static Point last(p0_t p0) {
return p0;
}
};
template<>
struct draw_polyline_<> {
template<class ...point_t>
friend
void draw_polyline(Frame *frame, COLOR color, point_t ...points);
template<class ...>
friend
struct draw_polyline_;
private:
static void draw(Frame *frame, COLOR color) {}
static constexpr bool HAS_ANY = false;
static Point first() {
return Point{0, 0};
}
static Point last() {
return Point{0, 0};
}
};
template<class ...point_t>
void draw_polyline(Frame *frame, COLOR color, point_t ...points) {
if constexpr (!draw_polyline_<point_t...>::HAS_ANY) {}
else {
draw_polyline_<point_t...>::draw(frame, color, points...);
draw_line(frame, draw_polyline_<point_t...>::last(points...), draw_polyline_<point_t...>::first(points...), color);
}
}
class Shader {
public:
[[nodiscard]] virtual COLOR get_color(int x, int y) const = 0;
};
class MonoShader : public Shader {
private:
COLOR color;
public:
explicit MonoShader(COLOR color) : color{color} {}
[[nodiscard]] COLOR get_color(int x, int y) const override {
return this->color;
}
};
class BarycentricInterpolatorShader : public Shader {
private:
int x0, y0, x1, y1, x2, y2, S;
COLOR C0, C1, C2;
public:
BarycentricInterpolatorShader(float _x0, float _y0, float _x1, float _y1, float
_x2, float _y2, COLOR A0, COLOR A1, COLOR A2) :
x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2),
S((_y1 - _y2) * (_x0 - _x2) + (_x2 - _x1) * (_y0 - _y2)), C0(A0), C1(A1),
C2(A2) {
}
COLOR get_color(int x, int y) const override {
// Барицентрическая интерполяция
float h0 = ((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2)) / S;
float h1 = ((y2 - y0) * (x - x2) + (x0 - x2) * (y - y2)) / S;
float h2 = 1 - h0 - h1;
float r = h0 * C0.red + h1 * C1.red + h2 * C2.red;
float g = h0 * C0.green + h1 * C1.green + h2 * C2.green;
float b = h0 * C0.blue + h1 * C1.blue + h2 * C2.blue;
float a = h0 * C0.alpha + h1 * C1.alpha + h2 * C2.alpha;
return COLOR(r, g, b, a);
}
};
void fill_triangle(Frame *f, int x0, int y0, int x1, int y1, int x2, int y2, Shader const *shader);
inline void fill_triangle(Frame *f, Point p0, Point p1, Point p2, Shader const *shader) {
fill_triangle(f, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, shader);
}
inline void fill_triangle(Frame *f, int x0, int y0, int x1, int y1, int x2, int y2, COLOR color) {
MonoShader s{color};
fill_triangle(f, x0, y0, x1, y1, x2, y2, &s);
}
inline void fill_triangle(Frame *f, Point p0, Point p1, Point p2, COLOR color) {
MonoShader s{color};
fill_triangle(f, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, &s);
}
COLOR ColorFromHSV(double hue, double saturation, double value);

View File

@ -1,74 +0,0 @@
#pragma once
#include <cmath>
#include <utility>
struct COLOR {
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
COLOR() : red(0), green(0), blue(0), alpha(255) {}
COLOR(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {}
};
class Point {
public:
int x;
int y;
inline Point(int x, int y) : x{x}, y{y} {};
[[nodiscard]] Point rotated_around(int cx, int cy, double angle_radians) const {
return Point{
static_cast<int>((this->x - cx) * std::cos(angle_radians) - (this->y - cy) * std::sin(angle_radians) + cx),
static_cast<int>((this->x - cx) * std::sin(angle_radians) + (this->y - cy) * std::cos(angle_radians) + cy)
};
}
[[nodiscard]] Point rotated_around(Point p, double angle_radians) const {
return this->rotated_around(p.x, p.y, angle_radians);
}
[[nodiscard]] Point moved(int dx, int dy) const {
return Point{this->x + dx, this->y + dy};
}
};
class Frame {
COLOR *pixels;
public:
const int width, height;
inline Frame(int _width, int _height) : width{_width}, height{_height} {
int size = width * height;
this->pixels = new COLOR[size];
}
private:
[[nodiscard]]inline COLOR _get_pixel(int x, int y) const {
return this->pixels[y * this->width + x];
}
[[nodiscard]] inline COLOR &_get_pixel(int x, int y) {
return this->pixels[y * this->width + x];
}
public:
inline void set_pixel(int x, int y, COLOR color) {
this->_get_pixel(x, y) = color;
}
[[nodiscard]] inline COLOR get_pixel(int x, int y) const {
return this->_get_pixel(x, y);
}
inline ~Frame() {
delete[]this->pixels;
}
};

View File

@ -1,13 +0,0 @@
#include <QApplication>
#include <QPushButton>
#include "ui.hpp"
int main(int argc, char **argv) {
QApplication qapp(argc, argv);
auto w = new MainWindow();
w->show();
QApplication::exec();
}

View File

@ -1,81 +0,0 @@
#include <tuple>
#include "frame.hpp"
#include "drawing_assets.hpp"
#include "painter.hpp"
class DemoPainter : public Painter {
public:
void draw(PainterState *state, Frame *frame) const override {
int W = frame->width, H = frame->height;
// Размер рисунка возьмём меньше (7 / 8), чтобы он не касался границ экрана
float a = 7.0f / 8 * ((W < H) ? W - 1 : H - 1) / sqrt(2);
if (a < 1) return; // Если окно очень маленькое, то ничего не рисуем
float angle = state->angle; // Угол поворота
a = a / 2;
Point center{W / 2, H / 2};
draw_polyline(
frame, COLOR{200, 30, 45},
center.moved(a, a).rotated_around(center, angle),
center.moved(a, -a).rotated_around(center, angle),
center.moved(-a, -a).rotated_around(center, angle),
center.moved(-a, a).rotated_around(center, angle)
);
// Рисуем описанную окружность
draw_circle(frame, center, int(a * sqrt(2) + 0.5f), COLOR(100, 100, 250));
// Рисуем пиксель, на который кликнул пользователь
if (state->clicked_pixel.x >= 0 && state->clicked_pixel.x < W &&
state->clicked_pixel.y >= 0 && state->clicked_pixel.y < H)
frame->set_pixel(state->clicked_pixel.x, state->clicked_pixel.y, {34, 175, 60}); // Пиксель зелёного цвета
}
};
class Variant3S1Painter : public Painter {
public:
void draw(PainterState *state, Frame *frame) const override {
int W = frame->width, H = frame->height;
// Размер рисунка возьмём меньше (7 / 8), чтобы он не касался границ экрана
float a = 7.0f / 8 * ((W < H) ? W - 1 : H - 1);
if (a < 1) return; // Если окно очень маленькое, то ничего не рисуем
float angle = state->angle; // Угол поворота
a = a / 2;
Point center{W / 2, H / 2};
// Рисуем описанную окружность
draw_circle(frame, center, a, COLOR(0, 0, 0));
draw_polyline(
frame, COLOR{0, 200, 0},
center.moved(0, a).rotated_around(center, 0 + angle),
center.moved(0, a).rotated_around(center, +2.0944 + angle),
center.moved(0, a).rotated_around(center, -2.0944 + angle)
);
draw_circle(frame, center, a / 2, COLOR(0, 200, 0));
draw_circle(frame, center.moved(0, a * 2 / 3).rotated_around(center, angle), a / 6, COLOR(0, 200, 0));
draw_circle(frame, center.moved(0, a * 2 / 3).rotated_around(center, +2.0944 + angle), a / 6, COLOR(0, 200, 0));
draw_circle(frame, center.moved(0, a * 2 / 3).rotated_around(center, -2.0944 + angle), a / 6, COLOR(0, 200, 0));
// Рисуем пиксель, на который кликнул пользователь
if (state->clicked_pixel.x >= 0 && state->clicked_pixel.x < W &&
state->clicked_pixel.y >= 0 && state->clicked_pixel.y < H)
frame->set_pixel(state->clicked_pixel.x, state->clicked_pixel.y, {34, 175, 60}); // Пиксель зелёного цвета
}
};
static auto predefined_painters_ = std::make_tuple(
DemoPainter(),
Variant3S1Painter()
);
Painter const *const predefined_painters[] = {
&std::get<0>(predefined_painters_),
&std::get<1>(predefined_painters_),
nullptr
};

View File

@ -1,45 +0,0 @@
#pragma once
#include "frame.hpp"
class PainterState {
public:
float angle = 0;
struct {
unsigned short x = -1, y = -1;
} clicked_pixel;
PainterState() = default;
void set_clicked_pixel(unsigned short x, unsigned short y) {
this->clicked_pixel.x = x;
this->clicked_pixel.y = y;
}
};
class Painter {
public:
virtual void draw(PainterState *state, Frame *frame) const = 0;
};
extern Painter const *const predefined_painters[];
class PixelGridPainter : public Painter {
private:
const COLOR c1;
const COLOR c2;
public:
inline PixelGridPainter(COLOR c1, COLOR c2) : c1{c1}, c2{c2} {}
inline void draw(PainterState *state, Frame *frame) const override {
for (int y = 0; y < frame->height; y++) {
for (int x = 0; x < frame->width; x++) {
if ((x + y) % 2 == 0)
frame->set_pixel(x, y, this->c1);
else
frame->set_pixel(x, y, this->c2);
}
}
}
};

View File

@ -1,26 +0,0 @@
#include "frame.hpp"
#include "shaders.hpp"
COLOR BarycentricInterpolator::get_color(int x, int y) const {
// Барицентрическая интерполяция
float h0 = ((y1 - y2) * (x - x2) + (x2 - x1) * (y - y2)) / S;
float h1 = ((y2 - y0) * (x - x2) + (x0 - x2) * (y - y2)) / S;
float h2 = 1 - h0 - h1;
float r = h0 * C0.red + h1 * C1.red + h2 * C2.red;
float g = h0 * C0.green + h1 * C1.green + h2 * C2.green;
float b = h0 * C0.blue + h1 * C1.blue + h2 * C2.blue;
float a = h0 * C0.alpha + h1 * C1.alpha + h2 * C2.alpha;
return COLOR(r, g, b, a);
}
COLOR RadialBrush::get_color(int x, int y) const {
double dx = (double) x - cx, dy = (double) y - cy;
double radius = sqrt(dx * dx + dy * dy);
float h0 = (sin(radius / 10 + angle) + 1.0f) / 2;
float h1 = 1 - h0;
float r = h0 * C0.red + h1 * C1.red;
float g = h0 * C0.green + h1 * C1.green;
float b = h0 * C0.blue + h1 * C1.blue;
return COLOR(r, g, b);
}

View File

@ -1,35 +0,0 @@
#pragma once
#include "painter.hpp"
#include "drawing_assets.hpp"
class BarycentricInterpolator : public Shader {
private:
float x0, y0, x1, y1, x2, y2, S;
COLOR C0, C1, C2;
public:
inline BarycentricInterpolator(float _x0, float _y0, float _x1, float _y1, float _x2, float _y2, COLOR A0, COLOR A1, COLOR A2) :
x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2),
S((_y1 - _y2) * (_x0 - _x2) + (_x2 - _x1) * (_y0 - _y2)),
C0(A0), C1(A1), C2(A2) {}
inline BarycentricInterpolator(Point p0, Point p1, Point p2, COLOR A0, COLOR A1, COLOR A2) :
BarycentricInterpolator(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, A0, A1, A2) {}
COLOR get_color(int x, int y) const override;
};
class RadialBrush : public Shader {
private:
float cx, cy;
COLOR C0, C1;
float angle;
public:
RadialBrush(float _x0, float _y0, float _x1, float _y1, COLOR A0, COLOR A1, float _angle) :
cx((_x0 + _x1) / 2.0f), cy((_y0 + _y1) / 2.0f),
C0(A0), C1(A1), angle(_angle) {}
COLOR get_color(int x, int y) const override;
};

View File

@ -1,129 +0,0 @@
#include <QWidget>
#include <QGridLayout>
#include <QLabel>
#include <QResizeEvent>
#include <QPainter>
#include <QDebug>
#include <iostream>
#include "ui.hpp"
const QString StatusBar::_scale_label_template{"[F2]/[F3] Масштаб: %1 пикселей"};
const QString StatusBar::_painter_label_template{"[Q] Отображаемая фигура: %1/%2"};
const QString StatusBar::_x_template{"X=%1"};
const QString StatusBar::_y_template{"Y=%1"};
StatusBar::StatusBar(QWidget *parent) : QWidget(parent) {
this->_layout = new QGridLayout(parent);
this->setLayout(this->_layout);
auto add_label = [&](QLabel **dst, QString text, int row, int column, QFlags<Qt::AlignmentFlag> alignment) {
*dst = new QLabel(text, this);
this->_layout->addWidget(*dst, row, column, alignment);
};
add_label(&(this->_scale_label), StatusBar::_scale_label_template.arg("??"), 0, 0, Qt::AlignRight);
add_label(&(this->_painter_label), StatusBar::_painter_label_template.arg("??", "??"), 1, 0, Qt::AlignRight);
add_label(&(this->_screen_coordinates.title), "Экранные координаты:", 0, 1, Qt::AlignRight);
add_label(&(this->_screen_coordinates.x), StatusBar::_x_template.arg("??"), 0, 2, Qt::AlignHCenter);
add_label(&(this->_screen_coordinates.y), StatusBar::_y_template.arg("??"), 0, 3, Qt::AlignHCenter);
add_label(&(this->_scaled_coordinates.title), "Системные координаты:", 1, 1, Qt::AlignRight);
add_label(&(this->_scaled_coordinates.x), StatusBar::_x_template.arg("??"), 1, 2, Qt::AlignHCenter);
add_label(&(this->_scaled_coordinates.y), StatusBar::_y_template.arg("??"), 1, 3, Qt::AlignHCenter);
this->_layout->setColumnStretch(4, 1);
}
void StatusBar::set_coordinates(unsigned int screen_x, unsigned int screen_y, unsigned int scaled_x, unsigned int scaled_y) {
this->_screen_coordinates.x->setText(StatusBar::_x_template.arg(screen_x));
this->_screen_coordinates.y->setText(StatusBar::_y_template.arg(screen_y));
this->_scaled_coordinates.x->setText(StatusBar::_x_template.arg(scaled_x));
this->_scaled_coordinates.y->setText(StatusBar::_y_template.arg(scaled_y));
}
void StatusBar::set_scale(unsigned int current_scale) {
this->_scale_label->setText(StatusBar::_scale_label_template.arg(current_scale));
}
void StatusBar::set_painter_index(unsigned int index, unsigned int painters_count) {
this->_painter_label->setText(StatusBar::_painter_label_template.arg(index).arg(painters_count));
}
Canvas::Canvas(QWidget *parent) : QWidget(parent), _current_frame{}, _sync{} {
this->setMouseTracking(true);
this->grabKeyboard();
this->_mouse_processing.is_pressed = false;
this->_mouse_processing.pressed_at = QPoint(0, 0);
this->_mouse_processing.is_moved_while_pressed = false;
}
void Canvas::set_frame(QImage &f) {
this->_sync.lock();
this->_current_frame = std::move(f);
this->_sync.unlock();
}
void Canvas::paintEvent(QPaintEvent *event) {
QPainter painter{};
painter.begin(this);
this->_sync.lock();
painter.drawImage(this->_current_frame.rect(), this->_current_frame);
this->_sync.unlock();
painter.end();
}
void Canvas::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
emit this->resized(event->size());
}
MainWindow::MainWindow() : QWidget{} {
this->_layout = new QGridLayout(this);
this->setLayout(this->_layout);
this->_status_bar = new StatusBar(this);
this->_layout->addWidget(this->_status_bar, 0, 0);
this->_canvas = new Canvas(this);
this->_layout->addWidget(this->_canvas, 1, 0);
this->_layout->setColumnStretch(0, 1);
this->_layout->setRowStretch(1, 1);
}
void Canvas::keyPressEvent(QKeyEvent *event) {
emit this->key_pressed(static_cast<Qt::Key>(event->key()));
std::cout << "key pressed" << std::endl;
}
void Canvas::mousePressEvent(QMouseEvent *event) {
this->_mouse_processing.is_pressed = true;
this->_mouse_processing.pressed_at = event->pos();
this->_mouse_processing.is_moved_while_pressed = false;
std::cout << "mouse press" << std::endl;
}
void Canvas::mouseMoveEvent(QMouseEvent *event) {
if (this->_mouse_processing.is_pressed) {
this->_mouse_processing.is_moved_while_pressed = true;
emit this->pressed_mouse_moved(event->pos());
} else {
emit this->pressed_mouse_moved(event->pos());
}
std::cout << "mouse move" << std::endl;
}
void Canvas::mouseReleaseEvent(QMouseEvent *event) {
this->_mouse_processing.is_pressed = false;
if (this->_mouse_processing.is_moved_while_pressed) {
emit this->mouse_dragged(this->_mouse_processing.pressed_at, event->pos());
} else {
emit this->mouse_clicked(event->pos());
}
std::cout << "mouse release" << std::endl;
}

View File

@ -1,107 +0,0 @@
#pragma once
#include <QWidget>
#include <QGridLayout>
#include <QLabel>
#include <QSize>
#include <QResizeEvent>
#include <QMutex>
#include <QMainWindow>
#include "frame.hpp"
class StatusBar : public QWidget {
Q_OBJECT
private:
QGridLayout *_layout;
QLabel *_scale_label;
static const QString _scale_label_template;
QLabel *_painter_label;
static const QString _painter_label_template;
struct {
QLabel *title;
QLabel *x;
QLabel *y;
} _screen_coordinates, _scaled_coordinates;
static const QString _x_template, _y_template;
public:
explicit StatusBar(QWidget *parent);
public slots:
void set_coordinates(unsigned screen_x, unsigned screen_y, unsigned scaled_x, unsigned scaled_y);
void set_scale(unsigned current_scale);
void set_painter_index(unsigned index, unsigned painters_count);
};
class Canvas : public QWidget {
Q_OBJECT
private:
QMutex _sync;
QImage _current_frame;
public:
explicit Canvas(QWidget *parent);
public slots:
void set_frame(QImage &f);
public:
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
signals:
void resized(QSize new_size);
private:
struct {
bool is_pressed;
QPoint pressed_at;
bool is_moved_while_pressed;
} _mouse_processing;
public:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
signals:
void key_pressed(Qt::Key key);
void released_mouse_moved(QPoint to);
void pressed_mouse_moved(QPoint to);
void mouse_clicked(QPoint where);
void mouse_dragged(QPoint from, QPoint to);
};
class MainWindow : public QWidget {
Q_OBJECT
private:
QGridLayout *_layout;
public:
StatusBar *_status_bar;
Canvas *_canvas;
MainWindow();
};