diff --git a/.gitignore b/.gitignore index eba4bb2..2c97f74 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ # ---------------------------------------------------------------------------- build -SFML* +SFML-* *.user *CMakeFiles* *Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt index 1318a4f..ebdc04a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.13) project(project-kyoku LANGUAGES CXX) @@ -16,38 +16,25 @@ set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(CMAKE_USE_PTHREADS_INIT 1) set(THREADS_PREFER_PTHREAD_FLAG ON) -file(GLOB_RECURSE SOURCES "src/main.cpp" "src/application/*.cpp" "src/application/*.h") +include_directories(${CMAKE_SOURCE_DIR}/include) +file(GLOB_RECURSE SOURCES "src/main.cpp") add_executable(project-kyoku ${SOURCES}) -option(SFML_BUILT "SFML_BUILT" OFF) - -if(SFML_BUILT) - set(SFML_LIB_DIR - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-graphics.so.2.5 - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-system.so.2.5 - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-window.so.2.5 - ${CMAKE_SOURCE_DIR}/SFML-2.5.1/lib/libsfml-audio.so.2.5) - set(SFML_INCL_DIR ${CMAKE_SOURCE_DIR}/SFML-2.5.1/include) - target_link_libraries(project-kyoku ${SFML_LIB_DIR}) -else() - find_package(SFML REQUIRED graphics window system) - include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include) - target_link_libraries(project-kyoku sfml-system sfml-audio sfml-graphics sfml-network) -endif() - -include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include) - SET(CMAKE_INSTALL_PREFIX /) # When new game modes appear, aggregate them into a ONE subdirectory -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modes/classicmode/CMakeLists.txt") - add_subdirectory(modes/classicmode) +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/modes/classicmode/CMakeLists.txt") + add_subdirectory(src/modes/classicmode) target_link_libraries(project-kyoku classicmode) endif() -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/CMakeLists.txt") - add_subdirectory(tools) +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/tools/CMakeLists.txt") + add_subdirectory(src/tools) target_link_libraries(project-kyoku tools) endif() -if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/core/CMakeLists.txt") - add_subdirectory(core) - target_link_libraries(project-kyoku core) +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/application/CMakeLists.txt") + add_subdirectory(src/application) + target_link_libraries(project-kyoku application) +endif() +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/impl/CMakeLists.txt") + add_subdirectory(src/impl) + target_link_libraries(project-kyoku impl) endif() diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt deleted file mode 100644 index 557d413..0000000 --- a/core/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 2.8.8) - -project(core) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(${CMAKE_SOURCE_DIR}/include) - -file(GLOB_RECURSE HEADERS "shared/*.h") -file(GLOB_RECURSE SOURCES "src/*.cpp") - -add_library(core STATIC ${SOURCES} ${HEADERS}) -target_include_directories(core PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared) -target_link_libraries(core tools) - -target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/core/shared) diff --git a/core/shared/core/inputtype.h b/core/shared/core/inputtype.h deleted file mode 100644 index 08bb8d5..0000000 --- a/core/shared/core/inputtype.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "tools/mathutils.h" - -struct PlayerInput -{ - microsec timestamp; - sf::Event event; -}; diff --git a/core/shared/core/updatedata.h b/core/shared/core/updatedata.h deleted file mode 100644 index bad6e0e..0000000 --- a/core/shared/core/updatedata.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include "tools/mathutils.h" - -struct UpdateData -{ - const microsec timestamp; - const sf::Time dt; -}; diff --git a/include/core/area.h b/include/core/area.h new file mode 100644 index 0000000..dfa4d48 --- /dev/null +++ b/include/core/area.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "core/point.h" +#include "core/vector.h" + +namespace kku +{ + +template >> +struct Area +{ + T left = 0; + T top = 0; + T width = 0; + T height = 0; + + inline kku::Point position() const noexcept + { + return kku::Point{static_cast(left), + static_cast(top) }; + } + + inline void moveBy(const kku::Vector2& vector) + { + top += vector.second; + left += vector.first; + } + + inline bool contains(const kku::Point& point) const + { + return point.x >= left ; // debug it when on computer + } +}; + +} diff --git a/core/shared/core/bpmsection.h b/include/core/bpmsection.h similarity index 63% rename from core/shared/core/bpmsection.h rename to include/core/bpmsection.h index 496627b..ec2c18b 100644 --- a/core/shared/core/bpmsection.h +++ b/include/core/bpmsection.h @@ -1,19 +1,24 @@ #pragma once -#include "tools/mathutils.h" +#include "core/time.h" + +namespace kku +{ struct BPMSection { - int bpm = 120; // Hi, osu - int fraction = 2; + unsigned int bpm = 120; // Hi, osu + unsigned int fraction = 2; microsec offset_start = 0; microsec interval = 0; }; -struct BPMSectionCompt +struct BPMSectionComparator { bool operator()(const BPMSection& lhs, const BPMSection& rhs) const noexcept { return lhs.offset_start < rhs.offset_start; } }; + +} \ No newline at end of file diff --git a/include/core/color.h b/include/core/color.h new file mode 100644 index 0000000..f0c599d --- /dev/null +++ b/include/core/color.h @@ -0,0 +1,14 @@ +#pragma once + +namespace kku +{ + +struct Color +{ + unsigned char red = 0; + unsigned char green = 0; + unsigned char blue = 0; + unsigned char alpha = 0; +}; + +} \ No newline at end of file diff --git a/include/core/corefactory.h b/include/core/corefactory.h new file mode 100644 index 0000000..c96357b --- /dev/null +++ b/include/core/corefactory.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "core/music.h" +#include "core/text.h" +#include "core/resourceholder.h" +#include "core/rectangle.h" +#include "core/vector.h" +#include "core/line.h" + +namespace kku +{ + +class CoreFactory +{ +public: + virtual ~CoreFactory() = default; + virtual std::shared_ptr getMusic() const = 0; + virtual std::shared_ptr getText(kku::Font::Id id) const = 0; + virtual std::shared_ptr getRectangle() const = 0; + virtual std::shared_ptr getLine() const = 0; + virtual kku::Vector2 getRenderSize() const = 0; +}; + +} \ No newline at end of file diff --git a/core/shared/core/editor.h b/include/core/editor.h similarity index 86% rename from core/shared/core/editor.h rename to include/core/editor.h index bcbce6c..a82c3b1 100644 --- a/core/shared/core/editor.h +++ b/include/core/editor.h @@ -1,26 +1,31 @@ #pragma once #include -#include "core/inputtype.h" +#include + +#include "core/gameevent.h" #include "core/updatedata.h" #include "core/bpmsection.h" +namespace kku +{ + class Editor { public: virtual ~Editor() = default; - virtual void input(PlayerInput&& inputdata) = 0; + virtual void input(GameEvent&& input) = 0; virtual void update(UpdateData&& updatedata) = 0; virtual void display() const = 0; virtual void recalculate(const microsec& timestamp) = 0; - void setBPMSections(const std::set& sections) noexcept + void setBPMSections(const std::set& sections) noexcept { _bpm_sections = sections; } - void setBPMSections(std::set&& sections) noexcept + void setBPMSections(std::set&& sections) noexcept { _bpm_sections = std::move(sections); } @@ -77,5 +82,7 @@ public: } protected: - std::set _bpm_sections; + std::set _bpm_sections; }; + +} \ No newline at end of file diff --git a/core/shared/core/game.h b/include/core/game.h similarity index 69% rename from core/shared/core/game.h rename to include/core/game.h index ce28878..54e1a39 100644 --- a/core/shared/core/game.h +++ b/include/core/game.h @@ -1,15 +1,20 @@ #pragma once -#include "core/inputtype.h" +#include "core/gameevent.h" #include "core/updatedata.h" +namespace kku +{ + class Game { public: virtual ~Game() = default; virtual void run() = 0; - virtual void input(PlayerInput&& inputdata) = 0; + virtual void input(GameEvent&& inputdata) = 0; virtual void update(UpdateData&& updatedata) = 0; virtual void display() const = 0; }; + +} \ No newline at end of file diff --git a/include/core/gameevent.h b/include/core/gameevent.h new file mode 100644 index 0000000..4bb117d --- /dev/null +++ b/include/core/gameevent.h @@ -0,0 +1,15 @@ +#pragma once + +#include "core/systemevent.h" +#include "core/time.h" + +namespace kku +{ + +struct GameEvent +{ + const microsec timestamp = 0; + const SystemEvent event; +}; + +} diff --git a/include/core/line.h b/include/core/line.h new file mode 100644 index 0000000..22d2d95 --- /dev/null +++ b/include/core/line.h @@ -0,0 +1,18 @@ +#pragma once + +#include "core/point.h" +#include "core/color.h" + +namespace kku +{ + +class Line +{ +public: + virtual ~Line() = default; + virtual void setPosition(const kku::Point& p1, const kku::Point& p2) = 0; + virtual void setColor(const kku::Color& c1, const kku::Color& c2) = 0; + virtual void display() = 0; +}; + +} \ No newline at end of file diff --git a/include/core/music.h b/include/core/music.h new file mode 100644 index 0000000..a1aa949 --- /dev/null +++ b/include/core/music.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "core/time.h" + +namespace kku +{ + +class Music +{ +public: + virtual ~Music() = default; + + virtual bool open(const std::string& filepath) = 0; + + virtual void play() = 0; + virtual void pause() = 0; + virtual void stop() = 0; + + virtual bool isPlaying() const = 0; + + virtual void setVolume(float volume) = 0; + + virtual void setOffset(const kku::microsec& offset) = 0; + virtual void moveOffset(const kku::microsec& delta) = 0; + + virtual kku::microsec fetchOffset() = 0; + virtual kku::microsec getDuration() const = 0; +}; + +} diff --git a/core/shared/core/note.h b/include/core/note.h similarity index 62% rename from core/shared/core/note.h rename to include/core/note.h index 93c984f..9db5844 100644 --- a/core/shared/core/note.h +++ b/include/core/note.h @@ -1,6 +1,10 @@ #pragma once -#include "core/inputtype.h" +#include "core/time.h" +#include "core/gameevent.h" + +namespace kku +{ class Note { @@ -16,34 +20,40 @@ public: virtual bool isInGame() const = 0; virtual bool shouldRemove() const = 0; - const microsec& offset() const noexcept + virtual void input(kku::GameEvent&& input) = 0; + + inline const microsec& getPerfectOffset() const noexcept { return _perfect_offset; } bool operator<(const Note& note) const { - return (_perfect_offset < note._perfect_offset); + return _perfect_offset < note._perfect_offset; } bool operator==(const Note& note) const { - return (_perfect_offset == note._perfect_offset); + return _perfect_offset == note._perfect_offset; } bool operator>(const Note& note) const { - return (_perfect_offset > note._perfect_offset); + return _perfect_offset > note._perfect_offset; } protected: microsec _perfect_offset; }; -struct NotePtrCompt +struct NotePtrComparator { bool operator()(const Note* lhs, const Note* rhs) const noexcept { - return lhs->offset() < rhs->offset(); + return lhs->getPerfectOffset() < rhs->getPerfectOffset(); } }; + +} + + diff --git a/include/core/point.h b/include/core/point.h new file mode 100644 index 0000000..a79192a --- /dev/null +++ b/include/core/point.h @@ -0,0 +1,46 @@ +#pragma once + +namespace kku +{ + +struct Point +{ + float x; + float y; + + constexpr inline explicit Point() noexcept : + x(0.), y(0.) + {} + + constexpr inline explicit Point(int x, int y) noexcept : + x(x), y(y) + {} + + constexpr inline explicit Point(float x, float y) noexcept : + x(x), y(y) + {} + + constexpr inline Point operator+(const Point& right) const noexcept + { + return Point{right.x + x, right.y + y}; + } + + constexpr inline Point operator-(const Point& right) const noexcept + { + return Point{right.x - x, right.y - y}; + } + + inline void moveBy(float x, float y) noexcept + { + this->x += x; + this->y += y; + } + + inline void scaleBy(float factor) noexcept + { + x *= factor; + y *= factor; + } +}; + +} \ No newline at end of file diff --git a/core/shared/core/precisionevaluator.h b/include/core/precisionevaluator.h similarity index 87% rename from core/shared/core/precisionevaluator.h rename to include/core/precisionevaluator.h index 416648c..2491643 100644 --- a/core/shared/core/precisionevaluator.h +++ b/include/core/precisionevaluator.h @@ -1,7 +1,4 @@ -#ifndef PRECISIONEVALUATOR_H -#define PRECISIONEVALUATOR_H - -#include "tools/mathutils.h" +#pragma once #include #include @@ -9,6 +6,11 @@ #include #include +#include "core/time.h" + +namespace kku +{ + template::value>> class PrecisionEvaluator { @@ -32,11 +34,12 @@ public: && music_play_offset < _end_handling_offset; } - inline Grade calculatePrecision(microsec odds) const noexcept + Grade calculatePrecision(microsec odds) const { microsec shift_from_perfect = std::abs(odds - offset()); - std::cout << "Shift " << ((odds > _offset) ? "late: " : "early: ") << shift_from_perfect << "\n"; + std::cout << "Shift " << ((odds > _offset) ? "late: " : "early: ") + << shift_from_perfect << "\n"; std::size_t raw_grade; for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade) @@ -63,4 +66,4 @@ private: const std::vector _intervals; }; -#endif // PRECISIONEVALUATOR_H +} diff --git a/include/core/rectangle.h b/include/core/rectangle.h new file mode 100644 index 0000000..546e0bb --- /dev/null +++ b/include/core/rectangle.h @@ -0,0 +1,26 @@ +#pragma once + +#include "core/area.h" +#include "core/color.h" + +namespace kku +{ + +class Rectangle +{ +public: + virtual ~Rectangle() = default; + virtual void setRect(const Area& rect) = 0; + virtual Area getRect() const = 0; + + virtual void setPosition(const Point& position) = 0; + virtual Point getPosition() const = 0; + virtual void move(const kku::Vector2& delta) = 0; + + virtual void setColor(const Color& color) = 0; + virtual bool contains(const kku::Point& position) const = 0; + + virtual void display() = 0; +}; + +} diff --git a/include/core/resourceholder.h b/include/core/resourceholder.h new file mode 100644 index 0000000..fee19ed --- /dev/null +++ b/include/core/resourceholder.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace kku +{ + +template +class ResourceHolder +{ +public: + inline void load(Id id, std::unique_ptr&& resource) noexcept + { + _resources[id] = std::move(resource); + } + + inline const std::shared_ptr& get(Id id) const + { + return _resources.find(id)->second; + } + +private: + std::map> _resources; +}; + +namespace Font +{ + enum class Id + { + GUI + }; +} + +} \ No newline at end of file diff --git a/include/sprite.h b/include/core/sprite.h similarity index 88% rename from include/sprite.h rename to include/core/sprite.h index 9f68944..6a67176 100644 --- a/include/sprite.h +++ b/include/core/sprite.h @@ -1,5 +1,8 @@ #pragma once +namespace kku +{ + class Sprite { public: @@ -7,3 +10,5 @@ public: virtual void reset() = 0; virtual void display() const = 0; }; + +} \ No newline at end of file diff --git a/include/spritecontainer.h b/include/core/spritecontainer.h similarity index 98% rename from include/spritecontainer.h rename to include/core/spritecontainer.h index 5542c5b..82e81cb 100644 --- a/include/spritecontainer.h +++ b/include/core/spritecontainer.h @@ -4,6 +4,9 @@ #include #include +namespace kku +{ + template::value>> class SpriteContainer @@ -56,3 +59,5 @@ private: std::size_t _poll_reserve_size; }; + +} \ No newline at end of file diff --git a/include/core/systemevent.h b/include/core/systemevent.h new file mode 100644 index 0000000..89c85ce --- /dev/null +++ b/include/core/systemevent.h @@ -0,0 +1,65 @@ +#pragma once + +#include + +#include "core/point.h" + +namespace kku +{ + +struct SystemEvent +{ + enum class Type + { + None = 0, + + Resize = 1, + + KeyPress = 2, + KeyRelease = 3, + + MouseWheelScroll = 4, + MouseMove = 5, + MousePress = 6, + MouseRelease = 7 + }; + + struct Size + { + std::size_t width = 0; + std::size_t height = 0; + }; + + struct Key + { + char view = char(0); + bool alt = false; + bool control = false; + bool shift = false; + }; + + struct Mouse + { + Point position; + + bool scrolled_up = false; + + enum class Button + { + None = 0, + Wheel = 1, + Left = 2, + Right = 3 + }; + + Button button = Button::Left; + }; + + struct None + {}; + + Type type = Type::None; + std::variant data; +}; + +} \ No newline at end of file diff --git a/include/core/text.h b/include/core/text.h new file mode 100644 index 0000000..ec9fe35 --- /dev/null +++ b/include/core/text.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include "core/color.h" +#include "core/point.h" +#include "core/vector.h" + +namespace kku +{ + +class Text +{ +public: + virtual ~Text() = default; + virtual void setString(const std::string& string) = 0; + virtual void setCharacterSize(std::size_t pixels) = 0; + virtual void setPosition(const Point& point) = 0; + virtual void move(const kku::Vector2& delta) = 0; + virtual void setColor(const Color& color) = 0; + + virtual void display() = 0; +}; + +} diff --git a/include/core/time.h b/include/core/time.h new file mode 100644 index 0000000..3fa70f4 --- /dev/null +++ b/include/core/time.h @@ -0,0 +1,22 @@ +#pragma once + +namespace kku +{ + +using microsec = long long; + +struct TimeRange +{ + const microsec begin = 0; + const microsec end = 0; + + constexpr inline explicit TimeRange() noexcept : + begin(0), end(0) + {} + + constexpr inline explicit TimeRange(microsec x, microsec y) noexcept : + begin(x), end(y) + {} +}; + +} diff --git a/core/shared/core/timeline.h b/include/core/timeline.h similarity index 85% rename from core/shared/core/timeline.h rename to include/core/timeline.h index 2f91009..d8f33b5 100644 --- a/core/shared/core/timeline.h +++ b/include/core/timeline.h @@ -3,11 +3,13 @@ #include #include #include -#include -#include "tools/mathutils.h" +#include "core/time.h" #include "core/note.h" +namespace kku +{ + template ::value>> class Timeline { @@ -29,7 +31,7 @@ public: while (!isExpired(head_iterator)) { - if ((*head_iterator)->offset() >= offset) + if ((*head_iterator)->getPerfectOffset() >= offset) { Iterator pre_head = head_iterator; --pre_head; @@ -48,7 +50,7 @@ public: } } - void setNotes(const std::set& notes) + void setNotes(const std::set& notes) { _timeline = std::move(notes); @@ -65,7 +67,7 @@ public: update(_current_offset); } - void insertNotes(const std::set& notes) + void insertNotes(const std::set& notes) { _timeline.insert(notes.begin(), notes.end()); recalculate(_current_offset); @@ -100,7 +102,7 @@ public: return_note = note_iterator; break; } - else if (note->offset() > music_offset) + else if (note->getPerfectOffset() > music_offset) break; ++note_iterator; @@ -114,7 +116,7 @@ public: return std::find_if(_timeline.begin(), _timeline.end(), [music_offset](const auto& note) { - return note->offset() == music_offset; + return note->getPerfectOffset() == music_offset; }); } @@ -134,14 +136,14 @@ public: } private: - std::set _timeline; + std::set _timeline; microsec _current_offset; inline void updateTopNote(const microsec& music_offset) noexcept { const auto& top_note = *_top_note; - bool already_played = top_note->offset() < music_offset + bool already_played = top_note->getPerfectOffset() < music_offset && !top_note->isActive(music_offset); if (already_played) @@ -150,3 +152,7 @@ private: Iterator _top_note; }; + +} + + diff --git a/include/core/updatedata.h b/include/core/updatedata.h new file mode 100644 index 0000000..17a2183 --- /dev/null +++ b/include/core/updatedata.h @@ -0,0 +1,16 @@ +#pragma once + +#include "core/time.h" + +namespace kku +{ + +struct UpdateData +{ + const microsec timestamp; + const microsec dt; +}; + +} + + diff --git a/include/core/vector.h b/include/core/vector.h new file mode 100644 index 0000000..7a8fd02 --- /dev/null +++ b/include/core/vector.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace kku +{ + +/* Meaning an element of a vector space in math. + * Don't mistake for std::vector + * For now we don't need it as a special class, + * so let it be a wrapper. */ + +template +using Vector2 = std::pair; + +template +inline constexpr auto makeVector(T&& l, T&& r) -> Vector2 +{ + return std::make_pair(std::forward(l), std::forward(r)); +} + +} diff --git a/include/state.h b/include/state.h deleted file mode 100644 index eb8b2ac..0000000 --- a/include/state.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -class GUIState : public sf::Drawable -{ -public: - - enum Tag { - SPLASH_SCREEN, - MAIN_MENU, - GAME_PICKER, - GAME, - EDITOR_PICKER, - EDITOR, - SETTINGS, - - AMOUNT - }; - - virtual ~GUIState() = default; - - virtual void input(const sf::Event& event) = 0; - virtual void update(const sf::Time& dt) = 0; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override = 0; - - virtual void enter(sf::Vector2u&& render_size) = 0; - virtual void leave() = 0; -}; diff --git a/modes/classicmode/CMakeLists.txt b/modes/classicmode/CMakeLists.txt deleted file mode 100644 index fd7c6a4..0000000 --- a/modes/classicmode/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -cmake_minimum_required(VERSION 2.8.8) - -project(classicmode) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(${CMAKE_SOURCE_DIR}/include) - -file(GLOB_RECURSE HEADERS "shared/*.h" ) - -file(GLOB_RECURSE SOURCES "editor/*.h" "editor/*.cpp" - "graphics/*.h" "graphics/*.cpp" - "game/*.h" "game/*.cpp" - "sfml/*.h" "sfml/*.cpp" - - "./classicfactory.cpp") - -add_library(classicmode STATIC ${SOURCES} ${HEADERS}) -target_include_directories(classicmode PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared) -target_include_directories(classicmode PRIVATE ${CMAKE_SOURCE_DIR}/core/shared) -target_link_libraries(classicmode tools core) - -target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/modes/classicmode/shared) - diff --git a/modes/classicmode/editor/classiceditor.h b/modes/classicmode/editor/classiceditor.h deleted file mode 100644 index 418e8e5..0000000 --- a/modes/classicmode/editor/classiceditor.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include - -#include "core/editor.h" -#include "core/timeline.h" - -#include "game/classicnote.h" -#include "classicmode/classicactions.h" - -class ClassicGraphicsManager; - -class ClassicEditor : public Editor -{ -public: - explicit ClassicEditor(const std::shared_ptr>& timeline, - const std::shared_ptr& graphics_manager); - - virtual void input(PlayerInput&& inputdata) override; - virtual void update(UpdateData&& updatedata) override; - virtual void display() const override; - virtual void recalculate(const microsec& timestamp) override; - - void selectNoteType(Type type) noexcept; - -private: - inline microsec adjustOffset(microsec offset) const noexcept; - - Context _context; - - const std::shared_ptr> _timeline; - const std::shared_ptr _graphics_manager; - - Type _selected_type; - microsec _current_time; - microsec _scroll_step; -}; diff --git a/modes/classicmode/editor/mockclassicnote.cpp b/modes/classicmode/editor/mockclassicnote.cpp deleted file mode 100644 index 14aadfc..0000000 --- a/modes/classicmode/editor/mockclassicnote.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "mockclassicnote.h" -#include "graphics/classicgraphicsmanager.h" -#include "graphics/animations/classicanimationscenario.h" - -MockClassicNote::MockClassicNote(MockArrowNoteInitializer&& init) : - ClassicNote({nullptr, {}, init.initializer.perfect_offset}), - _state(State::NONE), - _context(init.initializer.context) -{ - _elements.resize(init.elements.size()); - - for (std::size_t i = 0; i < _elements.size(); ++i) - { - _elements[i].coordinates = init.elements[i].coordinates; - _elements[i].type = init.elements[i].type; - } -} - -void MockClassicNote::putToGame() -{ - _state = State::FLYING; -} - -void MockClassicNote::update(const microsec &music_offset) -{ - switch (_state) - { - default: return; - break; - - case State::FLYING: - if (music_offset > offset()) - _state = State::DEAD; - break; - } - - for (auto& element : _elements) - if (element.animations[_state]) - element.animations[_state]->update(music_offset); -} - diff --git a/modes/classicmode/editor/mockclassicnote.h b/modes/classicmode/editor/mockclassicnote.h deleted file mode 100644 index 1165093..0000000 --- a/modes/classicmode/editor/mockclassicnote.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include - -#include "mockelement.h" -#include "game/classicnote.h" -#include "initializers/mockarrownoteinitializer.h" - -class MockClassicNote : public ClassicNote -{ -public: - explicit MockClassicNote(MockArrowNoteInitializer&& init); - virtual ~MockClassicNote() override = default; - - virtual void putToGame() override; - virtual void update(const microsec &music_offset) override; - virtual void input(PlayerInput&& inputdata) override; - - virtual void display(const ClassicGraphicsManager * const manager) const override; - virtual void setGraphics(ClassicGraphicsManager * const manager, TimeRange&& range) override; - -private: - std::vector _elements; - - State _state; - const Context *_context; -}; diff --git a/modes/classicmode/editor/mockelement.h b/modes/classicmode/editor/mockelement.h deleted file mode 100644 index 08b8aba..0000000 --- a/modes/classicmode/editor/mockelement.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "classicmode/classicactions.h" -#include "tools/mathutils.h" - -#include -#include -#include - -class ClassicSprite; -class ClassicAnimationScenario; - -struct MockElement -{ - std::shared_ptr sprite; - std::array, 4> animations; - Type type = Type::NONE; - - Coordinates coordinates; - std::vector falling_curve_interpolation; -}; \ No newline at end of file diff --git a/modes/classicmode/game/classicgame.cpp b/modes/classicmode/game/classicgame.cpp deleted file mode 100644 index 642d7b2..0000000 --- a/modes/classicmode/game/classicgame.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "classicgame.h" -#include "classicnote.h" -#include "classicmapcreator.h" -#include "graphics/classicscenegraphicsmanager.h" -#include "holdmanager.h" - -ClassicGame::ClassicGame(const std::shared_ptr>& timeline, - const std::shared_ptr& graphics_manager) : - _timeline(timeline), - _graphics_manager(graphics_manager), - _hold_manager(std::make_unique()) -{ - _slap_buffer.loadFromFile("Tick.ogg"); - _slap.setBuffer(_slap_buffer); - _slap.setVolume(50); - - _keys_to_buttons = - { - {sf::Keyboard::Up, Type::UP}, // Load from settings - {sf::Keyboard::Right, Type::RIGHT}, - {sf::Keyboard::Down, Type::DOWN}, - {sf::Keyboard::Left, Type::LEFT}, - - {sf::Keyboard::W, Type::UP}, - {sf::Keyboard::D, Type::RIGHT}, - {sf::Keyboard::S, Type::DOWN}, - {sf::Keyboard::A, Type::LEFT}, - - {sf::Keyboard::E, Type::SLIDER_RIGHT}, - {sf::Keyboard::Q, Type::SLIDER_LEFT} - }; - - _buttons_to_pressed_actions= - { - {Type::UP, Action::PRESS_UP}, - {Type::RIGHT, Action::PRESS_RIGHT}, - {Type::DOWN, Action::PRESS_DOWN}, - {Type::LEFT, Action::PRESS_LEFT}, - - {Type::SLIDER_RIGHT, Action::PRESS_SLIDER_RIGHT}, - {Type::SLIDER_LEFT, Action::PRESS_SLIDER_LEFT} - }; - - _buttons_to_released_actions= - { - {Type::UP, Action::RELEASE_UP}, - {Type::RIGHT, Action::RELEASE_RIGHT}, - {Type::DOWN, Action::RELEASE_DOWN}, - {Type::LEFT, Action::RELEASE_LEFT}, - - {Type::SLIDER_RIGHT, Action::RELEASE_SLIDER_RIGHT}, - {Type::SLIDER_LEFT, Action::RELEASE_SLIDER_LEFT} - }; -} - -ClassicGame::~ClassicGame() -{} - -void ClassicGame::run() -{ - _context.hold_manager = _hold_manager; - - auto beatmap = classic::createBeatmap("aa", _context); - _timeline->setNotes(beatmap.notes); -} - -void ClassicGame::input(PlayerInput&& inputdata) -{ - switch (inputdata.event.type) - { - default: - return; - break; - - case sf::Event::KeyPressed: - { - auto note_it = _timeline->getActiveNote(inputdata.timestamp); - - if (!_timeline->isExpired(note_it)) - { - auto note = (*note_it); - note->input(std::move(inputdata)); - _slap.play(); - } - } - break; - - case sf::Event::KeyReleased: - { - _hold_manager->checkRelease(inputdata.event.key.code); - } - break; - - } -} - -void ClassicGame::update(UpdateData&& updatedata) -{ - // UNCOMMENT TO TEST AUTOPLAY - auto note_it = _timeline->getActiveNote(updatedata.timestamp); - - if (!_timeline->isExpired(note_it) && updatedata.timestamp >= (*note_it)->offset()) - { - auto note = (*note_it); - note->input(PlayerInput{updatedata.timestamp, sf::Event{}}); - _slap.play(); - } - - _timeline->update(updatedata.timestamp); - _graphics_manager->update(updatedata.timestamp); -} - -void ClassicGame::display() const -{ - _graphics_manager->display(); -} diff --git a/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp b/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp deleted file mode 100644 index d18853e..0000000 --- a/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "classicdyinganimationscenario.h" -#include "graphics/classicsprite.h" - -void ClassicDyingAnimationScenario::launch(const std::shared_ptr sprite, const microsec& time_begin, const microsec &time_end) -{ - _sprite = sprite; - _time_begin = time_begin; - _time_end = time_end; - - _sprite->setColor(sf::Color(140, 140, 140)); - _sprite->setTrailColor(sf::Color(0, 0, 0, 0)); - _sprite->setTrailCoordinates(Coordinates(0, 0)); -} - -void ClassicDyingAnimationScenario::update(const microsec& music_offset) -{ - (void) music_offset; - - auto fill_color = _sprite->color(); - - if (fill_color.a == 0) - { - fill_color.a = 0; - _sprite->setColor(fill_color); - return; - } - - auto new_alpha = fill_color.a - 15; - fill_color.a = new_alpha < 0 ? 0 : new_alpha; - - _sprite->setColor(fill_color); -} - -bool ClassicDyingAnimationScenario::isDone() const -{ - return _sprite->color().a == 0; -} diff --git a/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp b/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp deleted file mode 100644 index 34e20b7..0000000 --- a/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "classicflyinganimationscenario.h" -#include "graphics/classicsprite.h" - -void ClassicFlyingAnimationScenario::launch(const std::shared_ptr sprite, const microsec& time_begin, const microsec &time_end) -{ - _sprite = sprite; - _time_begin = time_begin; - _time_end = time_end; - - _percentage = ((_time_end - _time_begin) * 0.01); -} - -float ClassicFlyingAnimationScenario::getPoint(float n1, float n2, float perc) const -{ - float diff = n2 - n1; - - return n1 + ( diff * perc ); -} - -void ClassicFlyingAnimationScenario::update(const microsec& music_offset) -{ - const auto crd = _sprite->coordinates(); - auto update_time = music_offset - _time_begin; - float i = update_time / _percentage * 0.01; - - float xa = getPoint( crd.x + 20. , crd.x + 90. , i ); - float ya = getPoint( crd.y - 600. , crd.y - 150. , i ); - float xb = getPoint( crd.x + 90. , crd.x , i ); - float yb = getPoint( crd.y - 150. , crd.y , i ); - - _sprite->setTrailCoordinates(Coordinates(getPoint( xa , xb , i ), getPoint( ya , yb , i ))); - - bool pastPerfectScore = (i >= 1); - - if (pastPerfectScore) - fadeTrailSprite(); -} - -bool ClassicFlyingAnimationScenario::isDone() const -{ - return false; -} - -void ClassicFlyingAnimationScenario::fadeTrailSprite() const -{ - auto fill_color = _sprite->trailColor(); - - if (fill_color.a == 0) - return; - - auto new_alpha = fill_color.a - 35; - fill_color.a = new_alpha < 0 ? 0 : new_alpha; - - _sprite->setTrailColor(fill_color); -} diff --git a/modes/classicmode/graphics/classicscenegraphicsmanager.h b/modes/classicmode/graphics/classicscenegraphicsmanager.h deleted file mode 100644 index 0d4cdc9..0000000 --- a/modes/classicmode/graphics/classicscenegraphicsmanager.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "game/classicnote.h" -#include "graphics/classicgraphicsmanager.h" -#include "core/timeline.h" - -class ClassicSprite; - -class ClassicSceneGraphicsManager : public ClassicGraphicsManager -{ -public: - explicit ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, - const std::shared_ptr& factory, - const microsec& visibility_offset); - - virtual void display() const override; - virtual void update(const microsec& offset) override; - - virtual void display(const std::vector& elements) const override; - virtual void setGraphics(std::vector& elements, TimeRange&& range) override; - -protected: - using Iterator = Timeline::Iterator; - - Iterator _first; - Iterator _last; - - const std::shared_ptr> _timeline; - - inline bool nothingToDraw() const noexcept; - inline bool isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const noexcept; - //inline sf::VertexArray makeLine(const Coordinates& c1, const Coordinates& c2) const; - - void fetchFirstNote(const microsec& offset); - void fetchLastNote(const microsec& offset); - void updateVisibleNotes(const microsec& offset); -}; diff --git a/modes/classicmode/graphics/classicsprite.cpp b/modes/classicmode/graphics/classicsprite.cpp deleted file mode 100644 index b2f94de..0000000 --- a/modes/classicmode/graphics/classicsprite.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "classicsprite.h" -#include - -ClassicSprite::ClassicSprite(const std::shared_ptr &render_target, - const sf::RectangleShape& shape) : - _prototype(shape), - _shape(shape), - _trail(shape), - _render_target(render_target) -{} - -void ClassicSprite::reset() -{ - _shape.setPosition(0, 0); - _trail.setPosition(0, 0); - - _shape = _prototype; - _trail = _prototype; -} - -void ClassicSprite::setCoordinates(const Coordinates& coordinates) -{ - _shape.setPosition(coordinates.x, coordinates.y); -} - -void ClassicSprite::setTrailCoordinates(const Coordinates &coordinates) -{ - _trail.setPosition(coordinates.x, coordinates.y); -} - -Coordinates ClassicSprite::coordinates() const -{ - return Coordinates(_shape.getPosition().x, _shape.getPosition().y); -} - -Coordinates ClassicSprite::trailCoordinates() const -{ - return Coordinates(_trail.getPosition().x, _trail.getPosition().y); -} - -void ClassicSprite::setColor(const sf::Color& color) -{ - _shape.setFillColor(color); -} - -void ClassicSprite::setTrailColor(const sf::Color& color) -{ - _trail.setFillColor(color); -} - -sf::Color ClassicSprite::color() const -{ - return _shape.getFillColor(); -} - -sf::Color ClassicSprite::trailColor() const -{ - return _trail.getFillColor(); -} - -void ClassicSprite::display() const -{ - _render_target->draw(_shape); - _render_target->draw(_trail); -} diff --git a/modes/classicmode/graphics/classicsprite.h b/modes/classicmode/graphics/classicsprite.h deleted file mode 100644 index 390d7ee..0000000 --- a/modes/classicmode/graphics/classicsprite.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include -#include "tools/mathutils.h" -#include "sprite.h" -#include -#include - -class ClassicSprite : public Sprite -{ -public: - explicit ClassicSprite(const std::shared_ptr& render_target, - const sf::RectangleShape& shape); - virtual void reset() override; - virtual void display() const override; - - void setCoordinates(const Coordinates &coordinates); - void setTrailCoordinates(const Coordinates &coordinates); - Coordinates coordinates() const; - Coordinates trailCoordinates() const; - - void setColor(const sf::Color& color); - void setTrailColor(const sf::Color& color); - sf::Color color() const; - sf::Color trailColor() const; - -private: - sf::RectangleShape _prototype; - - sf::RectangleShape _shape; - sf::RectangleShape _trail; - - const std::shared_ptr _render_target; -}; diff --git a/modes/classicmode/include/classicmode/elementinitializer.h b/modes/classicmode/include/classicmode/elementinitializer.h deleted file mode 100644 index f64b897..0000000 --- a/modes/classicmode/include/classicmode/elementinitializer.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "classicactions.h" -#include "core/inputtype.h" -#include "tools/mathutils.h" - -#include - -struct ElementInitializer -{ - Type type = Type::NONE; - Coordinates coordinates; - std::vector falling_curve_interpolation; -}; diff --git a/modes/classicmode/sfml/classicspritesfml.cpp b/modes/classicmode/sfml/classicspritesfml.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/modes/classicmode/sfml/classicspritesfml.h b/modes/classicmode/sfml/classicspritesfml.h deleted file mode 100644 index e69de29..0000000 diff --git a/modes/classicmode/shared/classicmode/classicfactorysfml.h b/modes/classicmode/shared/classicmode/classicfactorysfml.h deleted file mode 100644 index 99f79a7..0000000 --- a/modes/classicmode/shared/classicmode/classicfactorysfml.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -#include - -class Game; -class Editor; - -namespace classic -{ - std::unique_ptr initGame(const std::shared_ptr& render_target); - std::unique_ptr initEditor(const std::shared_ptr& render_target); -} diff --git a/src/application/CMakeLists.txt b/src/application/CMakeLists.txt new file mode 100644 index 0000000..c7f43d9 --- /dev/null +++ b/src/application/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.13) + +project(application) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared) + +file(GLOB_RECURSE HEADERS "shared/*.h" "include/*.h") +file(GLOB_RECURSE SOURCES "src/*.cpp") + +add_library(application STATIC ${SOURCES} ${HEADERS}) +target_link_libraries(application tools classicmode) +target_include_directories(application PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(application PRIVATE ${CMAKE_SOURCE_DIR}/src/modes/classicmode/shared) +target_include_directories(application PRIVATE ${CMAKE_SOURCE_DIR}/src/tools/shared) + +target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/src/application/shared) diff --git a/src/application/application.cpp b/src/application/application.cpp deleted file mode 100644 index eb28ec6..0000000 --- a/src/application/application.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "application.h" -#include "core/inputtype.h" -#include "core/editor.h" - -#include "mainmenu.h" -#include "gamestate.h" -#include "editorstate.h" - -#include "tools/music.h" -#include "classicmode/classicfactorysfml.h" - -#include - -const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 90.f); - -Application::Application() : - _game_window(std::make_unique(sf::VideoMode{1280, 720}, "Test", sf::Style::Default)) -{ - _font_holder.load(Fonts::Id::GUI, "SourceCodePro-Regular.ttf"); - - _game_window->setFramerateLimit(60); - _game_window->setKeyRepeatEnabled(false); - _game_window->setMouseCursorGrabbed(false); - _game_window->setVerticalSyncEnabled(true); - - MainMenu::Callbacks callbacks = - { - [&](){ pushState(GUIState::Tag::GAME); }, - [&](){ pushState(GUIState::Tag::EDITOR); } - }; - - EditorState::Callbacks editor_callbacks = {[&](){ popState(); }}; - - const auto main_menu = std::make_shared(std::move(callbacks), _font_holder); - const auto game_state = std::make_shared(classic::initGame(_game_window), GameState::Callbacks()); - const auto editor = std::make_shared(classic::initEditor(_game_window), std::move(editor_callbacks), _font_holder); - - _states[GUIState::Tag::MAIN_MENU] = main_menu; - _states[GUIState::Tag::GAME] = game_state; - _states[GUIState::Tag::EDITOR] = editor; - - pushState(GUIState::Tag::MAIN_MENU); -} - -void Application::run() -{ - _game_window->display(); - exec(); -} - -void Application::exec() -{ - sf::Clock timer; - sf::Time time_since_last_update = sf::Time::Zero; - - while (_game_window->isOpen()) - { - time_since_last_update += timer.restart(); - - input(); - - bool isOneFramePassed = time_since_last_update >= TIME_PER_FRAME; - if (isOneFramePassed) - { - time_since_last_update -= TIME_PER_FRAME; - update(time_since_last_update); - draw(); - } - } -} - -void Application::input() -{ - sf::Event event; - while (_game_window->pollEvent(event)) - { - switch(event.type) - { - case sf::Event::Closed: - _game_window->close(); - break; - - default: - _state_stack.back()->input(event); - break; - } - } -} - -void Application::update(const sf::Time& dt) -{ - _state_stack.back()->update(dt); -} - -void Application::draw() -{ - _game_window->clear(); - - for (const auto& state : _state_stack) - _game_window->draw(*state); - - _game_window->display(); -} - -void Application::pushState(GUIState::Tag new_state) -{ - if (!_state_stack.empty()) - _state_stack.back()->leave(); - - _state_stack.emplace_back(_states.at(new_state)); - _state_stack.back()->enter(_game_window->getSize()); -} - -void Application::popState() -{ - _state_stack.back()->leave(); - _state_stack.pop_back(); - _state_stack.back()->enter(_game_window->getSize()); -} diff --git a/src/application/application.h b/src/application/application.h deleted file mode 100644 index e817879..0000000 --- a/src/application/application.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "core/game.h" -#include "state.h" - -#include "tools/music.h" -#include "tools/resourceholder.h" - -class Application -{ -public: - explicit Application(); - void run(); - void input(); - void update(const sf::Time& dt); - void draw(); - -private: - std::array, GUIState::Tag::AMOUNT> _states; - std::vector> _state_stack; - - std::shared_ptr _game_window; - Music _music; - - void exec(); - void pushState(GUIState::Tag new_state); - void popState(); - - FontHolder _font_holder; -}; diff --git a/src/application/editorstate.h b/src/application/editorstate.h deleted file mode 100644 index 8f5e3f0..0000000 --- a/src/application/editorstate.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "state.h" -#include "tools/music.h" -#include "tools/resourceholder.h" -#include - -class BPMCalculator; -class Group; -class Editor; - -class EditorState : public GUIState -{ -public: - - struct Callbacks - { - std::function onLeaveEditorState; - }; - - explicit EditorState(std::unique_ptr&& editor, Callbacks&& callbacks, const FontHolder& font_holder); - virtual ~EditorState() override; - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - - virtual void enter(sf::Vector2u&& render_size) override; - virtual void leave() override; - -private: - const std::shared_ptr _font; - - Callbacks _callbacks; - - Music _music; - std::shared_ptr _bpm_calculator; - std::shared_ptr _group; - - std::unique_ptr _editor; -}; - diff --git a/src/application/gamestate.cpp b/src/application/gamestate.cpp deleted file mode 100644 index 1d96cf2..0000000 --- a/src/application/gamestate.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "gamestate.h" -#include "widgets/button.h" -#include "widgets/group.h" - -#include "core/game.h" - -GameState::GameState(const std::shared_ptr& game, Callbacks&& callbacks) : - _game(game), - _onLeaveGameCallback(callbacks.onLeaveGame) -{} - -void GameState::input(const sf::Event& event) -{ - if (event.key.code == sf::Keyboard::Space && event.type == sf::Event::KeyReleased) - _music.isPaused() ? _music.play() : _music.pause(); - - _game->input(PlayerInput{_music.fetchOffset(), event}); -} - -void GameState::update(const sf::Time& dt) -{ - _game->update(UpdateData{_music.fetchOffset(), dt}); -} - -void GameState::draw(sf::RenderTarget &target, sf::RenderStates states) const -{ - (void)target; (void)states; - _game->display(); -} - -void GameState::enter(sf::Vector2u&& render_size) -{ - (void)render_size; // We will need this later when I add UI to game state - _game->run(); - - _music.openFromFile("METEOR.flac"); - _music.setVolume(10); - _music.play(); -} - -void GameState::leave() -{ - _onLeaveGameCallback(); -} diff --git a/src/application/gamestate.h b/src/application/gamestate.h deleted file mode 100644 index 806a56b..0000000 --- a/src/application/gamestate.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "state.h" -#include "tools/music.h" -#include - -class Group; -class Game; - -class GameState : public GUIState -{ -public: - - struct Callbacks - { - std::function onLeaveGame; - }; - - - explicit GameState(const std::shared_ptr& game, Callbacks&& callbacks); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - - virtual void enter(sf::Vector2u&& render_size) override; - virtual void leave() override; - -private: - Music _music; - std::shared_ptr _game; - - std::function _onEnterGameCallback; - std::function _onLeaveGameCallback; -}; - diff --git a/src/application/include/application/editorstate.h b/src/application/include/application/editorstate.h new file mode 100644 index 0000000..6c1a1e0 --- /dev/null +++ b/src/application/include/application/editorstate.h @@ -0,0 +1,43 @@ +#pragma once + +#include "application/state.h" +#include "core/corefactory.h" +#include "core/music.h" + +class BPMCalculator; +class Group; + +namespace kku +{ +class Editor; +} + +class EditorState : public GUIState +{ +public: + + struct Callbacks + { + std::function onLeaveEditorState; + }; + + explicit EditorState(const std::shared_ptr& core_factory, std::unique_ptr&& editor, Callbacks&& callbacks); + virtual ~EditorState() override; + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + + virtual void enter() override; + virtual void leave() override; + +private: + const Callbacks _callbacks; + const std::shared_ptr _core_factory; + std::shared_ptr _music; + + std::shared_ptr _bpm_calculator; + std::shared_ptr _group; + + std::unique_ptr _editor; +}; + diff --git a/src/application/include/application/gamestate.h b/src/application/include/application/gamestate.h new file mode 100644 index 0000000..e3fa346 --- /dev/null +++ b/src/application/include/application/gamestate.h @@ -0,0 +1,35 @@ +#pragma once + +#include "state.h" +#include "core/music.h" +#include "core/game.h" + +class Group; + +class GameState : public GUIState +{ +public: + + struct Callbacks + { + std::function onLeaveGame; + }; + + + explicit GameState(const std::shared_ptr& game, Callbacks&& callbacks); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + + virtual void enter() override; + virtual void leave() override; + +private: + std::shared_ptr _music; + std::shared_ptr _game; + + std::function _onEnterGameCallback; + std::function _onLeaveGameCallback; +}; + diff --git a/src/application/include/application/mainmenu.h b/src/application/include/application/mainmenu.h new file mode 100644 index 0000000..2970001 --- /dev/null +++ b/src/application/include/application/mainmenu.h @@ -0,0 +1,32 @@ +#pragma once + +#include "application/state.h" +#include "core/corefactory.h" + +class Group; + +class MainMenu : public GUIState +{ +public: + + struct Callbacks + { + std::function onAppendGameState; + std::function onAppendEditorState; + }; + + explicit MainMenu(const std::shared_ptr& factory, Callbacks&& callbacks); + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + + virtual void enter() override; + virtual void leave() override; + +private: + const Callbacks _callbacks; + const std::shared_ptr _core_factory; + + std::shared_ptr _buttons; +}; + diff --git a/src/application/include/application/state.h b/src/application/include/application/state.h new file mode 100644 index 0000000..c48a421 --- /dev/null +++ b/src/application/include/application/state.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +#include "core/systemevent.h" +#include "core/vector.h" +#include "core/time.h" + +class GUIState +{ +public: + + enum Tag { + SPLASH_SCREEN, + MAIN_MENU, + GAME_PICKER, + GAME, + EDITOR_PICKER, + EDITOR, + SETTINGS, + + AMOUNT + }; + + virtual ~GUIState() = default; + + virtual void input(const kku::SystemEvent& event) = 0; + virtual void update(const kku::microsec& dt) = 0; + virtual void display() const = 0; + + virtual void enter() = 0; + virtual void leave() = 0; +}; diff --git a/src/application/mainmenu.cpp b/src/application/mainmenu.cpp deleted file mode 100644 index 15a7617..0000000 --- a/src/application/mainmenu.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "mainmenu.h" -#include "widgets/pushbutton.h" -#include "widgets/group.h" - -MainMenu::MainMenu(Callbacks&& callbacks, const FontHolder& font_holder) : - _font(font_holder.get(Fonts::Id::GUI)), - _callbacks(std::move(callbacks)), - _buttons(std::make_shared()) -{ -} - -void MainMenu::input(const sf::Event& event) -{ - _buttons->input(event); -} - -void MainMenu::update(const sf::Time& dt) -{ - _buttons->update(dt); -} - -void MainMenu::draw(sf::RenderTarget &target, sf::RenderStates states) const -{ - target.draw(*_buttons, states); -} - -void MainMenu::enter(sf::Vector2u&& render_size) -{ - const float window_width = render_size.x; - const float window_height = render_size.y; - - auto button_start = std::make_shared("Start", _font, 48); - button_start->setRect(sf::FloatRect(window_width / 3., window_height / 7., window_width / 3., window_height / 7.)); - button_start->setCallback(_callbacks.onAppendGameState); - - auto button_editor = std::make_shared("Editor", _font, 48); - button_editor->setRect(sf::FloatRect(window_width / 3., window_height / 7. * 3, window_width / 3., window_height / 7.)); - button_editor->setCallback(_callbacks.onAppendEditorState); - - _buttons->addChild(button_start); - _buttons->addChild(button_editor); - - _buttons->setVisibility(); -} - -void MainMenu::leave() -{ - _buttons->setVisibility(false); -} - diff --git a/src/application/mainmenu.h b/src/application/mainmenu.h deleted file mode 100644 index a792df5..0000000 --- a/src/application/mainmenu.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "state.h" -#include "tools/resourceholder.h" -#include - -class Group; - -class MainMenu : public GUIState -{ -public: - - struct Callbacks - { - std::function onAppendGameState; - std::function onAppendEditorState; - }; - - explicit MainMenu(Callbacks&& callbacks, const FontHolder &font_holder); - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - - virtual void enter(sf::Vector2u&& render_size) override; - virtual void leave() override; - -private: - const std::shared_ptr _font; - const Callbacks _callbacks; - - std::shared_ptr _buttons; -}; - diff --git a/src/application/shared/application/application.h b/src/application/shared/application/application.h new file mode 100644 index 0000000..3892930 --- /dev/null +++ b/src/application/shared/application/application.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +#include "../../include/application/state.h" // HOW? WHY DOESN'T "application/state.h" LINK ON BY ITSELF +#include "core/corefactory.h" + +class ClassicFactory; + +class Application +{ +public: + virtual ~Application() = default; + virtual bool init(); + virtual void display() = 0; + virtual void run() = 0; + + void input(const kku::SystemEvent& input); + void update(const kku::microsec& dt); + +protected: + std::shared_ptr _core_factory; + std::shared_ptr _game_factory; + + std::array, GUIState::Tag::AMOUNT> _states; + std::vector> _state_stack; + + void pushState(GUIState::Tag new_state); + void popState(); +}; diff --git a/src/application/src/application.cpp b/src/application/src/application.cpp new file mode 100644 index 0000000..28341d8 --- /dev/null +++ b/src/application/src/application.cpp @@ -0,0 +1,61 @@ +#include "application/application.h" +#include "core/gameevent.h" +#include "core/editor.h" + +#include "application/mainmenu.h" +#include "application/gamestate.h" +#include "application/editorstate.h" + +#include "classicmode/classicfactory.h" + +bool Application::init() +{ + if (!_game_factory || !_core_factory) + return false; + + MainMenu::Callbacks callbacks = + { + [&](){ pushState(GUIState::Tag::GAME); }, + [&](){ pushState(GUIState::Tag::EDITOR); } + }; + + EditorState::Callbacks editor_callbacks = {[&](){ popState(); }}; + + const auto main_menu = std::make_shared(_core_factory, std::move(callbacks)); + const auto game_state = std::make_shared(_game_factory->getGame(), GameState::Callbacks()); + const auto editor = std::make_shared(_core_factory, _game_factory->getEditor(), std::move(editor_callbacks)); + + _states[GUIState::Tag::MAIN_MENU] = main_menu; + _states[GUIState::Tag::GAME] = game_state; + _states[GUIState::Tag::EDITOR] = editor; + + pushState(GUIState::Tag::MAIN_MENU); + + return true; +} + +void Application::input(const kku::SystemEvent& event) +{ + _state_stack.back()->input(event); +} + +void Application::update(const kku::microsec& dt) +{ + _state_stack.back()->update(dt); +} + +void Application::pushState(GUIState::Tag new_state) +{ + if (!_state_stack.empty()) + _state_stack.back()->leave(); + + _state_stack.emplace_back(_states.at(new_state)); + _state_stack.back()->enter(); +} + +void Application::popState() +{ + _state_stack.back()->leave(); + _state_stack.pop_back(); + _state_stack.back()->enter(); +} diff --git a/src/application/editorstate.cpp b/src/application/src/editorstate.cpp similarity index 55% rename from src/application/editorstate.cpp rename to src/application/src/editorstate.cpp index a04ffba..9e091e4 100644 --- a/src/application/editorstate.cpp +++ b/src/application/src/editorstate.cpp @@ -1,4 +1,4 @@ -#include "editorstate.h" +#include "application/editorstate.h" #include "widgets/button.h" #include "widgets/group.h" #include "widgets/menubar.h" @@ -9,36 +9,37 @@ #include "core/editor.h" -#include - -EditorState::EditorState(std::unique_ptr&& editor, Callbacks&& callbacks, const FontHolder& font_holder) : - _font(font_holder.get(Fonts::Id::GUI)), +EditorState::EditorState(const std::shared_ptr& core_factory, + std::unique_ptr&& editor, + Callbacks&& callbacks) : _callbacks(std::move(callbacks)), + _core_factory(core_factory), _editor(std::move(editor)) {} EditorState::~EditorState() {} -void EditorState::input(const sf::Event& event) +void EditorState::input(const kku::SystemEvent& event) { _group->input(event); } -void EditorState::update(const sf::Time& dt) +void EditorState::update(const kku::microsec& dt) { _group->update(dt); } -void EditorState::draw(sf::RenderTarget &target, sf::RenderStates states) const +void EditorState::display() const { - target.draw(*_group, states); + _group->display(); } -void EditorState::enter(sf::Vector2u &&render_size) +void EditorState::enter() { - _music.openFromFile("METEOR.flac"); - _music.setVolume(5); + _music = _core_factory->getMusic(); + _music->open("METEOR.flac"); + _music->setVolume(5.f); auto& group = _group; auto& music = _music; @@ -46,15 +47,15 @@ void EditorState::enter(sf::Vector2u &&render_size) _bpm_calculator = std::make_shared(); auto& bpm_calculator = _bpm_calculator; - std::shared_ptr bpm_widget = std::make_shared(_bpm_calculator, _font); + std::shared_ptr bpm_widget = std::make_shared(_bpm_calculator, _core_factory); - auto button_start = std::make_shared("Start", _font); - auto button_stop = std::make_shared("Stop", _font); - auto button_apply = std::make_shared("Apply", _font); + auto button_start = std::make_shared("Start", _core_factory); + auto button_stop = std::make_shared("Stop", _core_factory); + auto button_apply = std::make_shared("Apply", _core_factory); button_start->setCallback([bpm_calculator, button_start, button_stop, &music]() { - music.play(); + music->play(); bpm_calculator->start(); button_start->setVisibility(false); button_stop->setVisibility(true); @@ -62,7 +63,7 @@ void EditorState::enter(sf::Vector2u &&render_size) button_stop->setCallback([bpm_calculator, button_start, button_stop, &music]() { - music.stop(); + music->stop(); bpm_calculator->stop(); button_start->setVisibility(true); button_stop->setVisibility(false); @@ -70,7 +71,7 @@ void EditorState::enter(sf::Vector2u &&render_size) button_apply->setCallback([&editor, bpm_calculator]() { - BPMSection section; + kku::BPMSection section; const auto& info = bpm_calculator->fetchApproximatedInfo(); section.bpm = info.BPM; section.interval = info.interval; @@ -84,21 +85,22 @@ void EditorState::enter(sf::Vector2u &&render_size) bpm_widget_init.stop = button_stop; bpm_widget_init.apply = button_apply; bpm_widget_init.start = button_start; - bpm_widget_init.current_time = [&music]() -> microsec { return music.fetchOffset(); }; + bpm_widget_init.current_time = [&music]() -> kku::microsec { return music->fetchOffset(); }; bpm_widget->init(std::move(bpm_widget_init)); const auto bpm_widget_callback = [&group, bpm_widget=bpm_widget, &music]() { - music.stop(); + music->stop(); bpm_widget->setVisibility(false); group->unblock(); }; - const float window_width = render_size.x; + const auto render_size = _core_factory->getRenderSize(); + const float window_width = render_size.first; - auto menu_bar = std::make_shared(_font); + auto menu_bar = std::make_shared(_core_factory); - auto bpm_button = std::make_shared("Calculate BPM", _font); + auto bpm_button = std::make_shared("Calculate BPM", _core_factory); bpm_button->setCallback([&group, bpm_widget=bpm_widget]() { @@ -106,29 +108,29 @@ void EditorState::enter(sf::Vector2u &&render_size) bpm_widget->setVisibility(true); }); - bpm_widget->setRect(sf::FloatRect(render_size.x / 3, render_size.y / 3, - render_size.x / 3, render_size.y / 3)); + bpm_widget->setRect(kku::Area{render_size.first / 3.f, render_size.second / 3.f, + render_size.first / 3.f, render_size.second / 3.f}); bpm_widget->addBarButton("X", bpm_widget_callback); bpm_widget->setVisibility(false); - auto test_menu_2 = std::make_shared(); - test_menu_2->setRect(sf::FloatRect{0, 0, 200, 27 * 5}); + auto test_menu_2 = std::make_shared(_core_factory); + test_menu_2->setRect(kku::Area{0., 0., 200., 27. * 5.}); - auto test_menu_3 = std::make_shared(); - test_menu_3->setRect(sf::FloatRect{0, 0, 200, 27 * 5}); + auto test_menu_3 = std::make_shared(_core_factory); + test_menu_3->setRect(kku::Area{0., 0., 200., 27. * 5.}); - auto test_cascade_button = std::make_shared("Show submenu", _font); + auto test_cascade_button = std::make_shared("Show submenu", _core_factory); - auto test_cascade_button_2 = std::make_shared("Show submenu 2", _font); + auto test_cascade_button_2 = std::make_shared("Show submenu 2", _core_factory); - auto quit_button = std::make_shared("Quit", _font); + auto quit_button = std::make_shared("Quit", _core_factory); quit_button->setCallback(_callbacks.onLeaveEditorState); - auto test_menu = std::make_shared(); - test_menu->setRect(sf::FloatRect{0, 0, 200, 27 * 3}); + auto test_menu = std::make_shared(_core_factory); + test_menu->setRect(kku::Area{0., 0., 200., 27. * 3.}); - menu_bar->setRect(sf::FloatRect(0, 0, window_width, 27)); + menu_bar->setRect(kku::Area{0., 0., window_width, 27.}); menu_bar->addRootSubMenu("test", test_menu); menu_bar->addDependentSubmenu(test_menu_2); menu_bar->addDependentSubmenu(test_menu_3); @@ -148,28 +150,29 @@ void EditorState::enter(sf::Vector2u &&render_size) menu_bar->setVisibility(true); EditorWidget::Callbacks callbacks; - callbacks.onDraw = [&editor](sf::RenderTarget& target, sf::RenderStates states) + callbacks.onDisplay = [&editor]() { - (void)target; (void)states; // fucking shit i am a retard damn fuck fuck editor->display(); }; - callbacks.onInput = [&editor, &music](const sf::Event& event) + callbacks.onInput = [&editor, &music](const kku::SystemEvent& event) { - if (event.key.code == sf::Keyboard::Space && event.type == sf::Event::KeyReleased) - music.isPaused() ? music.play() : music.pause(); - else if (event.type == sf::Event::MouseWheelScrolled) + if (event.type == kku::SystemEvent::Type::KeyRelease + && std::get(event.data).view == ' ') + music->isPlaying() ? music->pause() : music->play(); + else if (event.type == kku::SystemEvent::Type::MouseWheelScroll) { - music.moveOffset(event.mouseWheelScroll.delta > 0 ? 500000 : -500000); - editor->recalculate(music.fetchOffset()); + const auto& up = std::get(event.data).scrolled_up; + music->moveOffset(up ? 500000 : -500000); + editor->recalculate(music->fetchOffset()); } else - editor->input(PlayerInput{music.fetchOffset(), event}); + editor->input(kku::GameEvent{music->fetchOffset(), event}); }; - callbacks.onUpdate = [&editor, &music](const sf::Time& dt) + callbacks.onUpdate = [&editor, &music](const kku::microsec& dt) { - editor->update(UpdateData{music.fetchOffset(), dt}); + editor->update(kku::UpdateData{music->fetchOffset(), dt}); }; auto editor_widget = std::make_shared(std::move(callbacks)); diff --git a/src/application/src/gamestate.cpp b/src/application/src/gamestate.cpp new file mode 100644 index 0000000..9771dda --- /dev/null +++ b/src/application/src/gamestate.cpp @@ -0,0 +1,49 @@ +#include "application/gamestate.h" +#include "widgets/button.h" +#include "widgets/group.h" + +#include "core/game.h" + +GameState::GameState(const std::shared_ptr& game, Callbacks&& callbacks) : + _game(game), + _onLeaveGameCallback(callbacks.onLeaveGame) +{} + +void GameState::input(const kku::SystemEvent& event) +{ + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::KeyRelease: + if (std::get(event.data).view == ' ') + _music->isPlaying() ? _music->pause() : _music->play(); + } + + _game->input(kku::GameEvent{_music->fetchOffset(), event}); +} + +void GameState::update(const kku::microsec& dt) +{ + _game->update(kku::UpdateData{_music->fetchOffset(), dt}); +} + +void GameState::display() const +{ + _game->display(); +} + +void GameState::enter() +{ + _game->run(); + + _music->open("METEOR.flac"); + _music->setVolume(10); + _music->play(); +} + +void GameState::leave() +{ + _onLeaveGameCallback(); +} diff --git a/src/application/src/mainmenu.cpp b/src/application/src/mainmenu.cpp new file mode 100644 index 0000000..b19e5e8 --- /dev/null +++ b/src/application/src/mainmenu.cpp @@ -0,0 +1,53 @@ +#include "application/mainmenu.h" +#include "widgets/pushbutton.h" +#include "widgets/group.h" + +MainMenu::MainMenu(const std::shared_ptr& factory, MainMenu::Callbacks&& callbacks) : + _callbacks(std::move(callbacks)), + _core_factory(factory), + _buttons(std::make_shared()) +{ +} + +void MainMenu::input(const kku::SystemEvent& event) +{ + _buttons->input(event); +} + +void MainMenu::update(const kku::microsec& dt) +{ + _buttons->update(dt); +} + +void MainMenu::display() const +{ + _buttons->display(); +} + +void MainMenu::enter() +{ + const auto render_size = _core_factory->getRenderSize(); + const float window_width = render_size.first; + const float window_height = render_size.second; + + auto button_start = std::make_shared("Start", _core_factory, 48); + button_start->setRect(kku::Area{window_width / 3.f, window_height / 7.f, + window_width / 3.f, window_height / 7.f}); + button_start->setCallback(_callbacks.onAppendGameState); + + auto button_editor = std::make_shared("Editor", _core_factory, 48); + button_editor->setRect(kku::Area{window_width / 3.f, window_height / 7.f * 3, + window_width / 3.f, window_height / 7.f}); + button_editor->setCallback(_callbacks.onAppendEditorState); + + _buttons->addChild(button_start); + _buttons->addChild(button_editor); + + _buttons->setVisibility(); +} + +void MainMenu::leave() +{ + _buttons->setVisibility(false); +} + diff --git a/src/application/src/widgets/bpmcalculatorwidget.cpp b/src/application/src/widgets/bpmcalculatorwidget.cpp new file mode 100644 index 0000000..807fff2 --- /dev/null +++ b/src/application/src/widgets/bpmcalculatorwidget.cpp @@ -0,0 +1,140 @@ +#include "bpmcalculatorwidget.h" +#include "tools/bpmcalculator.h" +#include "core/editor.h" + +#include + +BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr& factory) : + Window(factory, "BPM Calculation"), + _bpm_calculator(bpm_calculator), + _slider(std::make_shared()), + _core_factory(factory), + _ticked(false) +{ + _bpm_value = _core_factory->getText(kku::Font::Id::GUI); + _bpm_value->setCharacterSize(40); + _bpm_value->setColor(kku::Color{0, 0, 0, 255}); + _bpm_value->setString("--"); + /*_slap_buffer.loadFromFile("Tick.ogg"); + _slap.setBuffer(_slap_buffer); + _slap.setVolume(30.);*/ +} + +void BPMCalculatorWidget::input(const kku::SystemEvent& event) +{ + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::KeyPress: + { + if (std::get(event.data).view == ' ') + { + _bpm_calculator->click(_current_time()); + } + break; + } + } + + Window::input(event); +} + +void BPMCalculatorWidget::update(const kku::microsec& dt) +{ + Window::update(dt); + + const auto beat_info = _bpm_calculator->fetchApproximatedInfo(); + if (beat_info.BPM != 0) + { + _bpm_value->setString(std::to_string(static_cast(beat_info.BPM))); + + const kku::microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time()); + const auto time_relation = static_cast(beat_info.interval) / static_cast(until_beat); + const auto slider_path_left = _slider->getRect().width / time_relation; + if (slider_path_left < 50) + { + //if (!_ticked) + //_slap.play(); + _ticked = true; + } + else + _ticked = false; + + _slider->setTickPosition(slider_path_left); + } +} + +void BPMCalculatorWidget::display() const +{ + Window::display(); + + if (_is_visible) + { + _slider->display(); + _button_start->display(); + _button_stop->display(); + _button_apply->display(); + _bpm_value->display(); + } +} + +void BPMCalculatorWidget::setRect(const kku::Area& rect) +{ + Window::setRect(rect); + _slider->setRect(kku::Area{0, 0, rect.width / 8 * 6, 100}); + _slider->setPosition(kku::Point{_window_content->getRect().left + rect.width / 8, + _window_content->getRect().top + rect.height / 8 * 3}); + + _button_start->setRect(kku::Area{0, 0, rect.width / 10 * 3, 30}); + _button_start->setPosition(kku::Point{_window_content->getRect().left + rect.width / 7, + _window_content->getRect().top + _window_content->getRect().height - 40}); + + _button_stop->setRect(kku::Area{0, 0, rect.width / 10 * 3, 30}); + _button_stop->setPosition(kku::Point{_window_content->getRect().left + rect.width / 7, + _window_content->getRect().top + _window_content->getRect().height - 40}); + + _button_apply->setRect(kku::Area{0, 0, rect.width / 10 * 3, 30}); + _button_apply->setPosition(kku::Point{_window_content->getRect().left + 50 + (2 * (rect.width / 7)), + _window_content->getRect().top + _window_content->getRect().height - 40}); + + _bpm_value->setPosition(kku::Point{_window_content->getRect().left + rect.width / 8, + _window_content->getRect().top + rect.height / 8 }); +} + +void BPMCalculatorWidget::move(const kku::Vector2& delta) +{ + Window::move(delta); + + _slider->move(delta); + _bpm_value->move(delta); +} + +void BPMCalculatorWidget::setPosition(const kku::Point& position) +{ + Window::setPosition(position); +} + +void BPMCalculatorWidget::init(Init &&init) +{ + _button_start = init.start; + _button_stop = init.stop; + _button_apply = init.apply; + + _current_time = init.current_time; + + addChild(_button_start); + addChild(_button_stop); + addChild(_button_apply); + + _button_stop->setVisibility(false); +} + +void BPMCalculatorWidget::setVisibility(bool is_visible) +{ + Window::setVisibility(is_visible); + + bool can_stop = _bpm_calculator->calculating(); + _button_stop->setVisibility(can_stop && is_visible); + _button_start->setVisibility(!can_stop && is_visible); +} diff --git a/src/application/src/widgets/bpmcalculatorwidget.h b/src/application/src/widgets/bpmcalculatorwidget.h new file mode 100644 index 0000000..2c65f84 --- /dev/null +++ b/src/application/src/widgets/bpmcalculatorwidget.h @@ -0,0 +1,54 @@ +#pragma once + +#include "core/time.h" +#include "core/text.h" +#include "window.h" +#include "bpmslider.h" +#include "pushbutton.h" + +#include + +class BPMCalculator; +class Editor; + +class BPMCalculatorWidget : public Window +{ +public: + + struct Init + { + std::shared_ptr start; + std::shared_ptr stop; + std::shared_ptr apply; + std::function current_time; + }; + + explicit BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr& factory); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + + virtual void setRect(const kku::Area& rect) override; + virtual void setPosition(const kku::Point& position) override; + + virtual void setVisibility(bool is_visible = true) override; + + void init(Init&& init); + +private: + std::shared_ptr _button_start; + std::shared_ptr _button_stop; + std::shared_ptr _button_apply; + + std::shared_ptr _bpm_calculator; + std::shared_ptr _slider; + + const std::shared_ptr _core_factory; + + bool _ticked; + std::shared_ptr _bpm_value; + std::function _current_time; +}; + diff --git a/src/application/src/widgets/bpmslider.cpp b/src/application/src/widgets/bpmslider.cpp new file mode 100644 index 0000000..506edcf --- /dev/null +++ b/src/application/src/widgets/bpmslider.cpp @@ -0,0 +1,66 @@ +#include "bpmslider.h" + +BPMSlider::BPMSlider() +{ + _slider_background->setColor(kku::Color{0, 0, 0, 255}); + _slider_tick->setColor(kku::Color{255, 0, 0, 255}); +} + +void BPMSlider::input(const kku::SystemEvent& event) +{ + Widget::input(event); +} + +void BPMSlider::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void BPMSlider::display() const +{ + _slider_background->display(); + _slider_tick->display(); + Widget::display(); +} + +void BPMSlider::setRect(const kku::Area& rect) +{ + _slider_background->setRect(rect); + _slider_tick->setRect(kku::Area{rect.left, + rect.top, + rect.width / 30.f, + rect.height}); +} + +void BPMSlider::setPosition(const kku::Point& position) +{ + _slider_background->setPosition(position); + _slider_tick->setPosition(position); +} + +void BPMSlider::move(const kku::Vector2& delta) +{ + _slider_background->move(delta); + _slider_tick->move(delta); +} + +bool BPMSlider::isUnderMouse(const kku::Point& position) const +{ + return _slider_background->contains(position); +} + +kku::Area BPMSlider::getRect() const +{ + return _slider_background->getRect(); +} + +kku::Point BPMSlider::getPosition() const +{ + return _slider_background->getPosition(); +} + +void BPMSlider::setTickPosition(float x_position) +{ + _slider_tick->setPosition(kku::Point{_slider_background->getPosition().x + x_position, + _slider_tick->getPosition().y}); +} diff --git a/src/application/src/widgets/bpmslider.h b/src/application/src/widgets/bpmslider.h new file mode 100644 index 0000000..cc1985a --- /dev/null +++ b/src/application/src/widgets/bpmslider.h @@ -0,0 +1,30 @@ +#pragma once + +#include "widget.h" +#include "core/rectangle.h" + +class BPMSlider : public Widget +{ +public: + explicit BPMSlider(); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + + void setTickPosition(float x_position); + +private: + std::shared_ptr _slider_background; + std::shared_ptr _slider_tick; +}; + + diff --git a/src/application/src/widgets/button.cpp b/src/application/src/widgets/button.cpp new file mode 100644 index 0000000..840c9f8 --- /dev/null +++ b/src/application/src/widgets/button.cpp @@ -0,0 +1,70 @@ +#include "button.h" +#include + +Button::Button(const std::string &text, const std::shared_ptr& factory, unsigned int font_size) : + _core_factory(factory) +{ + _button_text = _core_factory->getText(kku::Font::Id::GUI); + _button_text->setString(text); + _button_text->setColor(kku::Color{0, 0, 0, 255}); + _button_text->setCharacterSize(font_size); +} + +void Button::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void Button::display() const +{ + if (_is_visible) + { + _button_content->display(); + _button_text->display(); + } + + Widget::display(); +} + +void Button::setRect(const kku::Area& rect) +{ + _button_content->setRect(rect); + _button_text->setPosition(kku::Point{rect.left + 5, + rect.top + 5}); +} + +void Button::setPosition(const kku::Point& position) +{ + _button_content->setPosition(position); + + auto new_point = position; + new_point.moveBy(5.f, 5.f); + _button_text->setPosition(new_point); +} + +void Button::move(const kku::Vector2& delta) +{ + _button_content->move(delta); + _button_text->move(delta); + Widget::move(delta); +} + +bool Button::isUnderMouse(const kku::Point& position) const +{ + return _is_visible && _button_content->contains(position); +} + +void Button::setText(const std::string& text) +{ + _button_text->setString(text); +} + +kku::Area Button::getRect() const +{ + return _button_content->getRect(); +} + +kku::Point Button::getPosition() const +{ + return _button_content->getPosition(); +} diff --git a/src/application/src/widgets/button.h b/src/application/src/widgets/button.h new file mode 100644 index 0000000..6e75e1d --- /dev/null +++ b/src/application/src/widgets/button.h @@ -0,0 +1,33 @@ +#pragma once + +#include "widget.h" +#include "core/corefactory.h" + +#include + +class Button : public Widget +{ +public: + explicit Button(const std::string& text, const std::shared_ptr& factory, unsigned int font_size); + + virtual void input(const kku::SystemEvent& event) override = 0; + virtual void update(const kku::microsec& dt) override final; + virtual void display() const override final; + virtual void move(const kku::Vector2& delta) override final; + virtual bool isUnderMouse(const kku::Point& position) const override final; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + + virtual void setText(const std::string& text); + +protected: + std::shared_ptr _button_content; + std::shared_ptr _button_text; + + const std::shared_ptr _core_factory; +}; + diff --git a/src/application/src/widgets/cascademenubutton.cpp b/src/application/src/widgets/cascademenubutton.cpp new file mode 100644 index 0000000..8d03488 --- /dev/null +++ b/src/application/src/widgets/cascademenubutton.cpp @@ -0,0 +1,75 @@ +#include "cascademenubutton.h" +#include "menudrop.h" + +CascadeMenuButton::CascadeMenuButton(const std::string& text, const std::shared_ptr& factory, unsigned int font_size) : + Button(text, factory, font_size) +{ + _color_idle = kku::Color{230, 230, 230, 255}; + _color_hover = kku::Color{84, 158, 253, 255}; + _button_content->setColor(_color_idle); +} + +void CascadeMenuButton::input(const kku::SystemEvent& event) +{ + if (!_submenu) + return; + + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::MouseMove: + { + const auto position = std::get(event.data).position; + if (isUnderMouse(position)) + { + _button_content->setColor(_color_hover); + _submenu->lock(); + _submenu->setVisibility(true); + } + else + { + _submenu->unlock(); + if (!_submenu->isVisible()) + { + _button_content->setColor(_color_idle); + } + } + break; + } + + } +} + +void CascadeMenuButton::setRect(const kku::Area& rect) +{ + Button::setRect(rect); + resetRect(); +} + +void CascadeMenuButton::setSubmenu(const std::shared_ptr& submenu) +{ + _submenu = submenu; + resetRect(); +} + +const std::shared_ptr CascadeMenuButton::submenu() const +{ + return _submenu; +} + +void CascadeMenuButton::resetRect() +{ + if (_submenu) + { + _submenu->setPosition(kku::Point{_button_content->getPosition().x + _button_content->getRect().width, + _button_content->getPosition().y}); + } +} + +void CascadeMenuButton::setFillColors(kku::Color&& idle_color, kku::Color&& hover_color) +{ + _color_idle = idle_color; + _color_hover = hover_color; +} diff --git a/src/application/widgets/cascademenubutton.h b/src/application/src/widgets/cascademenubutton.h similarity index 51% rename from src/application/widgets/cascademenubutton.h rename to src/application/src/widgets/cascademenubutton.h index 352df4f..abfb670 100644 --- a/src/application/widgets/cascademenubutton.h +++ b/src/application/src/widgets/cascademenubutton.h @@ -7,19 +7,19 @@ class MenuDrop; class CascadeMenuButton : public Button { public: - explicit CascadeMenuButton(const std::string& text, const std::shared_ptr& font, unsigned int font_size = 12); - virtual void input(const sf::Event& event) override final; - virtual void setRect(const sf::FloatRect& rect) override final; + explicit CascadeMenuButton(const std::string& text, const std::shared_ptr& factory, unsigned int font_size = 12); + virtual void input(const kku::SystemEvent& event) override final; + virtual void setRect(const kku::Area& rect) override final; void setSubmenu(const std::shared_ptr& submenu); const std::shared_ptr submenu() const; void resetRect(); - void setFillColors(sf::Color&& idle_color, sf::Color&& hover_color); + void setFillColors(kku::Color&& idle_color, kku::Color&& hover_color); private: std::shared_ptr _submenu; - sf::Color _color_idle; - sf::Color _color_hover; + kku::Color _color_idle; + kku::Color _color_hover; }; diff --git a/src/application/src/widgets/editorwidget.cpp b/src/application/src/widgets/editorwidget.cpp new file mode 100644 index 0000000..bc2a3e4 --- /dev/null +++ b/src/application/src/widgets/editorwidget.cpp @@ -0,0 +1,55 @@ +#include "editorwidget.h" +#include "core/editor.h" + +EditorWidget::EditorWidget(Callbacks&& callbacks) : + _input(std::move(callbacks.onInput)), + _update(std::move(callbacks.onUpdate)), + _draw(std::move(callbacks.onDisplay)) +{} + +void EditorWidget::input(const kku::SystemEvent& event) +{ + _input(event); +} + +void EditorWidget::update(const kku::microsec& dt) +{ + _update(dt); +} + +void EditorWidget::display() const +{ + _draw(); +} + +void EditorWidget::move(const kku::Vector2& delta) +{ + (void)delta; + // delegate to children +} + +bool EditorWidget::isUnderMouse(const kku::Point& position) const +{ + return _parent->isUnderMouse(position); +} + +void EditorWidget::setRect(const kku::Area& rect) +{ + (void)rect; + // basically useless beacuse editor widget fills the entire screen +} + +kku::Area EditorWidget::getRect() const +{ + return {}; +} + +void EditorWidget::setPosition(const kku::Point& position) +{ + (void)position; +} + +kku::Point EditorWidget::getPosition() const +{ + return kku::Point{}; +} diff --git a/src/application/src/widgets/editorwidget.h b/src/application/src/widgets/editorwidget.h new file mode 100644 index 0000000..6ff404c --- /dev/null +++ b/src/application/src/widgets/editorwidget.h @@ -0,0 +1,36 @@ +#pragma once + +#include "widget.h" +#include + +class EditorWidget : public Widget +{ +public: + + struct Callbacks + { + std::function onInput; + std::function onUpdate; + std::function onDisplay; + }; + + explicit EditorWidget(Callbacks&& callbacks); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + +private: + std::function _input; + std::function _update; + std::function _draw; +}; + diff --git a/src/application/src/widgets/group.cpp b/src/application/src/widgets/group.cpp new file mode 100644 index 0000000..2642584 --- /dev/null +++ b/src/application/src/widgets/group.cpp @@ -0,0 +1,55 @@ +#include "group.h" + +void Group::input(const kku::SystemEvent& event) +{ + Widget::input(event); +} + +void Group::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void Group::display() const +{ + Widget::display(); +} + +void Group::setRect(const kku::Area& rect) +{ + _rect = rect; +} + +void Group::setPosition(const kku::Point& position) +{ + _rect.top = position.y; + _rect.left = position.x; +} + +void Group::move(const kku::Vector2& delta) +{ + _rect.top += delta.first; + _rect.left += delta.second; + + Widget::move(delta); +} + +bool Group::isUnderMouse(const kku::Point& position) const +{ + return _rect.contains(position); +} + +kku::Area Group::getRect() const +{ + return _rect; +} + +kku::Point Group::getPosition() const +{ + return kku::Point + { + _rect.top, + _rect.left + }; +} + diff --git a/src/application/src/widgets/group.h b/src/application/src/widgets/group.h new file mode 100644 index 0000000..6c6f2fe --- /dev/null +++ b/src/application/src/widgets/group.h @@ -0,0 +1,23 @@ +#pragma once + +#include "widget.h" + +class Group : public Widget +{ +public: + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + +private: + kku::Area _rect; +}; + diff --git a/src/application/src/widgets/menubar.cpp b/src/application/src/widgets/menubar.cpp new file mode 100644 index 0000000..e6e568e --- /dev/null +++ b/src/application/src/widgets/menubar.cpp @@ -0,0 +1,131 @@ +#include "menubar.h" + +MenuBar::MenuBar(const std::shared_ptr& factory) : + _core_factory(factory), + _bar_rect(factory->getRectangle()), + _amount_buttons(0), + _button_width(170) +{ + _bar_rect->setColor(kku::Color{88, 57, 107, 255}); +} + +void MenuBar::input(const kku::SystemEvent &event) +{ + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::MouseRelease: + { + const auto position = std::get(event.data).position; + if (!isUnderMouse(position)) + { + for (auto& submenu : _submenus) + submenu->unlock(); + } + break; + } + } + + Widget::input(event); +} + +void MenuBar::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void MenuBar::display() const +{ + if (_is_visible) + _bar_rect->display(); + + Widget::display(); +} + +void MenuBar::setRect(const kku::Area& rect) +{ + _bar_rect->setRect(rect); + + // Buttons will not resize +} + +void MenuBar::setPosition(const kku::Point& position) +{ + _bar_rect->setPosition(position); +} + +void MenuBar::move(const kku::Vector2& delta) +{ + _bar_rect->move(delta); + + Widget::move(delta); + + for (auto& menu : _submenus) + menu->move(delta); +} + +bool MenuBar::isUnderMouse(const kku::Point& position) const +{ + bool bar_under_mouse = _bar_rect->contains(position); + + bool submenus_under_mouse = std::any_of(_children.begin(), _children.end(), + [p=position](const auto& child) + { + return child->isUnderMouse(p); + }); + + return bar_under_mouse || submenus_under_mouse; +} + +void MenuBar::addRootSubMenu(std::string name, const std::shared_ptr& submenu) +{ + const auto new_button = std::make_shared(name, _core_factory); + + std::size_t current_index = _amount_buttons; + new_button->setRect(kku::Area{static_cast(current_index * _button_width), + 0.f, + static_cast(_button_width), + _bar_rect->getRect().height}); + new_button->setCallback([submenu=submenu]() + { + submenu->setVisibility(true); + submenu->lock(); + }); + + submenu->setPosition(kku::Point{static_cast(current_index * _button_width), + _bar_rect->getRect().height}); + + new_button->setColors(kku::Color{171, 141, 189, 255}, + kku::Color{48, 27, 57, 255}); + addChild(new_button); + addChild(submenu); + + _submenus.emplace_back(submenu); + + ++_amount_buttons; +} + +void MenuBar::addDependentSubmenu(const std::shared_ptr &submenu) +{ + _submenus.emplace_back(submenu); +} + +void MenuBar::setVisibility(bool is_visible) +{ + Widget::setVisibility(is_visible); + + for (auto& submenu : _submenus) + submenu->setVisibility(false); +} + +kku::Area MenuBar::getRect() const +{ + return _bar_rect->getRect(); +} + +kku::Point MenuBar::getPosition() const +{ + return _bar_rect->getPosition(); +} diff --git a/src/application/src/widgets/menubar.h b/src/application/src/widgets/menubar.h new file mode 100644 index 0000000..d356a47 --- /dev/null +++ b/src/application/src/widgets/menubar.h @@ -0,0 +1,35 @@ +#pragma once + +#include "widget.h" +#include "menudrop.h" +#include "button.h" + +class MenuBar : public Widget +{ +public: + explicit MenuBar(const std::shared_ptr& factory); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + virtual void setVisibility(bool is_visible = true) override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + + void addRootSubMenu(std::string name, const std::shared_ptr& submenu); + void addDependentSubmenu(const std::shared_ptr& submenu); + +private: + const std::shared_ptr _core_factory; + const std::shared_ptr _bar_rect; + std::size_t _amount_buttons; + std::size_t _button_width; + + std::vector> _submenus; +}; diff --git a/src/application/widgets/menudrop.cpp b/src/application/src/widgets/menudrop.cpp similarity index 50% rename from src/application/widgets/menudrop.cpp rename to src/application/src/widgets/menudrop.cpp index 1eebfbc..8b6165f 100644 --- a/src/application/widgets/menudrop.cpp +++ b/src/application/src/widgets/menudrop.cpp @@ -1,16 +1,17 @@ #include "menudrop.h" -#include "menuseparator.h" +#include "core/corefactory.h" -MenuDrop::MenuDrop() : +MenuDrop::MenuDrop(const std::shared_ptr& factory) : _is_locked(false), _button_height(27), _button_index(0) { _is_visible = false; - _content_rect.setFillColor(sf::Color(200, 200, 200)); + _content_rect = factory->getRectangle(); + _content_rect->setColor(kku::Color{200, 200, 200, 255}); } -void MenuDrop::input(const sf::Event& event) +void MenuDrop::input(const kku::SystemEvent& event) { if (!_is_visible) return; @@ -22,8 +23,10 @@ void MenuDrop::input(const sf::Event& event) default: break; - case sf::Event::MouseButtonReleased: - if (isUnderMouse(event.mouseButton.x, event.mouseButton.y)) + case kku::SystemEvent::Type::MouseRelease: + { + const auto position = std::get(event.data).position; + if (isUnderMouse(position)) { setVisibility(false); for (auto& submenu : _submenus) @@ -33,14 +36,19 @@ void MenuDrop::input(const sf::Event& event) } } break; - case sf::Event::MouseMoved: - if (!isUnderMouse(event.mouseMove.x, event.mouseMove.y)) + } + + case kku::SystemEvent::Type::MouseMove: + { + const auto position = std::get(event.data).position; + if (!isUnderMouse(position)) { if (!isLocked() && !hasActiveSubmenus()) setVisibility(false); } break; } + } } bool MenuDrop::hasActiveSubmenus() const @@ -52,33 +60,32 @@ bool MenuDrop::hasActiveSubmenus() const }); } -void MenuDrop::update(const sf::Time& dt) +void MenuDrop::update(const kku::microsec& dt) { Widget::update(dt); } -void MenuDrop::draw(sf::RenderTarget& target, sf::RenderStates states) const +void MenuDrop::display() const { if (_is_visible) - target.draw(_content_rect); + _content_rect->display(); - Widget::draw(target, states); + Widget::display(); } -void MenuDrop::setRect(const sf::FloatRect& rect) +void MenuDrop::setRect(const kku::Area& rect) { - _content_rect.setPosition(rect.left, rect.top); - _content_rect.setSize({rect.width, rect.height}); + _content_rect->setRect(rect); } -void MenuDrop::setPosition(const sf::Vector2f& position) +void MenuDrop::setPosition(const kku::Point& position) { - _content_rect.setPosition(position); + _content_rect->setPosition(position); } -void MenuDrop::move(const sf::Vector2f& delta) +void MenuDrop::move(const kku::Vector2& delta) { - _content_rect.move(delta); + _content_rect->move(delta); Widget::move(delta); @@ -86,9 +93,9 @@ void MenuDrop::move(const sf::Vector2f& delta) submenu->move(delta); } -bool MenuDrop::isUnderMouse(int mouse_x, int mouse_y) const +bool MenuDrop::isUnderMouse(const kku::Point& position) const { - return _is_visible && _content_rect.getGlobalBounds().contains(mouse_x, mouse_y); + return _is_visible && _content_rect->contains(position); } void MenuDrop::setVisibility(bool is_visible) @@ -113,20 +120,19 @@ void MenuDrop::addCascadeButton(const std::shared_ptr& button submenu->setParent(_parent); } -void MenuDrop::addSeparator() +void MenuDrop::addSeparator(const std::shared_ptr& separator) { - add(std::make_shared()); + add(separator); } void MenuDrop::add(const std::shared_ptr &widget) { - const auto& parent_size = _content_rect.getSize(); - const auto& parent_position = _content_rect.getPosition(); + const auto& parent_rect = _content_rect->getRect(); - widget->setRect(sf::FloatRect(parent_position.x, - parent_position.y + (_button_height * _button_index), - parent_size.x, - _button_height)); + widget->setRect(kku::Area{parent_rect.left, + parent_rect.top + (parent_rect.height * _button_index), + parent_rect.width, + static_cast(_button_height)}); addChild(widget); ++_button_index; @@ -147,12 +153,12 @@ bool MenuDrop::isLocked() const return _is_locked; } -sf::FloatRect MenuDrop::rect() const +kku::Area MenuDrop::getRect() const { - return _content_rect.getGlobalBounds(); + return _content_rect->getRect(); } -sf::Vector2f MenuDrop::position() const +kku::Point MenuDrop::getPosition() const { - return _content_rect.getPosition(); + return _content_rect->getPosition(); } diff --git a/src/application/src/widgets/menudrop.h b/src/application/src/widgets/menudrop.h new file mode 100644 index 0000000..1c6233b --- /dev/null +++ b/src/application/src/widgets/menudrop.h @@ -0,0 +1,46 @@ +#pragma once + +#include "widget.h" +#include "pushbutton.h" +#include "cascademenubutton.h" +#include "menuseparator.h" +#include "core/rectangle.h" + +class MenuDrop : public Widget +{ +public: + explicit MenuDrop(const std::shared_ptr& factory); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + virtual void setVisibility(bool is_visible = true) override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + + void addPushButton(const std::shared_ptr& button); + void addCascadeButton(const std::shared_ptr& button); + void addSeparator(const std::shared_ptr& separator); + + void lock(); + void unlock(); + bool isLocked() const; + +private: + std::shared_ptr _content_rect; + bool _is_locked; + + std::size_t _button_height; + std::size_t _button_index; + + std::vector> _submenus; + + void add(const std::shared_ptr& widget); + bool hasActiveSubmenus() const; +}; diff --git a/src/application/src/widgets/menuseparator.cpp b/src/application/src/widgets/menuseparator.cpp new file mode 100644 index 0000000..cb7d8d9 --- /dev/null +++ b/src/application/src/widgets/menuseparator.cpp @@ -0,0 +1,48 @@ +#include "menuseparator.h" + +void MenuSeparator::input(const kku::SystemEvent& event) +{ + Widget::input(event); +} + +void MenuSeparator::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void MenuSeparator::display() const +{ + _line->display(); +} + +void MenuSeparator::setRect(const kku::Area& rect) +{ + _rect = rect; + + //_line +} + +void MenuSeparator::setPosition(const kku::Point& position) +{ + (void)position; +} + +void MenuSeparator::move(const kku::Vector2& delta) +{ + (void)delta; +} + +bool MenuSeparator::isUnderMouse(const kku::Point& position) const +{ + return _is_visible && _rect.contains(position); +} + +kku::Area MenuSeparator::getRect() const +{ + return {}; +} + +kku::Point MenuSeparator::getPosition() const +{ + return kku::Point{}; +} diff --git a/src/application/src/widgets/menuseparator.h b/src/application/src/widgets/menuseparator.h new file mode 100644 index 0000000..2a1ea9d --- /dev/null +++ b/src/application/src/widgets/menuseparator.h @@ -0,0 +1,25 @@ +#pragma once + +#include "widget.h" +#include "core/line.h" + +class MenuSeparator : public Widget +{ +public: + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + +private: + std::shared_ptr _line; + kku::Area _rect; +}; + diff --git a/src/application/src/widgets/pushbutton.cpp b/src/application/src/widgets/pushbutton.cpp new file mode 100644 index 0000000..540f44f --- /dev/null +++ b/src/application/src/widgets/pushbutton.cpp @@ -0,0 +1,57 @@ +#include "pushbutton.h" + +PushButton::PushButton(const std::string& text, const std::shared_ptr& factory, unsigned int font_size) : + Button(text, factory, font_size), + _pressed(false) +{ + _color_idle = kku::Color{230, 230, 230, 255}; + _color_pressed = kku::Color{200, 200, 200, 255}; + _button_content = _core_factory->getRectangle(); + _button_content->setColor(_color_idle); +} + +void PushButton::input(const kku::SystemEvent& event) +{ + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::MousePress: + { + const auto position = std::get(event.data).position; + if (isUnderMouse(position)) + { + _pressed = true; + _button_content->setColor(_color_pressed); + } + break; + } + + case kku::SystemEvent::Type::MouseRelease: + { + if (_pressed) + { + const auto position = std::get(event.data).position; + _button_content->setColor(_color_idle); + _pressed = false; + if (isUnderMouse(position)) + _on_click_callback(); + } + break; + } + } +} + +void PushButton::setCallback(std::function callback) +{ + _on_click_callback = callback; +} + +void PushButton::setColors(kku::Color&& idle_color, kku::Color&& pressed_color) +{ + _color_idle = idle_color; + _color_pressed = pressed_color; + + _button_content->setColor(_pressed ? pressed_color : idle_color); +} diff --git a/src/application/widgets/pushbutton.h b/src/application/src/widgets/pushbutton.h similarity index 51% rename from src/application/widgets/pushbutton.h rename to src/application/src/widgets/pushbutton.h index a243d79..1711eaf 100644 --- a/src/application/widgets/pushbutton.h +++ b/src/application/src/widgets/pushbutton.h @@ -5,15 +5,15 @@ class PushButton : public Button { public: - explicit PushButton(const std::string& text, const std::shared_ptr& font, unsigned int font_size = 12); - virtual void input(const sf::Event& event) override final; + explicit PushButton(const std::string& text, const std::shared_ptr& factory, unsigned int font_size = 12); + virtual void input(const kku::SystemEvent& event) override final; void setCallback(std::function callback); - void setFillColors(sf::Color&& idle_color, sf::Color&& pressed_color); + void setColors(kku::Color&& idle_color, kku::Color&& pressed_color); private: - sf::Color _color_idle; - sf::Color _color_pressed; + kku::Color _color_idle; + kku::Color _color_pressed; bool _pressed; std::function _on_click_callback; diff --git a/src/application/widgets/widget.cpp b/src/application/src/widgets/widget.cpp similarity index 80% rename from src/application/widgets/widget.cpp rename to src/application/src/widgets/widget.cpp index 00c39ed..dc3a972 100644 --- a/src/application/widgets/widget.cpp +++ b/src/application/src/widgets/widget.cpp @@ -1,6 +1,7 @@ #include "widget.h" +#include -void Widget::input(const sf::Event &event) +void Widget::input(const kku::SystemEvent &event) { if (_blocker) _blocker->input(event); @@ -11,19 +12,19 @@ void Widget::input(const sf::Event &event) } } -void Widget::update(const sf::Time& dt) +void Widget::update(const kku::microsec& dt) { for (auto& child : _children) child->update(dt); } -void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const +void Widget::display() const { - for (auto& child : _children) - child->draw(target, states); + for (const auto& child : _children) + child->display(); } -void Widget::move(const sf::Vector2f &delta) +void Widget::move(const kku::Vector2& delta) { for (auto& child : _children) child->move(delta); diff --git a/src/application/src/widgets/widget.h b/src/application/src/widgets/widget.h new file mode 100644 index 0000000..320ad83 --- /dev/null +++ b/src/application/src/widgets/widget.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include "core/systemevent.h" +#include "core/rectangle.h" +#include "core/time.h" + +class Widget : public std::enable_shared_from_this +{ +public: + virtual ~Widget() = default; + + virtual void input(const kku::SystemEvent& event) = 0; + virtual void update(const kku::microsec& dt) = 0; + virtual void display() const = 0; + virtual void move(const kku::Vector2& delta) = 0; + virtual bool isUnderMouse(const kku::Point& position) const = 0; + + virtual void setRect(const kku::Area& rect) = 0; + virtual kku::Area getRect() const = 0; + + virtual void setPosition(const kku::Point& position) = 0; + virtual kku::Point getPosition() const = 0; + + virtual void setVisibility(bool is_visible = true); + bool isVisible() const; + + void addChild(const std::shared_ptr& child); + void setParent(const std::shared_ptr& parent); + + void blockBy(const std::shared_ptr& blocker); + void unblock(); + +protected: + std::vector> _children; + std::shared_ptr _parent; + std::shared_ptr _blocker; + bool _is_visible = true; +}; + diff --git a/src/application/src/widgets/window.cpp b/src/application/src/widgets/window.cpp new file mode 100644 index 0000000..a212376 --- /dev/null +++ b/src/application/src/widgets/window.cpp @@ -0,0 +1,132 @@ +#include "window.h" +#include "pushbutton.h" + +Window::Window(const std::shared_ptr& factory, const std::string& title) : + _core_factory(factory), + _is_dragging(false) +{ + _bar_title = _core_factory->getText(kku::Font::Id::GUI); + _bar_title->setString(title); + _bar_title->setCharacterSize(12); + _bar_title->setColor(kku::Color{188, 157, 207, 255}); + + _bar = _core_factory->getRectangle(); + _bar->setColor(kku::Color{88, 57, 107, 255}); + + _window_content = _core_factory->getRectangle(); + _window_content->setColor(kku::Color{188, 157, 207, 255}); +} + +void Window::input(const kku::SystemEvent& event) +{ + Widget::input(event); + + switch (event.type) + { + default: + break; + + case kku::SystemEvent::Type::MousePress: + { + const auto position = std::get(event.data).position; + if (_bar->contains(position)) + { + _is_dragging = true; + _previous_click_position = position; + } + break; + } + + case kku::SystemEvent::Type::MouseRelease: + _is_dragging = false; + break; + + case kku::SystemEvent::Type::MouseMove: + { + const auto position = std::get(event.data).position; + if (_is_dragging) + { + float x_mouse_diff = position.x - _previous_click_position.x; + float y_mouse_diff = position.y - _previous_click_position.y; + + _previous_click_position = position; + + move(kku::Vector2{x_mouse_diff, y_mouse_diff}); + } + break; + } + } +} + +void Window::update(const kku::microsec& dt) +{ + Widget::update(dt); +} + +void Window::display() const +{ + if (_is_visible) + { + _window_content->display(); + _bar->display(); + _bar_title->display(); + Widget::display(); + } +} + +void Window::setRect(const kku::Area& rect) +{ + _window_content->setRect(rect); + + kku::Area bar_rect = {rect.left, rect.top, rect.width, 30}; + _bar->setRect(bar_rect); + + _bar_title->setPosition(kku::Point{rect.left + 5, + rect.top + 5}); +} + +void Window::setPosition(const kku::Point& position) +{ + _window_content->setPosition(position); + _bar->setPosition(position); + + auto new_position = position; + new_position.moveBy(5.f, 5.f); + _bar_title->setPosition(new_position); +} + +void Window::move(const kku::Vector2& delta) +{ + _window_content->move(delta); + _bar->move(delta); + _bar_title->move(delta); + + Widget::move(delta); +} + +bool Window::isUnderMouse(const kku::Point& position) const +{ + return _is_visible && _window_content->contains(position); +} + +void Window::addBarButton(const std::string &text, std::function callback) +{ + const auto area = _window_content->getRect(); + + auto b = std::make_shared(text, _core_factory, 20); + b->setCallback(callback); + b->setRect({area.left + area.width - 35, + area.top, 30, 30}); + + Widget::addChild(b); +} + +kku::Area Window::getRect() const +{ + return _window_content->getRect(); +} + +kku::Point Window::getPosition() const +{ + return _window_content->getPosition(); +} diff --git a/src/application/src/widgets/window.h b/src/application/src/widgets/window.h new file mode 100644 index 0000000..2b5ec96 --- /dev/null +++ b/src/application/src/widgets/window.h @@ -0,0 +1,41 @@ +#pragma once + +#include "widget.h" +#include "core/corefactory.h" +#include "core/rectangle.h" +#include "core/vector.h" +#include "core/text.h" + +#include + +class Window : public Widget +{ +public: + explicit Window(const std::shared_ptr& factory, const std::string& title); + + virtual void input(const kku::SystemEvent& event) override; + virtual void update(const kku::microsec& dt) override; + virtual void display() const override; + virtual void move(const kku::Vector2& delta) override; + virtual bool isUnderMouse(const kku::Point& position) const override final; + + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + + void addBarButton(const std::string& text, std::function callback); + +protected: + std::shared_ptr _bar; + std::shared_ptr _window_content; + std::shared_ptr _bar_title; + + const std::shared_ptr _core_factory; + +private: + bool _is_dragging; + kku::Point _previous_click_position; +}; + diff --git a/src/application/widgets/bpmcalculatorwidget.cpp b/src/application/widgets/bpmcalculatorwidget.cpp deleted file mode 100644 index 85cff34..0000000 --- a/src/application/widgets/bpmcalculatorwidget.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "bpmcalculatorwidget.h" -#include "tools/bpmcalculator.h" -#include "core/editor.h" - -#include - -BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr& font) : - Window("BPM Calculation", font), - _bpm_calculator(bpm_calculator), - _slider(std::make_shared()), - _ticked(false) -{ - _bpm_value.setFont(*_font); - _bpm_value.setCharacterSize(40); - _bpm_value.setFillColor(sf::Color::Black); - _bpm_value.setString("--"); - _slap_buffer.loadFromFile("Tick.ogg"); - _slap.setBuffer(_slap_buffer); - _slap.setVolume(30.); -} - -void BPMCalculatorWidget::input(const sf::Event& event) -{ - switch (event.type) - { - default: - break; - - case sf::Event::KeyPressed: - if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space) - { - _bpm_calculator->click(_current_time()); - } - break; - } - - Window::input(event); -} - -void BPMCalculatorWidget::update(const sf::Time& dt) -{ - Window::update(dt); - - const auto beat_info = _bpm_calculator->fetchApproximatedInfo(); - if (beat_info.BPM != 0) - { - _bpm_value.setString(std::to_string(static_cast(beat_info.BPM))); - - const microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time()); - const auto time_relation = static_cast(beat_info.interval) / static_cast(until_beat); - const auto slider_path_left = _slider->rect().width / time_relation; - if (slider_path_left < 50) - { - if (!_ticked) - _slap.play(); - _ticked = true; - } - else - _ticked = false; - - _slider->setTickPosition(slider_path_left); - } -} - -void BPMCalculatorWidget::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - Window::draw(target, states); - - if (_is_visible) - { - _slider->draw(target, states); - _button_start->draw(target, states); - _button_stop->draw(target, states); - _button_apply->draw(target, states); - target.draw(_bpm_value, states); - } -} - -void BPMCalculatorWidget::setRect(const sf::FloatRect& rect) -{ - Window::setRect(rect); - _slider->setRect(sf::FloatRect{0, 0, rect.width / 8 * 6, 100}); - _slider->setPosition({_window_content.getGlobalBounds().left + rect.width / 8, - _window_content.getGlobalBounds().top + rect.height / 8 * 3}); - - _button_start->setRect(sf::FloatRect{0, 0, rect.width / 10 * 3, 30}); - _button_start->setPosition({_window_content.getGlobalBounds().left + rect.width / 7, - _window_content.getGlobalBounds().top + _window_content.getGlobalBounds().height - 40}); - - _button_stop->setRect(sf::FloatRect{0, 0, rect.width / 10 * 3, 30}); - _button_stop->setPosition({_window_content.getGlobalBounds().left + rect.width / 7, - _window_content.getGlobalBounds().top + _window_content.getGlobalBounds().height - 40}); - - _button_apply->setRect(sf::FloatRect{0, 0, rect.width / 10 * 3, 30}); - _button_apply->setPosition({_window_content.getGlobalBounds().left + 50 + (2 * (rect.width / 7)), - _window_content.getGlobalBounds().top + _window_content.getGlobalBounds().height - 40}); - - _bpm_value.setPosition({_window_content.getGlobalBounds().left + rect.width / 8, - _window_content.getGlobalBounds().top + rect.height / 8 }); -} - -void BPMCalculatorWidget::move(const sf::Vector2f &delta) -{ - Window::move(delta); - _slider->move(delta); - _bpm_value.move(delta); -} - -void BPMCalculatorWidget::setPosition(const sf::Vector2f &position) -{ - Window::setPosition(position); -} - -void BPMCalculatorWidget::init(Init &&init) -{ - _button_start = init.start; - _button_stop = init.stop; - _button_apply = init.apply; - - _current_time = init.current_time; - - addChild(_button_start); - addChild(_button_stop); - addChild(_button_apply); - - _button_stop->setVisibility(false); -} - -void BPMCalculatorWidget::setVisibility(bool is_visible) -{ - Window::setVisibility(is_visible); - - bool can_stop = _bpm_calculator->calculating(); - _button_stop->setVisibility(can_stop && is_visible); - _button_start->setVisibility(!can_stop && is_visible); -} diff --git a/src/application/widgets/bpmcalculatorwidget.h b/src/application/widgets/bpmcalculatorwidget.h deleted file mode 100644 index 1390de3..0000000 --- a/src/application/widgets/bpmcalculatorwidget.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "window.h" -#include "bpmslider.h" -#include "pushbutton.h" -#include -#include -#include -#include -#include -#include "tools/mathutils.h" - -class BPMCalculator; -class Editor; - -class BPMCalculatorWidget : public Window -{ -public: - - struct Init - { - std::shared_ptr start; - std::shared_ptr stop; - std::shared_ptr apply; - std::function current_time; - }; - - explicit BPMCalculatorWidget(const std::shared_ptr& bpm_calculator, const std::shared_ptr &font); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void setRect(const sf::FloatRect& rect) override; - virtual void setPosition(const sf::Vector2f& position) override; - virtual void move(const sf::Vector2f& delta) override; - - virtual void setVisibility(bool is_visible = true) override; - - void init(Init&& init); - -private: - std::shared_ptr _button_start; - std::shared_ptr _button_stop; - std::shared_ptr _button_apply; - - std::shared_ptr _bpm_calculator; - std::shared_ptr _slider; - - sf::SoundBuffer _slap_buffer; - sf::Sound _slap; - bool _ticked; - - sf::Text _bpm_value; - std::function _current_time; -}; - diff --git a/src/application/widgets/bpmslider.cpp b/src/application/widgets/bpmslider.cpp deleted file mode 100644 index f459cb3..0000000 --- a/src/application/widgets/bpmslider.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "bpmslider.h" - -BPMSlider::BPMSlider() -{ - _slider_background.setFillColor(sf::Color::Black); - _slider_tick.setFillColor(sf::Color::Red); -} - -void BPMSlider::input(const sf::Event& event) -{ - Widget::input(event); -} - -void BPMSlider::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void BPMSlider::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - target.draw(_slider_background, states); - target.draw(_slider_tick, states); - Widget::draw(target, states); -} - -void BPMSlider::setRect(const sf::FloatRect& rect) -{ - _slider_background.setPosition(rect.left, rect.top); - _slider_background.setSize({rect.width, rect.height}); - - _slider_tick.setPosition(rect.left, rect.top); - _slider_tick.setSize({rect.width / 30, rect.height}); -} - -void BPMSlider::setPosition(const sf::Vector2f& position) -{ - _slider_background.setPosition(position); - _slider_tick.setPosition(position); -} - -void BPMSlider::move(const sf::Vector2f& delta) -{ - _slider_background.move(delta); - _slider_tick.move(delta); -} - -bool BPMSlider::isUnderMouse(int mouse_x, int mouse_y) const -{ - return mouse_x == mouse_y; // just to compile -} - -sf::FloatRect BPMSlider::rect() const -{ - return _slider_background.getGlobalBounds(); -} - -sf::Vector2f BPMSlider::position() const -{ - return _slider_background.getPosition(); -} - -void BPMSlider::setTickPosition(float x_position) -{ - _slider_tick.setPosition(_slider_background.getPosition().x + x_position, _slider_tick.getPosition().y); -} diff --git a/src/application/widgets/bpmslider.h b/src/application/widgets/bpmslider.h deleted file mode 100644 index facc018..0000000 --- a/src/application/widgets/bpmslider.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "widget.h" - -#include -#include - -class BPMSlider : public Widget -{ -public: - explicit BPMSlider(); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - - void setTickPosition(float x_position); - -private: - sf::RectangleShape _slider_background; - sf::RectangleShape _slider_tick; -}; - - diff --git a/src/application/widgets/button.cpp b/src/application/widgets/button.cpp deleted file mode 100644 index 681e600..0000000 --- a/src/application/widgets/button.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "button.h" -#include - -Button::Button(const std::string &text, const std::shared_ptr& font, unsigned int font_size) : - _font(font) -{ - setText(text); - _button_text.setFillColor(sf::Color::Black); - _button_text.setCharacterSize(font_size); - _button_text.setFont(*_font); -} - -void Button::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void Button::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - if (_is_visible) - { - target.draw(_button_content, states); - target.draw(_button_text, states); - } - - Widget::draw(target, states); -} - -void Button::setRect(const sf::FloatRect& rect) -{ - _button_content.setPosition(rect.left, rect.top); - _button_content.setSize({rect.width, rect.height}); - _button_text.setPosition(rect.left + 5, rect.top + 5); -} - -void Button::setPosition(const sf::Vector2f &position) -{ - _button_content.setPosition(position); - _button_text.move(position.x + 5, position.y + 5); -} - -void Button::move(const sf::Vector2f &delta) -{ - _button_content.move(delta); - _button_text.move(delta); - Widget::move(delta); -} - -bool Button::isUnderMouse(int mouse_x, int mouse_y) const -{ - return _is_visible && _button_content.getGlobalBounds().contains(mouse_x, mouse_y); -} - -void Button::setText(const std::string& text) -{ - _button_text.setString(text); -} - -sf::FloatRect Button::rect() const -{ - return _button_content.getGlobalBounds(); -} - -sf::Vector2f Button::position() const -{ - return _button_content.getPosition(); -} diff --git a/src/application/widgets/button.h b/src/application/widgets/button.h deleted file mode 100644 index 5aeac8d..0000000 --- a/src/application/widgets/button.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "widget.h" -#include -#include -#include - -class Button : public Widget -{ -public: - explicit Button(const std::string& text, const std::shared_ptr& font, unsigned int font_size); - - virtual void input(const sf::Event& event) override = 0; - virtual void update(const sf::Time& dt) override final; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override final; - virtual void move(const sf::Vector2f& delta) override final; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override final; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - - virtual void setText(const std::string& text); - -protected: - sf::RectangleShape _button_content; - sf::Text _button_text; - std::shared_ptr _font; -}; - diff --git a/src/application/widgets/cascademenubutton.cpp b/src/application/widgets/cascademenubutton.cpp deleted file mode 100644 index bdea938..0000000 --- a/src/application/widgets/cascademenubutton.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "cascademenubutton.h" -#include "menudrop.h" - -CascadeMenuButton::CascadeMenuButton(const std::string& text, const std::shared_ptr &font, unsigned int font_size) : - Button(text, font, font_size) -{ - _color_idle = sf::Color(230, 230, 230); - _color_hover = sf::Color(84, 158, 253); - _button_content.setFillColor(_color_idle); -} - -void CascadeMenuButton::input(const sf::Event& event) -{ - if (!_submenu) - return; - - switch (event.type) - { - default: - break; - - case sf::Event::MouseMoved: - if (isUnderMouse(event.mouseMove.x, event.mouseMove.y)) - { - _button_content.setFillColor(_color_hover); - _submenu->lock(); - _submenu->setVisibility(true); - } - else - { - _submenu->unlock(); - if (!_submenu->isVisible()) - { - _button_content.setFillColor(sf::Color(_color_idle)); - } - } - break; - } -} - -void CascadeMenuButton::setRect(const sf::FloatRect& rect) -{ - Button::setRect(rect); - resetRect(); -} - -void CascadeMenuButton::setSubmenu(const std::shared_ptr& submenu) -{ - _submenu = submenu; - resetRect(); -} - -const std::shared_ptr CascadeMenuButton::submenu() const -{ - return _submenu; -} - -void CascadeMenuButton::resetRect() -{ - if (_submenu) - { - _submenu->setPosition({_button_content.getPosition().x + _button_content.getSize().x, - _button_content.getPosition().y}); - } -} - -void CascadeMenuButton::setFillColors(sf::Color&& idle_color, sf::Color&& hover_color) -{ - _color_idle = idle_color; - _color_hover = hover_color; -} diff --git a/src/application/widgets/editorwidget.cpp b/src/application/widgets/editorwidget.cpp deleted file mode 100644 index ef4c64e..0000000 --- a/src/application/widgets/editorwidget.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "editorwidget.h" -#include "core/editor.h" - -EditorWidget::EditorWidget(Callbacks&& callbacks) : - _input(std::move(callbacks.onInput)), - _update(std::move(callbacks.onUpdate)), - _draw(std::move(callbacks.onDraw)) -{} - -void EditorWidget::input(const sf::Event& event) -{ - _input(event); -} - -void EditorWidget::update(const sf::Time& dt) -{ - _update(dt); -} - -void EditorWidget::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - _draw(target, states); -} - -void EditorWidget::move(const sf::Vector2f& delta) -{ - (void)delta; - // delegate to children -} - -bool EditorWidget::isUnderMouse(int mouse_x, int mouse_y) const -{ - return _parent->isUnderMouse(mouse_x, mouse_y); -} - -void EditorWidget::setRect(const sf::FloatRect& rect) -{ - (void)rect; - // basically useless beacuse editor widget fills the entire screen -} - -sf::FloatRect EditorWidget::rect() const -{ - return {}; -} - -void EditorWidget::setPosition(const sf::Vector2f& position) -{ - (void)position; -} - -sf::Vector2f EditorWidget::position() const -{ - return {}; -} diff --git a/src/application/widgets/editorwidget.h b/src/application/widgets/editorwidget.h deleted file mode 100644 index 0c10b41..0000000 --- a/src/application/widgets/editorwidget.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "widget.h" - -class EditorWidget : public Widget -{ -public: - - struct Callbacks - { - std::function onInput; - std::function onUpdate; - std::function onDraw; - }; - - explicit EditorWidget(Callbacks&& callbacks); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - -private: - std::function _input; - std::function _update; - std::function _draw; -}; - diff --git a/src/application/widgets/group.cpp b/src/application/widgets/group.cpp deleted file mode 100644 index 03d5944..0000000 --- a/src/application/widgets/group.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "group.h" - -void Group::input(const sf::Event& event) -{ - Widget::input(event); -} - -void Group::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void Group::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - Widget::draw(target, states); -} - -void Group::setRect(const sf::FloatRect& rect) -{ - _rect = rect; -} - -void Group::setPosition(const sf::Vector2f& position) -{ - _rect.top = position.y; - _rect.left = position.x; -} - -void Group::move(const sf::Vector2f& delta) -{ - _rect.top += delta.y; - _rect.left += delta.x; - - Widget::move(delta); -} - -bool Group::isUnderMouse(int mouse_x, int mouse_y) const -{ - return _rect.contains(mouse_x, mouse_y); -} - -sf::FloatRect Group::rect() const -{ - return _rect; -} - -sf::Vector2f Group::position() const -{ - return sf::Vector2f - { - _rect.top, - _rect.left - }; -} - diff --git a/src/application/widgets/group.h b/src/application/widgets/group.h deleted file mode 100644 index 4f67bd1..0000000 --- a/src/application/widgets/group.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "widget.h" - -class Group : public Widget -{ -public: - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - -private: - sf::FloatRect _rect; -}; - diff --git a/src/application/widgets/menubar.cpp b/src/application/widgets/menubar.cpp deleted file mode 100644 index fa14f56..0000000 --- a/src/application/widgets/menubar.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "menubar.h" -#include "iostream" - -MenuBar::MenuBar(const std::shared_ptr& font) : - _font(font), - _amount_buttons(0), - _button_width(170) -{ - _bar_rect.setFillColor(sf::Color(88, 57, 107)); -} - -void MenuBar::input(const sf::Event &event) -{ - switch (event.type) - { - default: - break; - - case sf::Event::MouseButtonReleased: - if (!isUnderMouse(event.mouseButton.x, event.mouseButton.y)) - { - for (auto& submenu : _submenus) - submenu->unlock(); - } - break; - } - - Widget::input(event); -} - -void MenuBar::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void MenuBar::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - if (_is_visible) - target.draw(_bar_rect, states); - - Widget::draw(target, states); -} - -void MenuBar::setRect(const sf::FloatRect& rect) -{ - _bar_rect.setPosition(rect.left, rect.top); - _bar_rect.setSize({rect.width, rect.height}); - - // Buttons will not resize -} - -void MenuBar::setPosition(const sf::Vector2f& position) -{ - _bar_rect.setPosition(position); -} - -void MenuBar::move(const sf::Vector2f &delta) -{ - _bar_rect.move(delta); - - Widget::move(delta); - - for (auto& menu : _submenus) - menu->move(delta); -} - -bool MenuBar::isUnderMouse(int mouse_x, int mouse_y) const -{ - bool bar_under_mouse = _bar_rect.getGlobalBounds().contains(mouse_x, mouse_y); - - bool submenus_under_mouse = std::any_of(_children.begin(), _children.end(), - [x=mouse_x, y=mouse_y](const auto& child) - { - return child->isUnderMouse(x, y); - }); - - return bar_under_mouse || submenus_under_mouse; -} - -void MenuBar::addRootSubMenu(std::string name, const std::shared_ptr& submenu) -{ - const auto new_button = std::make_shared(name, _font); - - std::size_t current_index = _amount_buttons; - new_button->setRect(sf::FloatRect(current_index * _button_width, 0, _button_width, _bar_rect.getSize().y)); - new_button->setCallback([submenu=submenu]() - { - submenu->setVisibility(true); - submenu->lock(); - }); - - submenu->setPosition({static_cast(current_index * _button_width), - _bar_rect.getSize().y}); - - new_button->setFillColors(sf::Color(171, 141, 189), sf::Color(48, 27, 57)); - addChild(new_button); - addChild(submenu); - - _submenus.emplace_back(submenu); - - ++_amount_buttons; -} - -void MenuBar::addDependentSubmenu(const std::shared_ptr &submenu) -{ - _submenus.emplace_back(submenu);; -} - -void MenuBar::setVisibility(bool is_visible) -{ - Widget::setVisibility(is_visible); - - for (auto& submenu : _submenus) - submenu->setVisibility(false); -} - -sf::FloatRect MenuBar::rect() const -{ - return _bar_rect.getGlobalBounds(); -} - -sf::Vector2f MenuBar::position() const -{ - return _bar_rect.getPosition(); -} diff --git a/src/application/widgets/menubar.h b/src/application/widgets/menubar.h deleted file mode 100644 index fea7be5..0000000 --- a/src/application/widgets/menubar.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "widget.h" -#include "menudrop.h" -#include "button.h" - -#include - -class MenuBar : public Widget -{ -public: - explicit MenuBar(const std::shared_ptr& font); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - virtual void setVisibility(bool is_visible = true) override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - - void addRootSubMenu(std::string name, const std::shared_ptr& submenu); - void addDependentSubmenu(const std::shared_ptr& submenu); - -private: - std::shared_ptr _font; - sf::RectangleShape _bar_rect; - std::size_t _amount_buttons; - std::size_t _button_width; - - std::vector> _submenus; -}; diff --git a/src/application/widgets/menudrop.h b/src/application/widgets/menudrop.h deleted file mode 100644 index 59e7b04..0000000 --- a/src/application/widgets/menudrop.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "widget.h" -#include "pushbutton.h" -#include "cascademenubutton.h" -#include - -class MenuDrop : public Widget -{ -public: - explicit MenuDrop(); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - virtual void setVisibility(bool is_visible = true) override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - - void addPushButton(const std::shared_ptr& button); - void addCascadeButton(const std::shared_ptr& button); - void addSeparator(); - - void lock(); - void unlock(); - bool isLocked() const; - -private: - sf::RectangleShape _content_rect; - bool _is_locked; - - std::size_t _button_height; - std::size_t _button_index; - - std::vector> _submenus; - - void add(const std::shared_ptr& widget); - bool hasActiveSubmenus() const; -}; diff --git a/src/application/widgets/menuseparator.cpp b/src/application/widgets/menuseparator.cpp deleted file mode 100644 index abe0fb5..0000000 --- a/src/application/widgets/menuseparator.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "menuseparator.h" - -void MenuSeparator::input(const sf::Event& event) -{ - Widget::input(event); -} - -void MenuSeparator::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void MenuSeparator::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - target.draw(_line, states); -} - -void MenuSeparator::setRect(const sf::FloatRect& rect) -{ - _rect = rect; - - //_line -} - -void MenuSeparator::setPosition(const sf::Vector2f& position) -{ - (void)position; -} - -void MenuSeparator::move(const sf::Vector2f& delta) -{ - (void)delta; -} - -bool MenuSeparator::isUnderMouse(int mouse_x, int mouse_y) const -{ - return _is_visible && _rect.contains(mouse_x, mouse_y); -} - -sf::FloatRect MenuSeparator::rect() const -{ - return {}; -} - -sf::Vector2f MenuSeparator::position() const -{ - return {}; -} diff --git a/src/application/widgets/menuseparator.h b/src/application/widgets/menuseparator.h deleted file mode 100644 index 2412355..0000000 --- a/src/application/widgets/menuseparator.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "widget.h" - -#include - -class MenuSeparator : public Widget -{ -public: - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - -private: - sf::VertexArray _line; - sf::FloatRect _rect; -}; - diff --git a/src/application/widgets/pushbutton.cpp b/src/application/widgets/pushbutton.cpp deleted file mode 100644 index ec0f40c..0000000 --- a/src/application/widgets/pushbutton.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "pushbutton.h" -#include - -PushButton::PushButton(const std::string& text, const std::shared_ptr &font, unsigned int font_size) : - Button(text, font, font_size), - _pressed(false) -{ - _color_idle = sf::Color(230, 230, 230); - _color_pressed = sf::Color(200, 200, 200); - _button_content.setFillColor(_color_idle); -} - -void PushButton::input(const sf::Event& event) -{ - switch (event.type) - { - default: - break; - - case sf::Event::MouseButtonPressed: - if (isUnderMouse(event.mouseButton.x, event.mouseButton.y)) - { - _pressed = true; - _button_content.setFillColor(sf::Color(_color_pressed)); - } - break; - - case sf::Event::MouseButtonReleased: - if (_pressed) - { - _button_content.setFillColor(_color_idle); - _pressed = false; - if (isUnderMouse(event.mouseButton.x, event.mouseButton.y)) - _on_click_callback(); - } - break; - } -} - -void PushButton::setCallback(std::function callback) -{ - _on_click_callback = callback; -} - -void PushButton::setFillColors(sf::Color&& idle_color, sf::Color&& pressed_color) -{ - _color_idle = idle_color; - _color_pressed = pressed_color; - - _button_content.setFillColor(_pressed ? pressed_color : idle_color); -} diff --git a/src/application/widgets/widget.h b/src/application/widgets/widget.h deleted file mode 100644 index ac25b3b..0000000 --- a/src/application/widgets/widget.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -class Widget : public sf::Drawable, public std::enable_shared_from_this -{ -public: - virtual ~Widget() = default; - - virtual void input(const sf::Event& event) = 0; - virtual void update(const sf::Time& dt) = 0; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0; - virtual void move(const sf::Vector2f& delta) = 0; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const = 0; - - virtual void setRect(const sf::FloatRect& rect) = 0; - virtual sf::FloatRect rect() const = 0; - - virtual void setPosition(const sf::Vector2f& position) = 0; - virtual sf::Vector2f position() const = 0; - - virtual void setVisibility(bool is_visible = true); - bool isVisible() const; - - void addChild(const std::shared_ptr& child); - void setParent(const std::shared_ptr& parent); - - void blockBy(const std::shared_ptr& blocker); - void unblock(); - -protected: - std::vector> _children; - std::shared_ptr _parent; - std::shared_ptr _blocker; - bool _is_visible = true; -}; - diff --git a/src/application/widgets/window.cpp b/src/application/widgets/window.cpp deleted file mode 100644 index 4155fce..0000000 --- a/src/application/widgets/window.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "window.h" -#include "pushbutton.h" - -Window::Window(const std::string& text, const std::shared_ptr& font) : - _font(font), - _is_dragging(false) -{ - _bar_title.setFont(*font); - _bar_title.setString(text); - _bar_title.setCharacterSize(12); - _bar_title.setFillColor(sf::Color(188, 157, 207)); - _bar.setFillColor(sf::Color(88, 57, 107)); - _window_content.setFillColor(sf::Color(188, 157, 207)); -} - -void Window::input(const sf::Event& event) -{ - Widget::input(event); - - switch (event.type) - { - default: - break; - - case sf::Event::MouseButtonPressed: - if (_bar.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y)) - { - _is_dragging = true; - _previous_click_position = {static_cast(event.mouseButton.x), - static_cast(event.mouseButton.y)}; - } - break; - - case sf::Event::MouseButtonReleased: - _is_dragging = false; - break; - - case sf::Event::MouseMoved: - if (_is_dragging) - { - float x_mouse_diff = event.mouseMove.x - _previous_click_position.x; - float y_mouse_diff = event.mouseMove.y - _previous_click_position.y; - - _previous_click_position = {static_cast(event.mouseMove.x), - static_cast(event.mouseMove.y)}; - - move({x_mouse_diff, y_mouse_diff}); - } - break; - } -} - -void Window::update(const sf::Time& dt) -{ - Widget::update(dt); -} - -void Window::draw(sf::RenderTarget& target, sf::RenderStates states) const -{ - if (_is_visible) - { - target.draw(_window_content, states); - target.draw(_bar, states); - target.draw(_bar_title, states); - Widget::draw(target, states); - } -} - -void Window::setRect(const sf::FloatRect& rect) -{ - _window_content.setPosition(rect.left, rect.top); - _window_content.setSize({rect.width, rect.height}); - - _bar.setPosition(rect.left, rect.top); - _bar.setSize({rect.width, 30}); - _bar_title.setPosition(rect.left + 5, rect.top + 5); -} - -void Window::setPosition(const sf::Vector2f& position) -{ - _window_content.setPosition(position); - _bar.setPosition(position); - _bar_title.setPosition(position.x + 5, position.y + 5); -} - -void Window::move(const sf::Vector2f &delta) -{ - _window_content.move(delta); - _bar.move(delta); - _bar_title.move(delta); - - Widget::move(delta); -} - -bool Window::isUnderMouse(int mouse_x, int mouse_y) const -{ - return _is_visible && _window_content.getGlobalBounds().contains(mouse_x, mouse_y); -} - -void Window::addBarButton(const std::string &text, std::function callback) -{ - auto b = std::make_shared(text, _font, 20); - b->setCallback(callback); - b->setRect({_window_content.getGlobalBounds().left + _window_content.getSize().x - 35, - _window_content.getGlobalBounds().top, - 30, - 30}); - addChild(b); -} - -sf::FloatRect Window::rect() const -{ - return _window_content.getGlobalBounds(); -} - -sf::Vector2f Window::position() const -{ - return _window_content.getPosition(); -} diff --git a/src/application/widgets/window.h b/src/application/widgets/window.h deleted file mode 100644 index 0ff69ab..0000000 --- a/src/application/widgets/window.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "widget.h" - -#include -#include - -class Window : public Widget -{ -public: - explicit Window(const std::string& text, const std::shared_ptr &font); - - virtual void input(const sf::Event& event) override; - virtual void update(const sf::Time& dt) override; - virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override; - virtual void move(const sf::Vector2f& delta) override; - virtual bool isUnderMouse(int mouse_x, int mouse_y) const override final; - - virtual void setRect(const sf::FloatRect& rect) override; - virtual sf::FloatRect rect() const override; - - virtual void setPosition(const sf::Vector2f& position) override; - virtual sf::Vector2f position() const override; - - void addBarButton(const std::string& text, std::function callback); - -protected: - sf::RectangleShape _bar; - sf::RectangleShape _window_content; - sf::Text _bar_title; - - const std::shared_ptr _font; - -private: - bool _is_dragging; - sf::Vector2f _previous_click_position; -}; - diff --git a/src/impl/CMakeLists.txt b/src/impl/CMakeLists.txt new file mode 100644 index 0000000..624c324 --- /dev/null +++ b/src/impl/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.13) + +project(impl) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared) + +# check SFML by some compilation flag or idk +file(GLOB_RECURSE SOURCES "sfml/*.cpp" "sfml/*.h") +find_package(SFML REQUIRED graphics window system) +include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include) +target_link_libraries(project-kyoku sfml-system sfml-audio sfml-graphics sfml-network) +include_directories(${SFML_INCL_DIR} ${CMAKE_SOURCE_DIR}/include) +###### + +add_library(impl STATIC ${SOURCES}) +target_link_libraries(impl tools classicmode application) +target_include_directories(impl PRIVATE ${CMAKE_SOURCE_DIR}/src/modes/classicmode) +target_include_directories(impl PRIVATE ${CMAKE_SOURCE_DIR}/src/tools/shared) +target_include_directories(impl PRIVATE ${CMAKE_SOURCE_DIR}/src/application/shared) + +target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/src/impl/sfml) diff --git a/src/impl/sfml/application/applicationsfml.cpp b/src/impl/sfml/application/applicationsfml.cpp new file mode 100644 index 0000000..0963abc --- /dev/null +++ b/src/impl/sfml/application/applicationsfml.cpp @@ -0,0 +1,187 @@ +#include "applicationsfml.h" +#include "sfml/corefactorysfml.h" +#include "sfml/classicmode/classicfactorysfml.h" + +#include + +const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 90.f); + +ApplicationSFML::ApplicationSFML(const std::shared_ptr& render_window) : + _render_window(render_window) +{ + _render_window->setFramerateLimit(60); + _render_window->setKeyRepeatEnabled(false); + _render_window->setMouseCursorGrabbed(false); + _render_window->setVerticalSyncEnabled(true); + + _core_factory = std::make_shared(_render_window); + _game_factory = std::make_shared(_render_window); +} + +void ApplicationSFML::display() +{ + _render_window->clear(); + + for (const auto& state : _state_stack) + state->display(); + + _render_window->display(); +} + +void ApplicationSFML::run() +{ + sf::Clock timer; + sf::Time time_since_last_update = sf::Time::Zero; + + while (_render_window->isOpen()) + { + time_since_last_update += timer.restart(); + + sf::Event event; + while (_render_window->pollEvent(event)) + { + switch(event.type) + { + case sf::Event::Closed: + _render_window->close(); + break; + + default: + Application::input(convert(event)); + break; + } + } + + bool isOneFramePassed = time_since_last_update >= TIME_PER_FRAME; + if (isOneFramePassed) + { + time_since_last_update -= TIME_PER_FRAME; + update(time_since_last_update.asMicroseconds()); + display(); + } + } +} + +kku::SystemEvent ApplicationSFML::convert(const sf::Event& event) const +{ + switch (event.type) + { + default: + break; + + case sf::Event::Resized: + return kku::SystemEvent + { + kku::SystemEvent::Type::Resize, + kku::SystemEvent::Size + { + event.size.width, + event.size.height + } + }; + + case sf::Event::KeyPressed: + return kku::SystemEvent + { + kku::SystemEvent::Type::KeyPress, + kku::SystemEvent::Key + { + ' ', // converter + event.key.alt, + event.key.control, + event.key.shift + } + }; + + case sf::Event::KeyReleased: + return kku::SystemEvent + { + kku::SystemEvent::Type::KeyRelease, + kku::SystemEvent::Key + { + ' ', // converter + event.key.alt, + event.key.control, + event.key.shift + } + }; + + case sf::Event::MouseWheelScrolled: + return kku::SystemEvent + { + kku::SystemEvent::Type::MouseWheelScroll, + kku::SystemEvent::Mouse + { + kku::Point + { + event.mouseWheelScroll.x, + event.mouseWheelScroll.y + }, + + (event.mouseWheelScroll.delta > 0), + kku::SystemEvent::Mouse::Button::Wheel + } + }; + + case sf::Event::MouseMoved: + return kku::SystemEvent + { + kku::SystemEvent::Type::MouseMove, + kku::SystemEvent::Mouse + { + kku::Point + { + event.mouseMove.x, + event.mouseMove.y + }, + + false, + kku::SystemEvent::Mouse::Button::None + } + }; + + case sf::Event::MouseButtonPressed: + return kku::SystemEvent + { + kku::SystemEvent::Type::MousePress, + kku::SystemEvent::Mouse + { + kku::Point + { + event.mouseButton.x, + event.mouseButton.y + }, + + false, + ((event.mouseButton.button == sf::Mouse::Button::Left) + ? kku::SystemEvent::Mouse::Button::Left + : kku::SystemEvent::Mouse::Button::Right) + } + }; + + case sf::Event::MouseButtonReleased: + return kku::SystemEvent + { + kku::SystemEvent::Type::MouseRelease, + kku::SystemEvent::Mouse + { + kku::Point + { + event.mouseButton.x, + event.mouseButton.y + }, + + false, + ((event.mouseButton.button == sf::Mouse::Button::Left) + ? kku::SystemEvent::Mouse::Button::Left + : kku::SystemEvent::Mouse::Button::Right) + } + }; + } + + return kku::SystemEvent + { + kku::SystemEvent::Type::None, + kku::SystemEvent::None{} + }; +} diff --git a/src/impl/sfml/application/applicationsfml.h b/src/impl/sfml/application/applicationsfml.h new file mode 100644 index 0000000..1e57c69 --- /dev/null +++ b/src/impl/sfml/application/applicationsfml.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include "application/application.h" + +class ApplicationSFML : public Application +{ +public: + explicit ApplicationSFML(const std::shared_ptr& _render_window); + virtual void display() override; + virtual void run() override; + +private: + const std::shared_ptr _render_window; + + inline kku::SystemEvent convert(const sf::Event& event) const; +}; diff --git a/modes/classicmode/sfml/classicfactorysfml.cpp b/src/impl/sfml/classicmode/classicfactorysfml.cpp similarity index 54% rename from modes/classicmode/sfml/classicfactorysfml.cpp rename to src/impl/sfml/classicmode/classicfactorysfml.cpp index 18601a1..719ccf5 100644 --- a/modes/classicmode/sfml/classicfactorysfml.cpp +++ b/src/impl/sfml/classicmode/classicfactorysfml.cpp @@ -1,5 +1,5 @@ -#include "shared/classicmode/classicfactorysfml.h" -#include "sfml/spritefactorysfml.h" +#include "classicfactorysfml.h" +#include "spritefactorysfml.h" #include "graphics/classicscenegraphicsmanager.h" #include "core/timeline.h" @@ -7,25 +7,29 @@ #include "game/classicgame.h" #include "editor/classiceditor.h" -std::unique_ptr classic::initGame(const std::shared_ptr& render_target) +ClassicFactorySFML::ClassicFactorySFML(const std::shared_ptr& render_target) : + _render_target(render_target) +{} + +std::unique_ptr ClassicFactorySFML::getGame() const { // read offset from beatmap metadata - const microsec visibility_offset = 1648648; + const kku::microsec visibility_offset = 1648648; - const auto factory = std::make_shared(render_target); - const auto timeline = std::make_shared>(); + const auto factory = std::make_shared(_render_target); + const auto timeline = std::make_shared>(); const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); return std::make_unique(timeline, graphics_manager); } -std::unique_ptr classic::initEditor(const std::shared_ptr& render_target) +std::unique_ptr ClassicFactorySFML::getEditor() const { // read offset from beatmap metadata - const microsec visibility_offset = 1648648; + const kku::microsec visibility_offset = 1648648; - const auto factory = std::make_shared(render_target); - const auto timeline = std::make_shared>(); + const auto factory = std::make_shared(_render_target); + const auto timeline = std::make_shared>(); const auto graphics_manager = std::make_shared(timeline, factory, visibility_offset); return std::make_unique(timeline, graphics_manager); diff --git a/src/impl/sfml/classicmode/classicfactorysfml.h b/src/impl/sfml/classicmode/classicfactorysfml.h new file mode 100644 index 0000000..ddee17a --- /dev/null +++ b/src/impl/sfml/classicmode/classicfactorysfml.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include "shared/classicmode/classicfactory.h" + +class ClassicFactorySFML : public ClassicFactory +{ +public: + explicit ClassicFactorySFML(const std::shared_ptr& render_target); + virtual std::unique_ptr getGame() const override; + virtual std::unique_ptr getEditor() const override; + +private: + const std::shared_ptr _render_target; +}; diff --git a/src/impl/sfml/classicmode/classicspritesfml.cpp b/src/impl/sfml/classicmode/classicspritesfml.cpp new file mode 100644 index 0000000..ee42fa0 --- /dev/null +++ b/src/impl/sfml/classicmode/classicspritesfml.cpp @@ -0,0 +1,66 @@ +#include "classicspritesfml.h" + +ClassicSpriteSFML::ClassicSpriteSFML(const std::shared_ptr& render_target, + const sf::RectangleShape& shape) : + _prototype(shape), + _shape(shape), + _trail(shape), + _render_target(render_target) +{} + +void ClassicSpriteSFML::reset() +{ + _shape.setPosition(0, 0); + _trail.setPosition(0, 0); + + _shape = _prototype; + _trail = _prototype; +} + +void ClassicSpriteSFML::setPosition(const kku::Point& position) +{ + _shape.setPosition(position.x, position.y); +} + +void ClassicSpriteSFML::setTrailPosition(const kku::Point &position) +{ + _trail.setPosition(position.x, position.y); +} + +kku::Point ClassicSpriteSFML::getPosition() const +{ + return kku::Point{ _shape.getPosition().x, _shape.getPosition().y }; +} + +kku::Point ClassicSpriteSFML::getTrailPosition() const +{ + return kku::Point{ _trail.getPosition().x, _trail.getPosition().y }; +} + +void ClassicSpriteSFML::setColor(const kku::Color& color) +{ + _shape.setFillColor(sf::Color{ color.red, color.green, color.blue, color.alpha }); +} + +void ClassicSpriteSFML::setTrailColor(const kku::Color& color) +{ + _trail.setFillColor(sf::Color{ color.red, color.green, color.blue, color.alpha }); +} + +kku::Color ClassicSpriteSFML::getColor() const +{ + const auto color = _shape.getFillColor(); + return kku::Color{ color.r, color.g, color.b, color.a }; +} + +kku::Color ClassicSpriteSFML::getTrailColor() const +{ + const auto color = _trail.getFillColor(); + return kku::Color{ color.r, color.g, color.b, color.a }; +} + +void ClassicSpriteSFML::display() const +{ + _render_target->draw(_shape); + _render_target->draw(_trail); +} diff --git a/src/impl/sfml/classicmode/classicspritesfml.h b/src/impl/sfml/classicmode/classicspritesfml.h new file mode 100644 index 0000000..56bf6ed --- /dev/null +++ b/src/impl/sfml/classicmode/classicspritesfml.h @@ -0,0 +1,34 @@ +#pragma once + +#include "graphics/classicsprite.h" + +#include +#include + +class ClassicSpriteSFML : public ClassicSprite +{ +public: + explicit ClassicSpriteSFML(const std::shared_ptr& render_target, + const sf::RectangleShape& shape); + + virtual void reset() override; + virtual void display() const override; + + virtual void setPosition(const kku::Point &position) override; + virtual void setTrailPosition(const kku::Point &position) override; + virtual kku::Point getPosition() const override; + virtual kku::Point getTrailPosition() const override; + + virtual void setColor(const kku::Color& color) override; + virtual void setTrailColor(const kku::Color& color) override; + virtual kku::Color getColor() const override; + virtual kku::Color getTrailColor() const override; + +private: + sf::RectangleShape _prototype; + + sf::RectangleShape _shape; + sf::RectangleShape _trail; + + const std::shared_ptr _render_target; +}; diff --git a/modes/classicmode/sfml/spritefactorysfml.cpp b/src/impl/sfml/classicmode/spritefactorysfml.cpp similarity index 88% rename from modes/classicmode/sfml/spritefactorysfml.cpp rename to src/impl/sfml/classicmode/spritefactorysfml.cpp index 829c9b8..ab9fb5f 100644 --- a/modes/classicmode/sfml/spritefactorysfml.cpp +++ b/src/impl/sfml/classicmode/spritefactorysfml.cpp @@ -1,4 +1,5 @@ #include "spritefactorysfml.h" +#include "classicspritesfml.h" ClassicSpriteFactorySFML::ClassicSpriteFactorySFML(const std::shared_ptr& render_target) : _render_target(render_target) @@ -30,5 +31,5 @@ std::shared_ptr ClassicSpriteFactorySFML::create(Type type) const sprite.setFillColor(sf::Color(255, 239, 0)); } - return std::make_shared(_render_target, sprite); + return std::make_shared(_render_target, sprite); } diff --git a/modes/classicmode/sfml/spritefactorysfml.h b/src/impl/sfml/classicmode/spritefactorysfml.h similarity index 100% rename from modes/classicmode/sfml/spritefactorysfml.h rename to src/impl/sfml/classicmode/spritefactorysfml.h diff --git a/src/impl/sfml/corefactorysfml.cpp b/src/impl/sfml/corefactorysfml.cpp new file mode 100644 index 0000000..7c19893 --- /dev/null +++ b/src/impl/sfml/corefactorysfml.cpp @@ -0,0 +1,40 @@ +#include "corefactorysfml.h" + +#include "rectanglesfml.h" +#include "musicsfml.h" +#include "textsfml.h" +#include "linesfml.h" + +CoreFactorySFML::CoreFactorySFML(const std::shared_ptr& render_target) : + _render_target(render_target) +{ + auto gui_font = std::make_unique(); + gui_font->loadFromFile("SourceCodePro-Regular.ttf"); + _font_holder.load(kku::Font::Id::GUI, std::move(gui_font)); +} + +std::shared_ptr CoreFactorySFML::getMusic() const +{ + return std::make_unique(); +} + +std::shared_ptr CoreFactorySFML::getText(kku::Font::Id id) const +{ + return std::make_unique(_render_target, _font_holder.get(id)); +} + +std::shared_ptr CoreFactorySFML::getRectangle() const +{ + return std::make_unique(_render_target); +} + + std::shared_ptr CoreFactorySFML::getLine() const + { + return std::make_unique(_render_target); + } + +kku::Vector2 CoreFactorySFML::getRenderSize() const +{ + const sf::Vector2u size = _render_target->getSize(); + return kku::makeVector(size.x, size.y); +} diff --git a/src/impl/sfml/corefactorysfml.h b/src/impl/sfml/corefactorysfml.h new file mode 100644 index 0000000..0d2a8ed --- /dev/null +++ b/src/impl/sfml/corefactorysfml.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +#include "core/corefactory.h" + +class CoreFactorySFML : public kku::CoreFactory +{ +public: + explicit CoreFactorySFML(const std::shared_ptr& render_target); + virtual std::shared_ptr getMusic() const override; + virtual std::shared_ptr getText(kku::Font::Id id) const override; + virtual std::shared_ptr getRectangle() const override; + virtual std::shared_ptr getLine() const override; + virtual kku::Vector2 getRenderSize() const override; + +private: + const std::shared_ptr _render_target; + kku::ResourceHolder _font_holder; +}; diff --git a/src/impl/sfml/linesfml.cpp b/src/impl/sfml/linesfml.cpp new file mode 100644 index 0000000..5d4b7b2 --- /dev/null +++ b/src/impl/sfml/linesfml.cpp @@ -0,0 +1,24 @@ +#include "linesfml.h" + +LineSFML::LineSFML(const std::shared_ptr& render_target) : + _render_target(render_target) +{ + _vertex = sf::VertexArray(sf::LinesStrip, 2); +} + +void LineSFML::setPosition(const kku::Point& p1, const kku::Point& p2) +{ + _vertex[0].position = {p1.x, p1.y}; + _vertex[1].position = {p2.x, p2.y}; +} + +void LineSFML::setColor(const kku::Color& c1, const kku::Color& c2) +{ + _vertex[0].color = sf::Color{c1.red, c1.green, c1.blue, c1.alpha}; + _vertex[1].color = sf::Color{c2.red, c2.green, c2.blue, c2.alpha}; +} + +void LineSFML::display() +{ + _render_target->draw(_vertex); +} \ No newline at end of file diff --git a/src/impl/sfml/linesfml.h b/src/impl/sfml/linesfml.h new file mode 100644 index 0000000..224a0ff --- /dev/null +++ b/src/impl/sfml/linesfml.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +#include "core/line.h" + +class LineSFML : public kku::Line +{ +public: + explicit LineSFML(const std::shared_ptr& render_target); + virtual void setPosition(const kku::Point& p1, const kku::Point& p2) override; + virtual void setColor(const kku::Color& c1, const kku::Color& c2) override; + virtual void display() override; + +private: + const std::shared_ptr _render_target; + sf::VertexArray _vertex; +}; diff --git a/tools/src/music.cpp b/src/impl/sfml/musicsfml.cpp similarity index 74% rename from tools/src/music.cpp rename to src/impl/sfml/musicsfml.cpp index 45cee13..9b54f54 100644 --- a/tools/src/music.cpp +++ b/src/impl/sfml/musicsfml.cpp @@ -1,49 +1,49 @@ -#include "tools/music.h" +#include "musicsfml.h" -Music::Music() : +MusicSFML::MusicSFML() : _sfml_music_offset(0), _previous_frame_offset(0), _absolute_offset(0) {} -bool Music::openFromFile(const std::string& filepath) +bool MusicSFML::open(const std::string& filepath) { return _music.openFromFile(filepath); } -void Music::play() +void MusicSFML::play() { _music.play(); _sfml_music_offset = _offset_interpolator.restart().asMicroseconds(); } -void Music::pause() +void MusicSFML::pause() { _music.pause(); } -void Music::stop() +void MusicSFML::stop() { _music.stop(); } -bool Music::isPaused() const +bool MusicSFML::isPlaying() const { - return (_music.getStatus() != sf::Music::Playing); + return _music.getStatus() == sf::Music::Playing; } -void Music::setVolume(int volume) +void MusicSFML::setVolume(float volume) { _music.setVolume(volume); } -void Music::setOffset(const microsec& offset) +void MusicSFML::setOffset(const kku::microsec& offset) { //_previous_frame_offset += (offset - _absolute_offset); _music.setPlayingOffset(sf::microseconds(offset)); } -microsec Music::fetchOffset() +kku::microsec MusicSFML::fetchOffset() { if (_music.getStatus() != sf::Music::Status::Playing) return _absolute_offset; @@ -62,10 +62,11 @@ microsec Music::fetchOffset() return _absolute_offset; } -void Music::moveOffset(const microsec& delta) +void MusicSFML::moveOffset(const kku::microsec& delta) { const auto offset = fetchOffset(); const auto result = offset + delta; + if (result < 0) { setOffset(0); @@ -81,7 +82,8 @@ void Music::moveOffset(const microsec& delta) } } -microsec Music::getDuration() const +kku::microsec MusicSFML::getDuration() const { return _music.getDuration().asMicroseconds(); } + diff --git a/src/impl/sfml/musicsfml.h b/src/impl/sfml/musicsfml.h new file mode 100644 index 0000000..8327dd6 --- /dev/null +++ b/src/impl/sfml/musicsfml.h @@ -0,0 +1,35 @@ +#pragma once + +#include "core/music.h" + +#include +#include + +class MusicSFML : public kku::Music +{ +public: + explicit MusicSFML(); + virtual bool open(const std::string& filepath) override; + + virtual void play() override; + virtual void pause() override; + virtual void stop() override; + + virtual bool isPlaying() const override; + + virtual void setVolume(float volume) override; + + virtual void setOffset(const kku::microsec& offset) override; + virtual void moveOffset(const kku::microsec& delta) override; + + virtual kku::microsec fetchOffset() override; + virtual kku::microsec getDuration() const override; + +private: + sf::Music _music; + sf::Clock _offset_interpolator; + + kku::microsec _sfml_music_offset; + kku::microsec _previous_frame_offset; + kku::microsec _absolute_offset; +}; diff --git a/src/impl/sfml/rectanglesfml.cpp b/src/impl/sfml/rectanglesfml.cpp new file mode 100644 index 0000000..c82649d --- /dev/null +++ b/src/impl/sfml/rectanglesfml.cpp @@ -0,0 +1,51 @@ +#include "rectanglesfml.h" + +RectangleSFML::RectangleSFML(const std::shared_ptr& render_target) : + _render_target(render_target) +{} + +void RectangleSFML::setRect(const kku::Area& rect) +{ + _rectangle.setPosition(rect.left, rect.top); + _rectangle.setSize({rect.width, rect.height}); +} + +kku::Area RectangleSFML::getRect() const +{ + const auto position = _rectangle.getPosition(); + const auto size = _rectangle.getSize(); + + return kku::Area{position.x, position.y, size.x, size.y}; +} + +void RectangleSFML::move(const kku::Vector2& delta) +{ + _rectangle.move({delta.first, delta.second}); +} + +void RectangleSFML::setPosition(const kku::Point& position) +{ + _rectangle.setPosition({position.x, position.y}); +} + +kku::Point RectangleSFML::getPosition() const +{ + const auto position = _rectangle.getPosition(); + return kku::Point{position.x, position.y}; +} + +void RectangleSFML::setColor(const kku::Color& color) +{ + _rectangle.setFillColor(sf::Color{color.red, color.green, + color.blue, color.alpha}); +} + +bool RectangleSFML::contains(const kku::Point& position) const +{ + return _rectangle.getGlobalBounds().contains(position.x, position.y); +} + +void RectangleSFML::display() +{ + _render_target->draw(_rectangle); +} diff --git a/src/impl/sfml/rectanglesfml.h b/src/impl/sfml/rectanglesfml.h new file mode 100644 index 0000000..ffb4cb5 --- /dev/null +++ b/src/impl/sfml/rectanglesfml.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + +#include "core/rectangle.h" + +class RectangleSFML : public kku::Rectangle +{ +public: + explicit RectangleSFML(const std::shared_ptr& render_target); + virtual void setRect(const kku::Area& rect) override; + virtual kku::Area getRect() const override; + + virtual void setPosition(const kku::Point& position) override; + virtual kku::Point getPosition() const override; + virtual void move(const kku::Vector2& delta) override; + + virtual void setColor(const kku::Color& color) override; + virtual bool contains(const kku::Point& position) const override; + + virtual void display() override; + +private: + const std::shared_ptr _render_target; + sf::RectangleShape _rectangle; +}; diff --git a/src/impl/sfml/textsfml.cpp b/src/impl/sfml/textsfml.cpp new file mode 100644 index 0000000..9f25196 --- /dev/null +++ b/src/impl/sfml/textsfml.cpp @@ -0,0 +1,38 @@ +#include "textsfml.h" + +TextSFML::TextSFML(const std::shared_ptr& render_target, + const std::shared_ptr& font) : + _render_target(render_target) +{ + _text.setFont(*font); +} + +void TextSFML::setString(const std::string& string) +{ + _text.setString(string); +} + +void TextSFML::setCharacterSize(std::size_t pixels) +{ + _text.setCharacterSize(pixels); +} + +void TextSFML::setPosition(const kku::Point& point) +{ + _text.setPosition(point.x, point.y); +} + +void TextSFML::move(const kku::Vector2& delta) +{ + _text.move({delta.first, delta.second}); +} + +void TextSFML::setColor(const kku::Color& color) +{ + _text.setFillColor(sf::Color{color.red, color.green, color.blue, color.alpha}); +} + +void TextSFML::display() +{ + _render_target->draw(_text); +} diff --git a/src/impl/sfml/textsfml.h b/src/impl/sfml/textsfml.h new file mode 100644 index 0000000..296942c --- /dev/null +++ b/src/impl/sfml/textsfml.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include + +#include "core/text.h" + +class TextSFML : public kku::Text +{ +public: + explicit TextSFML(const std::shared_ptr& render_target, + const std::shared_ptr& font); + + virtual void setString(const std::string& string) override; + virtual void setCharacterSize(std::size_t pixels) override; + virtual void setPosition(const kku::Point& point) override; + virtual void move(const kku::Vector2& delta) override; + virtual void setColor(const kku::Color& color) override; + + virtual void display() override; + +protected: + std::shared_ptr _render_target; + sf::Text _text; +}; diff --git a/src/main.cpp b/src/main.cpp index 07d5556..b556378 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,8 @@ -#include "application/application.h" +#include "application/applicationsfml.h" int main() { - Application app; - app.run(); + ApplicationSFML app(std::make_shared(sf::VideoMode{1280, 720}, "Test", sf::Style::Fullscreen)); + if (app.init()) + app.run(); } diff --git a/src/modes/classicmode/CMakeLists.txt b/src/modes/classicmode/CMakeLists.txt new file mode 100644 index 0000000..00827be --- /dev/null +++ b/src/modes/classicmode/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.13) + +project(classicmode) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared) + +file(GLOB_RECURSE SOURCES "editor/*.h" "editor/*.cpp" + "graphics/*.h" "graphics/*.cpp" + "game/*.h" "game/*.cpp" + "shared/*.h" + "include/*.h") + +add_library(classicmode STATIC ${SOURCES} ${HEADERS}) +target_include_directories(classicmode PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(classicmode tools) + +target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/src/modes/classicmode/shared) + diff --git a/modes/classicmode/editor/classiceditor.cpp b/src/modes/classicmode/editor/classiceditor.cpp similarity index 65% rename from modes/classicmode/editor/classiceditor.cpp rename to src/modes/classicmode/editor/classiceditor.cpp index 0413b48..4e7a567 100644 --- a/modes/classicmode/editor/classiceditor.cpp +++ b/src/modes/classicmode/editor/classiceditor.cpp @@ -7,7 +7,7 @@ #include "graphics/animations/classicdyinganimationscenario.h" // -ClassicEditor::ClassicEditor(const std::shared_ptr>& timeline, +ClassicEditor::ClassicEditor(const std::shared_ptr>& timeline, const std::shared_ptr& graphics_manager) : _timeline(timeline), _graphics_manager(graphics_manager), @@ -18,26 +18,26 @@ ClassicEditor::ClassicEditor(const std::shared_ptr>& timel _timeline->setNotes({}); } -microsec ClassicEditor::adjustOffset(microsec offset) const noexcept +kku::microsec ClassicEditor::adjustOffset(kku::microsec offset) const noexcept { const auto& section = getBPMSectionAt(offset); - const microsec actual_offset = offset - section.offset_start; + const kku::microsec actual_offset = offset - section.offset_start; return actual_offset + (actual_offset % section.interval); } -void ClassicEditor::input(PlayerInput&& inputdata) +void ClassicEditor::input(kku::GameEvent&& input) { - _current_time = inputdata.timestamp; - const auto& event = inputdata.event; + _current_time = input.timestamp; + const auto& event = input.event; - switch (event.type) + switch (input.event.type) { default: break; - case sf::Event::MouseButtonPressed: + case kku::SystemEvent::Type::MousePress: { const auto note = _timeline->getNoteBy(_current_time); if (_timeline->isExpired(note) && !_bpm_sections.empty() && _current_time >= (*_bpm_sections.begin()).offset_start) @@ -45,16 +45,16 @@ void ClassicEditor::input(PlayerInput&& inputdata) ArrowNoteInitializer init; ArrowElementInitializer element; init.initializer.intervals = {}; - init.initializer.perfect_offset = inputdata.timestamp; + init.initializer.perfect_offset = input.timestamp; init.hold = false; init.initializer.context = nullptr; - element.element.coordinates = Coordinates(event.mouseButton.x, event.mouseButton.y); + element.element.position = std::get(event.data).position; element.element.falling_curve_interpolation = {}; - element.keys = {sf::Keyboard::W, sf::Keyboard::Up}; + element.keys = {'W', 'w'}; element.element.type = Type::UP; - init.elements = {element}; + init.elements = { element }; _timeline->insertNote(new ClassicArrowNote(std::move(init))); } @@ -64,7 +64,7 @@ void ClassicEditor::input(PlayerInput&& inputdata) } } -void ClassicEditor::update(UpdateData&& updatedata) +void ClassicEditor::update(kku::UpdateData&& updatedata) { _timeline->update(updatedata.timestamp); } @@ -73,7 +73,7 @@ void ClassicEditor::display() const { } -void ClassicEditor::recalculate(const microsec& timestamp) +void ClassicEditor::recalculate(const kku::microsec& timestamp) { _timeline->recalculate(timestamp); } diff --git a/src/modes/classicmode/editor/classiceditor.h b/src/modes/classicmode/editor/classiceditor.h new file mode 100644 index 0000000..21ab6c8 --- /dev/null +++ b/src/modes/classicmode/editor/classiceditor.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "core/editor.h" +#include "core/timeline.h" + +#include "game/classicnote.h" +#include "classicmode/classicactions.h" + +class ClassicGraphicsManager; + +class ClassicEditor : public kku::Editor +{ +public: + explicit ClassicEditor(const std::shared_ptr>& timeline, + const std::shared_ptr& graphics_manager); + + virtual void input(kku::GameEvent&& input) override; + virtual void update(kku::UpdateData&& updatedata) override; + virtual void display() const override; + virtual void recalculate(const kku::microsec& timestamp) override; + + void selectNoteType(Type type) noexcept; + +private: + inline kku::microsec adjustOffset(kku::microsec offset) const noexcept; + + Context _context; + + const std::shared_ptr> _timeline; + const std::shared_ptr _graphics_manager; + + Type _selected_type; + kku::microsec _current_time; + kku::microsec _scroll_step; +}; diff --git a/modes/classicmode/editor/initializers/mockarrownoteinitializer.h b/src/modes/classicmode/editor/initializers/mockarrownoteinitializer.h similarity index 100% rename from modes/classicmode/editor/initializers/mockarrownoteinitializer.h rename to src/modes/classicmode/editor/initializers/mockarrownoteinitializer.h diff --git a/modes/classicmode/game/arrowelement.h b/src/modes/classicmode/game/arrowelement.h similarity index 66% rename from modes/classicmode/game/arrowelement.h rename to src/modes/classicmode/game/arrowelement.h index 55f065a..8536462 100644 --- a/modes/classicmode/game/arrowelement.h +++ b/src/modes/classicmode/game/arrowelement.h @@ -2,8 +2,8 @@ #include "classicmode/classicactions.h" -#include "core/inputtype.h" -#include "tools/mathutils.h" +#include "core/gameevent.h" +#include "core/point.h" #include #include @@ -16,11 +16,11 @@ struct ArrowElement { std::shared_ptr sprite; std::array, 5> animations; - sf::Keyboard::Key pressed_as = sf::Keyboard::Unknown; + char pressed_as = ' '; - Coordinates coordinates; - std::vector falling_curve_interpolation; - std::array keys; + kku::Point position; + std::vector falling_curve_interpolation; + std::array keys; Type type = Type::NONE; bool pressed = false; diff --git a/modes/classicmode/game/classicarrownote.cpp b/src/modes/classicmode/game/classicarrownote.cpp similarity index 81% rename from modes/classicmode/game/classicarrownote.cpp rename to src/modes/classicmode/game/classicarrownote.cpp index ddcbb28..6bf61dc 100644 --- a/modes/classicmode/game/classicarrownote.cpp +++ b/src/modes/classicmode/game/classicarrownote.cpp @@ -12,7 +12,7 @@ ClassicArrowNote::ClassicArrowNote(ArrowNoteInitializer&& init) : for (std::size_t i = 0; i < _elements.size(); ++i) { _elements[i].keys = init.elements[i].keys; - _elements[i].coordinates = init.elements[i].element.coordinates; + _elements[i].position = init.elements[i].element.position; _elements[i].type = init.elements[i].element.type; } } @@ -22,22 +22,24 @@ void ClassicArrowNote::putToGame() _state = State::FLYING; } -void ClassicArrowNote::input(PlayerInput&& inputdata) +void ClassicArrowNote::input(kku::GameEvent&& input) { auto grade = ClassicNote::Grade::BAD; bool input_valid = std::any_of(_elements.begin(), _elements.end(), - [inputdata=inputdata](auto& element) + [input=input](auto& element) { if (element.pressed) return false; - auto key_iterator = std::find(element.keys.begin(), element.keys.end(), inputdata.event.key.code); + const char code = std::get(input.event.data).view; + auto key_iterator = std::find(element.keys.begin(), element.keys.end(), code); + bool found_key = key_iterator != element.keys.end(); if (found_key) { element.pressed = true; - element.pressed_as = inputdata.event.key.code; + element.pressed_as = code; } return found_key; @@ -47,7 +49,7 @@ void ClassicArrowNote::input(PlayerInput&& inputdata) if (all_pressed) { - grade = _evaluator.calculatePrecision(inputdata.timestamp); + grade = _evaluator.calculatePrecision(input.timestamp); if (isHold()) _context->hold_manager->emplace(this); } @@ -56,13 +58,13 @@ void ClassicArrowNote::input(PlayerInput&& inputdata) { _state = State::DYING; for (auto& element : _elements) - element.animations[_state]->launch(element.sprite, inputdata.timestamp, offset()); + element.animations[_state]->launch(element.sprite, input.timestamp, getPerfectOffset()); } std::cout << "User input: " << static_cast(grade) << "\n"; } -void ClassicArrowNote::update(const microsec& music_offset) +void ClassicArrowNote::update(const kku::microsec& music_offset) { switch (_state) { @@ -70,11 +72,11 @@ void ClassicArrowNote::update(const microsec& music_offset) break; case State::FLYING: - if (!_evaluator.isActive(music_offset) && music_offset > offset()) + if (!_evaluator.isActive(music_offset) && music_offset > getPerfectOffset()) { _state = State::DYING; for (auto& element : _elements) - element.animations[_state]->launch(element.sprite, music_offset, offset()); + element.animations[_state]->launch(element.sprite, music_offset, getPerfectOffset()); } break; @@ -94,7 +96,7 @@ void ClassicArrowNote::display(const ClassicGraphicsManager * const manager) con manager->display(_elements); } -void ClassicArrowNote::setGraphics(ClassicGraphicsManager * const manager, TimeRange&& range) +void ClassicArrowNote::setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) { manager->setGraphics(_elements, std::move(range)); } @@ -108,7 +110,7 @@ bool ClassicArrowNote::allElementsPressed() const }); } -bool ClassicArrowNote::isPressedAs(sf::Keyboard::Key key) const +bool ClassicArrowNote::isPressedAs(char key) const { return std::any_of(_elements.begin(), _elements.end(), [key](const auto& element) diff --git a/modes/classicmode/game/classicarrownote.h b/src/modes/classicmode/game/classicarrownote.h similarity index 75% rename from modes/classicmode/game/classicarrownote.h rename to src/modes/classicmode/game/classicarrownote.h index cc32ebd..c0c9c8d 100644 --- a/modes/classicmode/game/classicarrownote.h +++ b/src/modes/classicmode/game/classicarrownote.h @@ -2,6 +2,7 @@ #include "arrowelement.h" #include "classicnote.h" + #include "initializers/arrownoteinitializer.h" class ClassicArrowNote : public ClassicNote @@ -11,14 +12,14 @@ public: virtual ~ClassicArrowNote() = default; virtual void putToGame() override; - virtual void update(const microsec &music_offset) override; - virtual void input(PlayerInput&& inputdata) override; + virtual void update(const kku::microsec &music_offset) override; + virtual void input(kku::GameEvent&& input) override; virtual void display(const ClassicGraphicsManager * const manager) const override; - virtual void setGraphics(ClassicGraphicsManager * const manager, TimeRange&& range) override; + virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) override; bool allElementsPressed() const; - bool isPressedAs(sf::Keyboard::Key key) const; + bool isPressedAs(char key) const; inline bool isHold() const; private: diff --git a/src/modes/classicmode/game/classicgame.cpp b/src/modes/classicmode/game/classicgame.cpp new file mode 100644 index 0000000..15c38a8 --- /dev/null +++ b/src/modes/classicmode/game/classicgame.cpp @@ -0,0 +1,72 @@ +#include "classicgame.h" +#include "classicnote.h" +#include "classicmapcreator.h" +#include "graphics/classicscenegraphicsmanager.h" +#include "holdmanager.h" + +ClassicGame::ClassicGame(const std::shared_ptr>& timeline, + const std::shared_ptr& graphics_manager) : + _timeline(timeline), + _graphics_manager(graphics_manager), + _hold_manager(std::make_unique()) +{} + +ClassicGame::~ClassicGame() +{} + +void ClassicGame::run() +{ + _context.hold_manager = _hold_manager; + + auto beatmap = classic::createBeatmap("aa", _context); + _timeline->setNotes(beatmap.notes); +} + +void ClassicGame::input(kku::GameEvent&& input) +{ + switch (input.event.type) + { + default: + return; + break; + + case kku::SystemEvent::Type::KeyPress: + { + auto note_it = _timeline->getActiveNote(input.timestamp); + + if (!_timeline->isExpired(note_it)) + { + auto note = (*note_it); + note->input(std::move(input)); + } + } + break; + + case kku::SystemEvent::Type::KeyRelease: + { + _hold_manager->checkRelease(std::get(input.event.data).view); + } + break; + + } +} + +void ClassicGame::update(kku::UpdateData&& updatedata) +{ + // UNCOMMENT TO TEST AUTOPLAY + auto note_it = _timeline->getActiveNote(updatedata.timestamp); + + if (!_timeline->isExpired(note_it) && updatedata.timestamp >= (*note_it)->getPerfectOffset()) + { + auto note = (*note_it); + note->input(kku::GameEvent{updatedata.timestamp, kku::SystemEvent{kku::SystemEvent::Type::None, kku::SystemEvent::Key{}}}); + } + + _timeline->update(updatedata.timestamp); + _graphics_manager->update(updatedata.timestamp); +} + +void ClassicGame::display() const +{ + _graphics_manager->display(); +} diff --git a/modes/classicmode/game/classicgame.h b/src/modes/classicmode/game/classicgame.h similarity index 51% rename from modes/classicmode/game/classicgame.h rename to src/modes/classicmode/game/classicgame.h index bf97cfd..4717aeb 100644 --- a/modes/classicmode/game/classicgame.h +++ b/src/modes/classicmode/game/classicgame.h @@ -3,9 +3,6 @@ #include #include -#include -#include - #include "core/game.h" #include "core/timeline.h" @@ -17,30 +14,23 @@ class ClassicGraphicsManager; class HoldManager; -class ClassicGame final : public Game +class ClassicGame final : public kku::Game { public: - explicit ClassicGame(const std::shared_ptr>& timeline, + explicit ClassicGame(const std::shared_ptr>& timeline, const std::shared_ptr& graphics_manager); virtual ~ClassicGame() override; virtual void run() override; - virtual void input(PlayerInput&& inputdata) override; - virtual void update(UpdateData&& updatedata) override; + virtual void input(kku::GameEvent&& inputdata) override; + virtual void update(kku::UpdateData&& updatedata) override; virtual void display() const override; private: - std::map _keys_to_buttons; - std::map _buttons_to_pressed_actions; - std::map _buttons_to_released_actions; - - const std::shared_ptr> _timeline; + const std::shared_ptr> _timeline; const std::shared_ptr _graphics_manager; std::shared_ptr _hold_manager; - sf::SoundBuffer _slap_buffer; - sf::Sound _slap; - Context _context; }; diff --git a/modes/classicmode/game/classicmapcreator.cpp b/src/modes/classicmode/game/classicmapcreator.cpp similarity index 68% rename from modes/classicmode/game/classicmapcreator.cpp rename to src/modes/classicmode/game/classicmapcreator.cpp index a58aa16..c4d2c1c 100644 --- a/modes/classicmode/game/classicmapcreator.cpp +++ b/src/modes/classicmode/game/classicmapcreator.cpp @@ -10,17 +10,17 @@ auto classic::createBeatmap(const std::string& filepath, const Context &context) { (void) filepath; - microsec starting_beat_offset = 402162; + kku::microsec starting_beat_offset = 402162; int amount_of_beats = 209; - microsec interval = 1412162; - microsec tempo_interval = interval / 4; - microsec note_input_offset = 412162 / 2; + kku::microsec interval = 1412162; + kku::microsec tempo_interval = interval / 4; + kku::microsec note_input_offset = 412162 / 2; //microsec note_input_offset_fast = 412162 / 6; - microsec bpm_iterator = starting_beat_offset; - microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); + kku::microsec bpm_iterator = starting_beat_offset; + kku::microsec bpm_end = starting_beat_offset + (interval * amount_of_beats); - std::vector input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset}; - std::set notes; + std::vector input_intervals = {note_input_offset / 3, note_input_offset / 3 * 2, note_input_offset}; + std::set notes; input_intervals.shrink_to_fit(); bpm_iterator += tempo_interval; @@ -38,15 +38,15 @@ auto classic::createBeatmap(const std::string& filepath, const Context &context) init.hold = false; init.initializer.context = &context; - element.element.coordinates = Coordinates(x, 390.f); + element.element.position = kku::Point(x, 390.f); element.element.falling_curve_interpolation = {}; - element.keys = {sf::Keyboard::W, sf::Keyboard::Up}; + element.keys = {'W', 'w'}; element.element.type = Type::UP; if (counter == 0) { init.hold = true; - element.keys = {sf::Keyboard::D, sf::Keyboard::Right}; + element.keys = {'D', 'd'}; element.element.type = Type::RIGHT; } diff --git a/modes/classicmode/game/classicmapcreator.h b/src/modes/classicmode/game/classicmapcreator.h similarity index 60% rename from modes/classicmode/game/classicmapcreator.h rename to src/modes/classicmode/game/classicmapcreator.h index 87a2e11..c621750 100644 --- a/modes/classicmode/game/classicmapcreator.h +++ b/src/modes/classicmode/game/classicmapcreator.h @@ -2,7 +2,7 @@ #include -#include "tools/mathutils.h" +#include "core/time.h" #include "classicnote.h" namespace classic @@ -10,8 +10,8 @@ namespace classic struct Beatmap { - std::set notes; - microsec visibility_offset; + std::set notes; + kku::microsec visibility_offset; }; Beatmap createBeatmap(const std::string& filepath, const Context& context); diff --git a/modes/classicmode/game/classicnote.cpp b/src/modes/classicmode/game/classicnote.cpp similarity index 88% rename from modes/classicmode/game/classicnote.cpp rename to src/modes/classicmode/game/classicnote.cpp index 2ee4d03..44158d0 100644 --- a/modes/classicmode/game/classicnote.cpp +++ b/src/modes/classicmode/game/classicnote.cpp @@ -7,7 +7,7 @@ ClassicNote::ClassicNote(NoteInitializer &&init) : _context(init.context) {} -bool ClassicNote::isActive(const microsec& offset) const +bool ClassicNote::isActive(const kku::microsec& offset) const { return _evaluator.isActive(offset) && _state != State::DYING; diff --git a/modes/classicmode/game/classicnote.h b/src/modes/classicmode/game/classicnote.h similarity index 72% rename from modes/classicmode/game/classicnote.h rename to src/modes/classicmode/game/classicnote.h index d0d865f..1a14937 100644 --- a/modes/classicmode/game/classicnote.h +++ b/src/modes/classicmode/game/classicnote.h @@ -1,15 +1,15 @@ #pragma once -#include "classicmode/context.h" #include "core/note.h" #include "core/precisionevaluator.h" #include "classicmode/noteinitializer.h" +#include "classicmode/context.h" class ClassicSprite; class ClassicAnimationScenario; class ClassicGraphicsManager; -class ClassicNote : public Note +class ClassicNote : public kku::Note { public: @@ -32,20 +32,20 @@ public: explicit ClassicNote(NoteInitializer&& init); virtual ~ClassicNote() override = default; - virtual bool isActive(const microsec& offset) const override final; + virtual bool isActive(const kku::microsec& offset) const override final; virtual bool isInGame() const override final; virtual bool shouldRemove() const override final; virtual void putToGame() override = 0; - virtual void update(const microsec &music_offset) override = 0; + virtual void update(const kku::microsec &music_offset) override = 0; - virtual void input(PlayerInput&& inputdata) = 0; + virtual void input(kku::GameEvent&& input) override = 0; virtual void display(const ClassicGraphicsManager * const manager) const = 0; - virtual void setGraphics(ClassicGraphicsManager * const manager, TimeRange&& range) = 0; + virtual void setGraphics(ClassicGraphicsManager * const manager, kku::TimeRange&& range) = 0; protected: - const PrecisionEvaluator _evaluator; + const kku::PrecisionEvaluator _evaluator; State _state; const Context *_context; diff --git a/modes/classicmode/game/holdmanager.cpp b/src/modes/classicmode/game/holdmanager.cpp similarity index 90% rename from modes/classicmode/game/holdmanager.cpp rename to src/modes/classicmode/game/holdmanager.cpp index aeb204d..5f4bbae 100644 --- a/modes/classicmode/game/holdmanager.cpp +++ b/src/modes/classicmode/game/holdmanager.cpp @@ -2,13 +2,14 @@ #include "classicarrownote.h" #include +#include void HoldManager::emplace(ClassicArrowNote* note) { _notes_on_hold.emplace_back(note); } -void HoldManager::checkRelease(sf::Keyboard::Key released_key) +void HoldManager::checkRelease(char released_key) { bool key_match = std::any_of(_notes_on_hold.begin(), _notes_on_hold.end(), [released_key](const auto& note) diff --git a/modes/classicmode/game/holdmanager.h b/src/modes/classicmode/game/holdmanager.h similarity index 79% rename from modes/classicmode/game/holdmanager.h rename to src/modes/classicmode/game/holdmanager.h index 5527709..598ca3c 100644 --- a/modes/classicmode/game/holdmanager.h +++ b/src/modes/classicmode/game/holdmanager.h @@ -1,6 +1,7 @@ #pragma once -#include "core/inputtype.h" +#include "core/gameevent.h" + #include #include @@ -11,7 +12,7 @@ class HoldManager { public: void emplace(ClassicArrowNote* note); - void checkRelease(sf::Keyboard::Key released_key); + void checkRelease(char released_key); void drawHoldBar(); diff --git a/modes/classicmode/game/initializers/arrowelementinitializer.h b/src/modes/classicmode/game/initializers/arrowelementinitializer.h similarity index 74% rename from modes/classicmode/game/initializers/arrowelementinitializer.h rename to src/modes/classicmode/game/initializers/arrowelementinitializer.h index 8930f64..827a6f9 100644 --- a/modes/classicmode/game/initializers/arrowelementinitializer.h +++ b/src/modes/classicmode/game/initializers/arrowelementinitializer.h @@ -5,5 +5,5 @@ struct ArrowElementInitializer { ElementInitializer element; - std::array keys; + std::array keys; }; diff --git a/modes/classicmode/game/initializers/arrownoteinitializer.h b/src/modes/classicmode/game/initializers/arrownoteinitializer.h similarity index 100% rename from modes/classicmode/game/initializers/arrownoteinitializer.h rename to src/modes/classicmode/game/initializers/arrownoteinitializer.h diff --git a/modes/classicmode/graphics/animations/classicanimationscenario.h b/src/modes/classicmode/graphics/animations/classicanimationscenario.h similarity index 58% rename from modes/classicmode/graphics/animations/classicanimationscenario.h rename to src/modes/classicmode/graphics/animations/classicanimationscenario.h index c4dc02f..8ce4e3e 100644 --- a/modes/classicmode/graphics/animations/classicanimationscenario.h +++ b/src/modes/classicmode/graphics/animations/classicanimationscenario.h @@ -1,6 +1,7 @@ #pragma once -#include "tools/mathutils.h" +#include "core/time.h" + #include class ClassicSprite; @@ -10,12 +11,12 @@ class ClassicAnimationScenario public: virtual ~ClassicAnimationScenario() = default; - virtual void launch(const std::shared_ptr sprite, const microsec& time_begin, const microsec &time_end) = 0; - virtual void update(const microsec& music_offset) = 0; + virtual void launch(const std::shared_ptr sprite, const kku::microsec& time_begin, const kku::microsec &time_end) = 0; + virtual void update(const kku::microsec& music_offset) = 0; virtual bool isDone() const = 0; protected: std::shared_ptr _sprite; - microsec _time_begin; - microsec _time_end; + kku::microsec _time_begin; + kku::microsec _time_end; }; diff --git a/src/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp b/src/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp new file mode 100644 index 0000000..610fba2 --- /dev/null +++ b/src/modes/classicmode/graphics/animations/classicdyinganimationscenario.cpp @@ -0,0 +1,37 @@ +#include "classicdyinganimationscenario.h" +#include "graphics/classicsprite.h" + +void ClassicDyingAnimationScenario::launch(const std::shared_ptr sprite, const kku::microsec& time_begin, const kku::microsec &time_end) +{ + _sprite = sprite; + _time_begin = time_begin; + _time_end = time_end; + + _sprite->setColor(kku::Color{140, 140, 140, 255}); + _sprite->setTrailColor(kku::Color{0, 0, 0, 255}); + _sprite->setTrailPosition(kku::Point{0, 0}); +} + +void ClassicDyingAnimationScenario::update(const kku::microsec& music_offset) +{ + (void) music_offset; + + auto fill_color = _sprite->getColor(); + + if (fill_color.alpha == 0) + { + fill_color.alpha = 0; + _sprite->setColor(fill_color); + return; + } + + auto new_alpha = (int(fill_color.alpha) - 15) < 0 ? 0 : int(fill_color.alpha) - 15; + fill_color.alpha = new_alpha; + + _sprite->setColor(fill_color); +} + +bool ClassicDyingAnimationScenario::isDone() const +{ + return _sprite->getColor().alpha == 0; +} diff --git a/modes/classicmode/graphics/animations/classicdyinganimationscenario.h b/src/modes/classicmode/graphics/animations/classicdyinganimationscenario.h similarity index 63% rename from modes/classicmode/graphics/animations/classicdyinganimationscenario.h rename to src/modes/classicmode/graphics/animations/classicdyinganimationscenario.h index f8ebf97..9e71198 100644 --- a/modes/classicmode/graphics/animations/classicdyinganimationscenario.h +++ b/src/modes/classicmode/graphics/animations/classicdyinganimationscenario.h @@ -5,7 +5,7 @@ class ClassicDyingAnimationScenario : public ClassicAnimationScenario { public: - virtual void launch(const std::shared_ptr sprite, const microsec& time_begin, const microsec& time_end) override; - virtual void update(const microsec& music_offset) override; + virtual void launch(const std::shared_ptr sprite, const kku::microsec& time_begin, const kku::microsec& time_end) override; + virtual void update(const kku::microsec& music_offset) override; virtual bool isDone() const override; }; diff --git a/src/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp b/src/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp new file mode 100644 index 0000000..5fd1b74 --- /dev/null +++ b/src/modes/classicmode/graphics/animations/classicflyinganimationscenario.cpp @@ -0,0 +1,53 @@ +#include "classicflyinganimationscenario.h" +#include "graphics/classicsprite.h" + +void ClassicFlyingAnimationScenario::launch(const std::shared_ptr sprite, const kku::microsec& time_begin, const kku::microsec &time_end) +{ + _sprite = sprite; + _time_begin = time_begin; + _time_end = time_end; + + _percentage = ((_time_end - _time_begin) * 0.01); +} + +float ClassicFlyingAnimationScenario::getPoint(const kku::Point& point, float perc) const +{ + return point.x + ((point.y - point.x) * perc); +} + +void ClassicFlyingAnimationScenario::update(const kku::microsec& music_offset) +{ + const auto crd = _sprite->getPosition(); + auto update_time = music_offset - _time_begin; + float i = update_time / _percentage * 0.01; + + float xa = getPoint(kku::Point{crd.x + 20, crd.x + 90}, i); + float ya = getPoint(kku::Point{crd.y - 600, crd.y - 150}, i); + float xb = getPoint(kku::Point{crd.x + 90, crd.x}, i); + float yb = getPoint(kku::Point{crd.y - 150, crd.y}, i); + + _sprite->setTrailPosition(kku::Point(getPoint( kku::Point{xa, xb}, i ), getPoint( kku::Point{ya, yb}, i ))); + + bool pastPerfectScore = (i >= 1); + + if (pastPerfectScore) + fadeTrailSprite(); +} + +bool ClassicFlyingAnimationScenario::isDone() const +{ + return false; +} + +void ClassicFlyingAnimationScenario::fadeTrailSprite() const +{ + auto fill_color = _sprite->getTrailColor(); + + if (fill_color.alpha == 0) + return; + + auto new_alpha = (int(fill_color.alpha) - 15) < 0 ? 0 : int(fill_color.alpha) - 15; + fill_color.alpha = new_alpha; + + _sprite->setTrailColor(fill_color); +} diff --git a/modes/classicmode/graphics/animations/classicflyinganimationscenario.h b/src/modes/classicmode/graphics/animations/classicflyinganimationscenario.h similarity index 57% rename from modes/classicmode/graphics/animations/classicflyinganimationscenario.h rename to src/modes/classicmode/graphics/animations/classicflyinganimationscenario.h index 2438306..6771a5a 100644 --- a/modes/classicmode/graphics/animations/classicflyinganimationscenario.h +++ b/src/modes/classicmode/graphics/animations/classicflyinganimationscenario.h @@ -1,16 +1,17 @@ #pragma once #include "classicanimationscenario.h" +#include "core/point.h" class ClassicFlyingAnimationScenario : public ClassicAnimationScenario { public: - virtual void launch(const std::shared_ptr sprite, const microsec& time_begin, const microsec& time_end) override; - virtual void update(const microsec& music_offset) override; + virtual void launch(const std::shared_ptr sprite, const kku::microsec& time_begin, const kku::microsec& time_end) override; + virtual void update(const kku::microsec& music_offset) override; virtual bool isDone() const override; private: - float getPoint(float n1, float n2, float perc) const; + float getPoint(const kku::Point& position, float perc) const; void fadeTrailSprite() const; float _percentage; diff --git a/modes/classicmode/graphics/classicgraphicsmanager.h b/src/modes/classicmode/graphics/classicgraphicsmanager.h similarity index 70% rename from modes/classicmode/graphics/classicgraphicsmanager.h rename to src/modes/classicmode/graphics/classicgraphicsmanager.h index 854c8fa..90e824b 100644 --- a/modes/classicmode/graphics/classicgraphicsmanager.h +++ b/src/modes/classicmode/graphics/classicgraphicsmanager.h @@ -1,6 +1,6 @@ #pragma once -#include "spritecontainer.h" +#include "core/spritecontainer.h" #include "classicmode/classicactions.h" #include "graphics/classicspritefactory.h" @@ -11,7 +11,7 @@ class ClassicGraphicsManager : public std::enable_shared_from_this& factory, const microsec& visibility_offset) : + explicit ClassicGraphicsManager(const std::shared_ptr& factory, const kku::microsec& visibility_offset) : _sprite_container({Type::UP, Type::DOWN, Type::LEFT, Type::RIGHT}, factory), @@ -19,12 +19,12 @@ public: {} virtual void display(const std::vector& elements) const = 0; - virtual void setGraphics(std::vector& elements, TimeRange&& range) = 0; + virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) = 0; virtual void display() const = 0; - virtual void update(const microsec& offset) = 0; + virtual void update(const kku::microsec& offset) = 0; protected: - SpriteContainer _sprite_container; - microsec _visibility_offset; + kku::SpriteContainer _sprite_container; + kku::microsec _visibility_offset; }; diff --git a/modes/classicmode/graphics/classicscenegraphicsmanager.cpp b/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp similarity index 74% rename from modes/classicmode/graphics/classicscenegraphicsmanager.cpp rename to src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp index 937cef2..e599636 100644 --- a/modes/classicmode/graphics/classicscenegraphicsmanager.cpp +++ b/src/modes/classicmode/graphics/classicscenegraphicsmanager.cpp @@ -2,14 +2,13 @@ #include "graphics/classicsprite.h" #include "game/arrowelement.h" -#include "editor/mockelement.h" #include "graphics/animations/classicflyinganimationscenario.h" #include "graphics/animations/classicdyinganimationscenario.h" -ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, +ClassicSceneGraphicsManager::ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, const std::shared_ptr& factory, - const microsec& visibility_offset) : + const kku::microsec& visibility_offset) : ClassicGraphicsManager(factory, visibility_offset), _timeline(timeline) { @@ -28,7 +27,7 @@ void ClassicSceneGraphicsManager::display() const } } -void ClassicSceneGraphicsManager::update(const microsec &offset) +void ClassicSceneGraphicsManager::update(const kku::microsec &offset) { fetchLastNote(offset); fetchFirstNote(offset); @@ -46,8 +45,8 @@ void ClassicSceneGraphicsManager::display(const std::vector& eleme { //const auto& neighbor_sprite = elements[i - 1].sprite; - //const auto c1 = neighbor_sprite->trailCoordinates(); - //const auto c2 = sprite->trailCoordinates(); + //const auto c1 = neighbor_sprite->trailPosition(); + //const auto c2 = sprite->trailPosition(); //_render_target->draw(makeLine(c1, c2)); } @@ -56,13 +55,13 @@ void ClassicSceneGraphicsManager::display(const std::vector& eleme } } -void ClassicSceneGraphicsManager::setGraphics(std::vector& elements, TimeRange &&range) +void ClassicSceneGraphicsManager::setGraphics(std::vector& elements, kku::TimeRange &&range) { for (auto& element : elements) { element.sprite = _sprite_container.getSprite(element.type); - element.sprite->setCoordinates(element.coordinates); - element.sprite->setTrailCoordinates(Coordinates( 0.f, 9.f )); + element.sprite->setPosition(element.position); + element.sprite->setTrailPosition(kku::Point( 0.f, 9.f )); element.animations[ClassicNote::State::NONE] = nullptr; element.animations[ClassicNote::State::FLYING] = std::make_shared(); @@ -73,7 +72,7 @@ void ClassicSceneGraphicsManager::setGraphics(std::vector& element } } -/*sf::VertexArray ClassicSceneGraphicsSFML::makeLine(const Coordinates& c1, const Coordinates& c2) const +/*sf::VertexArray ClassicSceneGraphicsSFML::makeLine(const kku::Point& c1, const kku::Point& c2) const { sf::VertexArray line(sf::LinesStrip, 2); line[0].color = sf::Color::Yellow; @@ -84,13 +83,13 @@ void ClassicSceneGraphicsManager::setGraphics(std::vector& element return line; }*/ -void ClassicSceneGraphicsManager::updateVisibleNotes(const microsec &offset) +void ClassicSceneGraphicsManager::updateVisibleNotes(const kku::microsec &offset) { for (auto it = _first; it != _last; ++it) (*it)->update(offset); } -void ClassicSceneGraphicsManager::fetchFirstNote(const microsec& offset) +void ClassicSceneGraphicsManager::fetchFirstNote(const kku::microsec& offset) { (void)offset; // ???? @@ -108,7 +107,7 @@ void ClassicSceneGraphicsManager::fetchFirstNote(const microsec& offset) } } -void ClassicSceneGraphicsManager::fetchLastNote(const microsec& offset) +void ClassicSceneGraphicsManager::fetchLastNote(const kku::microsec& offset) { Iterator note_iterator = _timeline->getTopNote(); while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset)) @@ -121,7 +120,7 @@ void ClassicSceneGraphicsManager::fetchLastNote(const microsec& offset) if (!note->isInGame()) { note->putToGame(); - note->setGraphics(this, TimeRange{offset, note->offset()}); + note->setGraphics(this, kku::TimeRange{offset, note->getPerfectOffset()}); } ++note_iterator; @@ -136,7 +135,7 @@ bool ClassicSceneGraphicsManager::nothingToDraw() const noexcept || _timeline->isExpired(_last); } -bool ClassicSceneGraphicsManager::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const noexcept +bool ClassicSceneGraphicsManager::isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept { - return ((*iterator)->offset() - _visibility_offset) <= music_offset; + return ((*iterator)->getPerfectOffset() - _visibility_offset) <= music_offset; } diff --git a/src/modes/classicmode/graphics/classicscenegraphicsmanager.h b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h new file mode 100644 index 0000000..df27a60 --- /dev/null +++ b/src/modes/classicmode/graphics/classicscenegraphicsmanager.h @@ -0,0 +1,37 @@ +#pragma once + +#include "game/classicnote.h" +#include "graphics/classicgraphicsmanager.h" +#include "core/timeline.h" + +class ClassicSprite; + +class ClassicSceneGraphicsManager : public ClassicGraphicsManager +{ +public: + explicit ClassicSceneGraphicsManager(const std::shared_ptr>& timeline, + const std::shared_ptr& factory, + const kku::microsec& visibility_offset); + + virtual void display() const override; + virtual void update(const kku::microsec& offset) override; + + virtual void display(const std::vector& elements) const override; + virtual void setGraphics(std::vector& elements, kku::TimeRange&& range) override; + +protected: + using Iterator = kku::Timeline::Iterator; + + Iterator _first; + Iterator _last; + + const std::shared_ptr> _timeline; + + inline bool nothingToDraw() const noexcept; + inline bool isVisiblyClose(const Iterator& iterator, const kku::microsec& music_offset) const noexcept; + //inline sf::VertexArray makeLine(const kku::Point& c1, const kku::Point& c2) const; + + void fetchFirstNote(const kku::microsec& offset); + void fetchLastNote(const kku::microsec& offset); + void updateVisibleNotes(const kku::microsec& offset); +}; diff --git a/src/modes/classicmode/graphics/classicsprite.h b/src/modes/classicmode/graphics/classicsprite.h new file mode 100644 index 0000000..4ea04e6 --- /dev/null +++ b/src/modes/classicmode/graphics/classicsprite.h @@ -0,0 +1,24 @@ +#pragma once + +#include "core/sprite.h" +#include "core/point.h" +#include "core/color.h" + +#include + +class ClassicSprite : public kku::Sprite +{ +public: + virtual void reset() override = 0; + virtual void display() const override = 0; + + virtual void setPosition(const kku::Point &position) = 0; + virtual void setTrailPosition(const kku::Point &position) = 0; + virtual kku::Point getPosition() const = 0; + virtual kku::Point getTrailPosition() const = 0; + + virtual void setColor(const kku::Color& color) = 0; + virtual void setTrailColor(const kku::Color& color) = 0; + virtual kku::Color getColor() const = 0; + virtual kku::Color getTrailColor() const = 0; +}; diff --git a/modes/classicmode/graphics/classicspritefactory.h b/src/modes/classicmode/graphics/classicspritefactory.h similarity index 100% rename from modes/classicmode/graphics/classicspritefactory.h rename to src/modes/classicmode/graphics/classicspritefactory.h diff --git a/modes/classicmode/graphics/painters/classicnotepainter.h b/src/modes/classicmode/graphics/painters/classicnotepainter.h similarity index 100% rename from modes/classicmode/graphics/painters/classicnotepainter.h rename to src/modes/classicmode/graphics/painters/classicnotepainter.h diff --git a/modes/classicmode/include/classicmode/classicactions.h b/src/modes/classicmode/include/classicmode/classicactions.h similarity index 100% rename from modes/classicmode/include/classicmode/classicactions.h rename to src/modes/classicmode/include/classicmode/classicactions.h diff --git a/modes/classicmode/include/classicmode/context.h b/src/modes/classicmode/include/classicmode/context.h similarity index 100% rename from modes/classicmode/include/classicmode/context.h rename to src/modes/classicmode/include/classicmode/context.h diff --git a/src/modes/classicmode/include/classicmode/elementinitializer.h b/src/modes/classicmode/include/classicmode/elementinitializer.h new file mode 100644 index 0000000..6c719bb --- /dev/null +++ b/src/modes/classicmode/include/classicmode/elementinitializer.h @@ -0,0 +1,15 @@ +#pragma once + +#include "classicactions.h" +#include "core/gameevent.h" +#include "core/point.h" + +#include + +struct ElementInitializer +{ + Type type = Type::NONE; + + kku::Point position; + std::vector falling_curve_interpolation; +}; diff --git a/modes/classicmode/include/classicmode/noteinitializer.h b/src/modes/classicmode/include/classicmode/noteinitializer.h similarity index 55% rename from modes/classicmode/include/classicmode/noteinitializer.h rename to src/modes/classicmode/include/classicmode/noteinitializer.h index 6a98596..0e46ac1 100644 --- a/modes/classicmode/include/classicmode/noteinitializer.h +++ b/src/modes/classicmode/include/classicmode/noteinitializer.h @@ -4,11 +4,11 @@ #include #include "context.h" -#include "tools/mathutils.h" +#include "core/time.h" struct NoteInitializer { const Context *context; - std::vector intervals; - microsec perfect_offset = 0; + std::vector intervals; + kku::microsec perfect_offset = 0; }; diff --git a/src/modes/classicmode/shared/classicmode/classicfactory.h b/src/modes/classicmode/shared/classicmode/classicfactory.h new file mode 100644 index 0000000..194fa9f --- /dev/null +++ b/src/modes/classicmode/shared/classicmode/classicfactory.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "core/game.h" +#include "core/editor.h" + +class ClassicFactory +{ +public: + virtual ~ClassicFactory() = default; + virtual std::unique_ptr getGame() const = 0; + virtual std::unique_ptr getEditor() const = 0; +}; diff --git a/tools/CMakeLists.txt b/src/tools/CMakeLists.txt similarity index 85% rename from tools/CMakeLists.txt rename to src/tools/CMakeLists.txt index 92d4e92..ca2590b 100644 --- a/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.8) +cmake_minimum_required(VERSION 3.13) project(tools) @@ -11,4 +11,4 @@ file(GLOB_RECURSE SOURCES "src/*.cpp") add_library(tools STATIC ${SOURCES} ${HEADERS}) -target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/tools/shared) +target_include_directories(project-kyoku PRIVATE ${CMAKE_SOURCE_DIR}/src/tools/shared) diff --git a/src/tools/shared/tools/beatutils.h b/src/tools/shared/tools/beatutils.h new file mode 100644 index 0000000..4266927 --- /dev/null +++ b/src/tools/shared/tools/beatutils.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "core/time.h" + +namespace beat_utils +{ + struct BeatInfo + { + int BPM = 0; + kku::microsec interval = 0; + }; + + BeatInfo calculateBeatRateInfo(const std::vector& approximate_deltas); +} diff --git a/src/tools/shared/tools/bpmcalculator.h b/src/tools/shared/tools/bpmcalculator.h new file mode 100644 index 0000000..1ea1f28 --- /dev/null +++ b/src/tools/shared/tools/bpmcalculator.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include "core/music.h" +#include "tools/beatutils.h" + +class BPMCalculator +{ +public: + explicit BPMCalculator(); + + void start(); + void stop(); + void click(const kku::microsec& offset); + + bool calculating() const; + + const beat_utils::BeatInfo& fetchApproximatedInfo(); + kku::microsec fetchTimeUntilNextBeat(const kku::microsec& offset); + + kku::microsec getStartingOffset() const; + void setStartingOffset(kku::microsec offset); + void moveStartingOffsetBy(kku::microsec shift); + +private: + bool _need_recalculate; + bool _calculating; + + std::vector _deltas; + kku::microsec _previous_click_offset; + kku::microsec _first_click_offset; + + beat_utils::BeatInfo _approximated_info; + + inline void reset(); +}; diff --git a/tools/shared/tools/settingscontroller.h b/src/tools/shared/tools/settingscontroller.h similarity index 100% rename from tools/shared/tools/settingscontroller.h rename to src/tools/shared/tools/settingscontroller.h diff --git a/tools/src/beatutils.cpp b/src/tools/src/beatutils.cpp similarity index 58% rename from tools/src/beatutils.cpp rename to src/tools/src/beatutils.cpp index a9f444f..0fa5112 100644 --- a/tools/src/beatutils.cpp +++ b/src/tools/src/beatutils.cpp @@ -2,12 +2,12 @@ #include #include -auto beat_utils::calculateBeatRateInfo(const std::vector& approximate_deltas) -> BeatInfo +auto beat_utils::calculateBeatRateInfo(const std::vector& approximate_deltas) -> BeatInfo { if (approximate_deltas.empty()) return {}; - const microsec sum = std::accumulate(approximate_deltas.begin(), approximate_deltas.end(), 0); + const kku::microsec sum = std::accumulate(approximate_deltas.begin(), approximate_deltas.end(), 0); const std::size_t amount = approximate_deltas.size(); long double average = static_cast(sum) @@ -19,6 +19,6 @@ auto beat_utils::calculateBeatRateInfo(const std::vector& approximate_ return BeatInfo { bpm, - static_cast(1. / static_cast(bpm) * 60000000.) + static_cast(1. / static_cast(bpm) * 60000000.) }; } diff --git a/tools/src/bpmcalculator.cpp b/src/tools/src/bpmcalculator.cpp similarity index 75% rename from tools/src/bpmcalculator.cpp rename to src/tools/src/bpmcalculator.cpp index 26c64c8..ea597de 100644 --- a/tools/src/bpmcalculator.cpp +++ b/src/tools/src/bpmcalculator.cpp @@ -1,4 +1,5 @@ #include "tools/bpmcalculator.h" + #include #include #include @@ -34,7 +35,7 @@ bool BPMCalculator::calculating() const return _calculating; } -void BPMCalculator::click(const microsec &offset) +void BPMCalculator::click(const kku::microsec &offset) { if (!_calculating) return; @@ -48,7 +49,7 @@ void BPMCalculator::click(const microsec &offset) return; } - const microsec delta = offset - _previous_click_offset; + const kku::microsec delta = offset - _previous_click_offset; _deltas.emplace_back(delta); _previous_click_offset = offset; @@ -70,24 +71,24 @@ const beat_utils::BeatInfo& BPMCalculator::fetchApproximatedInfo() return _approximated_info; } -microsec BPMCalculator::getStartingOffset() const +kku::microsec BPMCalculator::getStartingOffset() const { return _first_click_offset; } -void BPMCalculator::setStartingOffset(microsec offset) +void BPMCalculator::setStartingOffset(kku::microsec offset) { _first_click_offset = offset; } -void BPMCalculator::moveStartingOffsetBy(microsec shift) +void BPMCalculator::moveStartingOffsetBy(kku::microsec shift) { _first_click_offset += shift; } -microsec BPMCalculator::fetchTimeUntilNextBeat(const microsec& offset) +kku::microsec BPMCalculator::fetchTimeUntilNextBeat(const kku::microsec& offset) { - const microsec actual_offset = offset - getStartingOffset(); + const kku::microsec actual_offset = offset - getStartingOffset(); return actual_offset % fetchApproximatedInfo().interval; } diff --git a/tools/shared/tools/beatutils.h b/tools/shared/tools/beatutils.h deleted file mode 100644 index f8c03d1..0000000 --- a/tools/shared/tools/beatutils.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include "tools/mathutils.h" - -namespace beat_utils -{ - struct BeatInfo - { - int BPM = 0; - microsec interval = 0; - }; - - BeatInfo calculateBeatRateInfo(const std::vector& approximate_deltas); -} diff --git a/tools/shared/tools/bpmcalculator.h b/tools/shared/tools/bpmcalculator.h deleted file mode 100644 index d9348b6..0000000 --- a/tools/shared/tools/bpmcalculator.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "tools/music.h" -#include "tools/beatutils.h" -#include - -class BPMCalculator -{ -public: - explicit BPMCalculator(); - - void start(); - void stop(); - void click(const microsec& offset); - - bool calculating() const; - - const beat_utils::BeatInfo& fetchApproximatedInfo(); - microsec fetchTimeUntilNextBeat(const microsec& offset); - - microsec getStartingOffset() const; - void setStartingOffset(microsec offset); - void moveStartingOffsetBy(microsec shift); - -private: - bool _need_recalculate; - bool _calculating; - - std::vector _deltas; - microsec _previous_click_offset; - microsec _first_click_offset; - - beat_utils::BeatInfo _approximated_info; - - inline void reset(); -}; diff --git a/tools/shared/tools/mathutils.h b/tools/shared/tools/mathutils.h deleted file mode 100644 index 19ff5a4..0000000 --- a/tools/shared/tools/mathutils.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -using microsec = long long; - -struct TimeRange -{ - const microsec begin = 0; - const microsec end = 0; - - constexpr inline explicit TimeRange() noexcept : - begin(0), end(0) - {} - - constexpr inline explicit TimeRange(microsec x, microsec y) noexcept : - begin(x), end(y) - {} -}; - -struct Coordinates -{ - float x; - float y; - - constexpr inline explicit Coordinates() noexcept : - x(0.), y(0.) - {} - - constexpr inline explicit Coordinates(int x, int y) noexcept : - x(x), y(y) - {} - - constexpr inline explicit Coordinates(float x, float y) noexcept : - x(x), y(y) - {} - - constexpr inline Coordinates operator+(const Coordinates& right) const noexcept - { - return Coordinates{right.x + x, right.y + y}; - } - - constexpr inline Coordinates operator-(const Coordinates& right) const noexcept - { - return Coordinates{right.x - x, right.y - y}; - } - - inline void moveBy(float x, float y) noexcept - { - this->x += x; - this->y += y; - } - - inline void moveBy(const Coordinates& right) noexcept - { - this->x += right.x; - this->y += right.y; - } - - inline void scale(float factor) noexcept - { - x *= factor; - y *= factor; - } -}; diff --git a/tools/shared/tools/music.h b/tools/shared/tools/music.h deleted file mode 100644 index a997ebc..0000000 --- a/tools/shared/tools/music.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -#include "tools/mathutils.h" - -class Music -{ -public: - explicit Music(); - - bool openFromFile(const std::string& filepath); - - void play(); - void pause(); - void stop(); - - bool isPaused() const; - - void setVolume(int volume); - - void setOffset(const microsec& offset); - void moveOffset(const microsec& delta); - microsec fetchOffset(); - microsec getDuration() const; - -private: - sf::Music _music; - sf::Clock _offset_interpolator; - - microsec _sfml_music_offset; - microsec _previous_frame_offset; - microsec _absolute_offset; -}; diff --git a/tools/shared/tools/resourceholder.h b/tools/shared/tools/resourceholder.h deleted file mode 100644 index 7f11589..0000000 --- a/tools/shared/tools/resourceholder.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include - -namespace sf { class Texture; class Font; } - -template -class ResourceHolder -{ -public: - bool load(Id id, const std::string& filename) - { - auto resource = std::make_unique(); - if (!resource->loadFromFile(filename)) - return false; - - _resources[id] = std::move(resource); - - return true; - } - - const std::shared_ptr& get(Id id) const - { - const auto found = _resources.find(id); - return found->second; - } - -private: - std::map> _resources; -}; - -namespace Fonts -{ - enum class Id - { - GUI - }; -} - -using FontHolder = ResourceHolder; -