Non tested notes drawing code

This commit is contained in:
Stepland 2019-01-14 21:43:56 +01:00
parent 438fa00558
commit 3dbfc2820c
8 changed files with 222 additions and 87 deletions

View File

@ -19,4 +19,8 @@ void Chart::setResolution(int resolution) {
Chart::Chart(const std::string &dif, int level, int resolution) : dif_name(dif),
level(level),
resolution(resolution),
Notes() {}
Notes() {
if (resolution <= 0) {
throw std::invalid_argument("Can't set a resolution of "+std::to_string(resolution));
}
}

View File

@ -10,7 +10,7 @@
#include "tinyfiledialogs.h"
#include "Toolbox.h"
EditorState::EditorState(Fumen &fumen) : fumen(fumen) {
EditorState::EditorState(Fumen &fumen) : fumen(fumen), markerEndingState(MISS) {
reloadFromFumen();
}
@ -80,6 +80,42 @@ void EditorState::reloadJacket() {
}
void EditorState::displayPlayfield() {
ImGui::SetNextWindowSize(ImVec2(400,400),ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(0,0),ImVec2(FLT_MAX,FLT_MAX),Toolbox::CustomConstraints::ContentSquare);
if (ImGui::Begin("Playfield",&showPlayfield,ImGuiWindowFlags_NoScrollbar)) {
float squareSize = ImGui::GetWindowSize().x / 4.f;
float TitlebarHeight = ImGui::GetWindowSize().y - ImGui::GetWindowSize().x;
if (selectedChart) {
int ImGuiIndex = 0;
for (auto note : getVisibleNotes()) {
std::optional<sf::Texture> t;
if ((t = playfield.marker.getSprite(playfield.markerEndingState,getSecondsAt(note.getTiming())))) {
int x = note.getPos()%4;
int y = note.getPos()/4;
ImGui::SetCursorPos({x*squareSize,TitlebarHeight + y*squareSize});
ImGui::PushID(ImGuiIndex);
ImGui::Image(*t,{squareSize,squareSize});
ImGui::PopID();
}
++ImGuiIndex;
}
}
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
ImGui::PushID(x+4*y);
ImGui::SetCursorPos({x*squareSize,TitlebarHeight + y*squareSize});
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(0,0,0,0));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(0,0,1.f,0.1f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(0,0,1.f,0.5f));
ImGui::ImageButton(playfield.button,{squareSize,squareSize},0);
ImGui::PopStyleColor(3);
ImGui::PopID();
}
}
}
ImGui::End();
}
/*
@ -135,6 +171,8 @@ void EditorState::displayStatus() {
ImGui::TextColored(ImVec4(1,0.42,0.41,1),"No jacket loaded");
}
}
ImGui::Checkbox("Beat Tick",&playBeatTick);
ImGui::Checkbox("Note Tick",&playNoteTick);
}
ImGui::End();
}
@ -224,6 +262,36 @@ void EditorState::displayTimeline() {
ImGui::PopStyleVar(3);
}
std::vector<Note> EditorState::getVisibleNotes() {
if (selectedChart) {
std::vector<Note> visibleNotes;
float minPos;
if (this->markerEndingState == MISS) {
minPos = playbackPosition.asSeconds() - 8.f/30.f;
} else {
minPos = playbackPosition.asSeconds() - 16.f/30.f;
}
float maxPos = playbackPosition.asSeconds() + 16.f/30.f;
int min_exclusive = static_cast<int>(getTicksAt(minPos));
int max_exclusive = static_cast<int>(getTicksAt(maxPos));
for (auto note : selectedChart->Notes) {
if (note.getTiming() > min_exclusive and note.getTiming() < max_exclusive) {
visibleNotes.push_back(note);
}
}
return visibleNotes;
} else {
return {};
}
}
void ESHelper::save(EditorState& ed) {
try {
ed.fumen.autoSaveAsMemon();

View File

@ -10,12 +10,14 @@
#include <SFML/Graphics.hpp>
#include "Fumen.h"
#include "Marker.h"
#include "Widgets.h"
class EditorState {
public:
Fumen fumen;
Marker marker;
Widgets::Playfield playfield;
MarkerEndingState markerEndingState;
std::optional<sf::Music> music;
std::optional<sf::Texture> jacket;
std::optional<Chart> selectedChart;
@ -23,7 +25,23 @@ public:
sf::Time playbackPosition;
sf::Time chartRuntime; // Timing at which the playback stops
bool playing;
float getBeats() {return ((playbackPosition.asSeconds()+fumen.offset)/60.f)* fumen.BPM;};
float getBeats() {return getBeatsAt(playbackPosition.asSeconds());};
float getBeatsAt(float seconds) {return ((seconds+fumen.offset)/60.f)* fumen.BPM;};
float getTicks() {return getTicksAt(playbackPosition.asSeconds());};
float getTicksAt(float seconds) {
if (selectedChart) {
return getBeatsAt(seconds)*selectedChart->getResolution();
} else {
return getBeatsAt(seconds)*240.f;
}
}
float getSecondsAt(int tick) {
if (selectedChart) {
return (60.f * tick)/(fumen.BPM * selectedChart->getResolution()) - fumen.offset;
} else {
return (60.f * tick)/(fumen.BPM * 240.f) - fumen.offset;
}
}
void reloadFromFumen();
void reloadMusic();
@ -42,6 +60,11 @@ public:
void displayPlaybackStatus();
void displayTimeline();
bool playBeatTick;
bool playNoteTick;
std::vector<Note> getVisibleNotes();
explicit EditorState(Fumen& fumen);
};

View File

@ -2,6 +2,9 @@
// Created by Syméon on 17/08/2017.
//
#include <cmath>
#include <sstream>
#include <iomanip>
#include "Marker.h"
Marker::Marker(std::string folder) {
@ -41,11 +44,48 @@ Marker::Marker(std::string folder) {
}
}
sf::Texture Marker::getSprite(Etat etat, int frame) {
std::optional<sf::Texture> Marker::getSprite(MarkerEndingState state, float seconds) {
std::ostringstream frameName;
int frame = static_cast<int>((seconds*30.f+16.f));
if (frame >= 0 and frame <= 15) {
frameName << "ma" << std::setfill('0') << std::setw(2) << frame;
return textures[frameName.str()];
} else {
if (state == MISS) {
if (frame >= 16 and frame <= 23) {
frameName << "ma" << std::setfill('0') << std::setw(2) << frame;
return textures[frameName.str()];
}
} else if (frame >= 16 and frame <= 32) {
switch (state) {
case EARLY:
frameName << "h1";
break;
case GOOD:
frameName << "h2";
break;
case GREAT:
frameName << "h3";
break;
case PERFECT:
frameName << "h4";
break;
default:
return {};
}
frameName << std::setfill('0') << std::setw(2) << frame-16;
return textures[frameName.str()];
}
}
return {};
}
/*
sf::Texture Marker::getSprite(MarkerEndingState state, int frame) {
int lower;
int upper;
switch(etat) {
switch(state) {
case MISS:
lower = 16;
upper = 32;
@ -61,8 +101,7 @@ sf::Texture Marker::getSprite(Etat etat, int frame) {
}
std::string tex_key;
switch (etat) {
case APPROCHE:
switch (state) {
case MISS:
tex_key += "ma";
break;
@ -86,3 +125,4 @@ sf::Texture Marker::getSprite(Etat etat, int frame) {
return textures[tex_key+std::to_string(frame)];
}
*/

View File

@ -11,8 +11,7 @@
#include <SFML/Graphics.hpp>
#include <map>
enum Etat {
APPROCHE,
enum MarkerEndingState {
MISS,
EARLY,
GOOD,
@ -25,7 +24,7 @@ class Marker {
public:
Marker(std::string folder = "mk0013");
sf::Texture getSprite(Etat etat, int frame);
std::optional<sf::Texture> getSprite(MarkerEndingState state, float seconds);
private:

View File

@ -5,7 +5,7 @@
#include "Widgets.h"
#include "Toolbox.h"
Ecran_attente::Ecran_attente() : gris_de_fond(sf::Color(38,38,38)) {
Widgets::Ecran_attente::Ecran_attente() : gris_de_fond(sf::Color(38,38,38)) {
if(!tex_FEIS_logo.loadFromFile("assets/textures/FEIS_logo.png"))
{
@ -17,7 +17,7 @@ Ecran_attente::Ecran_attente() : gris_de_fond(sf::Color(38,38,38)) {
}
void Ecran_attente::render(sf::RenderWindow& window) {
void Widgets::Ecran_attente::render(sf::RenderWindow& window) {
// effacement de la fenêtre en noir
window.clear(gris_de_fond);
@ -27,9 +27,7 @@ void Ecran_attente::render(sf::RenderWindow& window) {
window.draw(FEIS_logo);
}
Playfield::Playfield() {
marker = Marker();
Widgets::Playfield::Playfield() {
if (!button.loadFromFile(button_path,{0,0,192,192})) {
std::cerr << "Unable to load texture " << button_path;
throw std::runtime_error("Unable to load texture " + button_path);
@ -39,27 +37,3 @@ Playfield::Playfield() {
throw std::runtime_error("Unable to load texture " + button_path);
}
}
void Playfield::render(sf::RenderWindow &window, EditorState& editorState) {
ImGui::SetNextWindowSize(ImVec2(400,400),ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(0,0),ImVec2(FLT_MAX,FLT_MAX),Toolbox::CustomConstraints::ContentSquare);
ImGui::Begin("Playfield",&editorState.showPlayfield,ImGuiWindowFlags_NoScrollbar);
{
float squareSize = ImGui::GetWindowSize().x / 4.f;
float TitlebarHeight = ImGui::GetWindowSize().y - ImGui::GetWindowSize().x;
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
ImGui::PushID(x+4*y);
ImGui::SetCursorPos({x*squareSize,TitlebarHeight + y*squareSize});
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(0,0,0,0));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(0,0,1.f,0.1f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(0,0,1.f,0.5f));
ImGui::ImageButton(button,{squareSize,squareSize},0);
ImGui::PopStyleColor(3);
ImGui::PopID();
}
}
}
ImGui::End();
}

View File

@ -2,43 +2,41 @@
// Created by Syméon on 17/08/2017.
//
#ifndef FEIS_SCREEN_H
#define FEIS_SCREEN_H
#pragma once
#include <SFML/Graphics.hpp>
#include <imgui.h>
#include <imgui-SFML.h>
#include "Marker.h"
#include "EditorState.h"
class Ecran_attente {
namespace Widgets {
class Ecran_attente {
public:
public:
Ecran_attente();
void render(sf::RenderWindow &window);
Ecran_attente();
void render(sf::RenderWindow &window);
private:
private:
sf::Color gris_de_fond;
sf::Texture tex_FEIS_logo;
sf::Sprite FEIS_logo;
sf::Color gris_de_fond;
sf::Texture tex_FEIS_logo;
sf::Sprite FEIS_logo;
};
};
class Playfield {
class Playfield {
public:
public:
Playfield();
void render(sf::RenderWindow &window, EditorState& editorState);
Playfield();
Marker marker;
sf::Texture button;
sf::Texture button_pressed;
Marker marker;
MarkerEndingState markerEndingState;
sf::Texture button;
sf::Texture button_pressed;
private:
std::string button_path = "assets/textures/edit_textures/game_front_edit_tex_1.tex.png";
};
#endif //FEIS_SCREEN_H
private:
std::string button_path = "assets/textures/edit_textures/game_front_edit_tex_1.tex.png";
};
}

View File

@ -22,9 +22,25 @@ int main(int argc, char** argv) {
IO.Fonts->AddFontFromFileTTF("assets/fonts/NotoSans-Medium.ttf", 16.f);
ImGui::SFML::UpdateFontTexture();
std::string noteTickPath = "assets/sounds/sound note tick.wav";
sf::SoundBuffer noteTick;
if (!noteTick.loadFromFile(noteTickPath)) {
std::cerr << "Unable to load sound " << noteTickPath;
throw std::runtime_error("Unable to load sound " + noteTickPath);
}
sf::Sound noteTickSound(noteTick);
Ecran_attente bg;
Playfield playfield;
bool beatTicked = false;
std::string beatTickPath = "assets/sounds/sound beat tick.wav";
sf::SoundBuffer beatTick;
if (!beatTick.loadFromFile(beatTickPath)) {
std::cerr << "Unable to load sound " << beatTickPath;
throw std::runtime_error("Unable to load sound " + beatTickPath);
}
sf::Sound beatTickSound(beatTick);
Widgets::Ecran_attente bg;
std::optional<EditorState> editorState;
sf::Clock deltaClock;
@ -41,31 +57,33 @@ int main(int argc, char** argv) {
window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height)));
break;
case sf::Event::KeyPressed:
if (event.key.code == sf::Keyboard::Space) {
if (not ImGui::GetIO().WantTextInput) {
if (editorState) {
editorState->playing = not editorState->playing;
}
/*
if (editorState and editorState->music) {
switch (editorState->music->getStatus()) {
case sf::Music::Stopped:
case sf::Music::Paused:
editorState->music->play();
break;
case sf::Music::Playing:
editorState->music->pause();
break;
}
}
*/
}
}
switch (event.key.code) {
case sf::Keyboard::F3:
if (editorState) {
editorState->playBeatTick = not editorState->playBeatTick;
}
break;
case sf::Keyboard::F4:
if (editorState) {
editorState->playNoteTick = not editorState->playNoteTick;
}
break;
case sf::Keyboard::Space:
if (not ImGui::GetIO().WantTextInput) {
if (editorState) {
editorState->playing = not editorState->playing;
}
}
break;
}
break;
}
}
sf::Time delta = deltaClock.restart();
ImGui::SFML::Update(window, delta);
// Gestion du playback
if (editorState->playing) {
editorState->playbackPosition += delta;
if (editorState->music) {
@ -84,6 +102,16 @@ int main(int argc, char** argv) {
break;
}
}
if (editorState->playBeatTick) {
if (fmodf(editorState->getBeats(),1.f) < 0.5) {
if (not beatTicked) {
beatTickSound.play();
beatTicked = true;
}
} else {
beatTicked = false;
}
}
if (editorState->playbackPosition >= editorState->chartRuntime) {
editorState->playing = false;
editorState->playbackPosition = editorState->chartRuntime;
@ -99,7 +127,7 @@ int main(int argc, char** argv) {
// Dessin du fond
if (editorState) {
if (editorState->showPlayfield) {
playfield.render(window,*editorState);
editorState->displayPlayfield();
}
if (editorState->showProperties) {
editorState->displayProperties();
@ -118,6 +146,7 @@ int main(int argc, char** argv) {
bg.render(window);
}
// TODO : Use events instead
// Gestion des Raccourcis Clavier
// Ctrl+S