mirror of
https://gitlab.com/square-game-liberation-front/F.E.I.S.git
synced 2024-11-15 03:27:41 +01:00
New features :
- Note collisions are now highlighted in red, sometimes highlights weird spots but otherwise totally serviceable as is Small fixes : - The timeline now correctly scrubs to before the song starts - Claps now do happen after rewinding with the arrow keys
This commit is contained in:
parent
ddc6ff8bb3
commit
a314f1efe5
106
EditorState.cpp
106
EditorState.cpp
@ -88,10 +88,13 @@ void EditorState::setPlaybackAndMusicPosition(sf::Time newPosition) {
|
||||
} else if (newPosition > chartRuntime) {
|
||||
newPosition = chartRuntime;
|
||||
}
|
||||
previousPos = sf::seconds(newPosition.asSeconds() - 1.f/60.f);
|
||||
playbackPosition = newPosition;
|
||||
if (music) {
|
||||
if (playbackPosition.asSeconds() >= 0 and playbackPosition < music->getDuration()) {
|
||||
music->setPlayingOffset(playbackPosition);
|
||||
} else {
|
||||
music->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,20 +108,22 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
|
||||
float squareSize = ImGui::GetWindowSize().x / 4.f;
|
||||
float TitlebarHeight = ImGui::GetWindowSize().y - ImGui::GetWindowSize().x;
|
||||
int ImGuiIndex = 0;
|
||||
|
||||
if (chart) {
|
||||
|
||||
int ImGuiIndex = 0;
|
||||
|
||||
for (auto note : visibleNotes) {
|
||||
for (auto const& note : visibleNotes) {
|
||||
|
||||
float note_offset = (playbackPosition.asSeconds() - getSecondsAt(note.getTiming()));
|
||||
auto frame = static_cast<long long int>(std::floor(note_offset * 30.f));
|
||||
int x = note.getPos() % 4;
|
||||
int y = note.getPos() / 4;
|
||||
|
||||
|
||||
if (note.getLength() == 0) {
|
||||
|
||||
// Display normal notes
|
||||
|
||||
auto t = marker.getSprite(markerEndingState, note_offset);
|
||||
|
||||
if (t) {
|
||||
@ -131,18 +136,24 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
|
||||
} else {
|
||||
|
||||
// Display long notes
|
||||
|
||||
float tail_end_in_seconds = getSecondsAt(note.getTiming() + note.getLength());
|
||||
float tail_end_offset = playbackPosition.asSeconds() - tail_end_in_seconds;
|
||||
|
||||
if (playbackPosition.asSeconds() < tail_end_in_seconds) {
|
||||
|
||||
// Before or During the long note
|
||||
|
||||
int triangle = note.getTail_pos_as_note_pos();
|
||||
|
||||
auto triangle_x = static_cast<float>(triangle % 4);
|
||||
auto triangle_y = static_cast<float>(triangle / 4);
|
||||
|
||||
AffineTransform<float> x_trans(0.0f,ticksToSeconds(note.getLength()),triangle_x, static_cast<float>(x));
|
||||
AffineTransform<float> y_trans(0.0f,ticksToSeconds(note.getLength()),triangle_y, static_cast<float>(y));
|
||||
AffineTransform<float> x_trans(0.0f, ticksToSeconds(note.getLength()), triangle_x,
|
||||
static_cast<float>(x));
|
||||
AffineTransform<float> y_trans(0.0f, ticksToSeconds(note.getLength()), triangle_y,
|
||||
static_cast<float>(y));
|
||||
triangle_x = x_trans.clampedTransform(note_offset);
|
||||
triangle_y = y_trans.clampedTransform(note_offset);
|
||||
|
||||
@ -247,7 +258,8 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
++ImGuiIndex;
|
||||
|
||||
Toolbox::displayIfHasValue(
|
||||
playfield.longNoteMarker.getSquareBackgroundTexture(note_offset, note.getTail_pos()),
|
||||
playfield.longNoteMarker.getSquareBackgroundTexture(note_offset,
|
||||
note.getTail_pos()),
|
||||
{x * squareSize, TitlebarHeight + y * squareSize},
|
||||
{squareSize, squareSize},
|
||||
ImGuiIndex
|
||||
@ -287,7 +299,7 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
|
||||
} else {
|
||||
|
||||
// Display the ending marker
|
||||
// After long note end : Display the ending marker
|
||||
if (tail_end_offset > 0.0f) {
|
||||
auto t = marker.getSprite(markerEndingState, tail_end_offset);
|
||||
if (t) {
|
||||
@ -303,7 +315,7 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
}
|
||||
}
|
||||
|
||||
// display buttons over
|
||||
// Display button grid
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
ImGui::PushID(x+4*y);
|
||||
@ -318,6 +330,83 @@ void EditorState::displayPlayfield(Marker& marker, MarkerEndingState markerEndin
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
// Check for collisions then display them
|
||||
if (chart) {
|
||||
|
||||
std::array<std::vector<Note>, 16> notes_per_position = {};
|
||||
std::array<bool, 16> collisions = {};
|
||||
|
||||
for (auto const& note : visibleNotes) {
|
||||
notes_per_position[note.getPos()].push_back(note);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
|
||||
int size = notes_per_position.at(i).size();
|
||||
|
||||
if (size > 1) {
|
||||
|
||||
collisions.at(i) = true;
|
||||
|
||||
} else if (size == 1) {
|
||||
|
||||
auto note = notes_per_position.at(i).at(0);
|
||||
|
||||
int lower_bound = static_cast<int>(getTicksAt(getSecondsAt(note.getTiming())-1.f));
|
||||
int upper_bound = static_cast<int>(getTicksAt(getSecondsAt(note.getTiming())+1.f));
|
||||
|
||||
auto current_note_it = chart->ref.Notes.find(note);
|
||||
if (current_note_it != chart->ref.Notes.end()) {
|
||||
// backwards
|
||||
if (current_note_it != chart->ref.Notes.begin()) {
|
||||
auto other_note_it = current_note_it;
|
||||
--other_note_it;
|
||||
while (other_note_it != chart->ref.Notes.begin()) {
|
||||
if (other_note_it->getPos() == note.getPos()) {
|
||||
if (other_note_it->getTiming() > lower_bound) {
|
||||
collisions.at(i) = true;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
--other_note_it;
|
||||
}
|
||||
}
|
||||
|
||||
// forwards
|
||||
auto other_note_it = current_note_it;
|
||||
++other_note_it;
|
||||
while (other_note_it != chart->ref.Notes.end()) {
|
||||
if (other_note_it->getPos() == note.getPos()) {
|
||||
if (other_note_it->getTiming() < upper_bound) {
|
||||
collisions.at(i) = true;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++other_note_it;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
collisions.at(i) = false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (collisions.at(i)) {
|
||||
int x = i%4;
|
||||
int y = i/4;
|
||||
ImGui::SetCursorPos({x * squareSize, TitlebarHeight + y * squareSize});
|
||||
ImGui::PushID(ImGuiIndex);
|
||||
ImGui::Image(playfield.note_collision, {squareSize, squareSize});
|
||||
ImGui::PopID();
|
||||
++ImGuiIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
@ -446,7 +535,6 @@ void EditorState::displayTimeline() {
|
||||
ImGui::SetCursorPos({0,0});
|
||||
if(ImGui::VSliderFloat("",ImGui::GetContentRegionMax(),&slider_pos,0.f,1.f,"")) {
|
||||
setPlaybackAndMusicPosition(sf::seconds(scroll.backwards_transform(slider_pos)));
|
||||
this->lastTimingTicked = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,4 +38,9 @@ Widgets::Playfield::Playfield() {
|
||||
throw std::runtime_error("Unable to load texture " + button_path);
|
||||
}
|
||||
button_pressed.setSmooth(true);
|
||||
if (!note_collision.loadFromFile(button_path,{576,0,192,192})) {
|
||||
std::cerr << "Unable to load texture " << button_path;
|
||||
throw std::runtime_error("Unable to load texture " + button_path);
|
||||
}
|
||||
note_collision.setSmooth(true);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ namespace Widgets {
|
||||
Playfield();
|
||||
sf::Texture button;
|
||||
sf::Texture button_pressed;
|
||||
sf::Texture note_collision;
|
||||
LNMarker longNoteMarker;
|
||||
|
||||
private:
|
||||
|
24
main.cpp
24
main.cpp
@ -10,7 +10,6 @@
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// TODO : Highlight crossing notes
|
||||
// TODO : Different noise for chords
|
||||
// TODO : Density graph on the timeline
|
||||
// TODO : Pitch control (playback speed factor)
|
||||
@ -96,9 +95,13 @@ int main(int argc, char** argv) {
|
||||
if (editorState->musicVolume < 10) {
|
||||
editorState->musicVolume++;
|
||||
editorState->updateMusicVolume();
|
||||
std::stringstream ss;
|
||||
ss << "Music Volume : " << editorState->musicVolume*10 << "%";
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(ss.str()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO : there is something weird with the way I'm doing this, going back with the key often makes it go back twice
|
||||
if (editorState and editorState->chart) {
|
||||
float floatTicks = editorState->getTicks();
|
||||
int prevTick = static_cast<int>(floorf(floatTicks));
|
||||
@ -119,6 +122,9 @@ int main(int argc, char** argv) {
|
||||
if (editorState->musicVolume > 0) {
|
||||
editorState->musicVolume--;
|
||||
editorState->updateMusicVolume();
|
||||
std::stringstream ss;
|
||||
ss << "Music Volume : " << editorState->musicVolume*10 << "%";
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(ss.str()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -134,11 +140,17 @@ int main(int argc, char** argv) {
|
||||
case sf::Keyboard::Left:
|
||||
if (editorState and editorState->chart) {
|
||||
editorState->snap = Toolbox::getPreviousDivisor(editorState->chart->ref.getResolution(),editorState->snap);
|
||||
std::stringstream ss;
|
||||
ss << "Snap : " << Toolbox::toOrdinal(4*editorState->snap);
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(ss.str()));
|
||||
}
|
||||
break;
|
||||
case sf::Keyboard::Right:
|
||||
if (editorState and editorState->chart) {
|
||||
editorState->snap = Toolbox::getNextDivisor(editorState->chart->ref.getResolution(),editorState->snap);
|
||||
std::stringstream ss;
|
||||
ss << "Snap : " << Toolbox::toOrdinal(4*editorState->snap);
|
||||
notificationsQueue.push(std::make_shared<TextNotification>(ss.str()));
|
||||
}
|
||||
break;
|
||||
case sf::Keyboard::F3:
|
||||
@ -177,6 +189,7 @@ int main(int argc, char** argv) {
|
||||
case sf::Keyboard::S:
|
||||
if (event.key.control) {
|
||||
ESHelper::save(*editorState);
|
||||
notificationsQueue.push(std::make_shared<TextNotification>("Saved file"));
|
||||
}
|
||||
break;
|
||||
case sf::Keyboard::Y:
|
||||
@ -249,14 +262,11 @@ int main(int argc, char** argv) {
|
||||
for (auto note : editorState->visibleNotes) {
|
||||
float noteTiming = editorState->getSecondsAt(note.getTiming());
|
||||
if (noteTiming >= editorState->previousPos.asSeconds()
|
||||
and noteTiming <= editorState->playbackPosition.asSeconds()
|
||||
and note.getTiming() > editorState->lastTimingTicked) {
|
||||
and noteTiming <= editorState->playbackPosition.asSeconds()) {
|
||||
noteTickSound.play();
|
||||
editorState->lastTimingTicked = note.getTiming();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
editorState->lastTimingTicked = -1;
|
||||
}
|
||||
if (editorState->playbackPosition >= editorState->chartRuntime) {
|
||||
editorState->playing = false;
|
||||
@ -314,7 +324,7 @@ int main(int argc, char** argv) {
|
||||
if (c) {
|
||||
editorState->showNewChartDialog = false;
|
||||
if(editorState->fumen.Charts.try_emplace(c->dif_name,*c).second) {
|
||||
editorState->chart->ref = editorState->fumen.Charts[c->dif_name];
|
||||
editorState->chart.emplace(editorState->fumen.Charts.at(c->dif_name));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user