2026-02-09 11:41:12 -05:00
|
|
|
#pragma once
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
|
#include "../ui/Display.h"
|
|
|
|
|
#include "../settings/Settings.h"
|
|
|
|
|
#include "../sensors/MoistureSensor.h"
|
2026-02-10 17:05:42 -05:00
|
|
|
#include "../sensors/BatterySensor.h"
|
2026-02-09 11:41:12 -05:00
|
|
|
|
|
|
|
|
class FaceRenderer {
|
|
|
|
|
public:
|
|
|
|
|
enum Mood { HAPPY, DRY, TOO_WET };
|
|
|
|
|
|
|
|
|
|
void begin(Display& display, Settings& settings);
|
2026-02-10 17:05:42 -05:00
|
|
|
void loop(const MoistureSensor& moisture, const BatterySensor& battery);
|
2026-02-09 11:41:12 -05:00
|
|
|
|
|
|
|
|
bool isDeadMode() const { return _deadMode; }
|
|
|
|
|
Mood mood() const { return _mood; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Display* _display = nullptr;
|
|
|
|
|
Settings* _settings = nullptr;
|
|
|
|
|
|
|
|
|
|
Mood _mood = HAPPY;
|
|
|
|
|
|
|
|
|
|
bool _deadMode = false;
|
|
|
|
|
unsigned long _dryStartMs = 0;
|
|
|
|
|
static constexpr unsigned long DRY_DEADLINE_MS = 72UL * 60UL * 60UL * 1000UL;
|
|
|
|
|
unsigned long _nextDeadToggleMs = 0;
|
|
|
|
|
bool _deadShowTombstone = false;
|
|
|
|
|
|
|
|
|
|
unsigned long _nextFrameMs = 0;
|
|
|
|
|
static constexpr unsigned long FRAME_MS = 80;
|
|
|
|
|
|
|
|
|
|
int8_t _gazeX = 2, _gazeY = 2;
|
|
|
|
|
int8_t _targetX = 2, _targetY = 2;
|
|
|
|
|
unsigned long _nextGazeMs = 0;
|
|
|
|
|
|
|
|
|
|
unsigned long _lastBlinkMs = 0;
|
|
|
|
|
unsigned long _nextBlinkMs = 0;
|
|
|
|
|
bool _blinking = false;
|
|
|
|
|
uint8_t _blinkStep = 0;
|
|
|
|
|
unsigned long _blinkUntilMs = 0;
|
|
|
|
|
|
|
|
|
|
bool _silly = false;
|
|
|
|
|
uint8_t _sillyVariant = 0;
|
|
|
|
|
unsigned long _sillyUntilMs = 0;
|
|
|
|
|
unsigned long _nextSillyMs = 0;
|
|
|
|
|
unsigned long _lastSillyMs = 0;
|
|
|
|
|
static constexpr unsigned long SILLY_MAX_GAP_MS = 180000UL;
|
|
|
|
|
|
|
|
|
|
int8_t _shakeX = 0, _shakeY = 0;
|
|
|
|
|
unsigned long _nextShakeMs = 0;
|
|
|
|
|
|
|
|
|
|
void updateMood(int moisturePct);
|
|
|
|
|
void updateDeathMode(unsigned long now);
|
|
|
|
|
void updateHappy(unsigned long now);
|
|
|
|
|
void updateDry(unsigned long now);
|
|
|
|
|
void updateTooWet(unsigned long now);
|
|
|
|
|
|
2026-02-10 17:05:42 -05:00
|
|
|
void renderDead(unsigned long now, const BatterySensor& battery);
|
|
|
|
|
void renderNormal(unsigned long now, const BatterySensor& battery);
|
2026-02-09 11:41:12 -05:00
|
|
|
|
|
|
|
|
void drawEyesOpen(int pupilDx, int pupilDy);
|
|
|
|
|
void drawEyesClosed();
|
|
|
|
|
void drawEyesSmallPupils(int pupilDy, int sx, int sy);
|
|
|
|
|
void drawBrowsVerySad();
|
|
|
|
|
void drawMouthHappy();
|
|
|
|
|
void drawMouthFrown();
|
|
|
|
|
void drawMouthFlat();
|
|
|
|
|
void drawDroplet(int x, int y, bool pulse);
|
|
|
|
|
void drawBubbles(int off);
|
|
|
|
|
void drawSparkles(unsigned long now);
|
|
|
|
|
void drawSilly(uint8_t v);
|
|
|
|
|
void drawXEye(int cx, int cy);
|
|
|
|
|
void drawBigWaterText(unsigned long now);
|
|
|
|
|
|
|
|
|
|
unsigned long randRange(unsigned long lo, unsigned long hi);
|
|
|
|
|
int8_t randRangeI8(int8_t lo, int8_t hi);
|
|
|
|
|
};
|