forked from NaiJi/project-kyoku
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
|
build
|
||||||
SFML*
|
SFML-*
|
||||||
*.user
|
*.user
|
||||||
*CMakeFiles*
|
*CMakeFiles*
|
||||||
*Makefile
|
*Makefile
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
project(project-kyoku LANGUAGES CXX)
|
project(project-kyoku LANGUAGES CXX)
|
||||||
|
|
||||||
|
@ -16,38 +16,25 @@ set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||||
set(CMAKE_USE_PTHREADS_INIT 1)
|
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
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})
|
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 /)
|
SET(CMAKE_INSTALL_PREFIX /)
|
||||||
# When new game modes appear, aggregate them into a ONE subdirectory
|
# When new game modes appear, aggregate them into a ONE subdirectory
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modes/classicmode/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/modes/classicmode/CMakeLists.txt")
|
||||||
add_subdirectory(modes/classicmode)
|
add_subdirectory(src/modes/classicmode)
|
||||||
target_link_libraries(project-kyoku classicmode)
|
target_link_libraries(project-kyoku classicmode)
|
||||||
endif()
|
endif()
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/tools/CMakeLists.txt")
|
||||||
add_subdirectory(tools)
|
add_subdirectory(src/tools)
|
||||||
target_link_libraries(project-kyoku tools)
|
target_link_libraries(project-kyoku tools)
|
||||||
endif()
|
endif()
|
||||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/core/CMakeLists.txt")
|
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/application/CMakeLists.txt")
|
||||||
add_subdirectory(core)
|
add_subdirectory(src/application)
|
||||||
target_link_libraries(project-kyoku core)
|
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()
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "tools/mathutils.h"
|
#include "core/time.h"
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
struct BPMSection
|
struct BPMSection
|
||||||
{
|
{
|
||||||
int bpm = 120; // Hi, osu
|
unsigned int bpm = 120; // Hi, osu
|
||||||
int fraction = 2;
|
unsigned int fraction = 2;
|
||||||
microsec offset_start = 0;
|
microsec offset_start = 0;
|
||||||
microsec interval = 0;
|
microsec interval = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BPMSectionCompt
|
struct BPMSectionComparator
|
||||||
{
|
{
|
||||||
bool operator()(const BPMSection& lhs, const BPMSection& rhs) const noexcept
|
bool operator()(const BPMSection& lhs, const BPMSection& rhs) const noexcept
|
||||||
{
|
{
|
||||||
return lhs.offset_start < rhs.offset_start;
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "core/inputtype.h"
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "core/gameevent.h"
|
||||||
#include "core/updatedata.h"
|
#include "core/updatedata.h"
|
||||||
#include "core/bpmsection.h"
|
#include "core/bpmsection.h"
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
class Editor
|
class Editor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Editor() = default;
|
virtual ~Editor() = default;
|
||||||
|
|
||||||
virtual void input(PlayerInput&& inputdata) = 0;
|
virtual void input(GameEvent&& input) = 0;
|
||||||
virtual void update(UpdateData&& updatedata) = 0;
|
virtual void update(UpdateData&& updatedata) = 0;
|
||||||
virtual void draw() const = 0;
|
virtual void display() const = 0;
|
||||||
virtual void recalculate(const microsec& timestamp) = 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;
|
_bpm_sections = sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBPMSections(std::set<BPMSection, BPMSectionCompt>&& sections) noexcept
|
void setBPMSections(std::set<BPMSection, BPMSectionComparator>&& sections) noexcept
|
||||||
{
|
{
|
||||||
_bpm_sections = std::move(sections);
|
_bpm_sections = std::move(sections);
|
||||||
}
|
}
|
||||||
|
@ -77,5 +82,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "core/inputtype.h"
|
#include "core/time.h"
|
||||||
|
#include "core/gameevent.h"
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
class Note
|
class Note
|
||||||
{
|
{
|
||||||
|
@ -16,34 +20,40 @@ public:
|
||||||
virtual bool isInGame() const = 0;
|
virtual bool isInGame() const = 0;
|
||||||
virtual bool shouldRemove() 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;
|
return _perfect_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const Note& note) const
|
bool operator<(const Note& note) const
|
||||||
{
|
{
|
||||||
return (_perfect_offset < note._perfect_offset);
|
return _perfect_offset < note._perfect_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Note& note) const
|
bool operator==(const Note& note) const
|
||||||
{
|
{
|
||||||
return (_perfect_offset == note._perfect_offset);
|
return _perfect_offset == note._perfect_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const Note& note) const
|
bool operator>(const Note& note) const
|
||||||
{
|
{
|
||||||
return (_perfect_offset > note._perfect_offset);
|
return _perfect_offset > note._perfect_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
microsec _perfect_offset;
|
microsec _perfect_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NotePtrCompt
|
struct NotePtrComparator
|
||||||
{
|
{
|
||||||
bool operator()(const Note* lhs, const Note* rhs) const noexcept
|
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
|
#pragma once
|
||||||
#define PRECISIONEVALUATOR_H
|
|
||||||
|
|
||||||
#include "tools/mathutils.h"
|
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -9,6 +6,11 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "core/time.h"
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
template<typename Grade, typename = std::enable_if_t<std::is_enum<Grade>::value>>
|
template<typename Grade, typename = std::enable_if_t<std::is_enum<Grade>::value>>
|
||||||
class PrecisionEvaluator
|
class PrecisionEvaluator
|
||||||
{
|
{
|
||||||
|
@ -32,11 +34,12 @@ public:
|
||||||
&& music_play_offset < _end_handling_offset;
|
&& 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());
|
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;
|
std::size_t raw_grade;
|
||||||
for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade)
|
for (raw_grade = 0; raw_grade < _intervals.size(); ++raw_grade)
|
||||||
|
@ -63,4 +66,4 @@ private:
|
||||||
const std::vector<microsec> _intervals;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
class Sprite
|
class Sprite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Sprite() = default;
|
virtual ~Sprite() = default;
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
virtual void display() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -4,15 +4,18 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
template<typename Type, class SpriteFactory, class Sprite,
|
template<typename Type, class SpriteFactory, class Sprite,
|
||||||
typename = std::enable_if_t<std::is_enum<Type>::value>>
|
typename = std::enable_if_t<std::is_enum<Type>::value>>
|
||||||
class SpriteContainer
|
class SpriteContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SpriteContainer(std::initializer_list<Type>&& types,
|
explicit SpriteContainer(std::initializer_list<Type>&& types,
|
||||||
std::unique_ptr<SpriteFactory>&& factory,
|
const std::shared_ptr<SpriteFactory>& factory,
|
||||||
std::size_t reserve_size = 20) :
|
std::size_t reserve_size = 20) :
|
||||||
_sprite_factory(std::move(factory)),
|
_sprite_factory(factory),
|
||||||
_poll_reserve_size(reserve_size)
|
_poll_reserve_size(reserve_size)
|
||||||
{
|
{
|
||||||
for (const Type& type : types)
|
for (const Type& type : types)
|
||||||
|
@ -52,7 +55,9 @@ private:
|
||||||
using SpritePoll = std::stack<std::shared_ptr<Sprite>>;
|
using SpritePoll = std::stack<std::shared_ptr<Sprite>>;
|
||||||
|
|
||||||
std::map<Type, SpritePoll> _sprite_dispatcher;
|
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;
|
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 <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "tools/mathutils.h"
|
#include "core/time.h"
|
||||||
#include "core/note.h"
|
#include "core/note.h"
|
||||||
|
|
||||||
|
namespace kku
|
||||||
|
{
|
||||||
|
|
||||||
template <class TNote, class = std::enable_if_t<std::is_base_of<Note, TNote>::value>>
|
template <class TNote, class = std::enable_if_t<std::is_base_of<Note, TNote>::value>>
|
||||||
class Timeline
|
class Timeline
|
||||||
{
|
{
|
||||||
|
@ -29,7 +31,7 @@ public:
|
||||||
|
|
||||||
while (!isExpired(head_iterator))
|
while (!isExpired(head_iterator))
|
||||||
{
|
{
|
||||||
if ((*head_iterator)->offset() >= offset)
|
if ((*head_iterator)->getPerfectOffset() >= offset)
|
||||||
{
|
{
|
||||||
Iterator pre_head = head_iterator;
|
Iterator pre_head = head_iterator;
|
||||||
--pre_head;
|
--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);
|
_timeline = std::move(notes);
|
||||||
|
|
||||||
|
@ -65,7 +67,7 @@ public:
|
||||||
update(_current_offset);
|
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());
|
_timeline.insert(notes.begin(), notes.end());
|
||||||
recalculate(_current_offset);
|
recalculate(_current_offset);
|
||||||
|
@ -100,7 +102,7 @@ public:
|
||||||
return_note = note_iterator;
|
return_note = note_iterator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (note->offset() > music_offset)
|
else if (note->getPerfectOffset() > music_offset)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++note_iterator;
|
++note_iterator;
|
||||||
|
@ -114,7 +116,7 @@ public:
|
||||||
return std::find_if(_timeline.begin(), _timeline.end(),
|
return std::find_if(_timeline.begin(), _timeline.end(),
|
||||||
[music_offset](const auto& note)
|
[music_offset](const auto& note)
|
||||||
{
|
{
|
||||||
return note->offset() == music_offset;
|
return note->getPerfectOffset() == music_offset;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,14 +136,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::set<TNote*, NotePtrCompt> _timeline;
|
std::set<TNote*, NotePtrComparator> _timeline;
|
||||||
microsec _current_offset;
|
microsec _current_offset;
|
||||||
|
|
||||||
inline void updateTopNote(const microsec& music_offset) noexcept
|
inline void updateTopNote(const microsec& music_offset) noexcept
|
||||||
{
|
{
|
||||||
const auto& top_note = *_top_note;
|
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);
|
&& !top_note->isActive(music_offset);
|
||||||
|
|
||||||
if (already_played)
|
if (already_played)
|
||||||
|
@ -150,3 +152,7 @@ private:
|
||||||
|
|
||||||
Iterator _top_note;
|
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/button.h"
|
||||||
#include "widgets/group.h"
|
#include "widgets/group.h"
|
||||||
#include "widgets/menubar.h"
|
#include "widgets/menubar.h"
|
||||||
|
@ -9,36 +9,37 @@
|
||||||
|
|
||||||
#include "core/editor.h"
|
#include "core/editor.h"
|
||||||
|
|
||||||
#include <iostream>
|
EditorState::EditorState(const std::shared_ptr<kku::CoreFactory>& core_factory,
|
||||||
|
std::unique_ptr<kku::Editor>&& editor,
|
||||||
EditorState::EditorState(std::unique_ptr<Editor>&& editor, Callbacks&& callbacks, const FontHolder& font_holder) :
|
Callbacks&& callbacks) :
|
||||||
_font(font_holder.get(Fonts::Id::GUI)),
|
|
||||||
_callbacks(std::move(callbacks)),
|
_callbacks(std::move(callbacks)),
|
||||||
|
_core_factory(core_factory),
|
||||||
_editor(std::move(editor))
|
_editor(std::move(editor))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
EditorState::~EditorState()
|
EditorState::~EditorState()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void EditorState::input(const sf::Event& event)
|
void EditorState::input(const kku::SystemEvent& event)
|
||||||
{
|
{
|
||||||
_group->input(event);
|
_group->input(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorState::update(const sf::Time& dt)
|
void EditorState::update(const kku::microsec& dt)
|
||||||
{
|
{
|
||||||
_group->update(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 = _core_factory->getMusic();
|
||||||
_music.setVolume(5);
|
_music->open("METEOR.flac");
|
||||||
|
_music->setVolume(5.f);
|
||||||
|
|
||||||
auto& group = _group;
|
auto& group = _group;
|
||||||
auto& music = _music;
|
auto& music = _music;
|
||||||
|
@ -46,15 +47,15 @@ void EditorState::enter(sf::Vector2u &&render_size)
|
||||||
|
|
||||||
_bpm_calculator = std::make_shared<BPMCalculator>();
|
_bpm_calculator = std::make_shared<BPMCalculator>();
|
||||||
auto& bpm_calculator = _bpm_calculator;
|
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_start = std::make_shared<PushButton>("Start", _core_factory);
|
||||||
auto button_stop = std::make_shared<PushButton>("Stop", _font);
|
auto button_stop = std::make_shared<PushButton>("Stop", _core_factory);
|
||||||
auto button_apply = std::make_shared<PushButton>("Apply", _font);
|
auto button_apply = std::make_shared<PushButton>("Apply", _core_factory);
|
||||||
|
|
||||||
button_start->setCallback([bpm_calculator, button_start, button_stop, &music]()
|
button_start->setCallback([bpm_calculator, button_start, button_stop, &music]()
|
||||||
{
|
{
|
||||||
music.play();
|
music->play();
|
||||||
bpm_calculator->start();
|
bpm_calculator->start();
|
||||||
button_start->setVisibility(false);
|
button_start->setVisibility(false);
|
||||||
button_stop->setVisibility(true);
|
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]()
|
button_stop->setCallback([bpm_calculator, button_start, button_stop, &music]()
|
||||||
{
|
{
|
||||||
music.stop();
|
music->stop();
|
||||||
bpm_calculator->stop();
|
bpm_calculator->stop();
|
||||||
button_start->setVisibility(true);
|
button_start->setVisibility(true);
|
||||||
button_stop->setVisibility(false);
|
button_stop->setVisibility(false);
|
||||||
|
@ -70,7 +71,7 @@ void EditorState::enter(sf::Vector2u &&render_size)
|
||||||
|
|
||||||
button_apply->setCallback([&editor, bpm_calculator]()
|
button_apply->setCallback([&editor, bpm_calculator]()
|
||||||
{
|
{
|
||||||
BPMSection section;
|
kku::BPMSection section;
|
||||||
const auto& info = bpm_calculator->fetchApproximatedInfo();
|
const auto& info = bpm_calculator->fetchApproximatedInfo();
|
||||||
section.bpm = info.BPM;
|
section.bpm = info.BPM;
|
||||||
section.interval = info.interval;
|
section.interval = info.interval;
|
||||||
|
@ -84,21 +85,22 @@ void EditorState::enter(sf::Vector2u &&render_size)
|
||||||
bpm_widget_init.stop = button_stop;
|
bpm_widget_init.stop = button_stop;
|
||||||
bpm_widget_init.apply = button_apply;
|
bpm_widget_init.apply = button_apply;
|
||||||
bpm_widget_init.start = button_start;
|
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));
|
bpm_widget->init(std::move(bpm_widget_init));
|
||||||
const auto bpm_widget_callback = [&group, bpm_widget=bpm_widget, &music]()
|
const auto bpm_widget_callback = [&group, bpm_widget=bpm_widget, &music]()
|
||||||
{
|
{
|
||||||
music.stop();
|
music->stop();
|
||||||
bpm_widget->setVisibility(false);
|
bpm_widget->setVisibility(false);
|
||||||
group->unblock();
|
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]()
|
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->setVisibility(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
bpm_widget->setRect(sf::FloatRect(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.x / 3, render_size.y / 3));
|
render_size.first / 3.f, render_size.second / 3.f});
|
||||||
|
|
||||||
bpm_widget->addBarButton("X", bpm_widget_callback);
|
bpm_widget->addBarButton("X", bpm_widget_callback);
|
||||||
bpm_widget->setVisibility(false);
|
bpm_widget->setVisibility(false);
|
||||||
|
|
||||||
auto test_menu_2 = std::make_shared<MenuDrop>();
|
auto test_menu_2 = std::make_shared<MenuDrop>(_core_factory);
|
||||||
test_menu_2->setRect(sf::FloatRect{0, 0, 200, 27 * 5});
|
test_menu_2->setRect(kku::Area<float>{0., 0., 200., 27. * 5.});
|
||||||
|
|
||||||
auto test_menu_3 = std::make_shared<MenuDrop>();
|
auto test_menu_3 = std::make_shared<MenuDrop>(_core_factory);
|
||||||
test_menu_3->setRect(sf::FloatRect{0, 0, 200, 27 * 5});
|
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);
|
quit_button->setCallback(_callbacks.onLeaveEditorState);
|
||||||
|
|
||||||
auto test_menu = std::make_shared<MenuDrop>();
|
auto test_menu = std::make_shared<MenuDrop>(_core_factory);
|
||||||
test_menu->setRect(sf::FloatRect{0, 0, 200, 27 * 3});
|
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->addRootSubMenu("test", test_menu);
|
||||||
menu_bar->addDependentSubmenu(test_menu_2);
|
menu_bar->addDependentSubmenu(test_menu_2);
|
||||||
menu_bar->addDependentSubmenu(test_menu_3);
|
menu_bar->addDependentSubmenu(test_menu_3);
|
||||||
|
@ -148,28 +150,29 @@ void EditorState::enter(sf::Vector2u &&render_size)
|
||||||
menu_bar->setVisibility(true);
|
menu_bar->setVisibility(true);
|
||||||
|
|
||||||
EditorWidget::Callbacks callbacks;
|
EditorWidget::Callbacks callbacks;
|
||||||
callbacks.onDraw = [&editor](sf::RenderTarget& target, sf::RenderStates states)
|
callbacks.onDisplay = [&editor]()
|
||||||
{
|
{
|
||||||
(void)target; (void)states; // fucking shit i am a retard damn fuck fuck
|
editor->display();
|
||||||
editor->draw();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
if (event.type == kku::SystemEvent::Type::KeyRelease
|
||||||
music.isPaused() ? music.play() : music.pause();
|
&& std::get<kku::SystemEvent::Key>(event.data).view == kku::SystemEvent::Key::Code::Space)
|
||||||
else if (event.type == sf::Event::MouseWheelScrolled)
|
music->isPlaying() ? music->pause() : music->play();
|
||||||
|
else if (event.type == kku::SystemEvent::Type::MouseWheelScroll)
|
||||||
{
|
{
|
||||||
music.moveOffset(event.mouseWheelScroll.delta > 0 ? 500000 : -500000);
|
const auto& up = std::get<kku::SystemEvent::Mouse>(event.data).scrolled_up;
|
||||||
editor->recalculate(music.fetchOffset());
|
music->moveOffset(up ? 500000 : -500000);
|
||||||
|
editor->recalculate(music->fetchOffset());
|
||||||
}
|
}
|
||||||
else
|
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));
|
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
|
class CascadeMenuButton : public Button
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CascadeMenuButton(const std::string& text, const std::shared_ptr<sf::Font>& font, unsigned int font_size = 12);
|
explicit CascadeMenuButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& factory, unsigned int font_size = 12);
|
||||||
virtual void input(const sf::Event& event) override final;
|
virtual void input(const kku::SystemEvent& event) override final;
|
||||||
virtual void setRect(const sf::FloatRect& rect) override final;
|
virtual void setRect(const kku::Area<float>& rect) override final;
|
||||||
|
|
||||||
void setSubmenu(const std::shared_ptr<MenuDrop>& submenu);
|
void setSubmenu(const std::shared_ptr<MenuDrop>& submenu);
|
||||||
const std::shared_ptr<MenuDrop> submenu() const;
|
const std::shared_ptr<MenuDrop> submenu() const;
|
||||||
void resetRect();
|
void resetRect();
|
||||||
void setFillColors(sf::Color&& idle_color, sf::Color&& hover_color);
|
void setFillColors(kku::Color&& idle_color, kku::Color&& hover_color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<MenuDrop> _submenu;
|
std::shared_ptr<MenuDrop> _submenu;
|
||||||
|
|
||||||
sf::Color _color_idle;
|
kku::Color _color_idle;
|
||||||
sf::Color _color_hover;
|
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 "menudrop.h"
|
||||||
#include "menuseparator.h"
|
#include "core/corefactory.h"
|
||||||
|
|
||||||
MenuDrop::MenuDrop() :
|
MenuDrop::MenuDrop(const std::shared_ptr<kku::CoreFactory>& factory) :
|
||||||
_is_locked(false),
|
_is_locked(false),
|
||||||
_button_height(27),
|
_button_height(27),
|
||||||
_button_index(0)
|
_button_index(0)
|
||||||
{
|
{
|
||||||
_is_visible = false;
|
_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)
|
if (!_is_visible)
|
||||||
return;
|
return;
|
||||||
|
@ -22,8 +23,10 @@ void MenuDrop::input(const sf::Event& event)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sf::Event::MouseButtonReleased:
|
case kku::SystemEvent::Type::MouseRelease:
|
||||||
if (isUnderMouse(event.mouseButton.x, event.mouseButton.y))
|
{
|
||||||
|
const auto position = std::get<kku::SystemEvent::Mouse>(event.data).position;
|
||||||
|
if (isUnderMouse(position))
|
||||||
{
|
{
|
||||||
setVisibility(false);
|
setVisibility(false);
|
||||||
for (auto& submenu : _submenus)
|
for (auto& submenu : _submenus)
|
||||||
|
@ -33,8 +36,12 @@ void MenuDrop::input(const sf::Event& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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())
|
if (!isLocked() && !hasActiveSubmenus())
|
||||||
setVisibility(false);
|
setVisibility(false);
|
||||||
|
@ -42,6 +49,7 @@ void MenuDrop::input(const sf::Event& event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MenuDrop::hasActiveSubmenus() const
|
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);
|
Widget::update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuDrop::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void MenuDrop::display() const
|
||||||
{
|
{
|
||||||
if (_is_visible)
|
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->setRect(rect);
|
||||||
_content_rect.setSize({rect.width, rect.height});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
Widget::move(delta);
|
||||||
|
|
||||||
|
@ -86,9 +93,9 @@ void MenuDrop::move(const sf::Vector2f& delta)
|
||||||
submenu->move(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)
|
void MenuDrop::setVisibility(bool is_visible)
|
||||||
|
@ -113,20 +120,19 @@ void MenuDrop::addCascadeButton(const std::shared_ptr<CascadeMenuButton>& button
|
||||||
submenu->setParent(_parent);
|
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)
|
void MenuDrop::add(const std::shared_ptr<Widget> &widget)
|
||||||
{
|
{
|
||||||
const auto& parent_size = _content_rect.getSize();
|
const auto& parent_rect = _content_rect->getRect();
|
||||||
const auto& parent_position = _content_rect.getPosition();
|
|
||||||
|
|
||||||
widget->setRect(sf::FloatRect(parent_position.x,
|
widget->setRect(kku::Area<float>{parent_rect.left,
|
||||||
parent_position.y + (_button_height * _button_index),
|
parent_rect.top + (parent_rect.height * _button_index),
|
||||||
parent_size.x,
|
parent_rect.width,
|
||||||
_button_height));
|
static_cast<float>(_button_height)});
|
||||||
|
|
||||||
addChild(widget);
|
addChild(widget);
|
||||||
++_button_index;
|
++_button_index;
|
||||||
|
@ -147,12 +153,12 @@ bool MenuDrop::isLocked() const
|
||||||
return _is_locked;
|
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
|
class PushButton : public Button
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PushButton(const std::string& text, const std::shared_ptr<sf::Font>& font, unsigned int font_size = 12);
|
explicit PushButton(const std::string& text, const std::shared_ptr<kku::CoreFactory>& factory, unsigned int font_size = 12);
|
||||||
virtual void input(const sf::Event& event) override final;
|
virtual void input(const kku::SystemEvent& event) override final;
|
||||||
|
|
||||||
void setCallback(std::function<void(void)> callback);
|
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:
|
private:
|
||||||
sf::Color _color_idle;
|
kku::Color _color_idle;
|
||||||
sf::Color _color_pressed;
|
kku::Color _color_pressed;
|
||||||
|
|
||||||
bool _pressed;
|
bool _pressed;
|
||||||
std::function<void(void)> _on_click_callback;
|
std::function<void(void)> _on_click_callback;
|
|
@ -1,6 +1,7 @@
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
void Widget::input(const sf::Event &event)
|
void Widget::input(const kku::SystemEvent &event)
|
||||||
{
|
{
|
||||||
if (_blocker)
|
if (_blocker)
|
||||||
_blocker->input(event);
|
_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)
|
for (auto& child : _children)
|
||||||
child->update(dt);
|
child->update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void Widget::display() const
|
||||||
{
|
{
|
||||||
for (auto& child : _children)
|
for (const auto& child : _children)
|
||||||
child->draw(target, states);
|
child->display();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::move(const sf::Vector2f &delta)
|
void Widget::move(const kku::Vector2<float>& delta)
|
||||||
{
|
{
|
||||||
for (auto& child : _children)
|
for (auto& child : _children)
|
||||||
child->move(delta);
|
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