11#pragma once
22
3+ #include " pros/rtos.hpp"
34#include " stdint.h"
45
56#include < functional>
7+ #include < optional>
68
79namespace zest {
810
11+ /* *
12+ * @brief A friendlier, documented and safer API wrapper around the Vex SDK's display functions.
13+ *
14+ * @note Heavily inspired by vexide's display module: https://docs.rs/vexide/0.7.0/vexide/devices/display/index.html
15+ */
916struct Screen {
1017 /* * Vertical height taken up by the user program in pixels. */
1118 static constexpr int16_t HEADER_HEIGHT = 32 ;
@@ -20,14 +27,14 @@ struct Screen {
2027 struct TouchEvent {
2128 enum class State {
2229 /* * The screen has been released. */
23- Release ,
30+ Released ,
2431 /* * The screen has been touched. */
25- Press ,
32+ Pressed ,
2633 /* * The screen has been touched and is still being held. */
2734 Held
2835 };
2936
30- /* * The y coordinate of the touch. */
37+ /* * The current state of the touch. */
3138 State state;
3239 /* * The x coordinate of the touch. */
3340 int16_t x;
@@ -51,40 +58,87 @@ struct Screen {
5158 static TouchEvent get_last_touch ();
5259
5360 /* *
54- * @brief Subscribes the listener to be called when the screen begins to be pressed .
61+ * @brief Subscribes the listener to be called when the screen touch state changes .
5562 *
5663 * Spawn a new task to check for events if it is not already running.
5764 * All listeners are called from this task.
5865 *
66+ * TODO: Elaborate on below?
5967 * @warning If you have multiple listeners, avoid using delays, which can delay other callbacks
6068 * from being called, and result in lost information.
6169 * For this reason, it is recommended library developers use get_last_touch() instead of this
6270 * function.
6371 *
64- * @param listener_cb The function to call when the screen is pressed.
72+ * @param listener_cb The function to call when the screen's touch state changes.
73+ * @param state_filter Optional filter for the touch state. If provided, only events matching
74+ * this state will trigger the callback. For example, if state_filter ==
75+ * TouchEvent::State::Pressed, then the callback will only be called when the screen starts
76+ * being pressed.
77+ */
78+ static void on_touched (
79+ std::function<void (const TouchEvent&)> listener_cb,
80+ std::optional<TouchEvent::State> state_filter = std::nullopt
81+ );
82+
83+ /* *
84+ * @brief Subscribes the listener to be called when the screen begins to be pressed.
85+ * Wrapper for Screen::on_touched() with state_filter set to TouchEvent::State::Pressed.
86+ * @see Screen::on_touched()
6587 */
6688 static void on_pressed (std::function<void (const TouchEvent&)> listener_cb);
6789
6890 /* *
6991 * @brief Subscribes the listener to be called when the screen begins to be released.
70- *
71- * Spawn a new task to check for events if it is not already running.
72- * All listeners are called from this task.
73- *
74- * @warning If you have multiple listeners, avoid using delays, which can delay other callbacks
75- * from being called, and result in lost information.
76- * For this reason, it is recommended library developers use get_last_touch() instead of this
77- * function.
78- *
79- * @param listener_cb The function to call when the screen is pressed.
92+ * Wrapper for Screen::on_touched() with state_filter set to TouchEvent::State::Released.
93+ * @see Screen::on_touched()
8094 */
8195 static void on_released (std::function<void (const TouchEvent&)> listener_cb);
8296
83- // TODO: Should there be a on_held() function?
97+ /* *
98+ * @brief Subscribes the listener to be called when the screen begins to be held.
99+ * Wrapper for Screen::on_touched() with state_filter set to TouchEvent::State::Held.
100+ * @see Screen::on_touched()
101+ */
102+ static void on_held (std::function<void (const TouchEvent&)> listener_cb);
103+
104+ /* * @brief Determines where screen operations should be written. Immediate is the default. */
105+ enum class RenderMode {
106+ /* *
107+ * Draw operations are immediately applied to the screen without the need to call
108+ * Screen::render().
109+ * This is the default mode.
110+ */
111+ Immediate,
112+ /* *
113+ * Draw calls are written to an intermediate display buffer, rather than directly drawn to
114+ * the screen. This buffer can later be applied using Screen::render().
115+ *
116+ * This mode is necessary for preventing screen tearing when drawing at high speeds.
117+ */
118+ DoubleBuffered,
119+ };
120+
121+ /* *
122+ * @brief Changes the render mode of the screen.
123+ * @param new_mode The new render mode to set.
124+ * @see Screen::RenderMode
125+ */
126+ static void set_render_mode (RenderMode new_mode);
127+
128+ /* *
129+ * @brief Gets the current render mode of the screen.
130+ * @return The current render mode of the screen.
131+ * @see Screen::RenderMode
132+ */
133+ static RenderMode get_render_mode ();
84134
85- static void set_render_mode ();
86- static void get_render_mode ();
135+ /* *
136+ * @brief Flushes the screen's double buffer it is enabled.
137+ * This does nothing in the immediate render mode, but is required in the immediate render mode.
138+ * @see Screen::RenderMode
139+ */
87140 static void render ();
141+
88142 static void scroll ();
89143 static void scroll_region ();
90144
@@ -105,6 +159,10 @@ struct Screen {
105159 static void clear (auto color /* = TODO*/ );
106160
107161 static void draw_buffer ();
162+
163+ private:
164+ static RenderMode m_render_mode;
165+ static pros::Mutex m_mutex;
108166};
109167
110168} // namespace zest
0 commit comments