Merge pull request 'sfml-bridge' (#23) from sfml-bridge into master
Reviewed-on: http://dev.udongein.xyz/NaiJi/project-kyoku/pulls/23
This commit is contained in:
commit
381e4442ae
|
@ -2,7 +2,7 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
|
||||
build
|
||||
SFML*
|
||||
SFML-*
|
||||
*.user
|
||||
*CMakeFiles*
|
||||
*Makefile
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
|
@ -1,18 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/inputtype.h"
|
||||
#include "core/updatedata.h"
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
|
||||
class Game : public sf::Drawable
|
||||
{
|
||||
public:
|
||||
virtual ~Game() = default;
|
||||
|
||||
virtual void run() = 0;
|
||||
virtual void input(PlayerInput&& inputdata) = 0;
|
||||
virtual void update(UpdateData&& updatedata) = 0;
|
||||
|
||||
// Separate CORE from SFML in the future
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0;
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/Window/Event.hpp>
|
||||
#include "tools/mathutils.h"
|
||||
|
||||
struct PlayerInput
|
||||
{
|
||||
microsec timestamp;
|
||||
sf::Event event;
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <SFML/System/Time.hpp>
|
||||
#include "tools/mathutils.h"
|
||||
|
||||
struct UpdateData
|
||||
{
|
||||
const microsec timestamp;
|
||||
const sf::Time dt;
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "core/point.h"
|
||||
#include "core/vector.h"
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
|
||||
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<float>(left),
|
||||
static_cast<float>(top) };
|
||||
}
|
||||
|
||||
inline void moveBy(const kku::Vector2<T>& vector)
|
||||
{
|
||||
top += vector.second;
|
||||
left += vector.first;
|
||||
}
|
||||
|
||||
inline bool contains(const kku::Point& point) const
|
||||
{
|
||||
return point.x >= left ; // debug it when on computer
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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<kku::Music> getMusic() const = 0;
|
||||
virtual std::shared_ptr<kku::Text> getText(kku::Font::Id id) const = 0;
|
||||
virtual std::shared_ptr<kku::Rectangle> getRectangle() const = 0;
|
||||
virtual std::shared_ptr<kku::Line> getLine() const = 0;
|
||||
virtual kku::Vector2<std::size_t> getRenderSize() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,26 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include "core/inputtype.h"
|
||||
#include <algorithm>
|
||||
|
||||
#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 draw() const = 0;
|
||||
virtual void display() const = 0;
|
||||
virtual void recalculate(const microsec& timestamp) = 0;
|
||||
|
||||
void setBPMSections(const std::set<BPMSection, BPMSectionCompt>& sections) noexcept
|
||||
void setBPMSections(const std::set<BPMSection, BPMSectionComparator>& sections) noexcept
|
||||
{
|
||||
_bpm_sections = sections;
|
||||
}
|
||||
|
||||
void setBPMSections(std::set<BPMSection, BPMSectionCompt>&& sections) noexcept
|
||||
void setBPMSections(std::set<BPMSection, BPMSectionComparator>&& sections) noexcept
|
||||
{
|
||||
_bpm_sections = std::move(sections);
|
||||
}
|
||||
|
@ -77,5 +82,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
std::set<BPMSection, BPMSectionCompt> _bpm_sections;
|
||||
std::set<BPMSection, BPMSectionComparator> _bpm_sections;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/gameevent.h"
|
||||
#include "core/updatedata.h"
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
virtual ~Game() = default;
|
||||
|
||||
virtual void run() = 0;
|
||||
virtual void input(GameEvent&& inputdata) = 0;
|
||||
virtual void update(UpdateData&& updatedata) = 0;
|
||||
virtual void display() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
#ifndef PRECISIONEVALUATOR_H
|
||||
#define PRECISIONEVALUATOR_H
|
||||
|
||||
#include "tools/mathutils.h"
|
||||
#pragma once
|
||||
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
|
@ -9,6 +6,11 @@
|
|||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "core/time.h"
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
template<typename Grade, typename = std::enable_if_t<std::is_enum<Grade>::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<microsec> _intervals;
|
||||
};
|
||||
|
||||
#endif // PRECISIONEVALUATOR_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<float>& rect) = 0;
|
||||
virtual Area<float> getRect() const = 0;
|
||||
|
||||
virtual void setPosition(const Point& position) = 0;
|
||||
virtual Point getPosition() const = 0;
|
||||
virtual void move(const kku::Vector2<float>& delta) = 0;
|
||||
|
||||
virtual void setColor(const Color& color) = 0;
|
||||
virtual bool contains(const kku::Point& position) const = 0;
|
||||
|
||||
virtual void display() = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
template <typename Resource, typename Id>
|
||||
class ResourceHolder
|
||||
{
|
||||
public:
|
||||
inline void load(Id id, std::unique_ptr<Resource>&& resource) noexcept
|
||||
{
|
||||
_resources[id] = std::move(resource);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<Resource>& get(Id id) const
|
||||
{
|
||||
return _resources.find(id)->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<Id, std::shared_ptr<Resource>> _resources;
|
||||
};
|
||||
|
||||
namespace Font
|
||||
{
|
||||
enum class Id
|
||||
{
|
||||
GUI
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
class Sprite
|
||||
{
|
||||
public:
|
||||
virtual ~Sprite() = default;
|
||||
virtual void reset() = 0;
|
||||
virtual void display() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -4,15 +4,18 @@
|
|||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
template<typename Type, class SpriteFactory, class Sprite,
|
||||
typename = std::enable_if_t<std::is_enum<Type>::value>>
|
||||
class SpriteContainer
|
||||
{
|
||||
public:
|
||||
explicit SpriteContainer(std::initializer_list<Type>&& types,
|
||||
std::unique_ptr<SpriteFactory>&& factory,
|
||||
const std::shared_ptr<SpriteFactory>& factory,
|
||||
std::size_t reserve_size = 20) :
|
||||
_sprite_factory(std::move(factory)),
|
||||
_sprite_factory(factory),
|
||||
_poll_reserve_size(reserve_size)
|
||||
{
|
||||
for (const Type& type : types)
|
||||
|
@ -52,7 +55,9 @@ private:
|
|||
using SpritePoll = std::stack<std::shared_ptr<Sprite>>;
|
||||
|
||||
std::map<Type, SpritePoll> _sprite_dispatcher;
|
||||
std::unique_ptr<SpriteFactory> _sprite_factory;
|
||||
const std::shared_ptr<SpriteFactory> _sprite_factory;
|
||||
|
||||
std::size_t _poll_reserve_size;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
|
||||
#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
|
||||
{
|
||||
enum class Code
|
||||
{
|
||||
Unknown = -1,
|
||||
A = 0,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
Num0,
|
||||
Num1,
|
||||
Num2,
|
||||
Num3,
|
||||
Num4,
|
||||
Num5,
|
||||
Num6,
|
||||
Num7,
|
||||
Num8,
|
||||
Num9,
|
||||
Escape,
|
||||
LControl,
|
||||
LShift,
|
||||
LAlt,
|
||||
LSystem,
|
||||
RControl,
|
||||
RShift,
|
||||
RAlt,
|
||||
RSystem,
|
||||
Menu,
|
||||
LBracket,
|
||||
RBracket,
|
||||
Semicolon,
|
||||
Comma,
|
||||
Period,
|
||||
Quote,
|
||||
Slash,
|
||||
Backslash,
|
||||
Tilde,
|
||||
Equal,
|
||||
Hyphen,
|
||||
Space,
|
||||
Enter,
|
||||
Backspace,
|
||||
Tab,
|
||||
PageUp,
|
||||
PageDown,
|
||||
End,
|
||||
Home,
|
||||
Insert,
|
||||
Delete,
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
Numpad0,
|
||||
Numpad1,
|
||||
Numpad2,
|
||||
Numpad3,
|
||||
Numpad4,
|
||||
Numpad5,
|
||||
Numpad6,
|
||||
Numpad7,
|
||||
Numpad8,
|
||||
Numpad9,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
Pause
|
||||
};
|
||||
|
||||
Code view = Code::Unknown;
|
||||
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<Size, Key, Mouse, None> data;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#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<float>& delta) = 0;
|
||||
virtual void setColor(const Color& color) = 0;
|
||||
|
||||
virtual void display() = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -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)
|
||||
{}
|
||||
};
|
||||
|
||||
}
|
|
@ -3,11 +3,13 @@
|
|||
#include <set>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "tools/mathutils.h"
|
||||
#include "core/time.h"
|
||||
#include "core/note.h"
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
template <class TNote, class = std::enable_if_t<std::is_base_of<Note, TNote>::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<TNote*, NotePtrCompt>& notes)
|
||||
void setNotes(const std::set<TNote*, NotePtrComparator>& notes)
|
||||
{
|
||||
_timeline = std::move(notes);
|
||||
|
||||
|
@ -65,7 +67,7 @@ public:
|
|||
update(_current_offset);
|
||||
}
|
||||
|
||||
void insertNotes(const std::set<TNote*, NotePtrCompt>& notes)
|
||||
void insertNotes(const std::set<TNote*, NotePtrComparator>& 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<TNote*, NotePtrCompt> _timeline;
|
||||
std::set<TNote*, NotePtrComparator> _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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/time.h"
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
struct UpdateData
|
||||
{
|
||||
const microsec timestamp;
|
||||
const microsec dt;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace kku
|
||||
{
|
||||
|
||||
/* Meaning an element of a vector space in math.
|
||||
* Don't mistake for std::vector<T>
|
||||
* For now we don't need it as a special class,
|
||||
* so let it be a wrapper. */
|
||||
|
||||
template <typename T>
|
||||
using Vector2 = std::pair<T, T>;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr auto makeVector(T&& l, T&& r) -> Vector2<T>
|
||||
{
|
||||
return std::make_pair(std::forward<T>(l), std::forward<T>(r));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#include <SFML/Window/Event.hpp>
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
#include <SFML/Graphics/Rect.hpp>
|
||||
|
||||
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;
|
||||
};
|
|
@ -1,18 +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" "./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)
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#include "shared/classicmode/classicfactory.h"
|
||||
#include "game/classicgame.h"
|
||||
#include "graphics/classicgraphicsmanager.h"
|
||||
#include "tools/music.h"
|
||||
|
||||
#include "editor/classiceditor.h"
|
||||
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
|
||||
std::unique_ptr<Game> classic::initGame()
|
||||
{
|
||||
return std::make_unique<ClassicGame>();
|
||||
}
|
||||
|
||||
std::unique_ptr<Editor> classic::initEditor()
|
||||
{
|
||||
return std::make_unique<ClassicEditor>();
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
#include "classiceditor.h"
|
||||
|
||||
ClassicEditor::ClassicEditor() :
|
||||
_selected_type(Type::UP),
|
||||
_current_time(0),
|
||||
_scroll_step(500000)
|
||||
{
|
||||
std::set<MockClassicNote*, NotePtrCompt> set = {};
|
||||
|
||||
// VISIBILITY 1648648
|
||||
|
||||
_timeline.setNotes(set);
|
||||
}
|
||||
|
||||
microsec ClassicEditor::adjustOffset(microsec offset) const noexcept
|
||||
{
|
||||
const auto& section = getBPMSectionAt(offset);
|
||||
const microsec actual_offset = offset - section.offset_start;
|
||||
|
||||
return actual_offset + (actual_offset % section.interval);
|
||||
}
|
||||
|
||||
void ClassicEditor::input(PlayerInput&& inputdata)
|
||||
{
|
||||
_current_time = inputdata.timestamp;
|
||||
const auto& event = inputdata.event;
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
case sf::Event::MouseButtonPressed:
|
||||
{
|
||||
const auto note = _timeline.getNoteBy(_current_time);
|
||||
if (_timeline.isExpired(note) && !_bpm_sections.empty() && _current_time >= (*_bpm_sections.begin()).offset_start)
|
||||
{
|
||||
NoteInitializer init;
|
||||
init.context = &_context;
|
||||
init.intervals = {};
|
||||
init.perfect_offset = adjustOffset(_current_time);
|
||||
|
||||
ElementInitializer elem_init;
|
||||
elem_init.type = _selected_type;
|
||||
elem_init.coordinates = Coordinates{ event.mouseButton.x, event.mouseButton.y };
|
||||
elem_init.falling_curve_interpolation = {};
|
||||
|
||||
MockArrowNoteInitializer mock_init;
|
||||
mock_init.elements = {elem_init};
|
||||
mock_init.initializer = init;
|
||||
|
||||
_timeline.insertNote(new MockClassicNote(std::move(mock_init)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicEditor::update(UpdateData&& updatedata)
|
||||
{
|
||||
_timeline.update(updatedata.timestamp);
|
||||
}
|
||||
|
||||
void ClassicEditor::draw() const
|
||||
{
|
||||
}
|
||||
|
||||
void ClassicEditor::recalculate(const microsec& timestamp)
|
||||
{
|
||||
_timeline.recalculate(timestamp);
|
||||
}
|
||||
|
||||
void ClassicEditor::selectNoteType(Type type) noexcept
|
||||
{
|
||||
_selected_type = type;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/editor.h"
|
||||
#include "core/timeline.h"
|
||||
|
||||
#include "mockclassicnote.h"
|
||||
|
||||
class ClassicGraphicsManager;
|
||||
|
||||
class ClassicEditor : public Editor
|
||||
{
|
||||
public:
|
||||
explicit ClassicEditor();
|
||||
|
||||
virtual void input(PlayerInput&& inputdata) override;
|
||||
virtual void update(UpdateData&& updatedata) override;
|
||||
virtual void draw() const override;
|
||||
virtual void recalculate(const microsec& timestamp) override;
|
||||
|
||||
void selectNoteType(Type type) noexcept;
|
||||
|
||||
private:
|
||||
inline microsec adjustOffset(microsec offset) const noexcept;
|
||||
|
||||
Context _context;
|
||||
|
||||
std::shared_ptr<ClassicGraphicsManager> _graphics_manager;
|
||||
Timeline<MockClassicNote> _timeline;
|
||||
|
||||
Type _selected_type;
|
||||
microsec _current_time;
|
||||
microsec _scroll_step;
|
||||
};
|
|
@ -1,137 +0,0 @@
|
|||
#include "classiceditorgraphicsmanager.h"
|
||||
#include "graphics/classicsprite.h"
|
||||
|
||||
#include "graphics/classicflyinganimationscenario.h"
|
||||
#include "graphics/classicdyinganimationscenario.h"
|
||||
|
||||
ClassicEditorGraphicsManager::ClassicEditorGraphicsManager(Timeline<MockClassicNote> &timeline, const microsec& visibility_offset) :
|
||||
ClassicGraphicsManager(visibility_offset),
|
||||
_timeline(&timeline)
|
||||
{
|
||||
_timeline->expire(_first);
|
||||
_timeline->expire(_last);
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
if (nothingToDraw())
|
||||
return;
|
||||
|
||||
for (auto it = _first; it != _last; ++it)
|
||||
{
|
||||
(*it)->draw(this, target, states);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::draw(const std::vector<MockClassicNote::MockElement>& elements, sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
for (std::size_t i = 0; i < elements.size(); ++i)
|
||||
{
|
||||
const auto& sprite = elements[i].sprite;
|
||||
|
||||
if (i >= 1)
|
||||
{
|
||||
const auto& neighbor_sprite = elements[i - 1].sprite;
|
||||
|
||||
const auto c1 = neighbor_sprite->trailCoordinates();
|
||||
const auto c2 = sprite->trailCoordinates();
|
||||
|
||||
target.draw(makeLine(c1, c2));
|
||||
}
|
||||
|
||||
target.draw(*sprite, states);
|
||||
}
|
||||
}
|
||||
|
||||
sf::VertexArray ClassicEditorGraphicsManager::makeLine(const Coordinates& c1, const Coordinates& c2) const
|
||||
{
|
||||
sf::VertexArray line(sf::LinesStrip, 2);
|
||||
line[0].color = sf::Color::Yellow;
|
||||
line[0].position = {c1.x + 10, c1.y};
|
||||
line[1].color = sf::Color::Blue;
|
||||
line[1].position = {c2.x + 10, c2.y};
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::setGraphics(std::vector<MockClassicNote::MockElement>& elements, 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.animations[MockClassicNote::State::NONE] = nullptr;
|
||||
element.animations[MockClassicNote::State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
||||
element.animations[MockClassicNote::State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
||||
element.animations[MockClassicNote::State::DEAD] = nullptr;
|
||||
|
||||
element.animations[MockClassicNote::State::FLYING]->launch(element.sprite, range.begin, range.end);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::update(const microsec &offset)
|
||||
{
|
||||
fetchLastNote(offset);
|
||||
fetchFirstNote(offset);
|
||||
|
||||
updateVisibleNotes(offset);
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::updateVisibleNotes(const microsec &offset)
|
||||
{
|
||||
for (auto it = _first; it != _last; ++it)
|
||||
(*it)->update(offset);
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::fetchFirstNote(const microsec& offset)
|
||||
{
|
||||
(void)offset; // ????
|
||||
|
||||
if (nothingToDraw())
|
||||
return;
|
||||
|
||||
Iterator note_iterator = _first;
|
||||
while (note_iterator != _last)
|
||||
{
|
||||
auto note = *note_iterator;
|
||||
if (note->shouldRemove())
|
||||
++_first;
|
||||
|
||||
++note_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicEditorGraphicsManager::fetchLastNote(const microsec& offset)
|
||||
{
|
||||
Iterator note_iterator = _timeline->getTopNote();
|
||||
while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset))
|
||||
{
|
||||
if (nothingToDraw())
|
||||
_first = note_iterator;
|
||||
|
||||
auto note = *note_iterator;
|
||||
|
||||
if (!note->isInGame())
|
||||
{
|
||||
note->putToGame();
|
||||
note->setGraphics(this, TimeRange{offset, note->offset()});
|
||||
}
|
||||
|
||||
++note_iterator;
|
||||
}
|
||||
|
||||
_last = note_iterator;
|
||||
}
|
||||
|
||||
bool ClassicEditorGraphicsManager::nothingToDraw() const noexcept
|
||||
{
|
||||
return _timeline->isExpired(_first)
|
||||
|| _timeline->isExpired(_last);
|
||||
}
|
||||
|
||||
bool ClassicEditorGraphicsManager::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const noexcept
|
||||
{
|
||||
return ((*iterator)->offset() - _visibility_offset) <= music_offset;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "mockclassicnote.h"
|
||||
#include "graphics/classicgraphicsmanager.h"
|
||||
#include "core/timeline.h"
|
||||
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
|
||||
class ClassicSprite;
|
||||
|
||||
class ClassicEditorGraphicsManager : public ClassicGraphicsManager
|
||||
{
|
||||
public:
|
||||
explicit ClassicEditorGraphicsManager(Timeline<MockClassicNote>& timeline, const microsec& visibility_offset);
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
|
||||
void draw(const std::vector<MockClassicNote::MockElement>& elements, sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
void setGraphics(std::vector<MockClassicNote::MockElement> &elements, TimeRange&& range);
|
||||
|
||||
virtual void update(const microsec& offset) override;
|
||||
|
||||
private:
|
||||
using Iterator = Timeline<MockClassicNote>::Iterator;
|
||||
|
||||
Iterator _first;
|
||||
Iterator _last;
|
||||
|
||||
Timeline<MockClassicNote> * const _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);
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
#include "mockclassicnote.h"
|
||||
#include "graphics/classicgraphicsmanager.h"
|
||||
|
||||
// Replace with interface by dependency injection
|
||||
#include "graphics/classicflyinganimationscenario.h"
|
||||
#include "graphics/classicdyinganimationscenario.h"
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// A LOT OF CODE DUPLICATES game/arrowclassicnote, DO SOMETHING D:<
|
||||
|
||||
MockClassicNote::MockClassicNote(MockArrowNoteInitializer&& init) :
|
||||
Note(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;
|
||||
}
|
||||
}
|
||||
|
||||
bool MockClassicNote::isActive(const microsec& offset) const
|
||||
{
|
||||
return offset == Note::offset();
|
||||
}
|
||||
|
||||
bool MockClassicNote::isInGame() const
|
||||
{
|
||||
return _state == State::FLYING
|
||||
|| _state == State::DYING;
|
||||
}
|
||||
|
||||
bool MockClassicNote::shouldRemove() const
|
||||
{
|
||||
return _state == State::DEAD
|
||||
|| _state == State::NONE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
#include "core/note.h"
|
||||
#include "initializers/mockarrownoteinitializer.h"
|
||||
|
||||
class ClassicSprite;
|
||||
class ClassicAnimationScenario;
|
||||
|
||||
class MockClassicNote : public Note
|
||||
{
|
||||
public:
|
||||
|
||||
enum State
|
||||
{
|
||||
NONE,
|
||||
|
||||
FLYING,
|
||||
DYING,
|
||||
DEAD
|
||||
};
|
||||
|
||||
explicit MockClassicNote(MockArrowNoteInitializer&& init);
|
||||
virtual ~MockClassicNote() override = default;
|
||||
|
||||
virtual bool isActive(const microsec& offset) const override final;
|
||||
virtual bool isInGame() const override final;
|
||||
virtual bool shouldRemove() const override final;
|
||||
|
||||
virtual void putToGame() override final;
|
||||
virtual void update(const microsec &music_offset) override final;
|
||||
|
||||
struct MockElement
|
||||
{
|
||||
std::shared_ptr<ClassicSprite> sprite;
|
||||
std::array<std::shared_ptr<ClassicAnimationScenario>, 4> animations;
|
||||
Type type = Type::NONE;
|
||||
|
||||
Coordinates coordinates;
|
||||
std::vector<Coordinates> falling_curve_interpolation;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<MockElement> _elements;
|
||||
|
||||
State _state;
|
||||
const Context *_context;
|
||||
};
|
|
@ -1,45 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicnote.h"
|
||||
#include "initializers/arrownoteinitializer.h"
|
||||
|
||||
class ClassicArrowNote : public ClassicNote
|
||||
{
|
||||
public:
|
||||
explicit ClassicArrowNote(ArrowNoteInitializer&& init);
|
||||
virtual ~ClassicArrowNote() = default;
|
||||
|
||||
virtual void putToGame() override;
|
||||
virtual void update(const microsec &music_offset) override;
|
||||
virtual void input(PlayerInput&& inputdata) override;
|
||||
|
||||
virtual void draw(const ClassicGameGraphicsManager * const manager, sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
virtual void setGraphics(ClassicGameGraphicsManager * const manager, TimeRange&& range) override;
|
||||
|
||||
bool allElementsPressed() const;
|
||||
bool isPressedAs(sf::Keyboard::Key key) const;
|
||||
inline bool isHold() const;
|
||||
|
||||
struct ArrowElement
|
||||
{
|
||||
std::shared_ptr<ClassicSprite> sprite;
|
||||
std::array<std::shared_ptr<ClassicAnimationScenario>, 5> animations;
|
||||
sf::Keyboard::Key pressed_as = sf::Keyboard::Unknown;
|
||||
|
||||
Coordinates coordinates;
|
||||
std::vector<Coordinates> falling_curve_interpolation;
|
||||
std::array<sf::Keyboard::Key, 2> keys;
|
||||
Type type = Type::NONE;
|
||||
bool pressed = false;
|
||||
|
||||
// Each note may consist of several buttons.
|
||||
// For example, ↑ → or ↓ → ←
|
||||
// Note Element represents this idea.
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<ArrowElement> _elements;
|
||||
bool _is_hold;
|
||||
};
|
||||
|
||||
using ArrowElements = std::vector<ClassicArrowNote::ArrowElement>;
|
|
@ -1,114 +0,0 @@
|
|||
#include "classicgame.h"
|
||||
#include "classicnote.h"
|
||||
#include "classicmapcreator.h"
|
||||
#include "game/classicgamegraphicsmanager.h"
|
||||
#include "holdmanager.h"
|
||||
|
||||
ClassicGame::ClassicGame() :
|
||||
_graphics_manager(new ClassicGameGraphicsManager(_timeline, 1648648)),
|
||||
_hold_manager(std::make_unique<HoldManager>())
|
||||
{
|
||||
_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::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
_graphics_manager->draw(target, states);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
|
||||
#include "core/game.h"
|
||||
#include "core/timeline.h"
|
||||
|
||||
#include "classicmode/context.h"
|
||||
#include "classicnote.h"
|
||||
|
||||
#include "classicmode/classicactions.h"
|
||||
|
||||
class ClassicGraphicsManager;
|
||||
class HoldManager;
|
||||
|
||||
class ClassicGame final : public Game
|
||||
{
|
||||
public:
|
||||
explicit ClassicGame();
|
||||
virtual ~ClassicGame() override;
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
virtual void input(PlayerInput&& inputdata) override;
|
||||
virtual void update(UpdateData&& updatedata) override;
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
|
||||
private:
|
||||
std::map<sf::Keyboard::Key, Type> _keys_to_buttons;
|
||||
std::map<Type, Action> _buttons_to_pressed_actions;
|
||||
std::map<Type, Action> _buttons_to_released_actions;
|
||||
|
||||
ClassicGraphicsManager * const _graphics_manager;
|
||||
std::shared_ptr<HoldManager> _hold_manager;
|
||||
Timeline<ClassicNote> _timeline;
|
||||
|
||||
sf::SoundBuffer _slap_buffer;
|
||||
sf::Sound _slap;
|
||||
|
||||
Context _context;
|
||||
};
|
|
@ -1,137 +0,0 @@
|
|||
#include "classicgamegraphicsmanager.h"
|
||||
#include "graphics/classicsprite.h"
|
||||
|
||||
#include "graphics/classicflyinganimationscenario.h"
|
||||
#include "graphics/classicdyinganimationscenario.h"
|
||||
|
||||
ClassicGameGraphicsManager::ClassicGameGraphicsManager(Timeline<ClassicNote> &timeline, const microsec& visibility_offset) :
|
||||
ClassicGraphicsManager(visibility_offset),
|
||||
_timeline(&timeline)
|
||||
{
|
||||
_timeline->expire(_first);
|
||||
_timeline->expire(_last);
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
if (nothingToDraw())
|
||||
return;
|
||||
|
||||
for (auto it = _first; it != _last; ++it)
|
||||
{
|
||||
(*it)->draw(this, target, states);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::draw(const std::vector<ClassicArrowNote::ArrowElement>& elements, sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
for (std::size_t i = 0; i < elements.size(); ++i)
|
||||
{
|
||||
const auto& sprite = elements[i].sprite;
|
||||
|
||||
if (i >= 1)
|
||||
{
|
||||
const auto& neighbor_sprite = elements[i - 1].sprite;
|
||||
|
||||
const auto c1 = neighbor_sprite->trailCoordinates();
|
||||
const auto c2 = sprite->trailCoordinates();
|
||||
|
||||
target.draw(makeLine(c1, c2));
|
||||
}
|
||||
|
||||
target.draw(*sprite, states);
|
||||
}
|
||||
}
|
||||
|
||||
sf::VertexArray ClassicGameGraphicsManager::makeLine(const Coordinates& c1, const Coordinates& c2) const
|
||||
{
|
||||
sf::VertexArray line(sf::LinesStrip, 2);
|
||||
line[0].color = sf::Color::Yellow;
|
||||
line[0].position = {c1.x + 10, c1.y};
|
||||
line[1].color = sf::Color::Blue;
|
||||
line[1].position = {c2.x + 10, c2.y};
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::setGraphics(std::vector<ClassicArrowNote::ArrowElement>& elements, 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.animations[ClassicArrowNote::State::NONE] = nullptr;
|
||||
element.animations[ClassicArrowNote::State::FLYING] = std::make_shared<ClassicFlyingAnimationScenario>();
|
||||
element.animations[ClassicArrowNote::State::DYING] = std::make_shared<ClassicDyingAnimationScenario>();
|
||||
element.animations[ClassicArrowNote::State::DEAD] = nullptr;
|
||||
|
||||
element.animations[ClassicArrowNote::State::FLYING]->launch(element.sprite, range.begin, range.end);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::update(const microsec &offset)
|
||||
{
|
||||
fetchLastNote(offset);
|
||||
fetchFirstNote(offset);
|
||||
|
||||
updateVisibleNotes(offset);
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::updateVisibleNotes(const microsec &offset)
|
||||
{
|
||||
for (auto it = _first; it != _last; ++it)
|
||||
(*it)->update(offset);
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::fetchFirstNote(const microsec& offset)
|
||||
{
|
||||
(void)offset; // ????
|
||||
|
||||
if (nothingToDraw())
|
||||
return;
|
||||
|
||||
Iterator note_iterator = _first;
|
||||
while (note_iterator != _last)
|
||||
{
|
||||
auto note = *note_iterator;
|
||||
if (note->shouldRemove())
|
||||
++_first;
|
||||
|
||||
++note_iterator;
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicGameGraphicsManager::fetchLastNote(const microsec& offset)
|
||||
{
|
||||
Iterator note_iterator = _timeline->getTopNote();
|
||||
while (!_timeline->isExpired(note_iterator) && isVisiblyClose(note_iterator, offset))
|
||||
{
|
||||
if (nothingToDraw())
|
||||
_first = note_iterator;
|
||||
|
||||
auto note = *note_iterator;
|
||||
|
||||
if (!note->isInGame())
|
||||
{
|
||||
note->putToGame();
|
||||
note->setGraphics(this, TimeRange{offset, note->offset()});
|
||||
}
|
||||
|
||||
++note_iterator;
|
||||
}
|
||||
|
||||
_last = note_iterator;
|
||||
}
|
||||
|
||||
bool ClassicGameGraphicsManager::nothingToDraw() const noexcept
|
||||
{
|
||||
return _timeline->isExpired(_first)
|
||||
|| _timeline->isExpired(_last);
|
||||
}
|
||||
|
||||
bool ClassicGameGraphicsManager::isVisiblyClose(const Iterator& iterator, const microsec& music_offset) const noexcept
|
||||
{
|
||||
return ((*iterator)->offset() - _visibility_offset) <= music_offset;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "game/classicarrownote.h"
|
||||
#include "graphics/classicgraphicsmanager.h"
|
||||
#include "core/timeline.h"
|
||||
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
|
||||
class ClassicSprite;
|
||||
|
||||
class ClassicGameGraphicsManager : public ClassicGraphicsManager
|
||||
{
|
||||
public:
|
||||
explicit ClassicGameGraphicsManager(Timeline<ClassicNote>& timeline, const microsec& visibility_offset);
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
|
||||
void draw(const std::vector<ClassicArrowNote::ArrowElement>& elements, sf::RenderTarget& target, sf::RenderStates states) const;
|
||||
void setGraphics(std::vector<ClassicArrowNote::ArrowElement> &elements, TimeRange&& range);
|
||||
|
||||
virtual void update(const microsec& offset) override;
|
||||
|
||||
private:
|
||||
using Iterator = Timeline<ClassicNote>::Iterator;
|
||||
|
||||
Iterator _first;
|
||||
Iterator _last;
|
||||
|
||||
Timeline<ClassicNote> * const _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);
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
#include "classicdyinganimationscenario.h"
|
||||
#include "classicsprite.h"
|
||||
|
||||
void ClassicDyingAnimationScenario::launch(const std::shared_ptr<ClassicSprite> 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;
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
#include "classicflyinganimationscenario.h"
|
||||
#include "classicsprite.h"
|
||||
|
||||
void ClassicFlyingAnimationScenario::launch(const std::shared_ptr<ClassicSprite> 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);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "spritecontainer.h"
|
||||
#include "classicmode/classicactions.h"
|
||||
#include "graphics/classicspritefactory.h"
|
||||
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
|
||||
class ClassicSprite;
|
||||
|
||||
class ClassicGraphicsManager : public sf::Drawable
|
||||
{
|
||||
public:
|
||||
virtual ~ClassicGraphicsManager() = default;
|
||||
explicit ClassicGraphicsManager(const microsec& visibility_offset) :
|
||||
_sprite_container({Type::UP, Type::DOWN,
|
||||
Type::LEFT, Type::RIGHT},
|
||||
std::make_unique<ClassicSpriteFactory>()),
|
||||
_visibility_offset(visibility_offset)
|
||||
{}
|
||||
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override = 0;
|
||||
virtual void update(const microsec& offset) = 0;
|
||||
|
||||
protected:
|
||||
SpriteContainer<Type, ClassicSpriteFactory, ClassicSprite> _sprite_container;
|
||||
microsec _visibility_offset;
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
#include "classicsprite.h"
|
||||
#include <SFML/Graphics/RenderTarget.hpp>
|
||||
|
||||
ClassicSprite::ClassicSprite(const sf::RectangleShape& shape) :
|
||||
_prototype(shape),
|
||||
_shape(shape),
|
||||
_trail(shape)
|
||||
{}
|
||||
|
||||
void ClassicSprite::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
target.draw(_shape, states);
|
||||
target.draw(_trail, states);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "tools/mathutils.h"
|
||||
#include "sprite.h"
|
||||
#include <SFML/Graphics/RectangleShape.hpp>
|
||||
|
||||
class ClassicSprite : public Sprite, public sf::Drawable
|
||||
{
|
||||
public:
|
||||
explicit ClassicSprite(const sf::RectangleShape& shape);
|
||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
||||
virtual void reset() 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;
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "classicmode/classicactions.h"
|
||||
#include "classicsprite.h"
|
||||
|
||||
class ClassicSpriteFactory
|
||||
{
|
||||
public:
|
||||
inline std::shared_ptr<ClassicSprite> create(Type type)
|
||||
{
|
||||
sf::RectangleShape sprite;
|
||||
sprite.setSize({20.f, 20.f});
|
||||
switch (type)
|
||||
{
|
||||
case Type::UP:
|
||||
sprite.setFillColor(sf::Color(255, 0, 0));
|
||||
break;
|
||||
|
||||
case Type::DOWN:
|
||||
sprite.setFillColor(sf::Color(0, 255, 0));
|
||||
break;
|
||||
|
||||
case Type::LEFT:
|
||||
sprite.setFillColor(sf::Color(0, 0, 255));
|
||||
break;
|
||||
|
||||
case Type::RIGHT:
|
||||
sprite.setFillColor(sf::Color(255, 0, 255));
|
||||
break;
|
||||
|
||||
default: // yellow
|
||||
sprite.setFillColor(sf::Color(255, 239, 0));
|
||||
}
|
||||
|
||||
return std::make_shared<ClassicSprite>(sprite);
|
||||
}
|
||||
};
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "classicactions.h"
|
||||
#include "core/inputtype.h"
|
||||
#include "tools/mathutils.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct ElementInitializer
|
||||
{
|
||||
Type type = Type::NONE;
|
||||
Coordinates coordinates;
|
||||
std::vector<Coordinates> falling_curve_interpolation;
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
class Game;
|
||||
class Editor;
|
||||
|
||||
namespace classic
|
||||
{
|
||||
std::unique_ptr<Game> initGame();
|
||||
std::unique_ptr<Editor> initEditor();
|
||||
}
|
|
@ -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)
|
|
@ -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/classicfactory.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const sf::Time TIME_PER_FRAME = sf::seconds(1.f / 90.f);
|
||||
|
||||
Application::Application() :
|
||||
_game_window({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<MainMenu>(std::move(callbacks), _font_holder);
|
||||
const auto game_state = std::make_shared<GameState>(classic::initGame(), GameState::Callbacks());
|
||||
const auto editor = std::make_shared<EditorState>(classic::initEditor(), 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());
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/Font.hpp>
|
||||
#include <SFML/System/Clock.hpp>
|
||||
#include <SFML/Window/Keyboard.hpp>
|
||||
#include <SFML/Window/Event.hpp>
|
||||
|
||||
#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<std::shared_ptr<GUIState>, GUIState::Tag::AMOUNT> _states;
|
||||
std::vector<std::shared_ptr<GUIState>> _state_stack;
|
||||
|
||||
sf::RenderWindow _game_window;
|
||||
Music _music;
|
||||
|
||||
void exec();
|
||||
void pushState(GUIState::Tag new_state);
|
||||
void popState();
|
||||
|
||||
FontHolder _font_holder;
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
#include "tools/music.h"
|
||||
#include "tools/resourceholder.h"
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
|
||||
class BPMCalculator;
|
||||
class Group;
|
||||
class Editor;
|
||||
|
||||
class EditorState : public GUIState
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(void)> onLeaveEditorState;
|
||||
};
|
||||
|
||||
explicit EditorState(std::unique_ptr<Editor>&& 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<sf::Font> _font;
|
||||
|
||||
Callbacks _callbacks;
|
||||
|
||||
Music _music;
|
||||
std::shared_ptr<BPMCalculator> _bpm_calculator;
|
||||
std::shared_ptr<Group> _group;
|
||||
|
||||
std::unique_ptr<Editor> _editor;
|
||||
};
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#include "gamestate.h"
|
||||
#include "widgets/button.h"
|
||||
#include "widgets/group.h"
|
||||
|
||||
#include "core/game.h"
|
||||
|
||||
GameState::GameState(const std::shared_ptr<Game>& 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
|
||||
{
|
||||
_game->draw(target, states);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
#include "tools/music.h"
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
|
||||
class Group;
|
||||
class Game;
|
||||
|
||||
class GameState : public GUIState
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(void)> onLeaveGame;
|
||||
};
|
||||
|
||||
|
||||
explicit GameState(const std::shared_ptr<Game>& 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> _game;
|
||||
|
||||
std::function<void(void)> _onEnterGameCallback;
|
||||
std::function<void(void)> _onLeaveGameCallback;
|
||||
};
|
||||
|
|
@ -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<void(void)> onLeaveEditorState;
|
||||
};
|
||||
|
||||
explicit EditorState(const std::shared_ptr<kku::CoreFactory>& core_factory, std::unique_ptr<kku::Editor>&& 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<kku::CoreFactory> _core_factory;
|
||||
std::shared_ptr<kku::Music> _music;
|
||||
|
||||
std::shared_ptr<BPMCalculator> _bpm_calculator;
|
||||
std::shared_ptr<Group> _group;
|
||||
|
||||
std::unique_ptr<kku::Editor> _editor;
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
#include "core/music.h"
|
||||
#include "core/game.h"
|
||||
#include "core/corefactory.h"
|
||||
|
||||
class Group;
|
||||
|
||||
class GameState : public GUIState
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(void)> onLeaveGame;
|
||||
};
|
||||
|
||||
|
||||
explicit GameState(const std::shared_ptr<kku::CoreFactory>& core_factory, const std::shared_ptr<kku::Game>& 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:
|
||||
const std::shared_ptr<kku::CoreFactory> _core_factory;
|
||||
std::shared_ptr<kku::Music> _music;
|
||||
std::shared_ptr<kku::Game> _game;
|
||||
|
||||
std::function<void(void)> _onEnterGameCallback;
|
||||
std::function<void(void)> _onLeaveGameCallback;
|
||||
};
|
||||
|
|
@ -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<void(void)> onAppendGameState;
|
||||
std::function<void(void)> onAppendEditorState;
|
||||
};
|
||||
|
||||
explicit MainMenu(const std::shared_ptr<kku::CoreFactory>& 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<kku::CoreFactory> _core_factory;
|
||||
|
||||
std::shared_ptr<Group> _buttons;
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#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;
|
||||
};
|
|
@ -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<Group>())
|
||||
{
|
||||
}
|
||||
|
||||
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<PushButton>("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<PushButton>("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);
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
#include "tools/resourceholder.h"
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
|
||||
class Group;
|
||||
|
||||
class MainMenu : public GUIState
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(void)> onAppendGameState;
|
||||
std::function<void(void)> 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<sf::Font> _font;
|
||||
const Callbacks _callbacks;
|
||||
|
||||
std::shared_ptr<Group> _buttons;
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
|
||||
#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<kku::CoreFactory> _core_factory;
|
||||
std::shared_ptr<ClassicFactory> _game_factory;
|
||||
|
||||
std::array<std::shared_ptr<GUIState>, GUIState::Tag::AMOUNT> _states;
|
||||
std::vector<std::shared_ptr<GUIState>> _state_stack;
|
||||
|
||||
void pushState(GUIState::Tag new_state);
|
||||
void popState();
|
||||
};
|
|
@ -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<MainMenu>(_core_factory, std::move(callbacks));
|
||||
const auto game_state = std::make_shared<GameState>(_core_factory, _game_factory->getGame(), GameState::Callbacks());
|
||||
const auto editor = std::make_shared<EditorState>(_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();
|
||||
}
|
|
@ -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 <iostream>
|
||||
|
||||
EditorState::EditorState(std::unique_ptr<Editor>&& editor, Callbacks&& callbacks, const FontHolder& font_holder) :
|
||||
_font(font_holder.get(Fonts::Id::GUI)),
|
||||
EditorState::EditorState(const std::shared_ptr<kku::CoreFactory>& core_factory,
|
||||
std::unique_ptr<kku::Editor>&& 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<BPMCalculator>();
|
||||
auto& bpm_calculator = _bpm_calculator;
|
||||
std::shared_ptr<BPMCalculatorWidget> bpm_widget = std::make_shared<BPMCalculatorWidget>(_bpm_calculator, _font);
|
||||
std::shared_ptr<BPMCalculatorWidget> bpm_widget = std::make_shared<BPMCalculatorWidget>(_bpm_calculator, _core_factory);
|
||||
|
||||
auto button_start = std::make_shared<PushButton>("Start", _font);
|
||||
auto button_stop = std::make_shared<PushButton>("Stop", _font);
|
||||
auto button_apply = std::make_shared<PushButton>("Apply", _font);
|
||||
auto button_start = std::make_shared<PushButton>("Start", _core_factory);
|
||||
auto button_stop = std::make_shared<PushButton>("Stop", _core_factory);
|
||||
auto button_apply = std::make_shared<PushButton>("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<MenuBar>(_font);
|
||||
auto menu_bar = std::make_shared<MenuBar>(_core_factory);
|
||||
|
||||
auto bpm_button = std::make_shared<PushButton>("Calculate BPM", _font);
|
||||
auto bpm_button = std::make_shared<PushButton>("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<float>{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<MenuDrop>();
|
||||
test_menu_2->setRect(sf::FloatRect{0, 0, 200, 27 * 5});
|
||||
auto test_menu_2 = std::make_shared<MenuDrop>(_core_factory);
|
||||
test_menu_2->setRect(kku::Area<float>{0., 0., 200., 27. * 5.});
|
||||
|
||||
auto test_menu_3 = std::make_shared<MenuDrop>();
|
||||
test_menu_3->setRect(sf::FloatRect{0, 0, 200, 27 * 5});
|
||||
auto test_menu_3 = std::make_shared<MenuDrop>(_core_factory);
|
||||
test_menu_3->setRect(kku::Area<float>{0., 0., 200., 27. * 5.});
|
||||
|
||||
auto test_cascade_button = std::make_shared<CascadeMenuButton>("Show submenu", _font);
|
||||
auto test_cascade_button = std::make_shared<CascadeMenuButton>("Show submenu", _core_factory);
|
||||
|
||||
auto test_cascade_button_2 = std::make_shared<CascadeMenuButton>("Show submenu 2", _font);
|
||||
auto test_cascade_button_2 = std::make_shared<CascadeMenuButton>("Show submenu 2", _core_factory);
|
||||
|
||||
auto quit_button = std::make_shared<PushButton>("Quit", _font);
|
||||
auto quit_button = std::make_shared<PushButton>("Quit", _core_factory);
|
||||
quit_button->setCallback(_callbacks.onLeaveEditorState);
|
||||
|
||||
auto test_menu = std::make_shared<MenuDrop>();
|
||||
test_menu->setRect(sf::FloatRect{0, 0, 200, 27 * 3});
|
||||
auto test_menu = std::make_shared<MenuDrop>(_core_factory);
|
||||
test_menu->setRect(kku::Area<float>{0., 0., 200., 27. * 3.});
|
||||
|
||||
menu_bar->setRect(sf::FloatRect(0, 0, window_width, 27));
|
||||
menu_bar->setRect(kku::Area<float>{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->draw();
|
||||
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<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
|
||||
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<kku::SystemEvent::Mouse>(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<EditorWidget>(std::move(callbacks));
|
|
@ -0,0 +1,52 @@
|
|||
#include "application/gamestate.h"
|
||||
#include "widgets/button.h"
|
||||
#include "widgets/group.h"
|
||||
|
||||
#include "core/game.h"
|
||||
|
||||
GameState::GameState(const std::shared_ptr<kku::CoreFactory>& core_factory, const std::shared_ptr<kku::Game>& game, Callbacks&& callbacks) :
|
||||
_core_factory(core_factory),
|
||||
_game(game),
|
||||
_onLeaveGameCallback(callbacks.onLeaveGame)
|
||||
{
|
||||
_music = _core_factory->getMusic();
|
||||
}
|
||||
|
||||
void GameState::input(const kku::SystemEvent& event)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case kku::SystemEvent::Type::KeyRelease:
|
||||
if (std::get<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
|
||||
_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();
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#include "application/mainmenu.h"
|
||||
#include "widgets/pushbutton.h"
|
||||
#include "widgets/group.h"
|
||||
|
||||
MainMenu::MainMenu(const std::shared_ptr<kku::CoreFactory>& factory, MainMenu::Callbacks&& callbacks) :
|
||||
_callbacks(std::move(callbacks)),
|
||||
_core_factory(factory),
|
||||
_buttons(std::make_shared<Group>())
|
||||
{
|
||||
}
|
||||
|
||||
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<PushButton>("Start", _core_factory, 48);
|
||||
button_start->setRect(kku::Area<float>{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<PushButton>("Editor", _core_factory, 48);
|
||||
button_editor->setRect(kku::Area<float>{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);
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
#include "bpmcalculatorwidget.h"
|
||||
#include "tools/bpmcalculator.h"
|
||||
#include "core/editor.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr<BPMCalculator>& bpm_calculator, const std::shared_ptr<kku::CoreFactory>& factory) :
|
||||
Window(factory, "BPM Calculation"),
|
||||
_bpm_calculator(bpm_calculator),
|
||||
_slider(std::make_shared<BPMSlider>()),
|
||||
_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<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
|
||||
{
|
||||
_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<int>(beat_info.BPM)));
|
||||
|
||||
const kku::microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time());
|
||||
const auto time_relation = static_cast<long double>(beat_info.interval) / static_cast<long double>(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<float>& rect)
|
||||
{
|
||||
Window::setRect(rect);
|
||||
_slider->setRect(kku::Area<float>{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<float>{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<float>{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<float>{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<float>& 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);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/time.h"
|
||||
#include "core/text.h"
|
||||
#include "window.h"
|
||||
#include "bpmslider.h"
|
||||
#include "pushbutton.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class BPMCalculator;
|
||||
class Editor;
|
||||
|
||||
class BPMCalculatorWidget : public Window
|
||||
{
|
||||
public:
|
||||
|
||||
struct Init
|
||||
{
|
||||
std::shared_ptr<PushButton> start;
|
||||
std::shared_ptr<PushButton> stop;
|
||||
std::shared_ptr<PushButton> apply;
|
||||
std::function<kku::microsec(void)> current_time;
|
||||
};
|
||||
|
||||
explicit BPMCalculatorWidget(const std::shared_ptr<BPMCalculator>& bpm_calculator, const std::shared_ptr<kku::CoreFactory>& 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<float>& delta) override;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& 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<PushButton> _button_start;
|
||||
std::shared_ptr<PushButton> _button_stop;
|
||||
std::shared_ptr<PushButton> _button_apply;
|
||||
|
||||
std::shared_ptr<BPMCalculator> _bpm_calculator;
|
||||
std::shared_ptr<BPMSlider> _slider;
|
||||
|
||||
const std::shared_ptr<kku::CoreFactory> _core_factory;
|
||||
|
||||
bool _ticked;
|
||||
std::shared_ptr<kku::Text> _bpm_value;
|
||||
std::function<kku::microsec(void)> _current_time;
|
||||
};
|
||||
|
|
@ -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<float>& rect)
|
||||
{
|
||||
_slider_background->setRect(rect);
|
||||
_slider_tick->setRect(kku::Area<float>{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<float>& delta)
|
||||
{
|
||||
_slider_background->move(delta);
|
||||
_slider_tick->move(delta);
|
||||
}
|
||||
|
||||
bool BPMSlider::isUnderMouse(const kku::Point& position) const
|
||||
{
|
||||
return _slider_background->contains(position);
|
||||
}
|
||||
|
||||
kku::Area<float> 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});
|
||||
}
|
|
@ -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<float>& delta) override;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> 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<kku::Rectangle> _slider_background;
|
||||
std::shared_ptr<kku::Rectangle> _slider_tick;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#include "button.h"
|
||||
#include <iostream>
|
||||
|
||||
Button::Button(const std::string &text, const std::shared_ptr<kku::CoreFactory>& 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<float>& 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<float>& 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<float> Button::getRect() const
|
||||
{
|
||||
return _button_content->getRect();
|
||||
}
|
||||
|
||||
kku::Point Button::getPosition() const
|
||||
{
|
||||
return _button_content->getPosition();
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
#include "core/corefactory.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class Button : public Widget
|
||||
{
|
||||
public:
|
||||
explicit Button(const std::string& text, const std::shared_ptr<kku::CoreFactory>& 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<float>& delta) override final;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override final;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> 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<kku::Rectangle> _button_content;
|
||||
std::shared_ptr<kku::Text> _button_text;
|
||||
|
||||
const std::shared_ptr<kku::CoreFactory> _core_factory;
|
||||
};
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
#include "cascademenubutton.h"
|
||||
#include "menudrop.h"
|
||||
|
||||
CascadeMenuButton::CascadeMenuButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& 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<kku::SystemEvent::Mouse>(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<float>& rect)
|
||||
{
|
||||
Button::setRect(rect);
|
||||
resetRect();
|
||||
}
|
||||
|
||||
void CascadeMenuButton::setSubmenu(const std::shared_ptr<MenuDrop>& submenu)
|
||||
{
|
||||
_submenu = submenu;
|
||||
resetRect();
|
||||
}
|
||||
|
||||
const std::shared_ptr<MenuDrop> 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;
|
||||
}
|
|
@ -7,19 +7,19 @@ class MenuDrop;
|
|||
class CascadeMenuButton : public Button
|
||||
{
|
||||
public:
|
||||
explicit CascadeMenuButton(const std::string& text, const std::shared_ptr<sf::Font>& 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<kku::CoreFactory>& factory, unsigned int font_size = 12);
|
||||
virtual void input(const kku::SystemEvent& event) override final;
|
||||
virtual void setRect(const kku::Area<float>& rect) override final;
|
||||
|
||||
void setSubmenu(const std::shared_ptr<MenuDrop>& submenu);
|
||||
const std::shared_ptr<MenuDrop> 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<MenuDrop> _submenu;
|
||||
|
||||
sf::Color _color_idle;
|
||||
sf::Color _color_hover;
|
||||
kku::Color _color_idle;
|
||||
kku::Color _color_hover;
|
||||
};
|
||||
|
|
@ -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<float>& delta)
|
||||
{
|
||||
(void)delta;
|
||||
// delegate to children
|
||||
}
|
||||
|
||||
bool EditorWidget::isUnderMouse(const kku::Point& position) const
|
||||
{
|
||||
return _parent->isUnderMouse(position);
|
||||
}
|
||||
|
||||
void EditorWidget::setRect(const kku::Area<float>& rect)
|
||||
{
|
||||
(void)rect;
|
||||
// basically useless beacuse editor widget fills the entire screen
|
||||
}
|
||||
|
||||
kku::Area<float> EditorWidget::getRect() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void EditorWidget::setPosition(const kku::Point& position)
|
||||
{
|
||||
(void)position;
|
||||
}
|
||||
|
||||
kku::Point EditorWidget::getPosition() const
|
||||
{
|
||||
return kku::Point{};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
#include <functional>
|
||||
|
||||
class EditorWidget : public Widget
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(const kku::SystemEvent& event)> onInput;
|
||||
std::function<void(const kku::microsec& dt)> onUpdate;
|
||||
std::function<void(void)> 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<float>& delta) override;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> getRect() const override;
|
||||
|
||||
virtual void setPosition(const kku::Point& position) override;
|
||||
virtual kku::Point getPosition() const override;
|
||||
|
||||
private:
|
||||
std::function<void(const kku::SystemEvent& event)> _input;
|
||||
std::function<void(const kku::microsec& dt)> _update;
|
||||
std::function<void(void)> _draw;
|
||||
};
|
||||
|
|
@ -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<float>& rect)
|
||||
{
|
||||
_rect = rect;
|
||||
}
|
||||
|
||||
void Group::setPosition(const kku::Point& position)
|
||||
{
|
||||
_rect.top = position.y;
|
||||
_rect.left = position.x;
|
||||
}
|
||||
|
||||
void Group::move(const kku::Vector2<float>& 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<float> Group::getRect() const
|
||||
{
|
||||
return _rect;
|
||||
}
|
||||
|
||||
kku::Point Group::getPosition() const
|
||||
{
|
||||
return kku::Point
|
||||
{
|
||||
_rect.top,
|
||||
_rect.left
|
||||
};
|
||||
}
|
||||
|
|
@ -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<float>& delta) override;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> getRect() const override;
|
||||
|
||||
virtual void setPosition(const kku::Point& position) override;
|
||||
virtual kku::Point getPosition() const override;
|
||||
|
||||
private:
|
||||
kku::Area<float> _rect;
|
||||
};
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
#include "menubar.h"
|
||||
|
||||
MenuBar::MenuBar(const std::shared_ptr<kku::CoreFactory>& 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<kku::SystemEvent::Mouse>(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<float>& 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<float>& 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<MenuDrop>& submenu)
|
||||
{
|
||||
const auto new_button = std::make_shared<PushButton>(name, _core_factory);
|
||||
|
||||
std::size_t current_index = _amount_buttons;
|
||||
new_button->setRect(kku::Area<float>{static_cast<float>(current_index * _button_width),
|
||||
0.f,
|
||||
static_cast<float>(_button_width),
|
||||
_bar_rect->getRect().height});
|
||||
new_button->setCallback([submenu=submenu]()
|
||||
{
|
||||
submenu->setVisibility(true);
|
||||
submenu->lock();
|
||||
});
|
||||
|
||||
submenu->setPosition(kku::Point{static_cast<float>(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<MenuDrop> &submenu)
|
||||
{
|
||||
_submenus.emplace_back(submenu);
|
||||
}
|
||||
|
||||
void MenuBar::setVisibility(bool is_visible)
|
||||
{
|
||||
Widget::setVisibility(is_visible);
|
||||
|
||||
for (auto& submenu : _submenus)
|
||||
submenu->setVisibility(false);
|
||||
}
|
||||
|
||||
kku::Area<float> MenuBar::getRect() const
|
||||
{
|
||||
return _bar_rect->getRect();
|
||||
}
|
||||
|
||||
kku::Point MenuBar::getPosition() const
|
||||
{
|
||||
return _bar_rect->getPosition();
|
||||
}
|
|
@ -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<kku::CoreFactory>& 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<float>& 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<float>& rect) override;
|
||||
virtual kku::Area<float> 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<MenuDrop>& submenu);
|
||||
void addDependentSubmenu(const std::shared_ptr<MenuDrop>& submenu);
|
||||
|
||||
private:
|
||||
const std::shared_ptr<kku::CoreFactory> _core_factory;
|
||||
const std::shared_ptr<kku::Rectangle> _bar_rect;
|
||||
std::size_t _amount_buttons;
|
||||
std::size_t _button_width;
|
||||
|
||||
std::vector<std::shared_ptr<MenuDrop>> _submenus;
|
||||
};
|
|
@ -1,16 +1,17 @@
|
|||
#include "menudrop.h"
|
||||
#include "menuseparator.h"
|
||||
#include "core/corefactory.h"
|
||||
|
||||
MenuDrop::MenuDrop() :
|
||||
MenuDrop::MenuDrop(const std::shared_ptr<kku::CoreFactory>& 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<kku::SystemEvent::Mouse>(event.data).position;
|
||||
if (isUnderMouse(position))
|
||||
{
|
||||
setVisibility(false);
|
||||
for (auto& submenu : _submenus)
|
||||
|
@ -33,8 +36,12 @@ 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<kku::SystemEvent::Mouse>(event.data).position;
|
||||
if (!isUnderMouse(position))
|
||||
{
|
||||
if (!isLocked() && !hasActiveSubmenus())
|
||||
setVisibility(false);
|
||||
|
@ -42,6 +49,7 @@ void MenuDrop::input(const sf::Event& event)
|
|||
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<float>& 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<float>& 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<CascadeMenuButton>& button
|
|||
submenu->setParent(_parent);
|
||||
}
|
||||
|
||||
void MenuDrop::addSeparator()
|
||||
void MenuDrop::addSeparator(const std::shared_ptr<MenuSeparator>& separator)
|
||||
{
|
||||
add(std::make_shared<MenuSeparator>());
|
||||
add(separator);
|
||||
}
|
||||
|
||||
void MenuDrop::add(const std::shared_ptr<Widget> &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<float>{parent_rect.left,
|
||||
parent_rect.top + (parent_rect.height * _button_index),
|
||||
parent_rect.width,
|
||||
static_cast<float>(_button_height)});
|
||||
|
||||
addChild(widget);
|
||||
++_button_index;
|
||||
|
@ -147,12 +153,12 @@ bool MenuDrop::isLocked() const
|
|||
return _is_locked;
|
||||
}
|
||||
|
||||
sf::FloatRect MenuDrop::rect() const
|
||||
kku::Area<float> 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();
|
||||
}
|
|
@ -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<kku::CoreFactory>& 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<float>& 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<float>& rect) override;
|
||||
virtual kku::Area<float> getRect() const override;
|
||||
|
||||
virtual void setPosition(const kku::Point& position) override;
|
||||
virtual kku::Point getPosition() const override;
|
||||
|
||||
void addPushButton(const std::shared_ptr<PushButton>& button);
|
||||
void addCascadeButton(const std::shared_ptr<CascadeMenuButton>& button);
|
||||
void addSeparator(const std::shared_ptr<MenuSeparator>& separator);
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
bool isLocked() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<kku::Rectangle> _content_rect;
|
||||
bool _is_locked;
|
||||
|
||||
std::size_t _button_height;
|
||||
std::size_t _button_index;
|
||||
|
||||
std::vector<std::shared_ptr<MenuDrop>> _submenus;
|
||||
|
||||
void add(const std::shared_ptr<Widget>& widget);
|
||||
bool hasActiveSubmenus() const;
|
||||
};
|
|
@ -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<float>& rect)
|
||||
{
|
||||
_rect = rect;
|
||||
|
||||
//_line
|
||||
}
|
||||
|
||||
void MenuSeparator::setPosition(const kku::Point& position)
|
||||
{
|
||||
(void)position;
|
||||
}
|
||||
|
||||
void MenuSeparator::move(const kku::Vector2<float>& delta)
|
||||
{
|
||||
(void)delta;
|
||||
}
|
||||
|
||||
bool MenuSeparator::isUnderMouse(const kku::Point& position) const
|
||||
{
|
||||
return _is_visible && _rect.contains(position);
|
||||
}
|
||||
|
||||
kku::Area<float> MenuSeparator::getRect() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
kku::Point MenuSeparator::getPosition() const
|
||||
{
|
||||
return kku::Point{};
|
||||
}
|
|
@ -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<float>& delta) override;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> getRect() const override;
|
||||
|
||||
virtual void setPosition(const kku::Point& position) override;
|
||||
virtual kku::Point getPosition() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<kku::Line> _line;
|
||||
kku::Area<float> _rect;
|
||||
};
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#include "pushbutton.h"
|
||||
|
||||
PushButton::PushButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& 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<kku::SystemEvent::Mouse>(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<kku::SystemEvent::Mouse>(event.data).position;
|
||||
_button_content->setColor(_color_idle);
|
||||
_pressed = false;
|
||||
if (isUnderMouse(position))
|
||||
_on_click_callback();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PushButton::setCallback(std::function<void(void)> 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);
|
||||
}
|
|
@ -5,15 +5,15 @@
|
|||
class PushButton : public Button
|
||||
{
|
||||
public:
|
||||
explicit PushButton(const std::string& text, const std::shared_ptr<sf::Font>& 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<kku::CoreFactory>& factory, unsigned int font_size = 12);
|
||||
virtual void input(const kku::SystemEvent& event) override final;
|
||||
|
||||
void setCallback(std::function<void(void)> 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<void(void)> _on_click_callback;
|
|
@ -1,6 +1,7 @@
|
|||
#include "widget.h"
|
||||
#include <algorithm>
|
||||
|
||||
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<float>& delta)
|
||||
{
|
||||
for (auto& child : _children)
|
||||
child->move(delta);
|
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "core/systemevent.h"
|
||||
#include "core/rectangle.h"
|
||||
#include "core/time.h"
|
||||
|
||||
class Widget : public std::enable_shared_from_this<Widget>
|
||||
{
|
||||
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<float>& delta) = 0;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const = 0;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) = 0;
|
||||
virtual kku::Area<float> 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<Widget>& child);
|
||||
void setParent(const std::shared_ptr<Widget>& parent);
|
||||
|
||||
void blockBy(const std::shared_ptr<Widget>& blocker);
|
||||
void unblock();
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<Widget>> _children;
|
||||
std::shared_ptr<Widget> _parent;
|
||||
std::shared_ptr<Widget> _blocker;
|
||||
bool _is_visible = true;
|
||||
};
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include "window.h"
|
||||
#include "pushbutton.h"
|
||||
|
||||
Window::Window(const std::shared_ptr<kku::CoreFactory>& 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<kku::SystemEvent::Mouse>(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<kku::SystemEvent::Mouse>(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<float>{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<float>& rect)
|
||||
{
|
||||
_window_content->setRect(rect);
|
||||
|
||||
kku::Area<float> 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<float>& 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<void(void)> callback)
|
||||
{
|
||||
const auto area = _window_content->getRect();
|
||||
|
||||
auto b = std::make_shared<PushButton>(text, _core_factory, 20);
|
||||
b->setCallback(callback);
|
||||
b->setRect({area.left + area.width - 35,
|
||||
area.top, 30, 30});
|
||||
|
||||
Widget::addChild(b);
|
||||
}
|
||||
|
||||
kku::Area<float> Window::getRect() const
|
||||
{
|
||||
return _window_content->getRect();
|
||||
}
|
||||
|
||||
kku::Point Window::getPosition() const
|
||||
{
|
||||
return _window_content->getPosition();
|
||||
}
|
|
@ -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 <functional>
|
||||
|
||||
class Window : public Widget
|
||||
{
|
||||
public:
|
||||
explicit Window(const std::shared_ptr<kku::CoreFactory>& 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<float>& delta) override;
|
||||
virtual bool isUnderMouse(const kku::Point& position) const override final;
|
||||
|
||||
virtual void setRect(const kku::Area<float>& rect) override;
|
||||
virtual kku::Area<float> 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<void(void)> callback);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<kku::Rectangle> _bar;
|
||||
std::shared_ptr<kku::Rectangle> _window_content;
|
||||
std::shared_ptr<kku::Text> _bar_title;
|
||||
|
||||
const std::shared_ptr<kku::CoreFactory> _core_factory;
|
||||
|
||||
private:
|
||||
bool _is_dragging;
|
||||
kku::Point _previous_click_position;
|
||||
};
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
#include "bpmcalculatorwidget.h"
|
||||
#include "tools/bpmcalculator.h"
|
||||
#include "core/editor.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BPMCalculatorWidget::BPMCalculatorWidget(const std::shared_ptr<BPMCalculator>& bpm_calculator, const std::shared_ptr<sf::Font>& font) :
|
||||
Window("BPM Calculation", font),
|
||||
_bpm_calculator(bpm_calculator),
|
||||
_slider(std::make_shared<BPMSlider>()),
|
||||
_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<int>(beat_info.BPM)));
|
||||
|
||||
const microsec until_beat = _bpm_calculator->fetchTimeUntilNextBeat(_current_time());
|
||||
const auto time_relation = static_cast<long double>(beat_info.interval) / static_cast<long double>(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);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "window.h"
|
||||
#include "bpmslider.h"
|
||||
#include "pushbutton.h"
|
||||
#include <functional>
|
||||
#include <SFML/Graphics/RectangleShape.hpp>
|
||||
#include <SFML/Graphics/Text.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include "tools/mathutils.h"
|
||||
|
||||
class BPMCalculator;
|
||||
class Editor;
|
||||
|
||||
class BPMCalculatorWidget : public Window
|
||||
{
|
||||
public:
|
||||
|
||||
struct Init
|
||||
{
|
||||
std::shared_ptr<PushButton> start;
|
||||
std::shared_ptr<PushButton> stop;
|
||||
std::shared_ptr<PushButton> apply;
|
||||
std::function<microsec(void)> current_time;
|
||||
};
|
||||
|
||||
explicit BPMCalculatorWidget(const std::shared_ptr<BPMCalculator>& bpm_calculator, const std::shared_ptr<sf::Font> &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<PushButton> _button_start;
|
||||
std::shared_ptr<PushButton> _button_stop;
|
||||
std::shared_ptr<PushButton> _button_apply;
|
||||
|
||||
std::shared_ptr<BPMCalculator> _bpm_calculator;
|
||||
std::shared_ptr<BPMSlider> _slider;
|
||||
|
||||
sf::SoundBuffer _slap_buffer;
|
||||
sf::Sound _slap;
|
||||
bool _ticked;
|
||||
|
||||
sf::Text _bpm_value;
|
||||
std::function<microsec(void)> _current_time;
|
||||
};
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
|
||||
#include <SFML/Graphics/RectangleShape.hpp>
|
||||
#include <SFML/Graphics/Text.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#include "button.h"
|
||||
#include <iostream>
|
||||
|
||||
Button::Button(const std::string &text, const std::shared_ptr<sf::Font>& 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();
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
#include <functional>
|
||||
#include <SFML/Graphics/RectangleShape.hpp>
|
||||
#include <SFML/Graphics/Text.hpp>
|
||||
|
||||
class Button : public Widget
|
||||
{
|
||||
public:
|
||||
explicit Button(const std::string& text, const std::shared_ptr<sf::Font>& 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<sf::Font> _font;
|
||||
};
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
#include "cascademenubutton.h"
|
||||
#include "menudrop.h"
|
||||
|
||||
CascadeMenuButton::CascadeMenuButton(const std::string& text, const std::shared_ptr<sf::Font> &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<MenuDrop>& submenu)
|
||||
{
|
||||
_submenu = submenu;
|
||||
resetRect();
|
||||
}
|
||||
|
||||
const std::shared_ptr<MenuDrop> 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;
|
||||
}
|
|
@ -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 {};
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "widget.h"
|
||||
|
||||
class EditorWidget : public Widget
|
||||
{
|
||||
public:
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
std::function<void(const sf::Event& event)> onInput;
|
||||
std::function<void(const sf::Time& dt)> onUpdate;
|
||||
std::function<void(sf::RenderTarget& target, sf::RenderStates states)> 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<void(const sf::Event& event)> _input;
|
||||
std::function<void(const sf::Time& dt)> _update;
|
||||
std::function<void(sf::RenderTarget& target, sf::RenderStates states)> _draw;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue