mirror of
https://github.com/esphome/esphome.git
synced 2025-03-13 20:15:17 +01:00
Add a local coordinate system
This introduces a local coordinate system to the display component. This is useful for nested/localised drawing without having to do repeated and error prone coordinate maths
This commit is contained in:
parent
b43c5b851a
commit
fb06f98df3
4 changed files with 85 additions and 0 deletions
|
@ -579,6 +579,31 @@ bool Display::clip(int x, int y) {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
void Display::set_local_coordinates_relative_to_current(int x_offset, int y_offset) {
|
||||
Point p(0, 0);
|
||||
if (!this->local_coordinate_.empty()) {
|
||||
p = this->local_coordinate_.back();
|
||||
}
|
||||
p.x += x_offset;
|
||||
p.y += y_offset;
|
||||
|
||||
this->local_coordinate_.push_back(p);
|
||||
}
|
||||
void Display::pop_local_coordinates() {
|
||||
if (this->local_coordinate_.empty()) {
|
||||
ESP_LOGE(TAG, "pop_local_coordinates: No local coordinates set");
|
||||
} else {
|
||||
this->local_coordinate_.pop_back();
|
||||
}
|
||||
}
|
||||
Point Display::get_local_coordinates() {
|
||||
Point p(0, 0);
|
||||
if (!this->local_coordinate_.empty()) {
|
||||
p = this->local_coordinate_.back();
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
bool Display::clamp_x_(int x, int w, int &min_x, int &max_x) {
|
||||
min_x = std::max(x, 0);
|
||||
max_x = std::min(x + w, this->get_width());
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
#include <vector>
|
||||
|
||||
#include "rect.h"
|
||||
#include "point.h"
|
||||
|
||||
#include "esphome/core/color.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/time.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "display_color_utils.h"
|
||||
|
||||
#ifdef USE_GRAPH
|
||||
|
@ -631,6 +633,36 @@ class Display : public PollingComponent {
|
|||
*/
|
||||
bool clip(int x, int y);
|
||||
|
||||
/** Changes the local coordinates to be relative to (x, y). After calling a pixel
|
||||
* drawn at (10, 20) would be drawn to the screen at (x + 10, y + 20)
|
||||
*
|
||||
* @param[in] x: x coordinate as the new local. Absolute to the displays underlying 0
|
||||
* @param[in] y: y coordinate as the new local. Absolute to the displays underlying 0
|
||||
*/
|
||||
void set_local_coordinate(int x, int y) { this->local_coordinate_.emplace_back(x, y); };
|
||||
|
||||
/** Changes the local coordinates to be to be (x_local + x_offset, y_local + y_offset)
|
||||
* After calling a pixel drawn at (10, 20) would be drawn to the screen at
|
||||
* (x_local + x_offset + 10, y_local + y_offset + 20)
|
||||
*
|
||||
* @param[in] x_offset: x offset from the current local. Relative to the local x
|
||||
* @param[in] y_offset: y offset from the current local. Relative to the local y
|
||||
*/
|
||||
void set_local_coordinates_relative_to_current(int x_offset, int y_offset);
|
||||
|
||||
/** Removes the most recent local coordinate system from use
|
||||
*/
|
||||
void pop_local_coordinates();
|
||||
|
||||
/** Gets the current local coordinates in the displays absolute coordinate system
|
||||
*/
|
||||
Point get_local_coordinates();
|
||||
|
||||
/** Clears all the local coordinate systems and revers to the displays absolute coordinate
|
||||
* system
|
||||
*/
|
||||
void clear_local_coordinates() { this->local_coordinate_.clear(); };
|
||||
|
||||
void test_card();
|
||||
void show_test_card() { this->show_test_card_ = true; }
|
||||
|
||||
|
@ -662,6 +694,7 @@ class Display : public PollingComponent {
|
|||
std::vector<DisplayOnPageChangeTrigger *> on_page_change_triggers_;
|
||||
bool auto_clear_enabled_{true};
|
||||
std::vector<Rect> clipping_rectangle_;
|
||||
std::vector<Point> local_coordinate_;
|
||||
bool show_test_card_{false};
|
||||
};
|
||||
|
||||
|
@ -737,5 +770,7 @@ class DisplayOnPageChangeTrigger : public Trigger<DisplayPage *, DisplayPage *>
|
|||
DisplayPage *to_{nullptr};
|
||||
};
|
||||
|
||||
const LogString *text_align_to_string(TextAlign textalign);
|
||||
|
||||
} // namespace display
|
||||
} // namespace esphome
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "point.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace display {
|
||||
|
@ -45,6 +46,11 @@ int DisplayBuffer::get_height() {
|
|||
}
|
||||
|
||||
void HOT DisplayBuffer::draw_pixel_at(int x, int y, Color color) {
|
||||
// Convert (x, y) from the local coordinate system to the display absolute coordinate system
|
||||
Point local_coord = this->get_local_coordinates();
|
||||
x += local_coord.x;
|
||||
y += local_coord.y;
|
||||
|
||||
if (!this->get_clipping().inside(x, y))
|
||||
return; // NOLINT
|
||||
|
||||
|
|
19
esphome/components/display/point.h
Normal file
19
esphome/components/display/point.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace display {
|
||||
|
||||
class Point {
|
||||
public:
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
|
||||
Point() : x(VALUE_NO_SET), y(VALUE_NO_SET){};
|
||||
inline Point(int16_t x, int16_t y) ESPHOME_ALWAYS_INLINE : x(x), y(y){};
|
||||
};
|
||||
|
||||
} // namespace display
|
||||
} // namespace esphome
|
Loading…
Add table
Reference in a new issue