diff --git a/Userland/Demos/CatDog/CatDog.cpp b/Userland/Demos/CatDog/CatDog.cpp index d17bcf9424..8229bcc389 100644 --- a/Userland/Demos/CatDog/CatDog.cpp +++ b/Userland/Demos/CatDog/CatDog.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Richard Gráčik + * Copyright (c) 2022, kleines Filmröllchen * * SPDX-License-Identifier: BSD-2-Clause */ @@ -85,13 +86,13 @@ void CatDog::timer_event(Core::TimerEvent&) } if (!m_up && !m_down && !m_left && !m_right) { - m_curr_bmp = m_still; - if (m_timer.elapsed() > 5000) { - m_curr_bmp = m_sleep1; - if (m_curr_frame == 2) - m_curr_bmp = m_sleep2; - m_sleeping = true; - } + // Select the movement-free image based on the main state. + if (m_timer.elapsed() > 5000) + m_main_state = MainState::Sleeping; + set_image_by_main_state(); + } else if (is_non_application_state(m_main_state)) { + // If CatDog currently moves, it should be idle the next time it stops. + m_main_state = MainState::Idle; } update(); @@ -113,11 +114,11 @@ void CatDog::track_mouse_move(Gfx::IntPoint const& point) return; m_temp_pos = relative_point; m_timer.start(); - if (m_sleeping) { - m_curr_bmp = m_alert; + if (m_main_state == MainState::Sleeping) { + m_main_state = MainState::Alerted; + set_image_by_main_state(); update(); } - m_sleeping = false; } void CatDog::mousedown_event(GUI::MouseEvent& event) diff --git a/Userland/Demos/CatDog/CatDog.h b/Userland/Demos/CatDog/CatDog.h index 8bcae387a9..f814ad2195 100644 --- a/Userland/Demos/CatDog/CatDog.h +++ b/Userland/Demos/CatDog/CatDog.h @@ -1,13 +1,17 @@ /* * Copyright (c) 2021, Richard Gráčik + * Copyright (c) 2022, kleines Filmröllchen * * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include #include #include #include #include +#include #include #pragma once @@ -17,6 +21,17 @@ class CatDog final : public GUI::Widget C_OBJECT(CatDog); public: + // The general state, does not contain movement direction or whether CatDog is roaming. + enum class MainState { + Idle, // default state + Alerted, // woken by mouse cursor or speaking after being idle + Sleeping, // mouse hasn't moved in some time + }; + static bool is_non_application_state(MainState state) + { + return state == MainState::Idle || state == MainState::Alerted || state == MainState::Sleeping; + } + virtual void timer_event(Core::TimerEvent&) override; virtual void paint_event(GUI::PaintEvent& event) override; virtual void track_mouse_move(Gfx::IntPoint const& point) override; @@ -33,20 +48,25 @@ public: { m_roaming = roaming; if (!roaming) { - m_sleeping = false; + // If we stop CatDog while it's in a program-specific state, we don't want it to be alerted. + if (m_main_state == MainState::Idle || m_main_state == MainState::Sleeping) + m_main_state = MainState::Alerted; m_curr_frame = 0; - m_curr_bmp = m_alert; + set_image_by_main_state(); update(); } } + MainState main_state() const { return m_main_state; } + private: Gfx::IntPoint m_temp_pos; Core::ElapsedTimer m_timer; int m_curr_frame = 1; int m_moveX, m_moveY = 0; - bool m_up, m_down, m_left, m_right, m_sleeping = false; + MainState m_main_state { MainState::Alerted }; + bool m_up, m_down, m_left, m_right; bool m_roaming { true }; NonnullRefPtr m_alert = *Gfx::Bitmap::try_load_from_file("/res/icons/catdog/alert.png").release_value_but_fixme_should_propagate_errors(); @@ -71,8 +91,29 @@ private: NonnullRefPtr m_wrun2 = *Gfx::Bitmap::try_load_from_file("/res/icons/catdog/wrun2.png").release_value_but_fixme_should_propagate_errors(); NonnullRefPtr m_curr_bmp = m_alert; + + // Used if CatDog is still; may also account for animation frames. + void set_image_by_main_state() + { + switch (m_main_state) { + case MainState::Idle: + m_curr_bmp = m_still; + break; + case MainState::Alerted: + m_curr_bmp = m_alert; + break; + case MainState::Sleeping: + if (m_curr_frame == 1) + m_curr_bmp = m_sleep1; + else + m_curr_bmp = m_sleep2; + break; + } + } + CatDog() : m_temp_pos { 0, 0 } { + set_image_by_main_state(); } };