You can subscribe to this list here.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(25) |
Jul
(288) |
Aug
(119) |
Sep
(31) |
Oct
(59) |
Nov
(458) |
Dec
(359) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(268) |
Feb
(26) |
Mar
(36) |
Apr
(48) |
May
(119) |
Jun
(37) |
Jul
(173) |
Aug
(429) |
Sep
(137) |
Oct
(156) |
Nov
(59) |
Dec
(45) |
| 2011 |
Jan
(398) |
Feb
(257) |
Mar
(49) |
Apr
(5) |
May
(34) |
Jun
(11) |
Jul
(38) |
Aug
(12) |
Sep
(1) |
Oct
(49) |
Nov
(5) |
Dec
(10) |
| 2012 |
Jan
(21) |
Feb
(32) |
Mar
(20) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(173) |
Aug
|
Sep
(25) |
Oct
(6) |
Nov
(44) |
Dec
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 16:27:15
|
Module: editor
Branch: master
Commit: 439a1387f8cd412bd79f2957ce4d1274a5c854de
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 18:26:09 2011 +0200
Implement an Operation combiner.
Allows grouping several Operations to a single undo-step.
---
editorapp.cc | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index cf2881e..89374e1 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -185,6 +185,11 @@ void EditorApp::on_actionUndo_triggered()
{
if (opStack.top().op() == "BLOCK")
return;
+ else if (opStack.top().op() == "COMBINER") {
+ int count = opStack.top().i(1);
+ for (int i = 0; i < count; ++i) opStack.pop();
+ // TODO: Redo handling
+ }
// TODO: Move popped to redo stack
opStack.pop();
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 16:27:13
|
Module: editor
Branch: master
Commit: db637e0ff60222a80bc90cdbc78e2db6914ce7cf
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 18:25:17 2011 +0200
Implement split action using Operations. Doesn't crash anymore.
Also some tweaks to initial note creation.
---
notegraphwidget.cc | 51 +++++++++++++++++++++++----------------------------
1 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 2cd67e0..f27487b 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -80,12 +80,14 @@ void NoteGraphWidget::setLyrics(QString lyrics)
QTextStream ts(&lyrics, QIODevice::ReadOnly);
clear();
+ bool first = true;
while (!ts.atEnd()) {
QString word;
ts >> word;
if (!word.isEmpty()) {
- m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, n2px(m_lowestNote + 12 * m_octaves - 6))));
+ m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, n2px(m_lowestNote + 12 * m_octaves - 6)), QSize(), !first));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
+ first = false;
}
}
@@ -103,12 +105,14 @@ void NoteGraphWidget::setLyrics(const VocalTrack &track)
std::cout << "--: " << m_octaves << " " << m_lowestNote << std::endl;
setFixedSize(s2px(track.endTime), ndiff2px(m_octaves*12));
+ bool first = true;
const Notes ¬es = track.notes;
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
if (it->type == Note::NORMAL || it->type == Note::GOLDEN || it->type == Note::FREESTYLE) {
m_notes.push_back(new NoteLabel(*it, this, QPoint(s2px(it->begin), n2px(it->note)),
- QSize(s2px(it->length()), 0), false));
+ QSize(s2px(it->length()), 0), !first));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
+ first = false;
}
}
@@ -118,16 +122,12 @@ void NoteGraphWidget::setLyrics(const VocalTrack &track)
void NoteGraphWidget::finalizeNewLyrics()
{
// Set first and last to non-floating and put the last one to the end of the song
- if (m_notes.size() > 0) {
- Operation floatop1("FLOATING"); floatop1 << (int)0 << false;
- doOperation(floatop1);
- if (m_notes.size() > 1) {
- Operation floatop2("FLOATING"); floatop2 << (int)m_notes.size()-1 << false;
- doOperation(floatop2);
- Operation moveop("MOVE");
- moveop << (int)m_notes.size()-1 << width() - m_notes.back()->width() << m_notes.back()->y();
- doOperation(moveop);
- }
+ if (m_notes.size() > 1) {
+ Operation floatop("FLOATING"); floatop << (int)m_notes.size()-1 << false;
+ doOperation(floatop);
+ Operation moveop("MOVE");
+ moveop << (int)m_notes.size()-1 << width() - m_notes.back()->width() << m_notes.back()->y();
+ doOperation(moveop);
// Make sure there is enough room
setFixedWidth(std::max<int>(width(), m_notes.size() * NoteLabel::min_width + m_notes.front()->width() * 2));
}
@@ -234,22 +234,17 @@ void NoteGraphWidget::mousePressEvent(QMouseEvent *event)
QString secondst = child->lyric().right(child->lyric().length() - cutpos);
int w1 = relRatio * child->width();
- // Create new labels
- NoteLabel *newLabel1 = new NoteLabel(Note(firstst.toStdString()), this, child->pos(), QSize(w1, 0));
- NoteLabel *newLabel2 = new NoteLabel(Note(secondst.toStdString()), this, newLabel1->pos() + QPoint(newLabel1->width(), 0), QSize(child->width() - w1, 0));
- // Insert them to the list removing the old one
- NoteLabels::iterator it = std::find(m_notes.begin(), m_notes.end(), child);
- if (it != m_notes.end()) {
- m_notes.insert(it, newLabel1);
- m_notes.insert(it, newLabel2);
- m_notes.erase(it);
- } else {
- m_notes.push_back(newLabel1);
- m_notes.push_back(newLabel2);
- }
-
- // Delete the old one
- child->close();
+ // Create operations for adding the new labels and deleting the old one
+ int id = getNoteLabelId(child);
+ Operation new1("NEW"), new2("NEW");
+ new1 << id << firstst << child->pos().x() << child->pos().y() << w1 << 0 << child->isFloating();
+ new2 << id+1 << secondst << child->pos().x() + w1 << child->pos().y() << child->width() - w1 << 0 << child->isFloating();
+ Operation del("DEL"); del << id+2;
+ Operation combiner("COMBINER"); combiner << 3; // This will combine the previous ones to one undo action
+ std::cout << new1.dump() << std::endl << new2.dump() << std::endl << del.dump() << std::endl;
+ doOperation(new1); doOperation(new2); doOperation(del); doOperation(combiner);
+
+ m_selectedNote = NULL;
}
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 16:27:10
|
Module: editor
Branch: master
Commit: 6d5699bd0cabb1eed1c5facf3efef3e1ccf89b0b
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 17:41:57 2011 +0200
Fix & make delete undoable.
---
notegraphwidget.cc | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 8f50644..2cd67e0 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -356,10 +356,10 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
break;
case Qt::Key_Delete: // Delete selected note
if (m_selectedNote) {
- // FIXME: Erase from the list!!!
- m_selectedNote->close();
+ Operation op("DEL");
+ op << getNoteLabelId(m_selectedNote);
+ doOperation(op);
m_selectedNote = NULL;
- updateNotes();
}
break;
default:
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 15:38:51
|
Module: editor
Branch: master
Commit: 4998a446affcffa6ae3b61a59e4cc1a2764d98d6
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 17:37:29 2011 +0200
Fix a line deleted by mistake.
---
notegraphwidget.cc | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 202b561..8f50644 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -10,6 +10,7 @@
namespace {
static Operation opFromNote(const NoteLabel& note, int id) {
Operation op("NEW");
+ op << id << note.lyric() << note.x() << note.y() << note.width() << note.height() << note.isFloating();
return op;
}
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 14:12:28
|
Module: editor
Branch: master
Commit: 5646d8e9b0164433ec9cc1e52ff3ae19aa9667f0
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 16:11:41 2011 +0200
Framework for exporting song to various formats.
---
editor.ui | 6 ------
editorapp.cc | 36 +++++++++++++++++++++++++++++++++++-
editorapp.hh | 3 +++
song.hh | 18 +++++++++++++++++-
songwriter-ini.cc | 29 +++++++++++++++++++++++++++++
songwriter-txt.cc | 19 +++++++++++++++++++
songwriter-xml .cc | 20 ++++++++++++++++++++
songwriter.hh | 37 +++++++++++++++++++++++++++++++++++++
8 files changed, 160 insertions(+), 8 deletions(-)
diff --git a/editor.ui b/editor.ui
index f62336f..c43993b 100644
--- a/editor.ui
+++ b/editor.ui
@@ -464,17 +464,11 @@
</property>
</action>
<action name="actionUltraStarTXT">
- <property name="enabled">
- <bool>false</bool>
- </property>
<property name="text">
<string>&UltraStar TXT</string>
</property>
</action>
<action name="actionFoFMIDI">
- <property name="enabled">
- <bool>false</bool>
- </property>
<property name="text">
<string>&FoF MIDI</string>
</property>
diff --git a/editorapp.cc b/editorapp.cc
index 59504fa..cf2881e 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -3,6 +3,7 @@
#include "editorapp.hh"
#include "notelabel.hh"
#include "notegraphwidget.hh"
+#include "songwriter.hh"
EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
@@ -104,7 +105,7 @@ void EditorApp::on_actionNew_triggered()
void EditorApp::on_actionOpen_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
- "",
+ QDir::homePath(),
tr("All supported formats (*.TBD!!! *.xml *.mid *.ini *.txt)") + ";;" +
tr("Project files (*.TBD!!!)") + ";;" + // FIXME: Project file extension
tr("SingStar XML (*.xml)") + ";;" +
@@ -128,6 +129,39 @@ void EditorApp::on_actionOpen_triggered()
}
}
+void EditorApp::on_actionSingStarXML_triggered()
+{
+ QString path = QFileDialog::getExistingDirectory(this, tr("Export SingStar XML"), QDir::homePath());
+ if (!path.isNull()) {
+ try { SingStarXMLWriter(*song.data(), path); }
+ catch (const std::exception& e) {
+ QMessageBox::critical(this, tr("Error exporting song!"), e.what());
+ }
+ }
+}
+
+void EditorApp::on_actionUltraStarTXT_triggered()
+{
+ QString path = QFileDialog::getExistingDirectory(this, tr("Export UltraStar TXT"), QDir::homePath());
+ if (!path.isNull()) {
+ try { UltraStarTXTWriter(*song.data(), path); }
+ catch (const std::exception& e) {
+ QMessageBox::critical(this, tr("Error exporting song!"), e.what());
+ }
+ }
+}
+
+void EditorApp::on_actionFoFMIDI_triggered()
+{
+ QString path = QFileDialog::getExistingDirectory(this, tr("Export FoF MIDI"), QDir::homePath());
+ if (!path.isNull()) {
+ try { FoFMIDIWriter(*song.data(), path); }
+ catch (const std::exception& e) {
+ QMessageBox::critical(this, tr("Error exporting song!"), e.what());
+ }
+ }
+}
+
void EditorApp::on_actionExit_triggered()
{
// TODO: Check if a save prompt is in order
diff --git a/editorapp.hh b/editorapp.hh
index 4a66eed..9a3b53a 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -25,6 +25,9 @@ public slots:
// File menu
void on_actionNew_triggered();
void on_actionOpen_triggered();
+ void on_actionSingStarXML_triggered();
+ void on_actionUltraStarTXT_triggered();
+ void on_actionFoFMIDI_triggered();
void on_actionExit_triggered();
// Edit menu
diff --git a/song.hh b/song.hh
index 43903fb..dfacd36 100644
--- a/song.hh
+++ b/song.hh
@@ -77,7 +77,23 @@ class Song {
}
}
}
- };
+ }
+ VocalTrack getVocalTrack(std::string vocalTrack = TrackName::LEAD_VOCAL) const {
+ if(vocalTracks.find(vocalTrack) != vocalTracks.end()) {
+ return vocalTracks.find(vocalTrack)->second;
+ } else {
+ if(vocalTracks.find(TrackName::LEAD_VOCAL) != vocalTracks.end()) {
+ return vocalTracks.find(TrackName::LEAD_VOCAL)->second;
+ } else {
+ if(!vocalTracks.empty()) {
+ return vocalTracks.begin()->second;
+ } else {
+ return dummyVocal;
+ }
+ }
+ }
+ }
+
std::vector<std::string> getVocalTrackNames() {
std::vector<std::string> result;
for (VocalTracks::const_iterator it = vocalTracks.begin(); it != vocalTracks.end(); ++it) {
diff --git a/songwriter-ini.cc b/songwriter-ini.cc
new file mode 100644
index 0000000..b9b1cf1
--- /dev/null
+++ b/songwriter-ini.cc
@@ -0,0 +1,29 @@
+#include "songwriter.hh"
+#include <fstream>
+#include <iostream>
+
+void FoFMIDIWriter::writeMIDI() {
+ throw std::runtime_error("MIDI export is not implemented.");
+ std::ofstream f((path + "notes.mid").c_str(), std::ios::binary);
+ // FIXME: The following is just an example and doesn't actually output MID format
+ char buf[1024] = {};
+ Notes const& notes = s.getVocalTrack().notes;
+ std::cout << notes.size() << std::endl;
+ for (unsigned int i = 0; i < notes.size(); ++i) {
+ Note const& n = notes[i];
+ buf[0] = 0xFF;
+ buf[1] = n.note; // MIDI note value
+ // Others are n.begin, n.end, n.type etc. (see notes.hh)
+ f.write(buf, 1024);
+ }
+}
+
+void FoFMIDIWriter::writeINI() {
+ std::ofstream f((path + "song.ini").c_str(), std::ios::binary);
+ f << "[song]\n";
+ f << "name = " << s.title << std::endl;
+ f << "artist = " << s.artist << std::endl;
+ f << "genre = " << s.genre << std::endl;
+ f << "year = " << s.year << std::endl;
+}
+
diff --git a/songwriter-txt.cc b/songwriter-txt.cc
new file mode 100644
index 0000000..ffa6e7e
--- /dev/null
+++ b/songwriter-txt.cc
@@ -0,0 +1,19 @@
+#include "songwriter.hh"
+#include <fstream>
+#include <iostream>
+
+void UltraStarTXTWriter::writeTXT() {
+ throw std::runtime_error("TXT export is not implemented.");
+ std::ofstream f((path + "notes.txt").c_str(), std::ios::binary);
+ // FIXME: The following is just an example and doesn't actually output TXT format
+ char buf[1024] = {};
+ Notes const& notes = s.getVocalTrack().notes;
+ std::cout << notes.size() << std::endl;
+ for (unsigned int i = 0; i < notes.size(); ++i) {
+ Note const& n = notes[i];
+ buf[0] = 0xFF;
+ buf[1] = n.note; // MIDI note value
+ // Others are n.begin, n.end, n.type etc. (see notes.hh)
+ f.write(buf, 1024);
+ }
+}
diff --git a/songwriter-xml .cc b/songwriter-xml .cc
new file mode 100644
index 0000000..71d2581
--- /dev/null
+++ b/songwriter-xml .cc
@@ -0,0 +1,20 @@
+#include "songwriter.hh"
+#include <fstream>
+#include <iostream>
+
+void SingStarXMLWriter::writeXML() {
+ throw std::runtime_error("XML export is not implemented.");
+ // FIXME: Use QtXML
+ std::ofstream f((path + "notes.xml").c_str(), std::ios::binary);
+ // FIXME: The following is just an example and doesn't actually output XML format
+ char buf[1024] = {};
+ Notes const& notes = s.getVocalTrack().notes;
+ std::cout << notes.size() << std::endl;
+ for (unsigned int i = 0; i < notes.size(); ++i) {
+ Note const& n = notes[i];
+ buf[0] = 0xFF;
+ buf[1] = n.note; // MIDI note value
+ // Others are n.begin, n.end, n.type etc. (see notes.hh)
+ f.write(buf, 1024);
+ }
+}
diff --git a/songwriter.hh b/songwriter.hh
new file mode 100644
index 0000000..3d06e60
--- /dev/null
+++ b/songwriter.hh
@@ -0,0 +1,37 @@
+#include "song.hh"
+#include <QDir>
+#include <fstream>
+
+struct SongWriter
+{
+ SongWriter(const Song& s_, const QString& path_)
+ : s(s_), path(path_.toStdString()) { QDir dir; dir.mkpath(path_); }
+ const Song& s;
+ std::string path;
+};
+
+struct SingStarXMLWriter: public SongWriter
+{
+ SingStarXMLWriter(const Song& s_, const QString& path_)
+ : SongWriter(s_, path_) { writeXML(); }
+private:
+ void writeXML();
+};
+
+struct UltraStarTXTWriter: public SongWriter
+{
+ UltraStarTXTWriter(const Song& s_, const QString& path_)
+ : SongWriter(s_, path_) { writeTXT(); }
+private:
+ void writeTXT();
+};
+
+struct FoFMIDIWriter: public SongWriter
+{
+ FoFMIDIWriter(const Song& s_, const QString& path_)
+ : SongWriter(s_, path_) { writeINI(); writeMIDI(); }
+
+private:
+ void writeINI();
+ void writeMIDI();
+};
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 13:17:52
|
Module: editor
Branch: master
Commit: 1fc438555df7d039b4d33431fac1ce1008c267ad
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 15:16:53 2011 +0200
Note loading now determines the needed viewport.
Makes US notes visible again.
---
editorapp.cc | 4 ++--
notegraphwidget.cc | 17 ++++++++++++++---
notegraphwidget.hh | 4 +++-
notelabel.cc | 1 -
4 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index e3fc389..59504fa 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -55,7 +55,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
void EditorApp::operationDone(const Operation &op)
{
- std::cout << "Push op: " << op.dump() << std::endl;
+ //std::cout << "Push op: " << op.dump() << std::endl;
opStack.push(op);
}
@@ -117,7 +117,7 @@ void EditorApp::on_actionOpen_triggered()
QFileInfo finfo(fileName);
try {
song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
- noteGraph->setLyrics(song->getVocalTrack().notes);
+ noteGraph->setLyrics(song->getVocalTrack());
updateSongMeta(true);
noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
ui.tabWidget->setCurrentIndex(1); // Swicth to song properties tab
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 7a6e99b..202b561 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -10,7 +10,6 @@
namespace {
static Operation opFromNote(const NoteLabel& note, int id) {
Operation op("NEW");
- op << id << note.lyric() << note.x() << note.y() << note.width() << note.height() << note.isFloating();
return op;
}
}
@@ -40,7 +39,7 @@ NoteGraphWidget::NoteGraphWidget(QWidget *parent)
progress.setValue(width);
// FIXME: Width should come from song length * pixPerSec
- setFixedSize(std::max(width, (unsigned)1024), noteYStep * 12 * m_octaves);
+ setFixedSize(std::max(width, (unsigned)1024), h());
setFocusPolicy(Qt::StrongFocus);
setWhatsThis(tr("Note graph that displays the song notes and allows you to manipulate them."));
@@ -92,9 +91,18 @@ void NoteGraphWidget::setLyrics(QString lyrics)
finalizeNewLyrics();
}
-void NoteGraphWidget::setLyrics(const Notes ¬es)
+void NoteGraphWidget::setLyrics(const VocalTrack &track)
{
clear();
+
+ // Determine how many octaves are needed and what is the base line
+ int diff = track.noteMax - track.noteMin;
+ m_octaves = std::ceil(diff / 12.0f) + 1;
+ m_lowestNote = clamp(track.noteMin - 6, 0, 1000);
+ std::cout << "--: " << m_octaves << " " << m_lowestNote << std::endl;
+ setFixedSize(s2px(track.endTime), ndiff2px(m_octaves*12));
+
+ const Notes ¬es = track.notes;
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
if (it->type == Note::NORMAL || it->type == Note::GOLDEN || it->type == Note::FREESTYLE) {
m_notes.push_back(new NoteLabel(*it, this, QPoint(s2px(it->begin), n2px(it->note)),
@@ -411,6 +419,9 @@ int NoteGraphWidget::s2px(double sec) const {
double NoteGraphWidget::px2s(int px) const {
return px / m_pixPerSec;
}
+int NoteGraphWidget::ndiff2px(int dn) const {
+ return dn * noteYStep;
+}
int NoteGraphWidget::n2px(int note) const {
int highestNote = m_lowestNote + 12 * m_octaves;
return (highestNote - note) * noteYStep;
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index 065229d..4d40379 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -21,7 +21,7 @@ public:
void clear();
void setLyrics(QString lyrics);
- void setLyrics(const Notes ¬es);
+ void setLyrics(const VocalTrack &track);
void updateNotes();
void selectNote(NoteLabel* note);
@@ -33,8 +33,10 @@ public:
int s2px(double sec) const;
double px2s(int px) const;
+ int ndiff2px(int dn) const;
int n2px(int note) const;
int px2n(int px) const;
+ int h() const { return 12 * m_octaves * noteYStep; }
signals:
diff --git a/notelabel.cc b/notelabel.cc
index 9705d65..c2d08ce 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -17,7 +17,6 @@ NoteLabel::NoteLabel(const Note ¬e, QWidget *parent, const QPoint &position,
createPixmap(size);
if (!position.isNull())
move(position);
- std::cout << x() << " " << y() << " " << width() << std::endl;
setMouseTracking(true);
setMinimumSize(min_width, 10);
setAttribute(Qt::WA_DeleteOnClose);
|
|
From: Yoda-JM <yo...@us...> - 2011-01-13 12:52:26
|
Module: editor
Branch: master
Commit: bca162e06f489ac6c5567b0cd6bc7feda9e3b7d8
Author: Vincent Le Ligeour <yo...@us...>
Date: Thu Jan 13 13:51:54 2011 +0100
Added more visualization hacks
---
pitchvis.cc | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/pitchvis.cc b/pitchvis.cc
index 441db92..bc97bca 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -67,18 +67,17 @@ PitchVis::PitchVis(std::string const& filename): height(1024) {
p.r = 0.0; p.g = 1.0; p.b = 0.0;
break;
case 1:
- p.r = 0.0; p.g = 0.5; p.b = 0.0;
+ p.r = 0.15; p.g = 0.15; p.b = 0.0;
break;
case 2:
- p.r = 0.0; p.g = 0.3; p.b = 0.0;
+ p.r = 0.05; p.g = 0.05; p.b = 0.0;
break;
}
- (*this)(x, y) += p;
- p.r *= 0.5;
- p.g *= 0.5;
- p.b *= 0.5;
- (*this)(x, y + 1) += p;
- (*this)(x, y - 1) += p;
+ (*this)(x, y) = p;
+ for(int j = -3 ; j < 4 ; ++j) {
+ if(y + j < 0 || y + j >= height) continue;
+ (*this)(x, y + j) = p;
+ }
++i;
}
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 12:32:04
|
Module: editor
Branch: master
Commit: da9a210331238694c1c0bfcf7a7a99bf702c8b5d
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 14:30:16 2011 +0200
Song metadata stuff.
* New textboxes: genre & year
* Textboxes are populated when loading US TXT file
* Changes in the textboxes are updated to the Song class
---
editor.ui | 41 ++++++++++++++++++++++++++++++++++++++++-
editorapp.cc | 36 +++++++++++++++++++++++++++++++++++-
editorapp.hh | 6 ++++++
song.hh | 6 ++++--
4 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/editor.ui b/editor.ui
index 8165720..f62336f 100644
--- a/editor.ui
+++ b/editor.ui
@@ -220,7 +220,7 @@
<attribute name="whatsThis">
<string>This tab lets you to configure the song metadata.</string>
</attribute>
- <layout class="QFormLayout" name="formLayout">
+ <layout class="QGridLayout" name="gridLayout_5" columnstretch="10,70,10,20">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@@ -231,6 +231,19 @@
<item row="0" column="1">
<widget class="QLineEdit" name="txtTitle"/>
</item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Genre</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QLineEdit" name="txtGenre"/>
+ </item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
@@ -241,6 +254,19 @@
<item row="1" column="1">
<widget class="QLineEdit" name="txtArtist"/>
</item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_10">
+ <property name="text">
+ <string>Year</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QLineEdit" name="txtYear"/>
+ </item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
@@ -255,6 +281,19 @@
</property>
</widget>
</item>
+ <item row="3" column="1">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
</widget>
diff --git a/editorapp.cc b/editorapp.cc
index 7eb9a07..e3fc389 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -35,6 +35,8 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
updateNoteInfo(NULL);
+ song.reset(new Song);
+
// Some icons to menus to make them prettier
ui.actionNew->setIcon(QIcon::fromTheme("document-new"));
ui.actionOpen->setIcon(QIcon::fromTheme("document-open"));
@@ -116,6 +118,9 @@ void EditorApp::on_actionOpen_triggered()
try {
song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
noteGraph->setLyrics(song->getVocalTrack().notes);
+ updateSongMeta(true);
+ noteGraph->doOperation(Operation("BLOCK")); // Lock the undo stack
+ ui.tabWidget->setCurrentIndex(1); // Swicth to song properties tab
} catch (const std::exception& e) {
QMessageBox::critical(this, tr("Error loading file!"), e.what());
}
@@ -174,7 +179,7 @@ void EditorApp::on_actionMusicFile_triggered()
if (!fileName.isNull()) {
ui.valMusicFile->setText(fileName);
- ui.tabWidget->setCurrentIndex(1);
+ ui.tabWidget->setCurrentIndex(1); // Swicth to song properties tab
// TODO: Do something with the file
}
}
@@ -232,6 +237,35 @@ void EditorApp::on_actionAbout_triggered()
);
}
+void EditorApp::updateSongMeta(bool readFromSongToUI)
+{
+ if (!song) return;
+ // TODO: Undo
+ if (!readFromSongToUI) {
+ if (ui.txtTitle->text().toStdString() != song->title) {
+ song->title = ui.txtTitle->text().toStdString();
+ }
+ if (ui.txtArtist->text().toStdString() != song->artist) {
+ song->artist = ui.txtArtist->text().toStdString();
+ }
+ if (ui.txtGenre->text().toStdString() != song->genre) {
+ song->genre = ui.txtGenre->text().toStdString();
+ }
+ if (ui.txtYear->text().toStdString() != song->year) {
+ song->year = ui.txtYear->text().toStdString();
+ }
+ } else {
+ if (!song->title.empty()) ui.txtTitle->setText(QString::fromStdString(song->title));
+ if (!song->artist.empty()) ui.txtArtist->setText(QString::fromStdString(song->artist));
+ if (!song->genre.empty()) ui.txtGenre->setText(QString::fromStdString(song->genre));
+ if (!song->year.empty()) ui.txtYear->setText(QString::fromStdString(song->year));
+ }
+}
+
+void EditorApp::on_txtTitle_editingFinished() { updateSongMeta(); }
+void EditorApp::on_txtArtist_editingFinished() { updateSongMeta(); }
+void EditorApp::on_txtGenre_editingFinished() { updateSongMeta(); }
+void EditorApp::on_txtYear_editingFinished() { updateSongMeta(); }
void EditorApp::on_cmbNoteType_currentIndexChanged(int index)
{
diff --git a/editorapp.hh b/editorapp.hh
index 3865b25..4a66eed 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -14,6 +14,8 @@ class EditorApp: public QMainWindow
public:
EditorApp(QWidget *parent = 0);
+ void updateSongMeta(bool readFromSongToUI = false);
+
public slots:
void operationDone(const Operation &op);
void updateNoteInfo(NoteLabel *note);
@@ -38,6 +40,10 @@ public slots:
void on_actionAbout_triggered();
// Note properties tab
+ void on_txtTitle_editingFinished();
+ void on_txtArtist_editingFinished();
+ void on_txtGenre_editingFinished();
+ void on_txtYear_editingFinished();
void on_cmbNoteType_currentIndexChanged(int);
void on_chkFloating_stateChanged(int);
diff --git a/song.hh b/song.hh
index 942161b..43903fb 100644
--- a/song.hh
+++ b/song.hh
@@ -38,7 +38,8 @@ class Song {
VocalTracks vocalTracks; ///< notes for the sing part
VocalTrack dummyVocal; ///< notes for the sing part
public:
- /// constructor
+ /// constructors
+ Song(): dummyVocal(TrackName::LEAD_VOCAL) { reload(true); }
Song(std::string const& path_, std::string const& filename_): dummyVocal(TrackName::LEAD_VOCAL), path(path_), filename(filename_) { reload(false); }
/// reload song
void reload(bool errorIgnore = true);
@@ -60,7 +61,7 @@ class Song {
void insertVocalTrack(std::string vocalTrack, VocalTrack track) {
vocalTracks.erase(vocalTrack);
vocalTracks.insert(std::make_pair<std::string, VocalTrack>(vocalTrack, track));
- };
+ }
// Get a selected track, or LEAD_VOCAL if not found or the first one if not found
VocalTrack& getVocalTrack(std::string vocalTrack = TrackName::LEAD_VOCAL) {
if(vocalTracks.find(vocalTrack) != vocalTracks.end()) {
@@ -101,6 +102,7 @@ class Song {
std::string text; ///< songtext
std::string creator; ///< creator
std::string language; ///< language
+ std::string year; ///< year
std::map<std::string,std::string> music; ///< music files (background, guitar, rhythm/bass, drums, vocals)
std::string cover; ///< cd cover
std::string background; ///< background image
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 11:09:30
|
Module: editor
Branch: master
Commit: 54114b08c0ef2a70ee0009bf9e246c5f8e5c9a50
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 13:08:50 2011 +0200
More verbose note tooltip.
---
editor.ui | 8 ++++----
notelabel.cc | 14 ++++++++++----
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/editor.ui b/editor.ui
index c71a596..8165720 100644
--- a/editor.ui
+++ b/editor.ui
@@ -88,7 +88,7 @@
<item row="0" column="1">
<widget class="QLabel" name="valNoteBegin">
<property name="text">
- <string>XXX</string>
+ <string>-</string>
</property>
</widget>
</item>
@@ -102,7 +102,7 @@
<item row="1" column="1">
<widget class="QLabel" name="valNoteEnd">
<property name="text">
- <string>XXX</string>
+ <string>-</string>
</property>
</widget>
</item>
@@ -161,7 +161,7 @@
<item row="2" column="1">
<widget class="QLabel" name="valNoteDuration">
<property name="text">
- <string>XXX</string>
+ <string>-</string>
</property>
</widget>
</item>
@@ -175,7 +175,7 @@
<item row="3" column="1">
<widget class="QLabel" name="valNote">
<property name="text">
- <string>XXX</string>
+ <string>-</string>
</property>
</widget>
</item>
diff --git a/notelabel.cc b/notelabel.cc
index a3b192e..9705d65 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -78,8 +78,8 @@ void NoteLabel::createPixmap(QSize size)
setPixmap(QPixmap::fromImage(image));
- setToolTip(QString("\"%1\"\n%2").arg(lyric()).arg(QString::fromStdString(m_note.typeString())));
setStatusTip(QString("Lyric: ") + lyric());
+ updateNote();
}
void NoteLabel::resizeEvent(QResizeEvent *event)
@@ -90,8 +90,6 @@ void NoteLabel::resizeEvent(QResizeEvent *event)
void NoteLabel::mouseMoveEvent(QMouseEvent *event)
{
- QToolTip::showText(event->globalPos(), toolTip(), this);
-
NoteGraphWidget* ngw = qobject_cast<NoteGraphWidget*>(parent());
if (m_resizing != 0) {
// Resizing
@@ -120,7 +118,7 @@ void NoteLabel::mouseMoveEvent(QMouseEvent *event)
}
}
updateNote();
-
+ QToolTip::showText(event->globalPos(), toolTip(), this);
event->ignore(); // Propagate event to parent
}
@@ -151,4 +149,12 @@ void NoteLabel::updateNote()
// Update note length
m_note.end = m_note.begin + ngw->px2s(width());
}
+ MusicalScale ms;
+ setToolTip(QString("\"%1\"\n%2\n%3\n%4 s - %5 s")
+ .arg(lyric())
+ .arg(QString::fromStdString(m_note.typeString()))
+ .arg(QString::fromStdString(ms.getNoteStr(ms.getNoteFreq(m_note.note))))
+ .arg(QString::number(m_note.begin))
+ .arg(QString::number(m_note.end))
+ );
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 11:09:27
|
Module: editor
Branch: master
Commit: d1bbc4397d33d0947a9787da06178f54c3cbf125
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 13:02:01 2011 +0200
Display better note info in UI.
---
editorapp.cc | 10 ++++++----
notegraphwidget.cc | 2 ++
notelabel.cc | 19 +++++++++++++------
notelabel.hh | 1 +
4 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 1c8025a..7eb9a07 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -60,10 +60,12 @@ void EditorApp::operationDone(const Operation &op)
void EditorApp::updateNoteInfo(NoteLabel *note)
{
if (note) {
- ui.valNoteBegin->setText(QString::number(note->x()));
- ui.valNoteEnd->setText(QString::number(note->x() + note->width()));
- ui.valNoteDuration->setText(QString::number(note->width()));
- ui.valNote->setText(QString::number(note->y() / NoteGraphWidget::noteYStep));
+ MusicalScale ms;
+ ui.valNoteBegin->setText(QString::number(note->note().begin) + tr(" s"));
+ ui.valNoteEnd->setText(QString::number(note->note().end) + tr(" s"));
+ ui.valNoteDuration->setText(QString::number(note->note().length()) + tr(" s"));
+ ui.valNote->setText(QString::fromStdString(ms.getNoteStr(ms.getNoteFreq(note->note().note)))
+ + " (" + QString::number(note->note().note) + ")");
ui.cmbNoteType->setEnabled(true);
ui.cmbNoteType->setCurrentIndex(note->note().getTypeInt());
ui.chkFloating->setEnabled(true);
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index adbd0c8..7a6e99b 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -312,6 +312,8 @@ void NoteGraphWidget::mouseMoveEvent(QMouseEvent *event)
m_panHotSpot = event->pos() - diff;
}
}
+
+ emit updateNoteInfo(m_selectedNote);
}
diff --git a/notelabel.cc b/notelabel.cc
index a7a44c7..a3b192e 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -85,9 +85,7 @@ void NoteLabel::createPixmap(QSize size)
void NoteLabel::resizeEvent(QResizeEvent *event)
{
createPixmap(event->size());
- // Update note length
- NoteGraphWidget* ngw = qobject_cast<NoteGraphWidget*>(parent());
- if (ngw) m_note.end = m_note.begin + ngw->px2s(width());
+ updateNote();
}
void NoteLabel::mouseMoveEvent(QMouseEvent *event)
@@ -121,9 +119,7 @@ void NoteLabel::mouseMoveEvent(QMouseEvent *event)
setCursor(QCursor(Qt::OpenHandCursor));
}
}
-
- // Update note pos
- if (ngw) m_note.begin = ngw->px2s(m_note.begin);
+ updateNote();
event->ignore(); // Propagate event to parent
}
@@ -145,3 +141,14 @@ void NoteLabel::startDragging(const QPoint& point)
else setCursor(QCursor());
}
+void NoteLabel::updateNote()
+{
+ NoteGraphWidget* ngw = qobject_cast<NoteGraphWidget*>(parent());
+ if (ngw) {
+ // Update note pos
+ m_note.note = ngw->px2n(y());
+ m_note.begin = ngw->px2s(x());
+ // Update note length
+ m_note.end = m_note.begin + ngw->px2s(width());
+ }
+}
diff --git a/notelabel.hh b/notelabel.hh
index f965395..49efe59 100644
--- a/notelabel.hh
+++ b/notelabel.hh
@@ -26,6 +26,7 @@ public:
Note& note() { return m_note; }
Note note() const { return m_note; }
+ void updateNote();
bool isFloating() const { return m_floating; }
void setFloating(bool state) { m_floating = state; createPixmap(size()); }
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 11:09:25
|
Module: editor
Branch: master
Commit: 86798c9cb8ff2bbe617edcf57c21847d4e89fabb
Author: Tapio Vierros <tap...@gm...>
Date: Thu Jan 13 12:45:04 2011 +0200
Some kind of pixel/sec/pitch mappings.
---
notegraphwidget.cc | 33 ++++++++++++++++++++++++---------
notegraphwidget.hh | 10 ++++++++++
notelabel.cc | 24 +++++++++++++++---------
notes.hh | 7 +++++++
4 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 9b18115..adbd0c8 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -16,10 +16,11 @@ namespace {
}
-const int NoteGraphWidget::noteYStep = 40;
+const int NoteGraphWidget::noteYStep = 28;
NoteGraphWidget::NoteGraphWidget(QWidget *parent)
- : QLabel(parent), m_panHotSpot(), m_selectedNote(), m_selectedAction(NONE), m_actionHappened(), m_pitch("music.raw")
+ : QLabel(parent), m_pixPerSec(200), m_lowestNote(MusicalScale::getBaseId()), m_octaves(3),
+ m_panHotSpot(), m_selectedNote(), m_selectedAction(NONE), m_actionHappened(), m_pitch("music.raw")
{
unsigned width = m_pitch.width(), height = m_pitch.height;
QProgressDialog progress(tr("Rendering pitch data..."), tr("&Abort"), 0, width, this);
@@ -39,7 +40,7 @@ NoteGraphWidget::NoteGraphWidget(QWidget *parent)
progress.setValue(width);
// FIXME: Width should come from song length * pixPerSec
- setFixedSize(std::max(width, (unsigned)1024), height);
+ setFixedSize(std::max(width, (unsigned)1024), noteYStep * 12 * m_octaves);
setFocusPolicy(Qt::StrongFocus);
setWhatsThis(tr("Note graph that displays the song notes and allows you to manipulate them."));
@@ -83,7 +84,7 @@ void NoteGraphWidget::setLyrics(QString lyrics)
QString word;
ts >> word;
if (!word.isEmpty()) {
- m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, 2 * noteYStep)));
+ m_notes.push_back(new NoteLabel(Note(word.toStdString()), this, QPoint(0, n2px(m_lowestNote + 12 * m_octaves - 6))));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
}
}
@@ -95,11 +96,9 @@ void NoteGraphWidget::setLyrics(const Notes ¬es)
{
clear();
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
- // TODO: Implement proper seconds-to-pixels mapping and note height thingy
- const float sec2pix = 200;
if (it->type == Note::NORMAL || it->type == Note::GOLDEN || it->type == Note::FREESTYLE) {
- m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, height() - it->note * noteYStep),
- QSize((it->end - it->begin)*sec2pix, 0), false));
+ m_notes.push_back(new NoteLabel(*it, this, QPoint(s2px(it->begin), n2px(it->note)),
+ QSize(s2px(it->length()), 0), false));
doOperation(opFromNote(*m_notes.back(), m_notes.size()-1), Operation::NO_EXEC);
}
}
@@ -252,7 +251,7 @@ void NoteGraphWidget::mouseReleaseEvent(QMouseEvent *event)
if (m_selectedNote) {
m_selectedNote->startResizing(0);
m_selectedNote->startDragging(QPoint());
- m_selectedNote->move(m_selectedNote->pos().x(), int(round(m_selectedNote->pos().y() / float(noteYStep))) * noteYStep);
+ m_selectedNote->move(m_selectedNote->pos().x(), n2px(px2n(m_selectedNote->pos().y())));
if (m_actionHappened) {
// Operation for undo stack & saving
Operation op("SETGEOM");
@@ -404,6 +403,22 @@ void NoteGraphWidget::doOperation(const Operation& op, Operation::OperationFlags
}
+int NoteGraphWidget::s2px(double sec) const {
+ return sec * m_pixPerSec;
+}
+double NoteGraphWidget::px2s(int px) const {
+ return px / m_pixPerSec;
+}
+int NoteGraphWidget::n2px(int note) const {
+ int highestNote = m_lowestNote + 12 * m_octaves;
+ return (highestNote - note) * noteYStep;
+}
+int NoteGraphWidget::px2n(int px) const {
+ int highestNote = m_lowestNote + 12 * m_octaves;
+ return highestNote - round(px / (float)noteYStep);
+}
+
+
void FloatingGap::addNote(NoteLabel* n)
{
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index 3a45f28..065229d 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -31,6 +31,12 @@ public:
NoteLabels& noteLabels() { return m_notes; }
void doOperation(const Operation& op, Operation::OperationFlags flags = Operation::NORMAL);
+ int s2px(double sec) const;
+ double px2s(int px) const;
+ int n2px(int note) const;
+ int px2n(int px) const;
+
+
signals:
void updateNoteInfo(NoteLabel*);
void operationDone(const Operation&);
@@ -46,6 +52,10 @@ protected:
private:
void finalizeNewLyrics();
+ double m_pixPerSec; ///< Pixels per second
+ int m_lowestNote; ///< Note id / midi pitch of the lowest note in the view
+ int m_octaves; ///< How many octaves are displayed in the view
+
int m_requiredWidth;
QPoint m_panHotSpot;
NoteLabel* m_selectedNote;
diff --git a/notelabel.cc b/notelabel.cc
index 3283ef7..a7a44c7 100644
--- a/notelabel.cc
+++ b/notelabel.cc
@@ -1,14 +1,15 @@
#include <QtGui>
+#include <iostream>
#include "notelabel.hh"
#include "notegraphwidget.hh"
namespace {
- static const int text_margin = 12; // Margin of the label texts
+ static const int text_margin = 3; // Margin of the label texts
}
const int NoteLabel::resize_margin = 5; // How many pixels is the resize area
const int NoteLabel::min_width = 10; // How many pixels is the resize area
-const int NoteLabel::default_size = 50; // The preferred size of notes
+const int NoteLabel::default_size = 100; // The preferred size of notes
NoteLabel::NoteLabel(const Note ¬e, QWidget *parent, const QPoint &position, const QSize &size, bool floating)
: QLabel(parent), m_note(note), m_selected(false), m_floating(floating), m_resizing(0), m_hotspot()
@@ -16,7 +17,7 @@ NoteLabel::NoteLabel(const Note ¬e, QWidget *parent, const QPoint &position,
createPixmap(size);
if (!position.isNull())
move(position);
-
+ std::cout << x() << " " << y() << " " << width() << std::endl;
setMouseTracking(true);
setMinimumSize(min_width, 10);
setAttribute(Qt::WA_DeleteOnClose);
@@ -25,21 +26,20 @@ NoteLabel::NoteLabel(const Note ¬e, QWidget *parent, const QPoint &position,
void NoteLabel::createPixmap(QSize size)
{
- QFontMetrics metric(font());
+ QFont font;
+ font.setStyleStrategy(QFont::ForceOutline);
+ QFontMetrics metric(font);
if (size.width() <= 0) {
size.rwidth() = default_size;
}
if (size.height() <= 0) {
- size.rheight() = metric.size(Qt::TextSingleLine, lyric()).height() + text_margin;
+ size.rheight() = metric.size(Qt::TextSingleLine, lyric()).height() + 2 * text_margin;
}
QImage image(size.width(), size.height(),
QImage::Format_ARGB32_Premultiplied);
image.fill(qRgba(0, 0, 0, 0));
- QFont font;
- font.setStyleStrategy(QFont::ForceOutline);
-
QLinearGradient gradient(0, 0, 0, image.height()-1);
gradient.setColorAt(0.0, Qt::white);
float ff = m_floating ? 1.0f : 0.5f;
@@ -67,7 +67,7 @@ void NoteLabel::createPixmap(QSize size)
painter.setFont(font);
painter.setBrush(Qt::black);
- painter.drawText(QRect(QPoint(6, 6), QSize(size.width()-text_margin, size.height()-text_margin)), Qt::AlignCenter, lyric());
+ painter.drawText(QRect(QPoint(text_margin, text_margin), QSize(size.width()-text_margin, size.height()-text_margin)), Qt::AlignCenter, lyric());
// Render sentence end indicator
if (m_note.lineBreak) {
@@ -85,6 +85,9 @@ void NoteLabel::createPixmap(QSize size)
void NoteLabel::resizeEvent(QResizeEvent *event)
{
createPixmap(event->size());
+ // Update note length
+ NoteGraphWidget* ngw = qobject_cast<NoteGraphWidget*>(parent());
+ if (ngw) m_note.end = m_note.begin + ngw->px2s(width());
}
void NoteLabel::mouseMoveEvent(QMouseEvent *event)
@@ -119,6 +122,9 @@ void NoteLabel::mouseMoveEvent(QMouseEvent *event)
}
}
+ // Update note pos
+ if (ngw) m_note.begin = ngw->px2s(m_note.begin);
+
event->ignore(); // Propagate event to parent
}
diff --git a/notes.hh b/notes.hh
index e5f8b9e..e2b6bb2 100644
--- a/notes.hh
+++ b/notes.hh
@@ -27,8 +27,13 @@ class MusicalScale {
double getNote(double freq) const;
/// get note offset for frequence
double getNoteOffset(double freq) const;
+ /// get octave number
+
+ /// get base id
+ static int getBaseId() { return m_baseId; }
};
+
/// stores duration of a note
struct Duration {
double begin, ///< beginning timestamp in seconds
@@ -62,6 +67,8 @@ struct Note {
int notePrev; ///< MIDI pitch of the previous note (should be same as note for everything but SLIDE)
std::string syllable; ///< lyrics syllable for that note
bool lineBreak; ///< is this note ending a syllable?
+ /// note length
+ double length() const { return end - begin; }
/// difference of n from note
double diff(double n) const { return diff(note, n); }
/// difference of n from note, so that note + diff(note, n) is n (mod 12)
|
|
From: Yoda-JM <yo...@us...> - 2011-01-13 11:02:55
|
Module: editor
Branch: master
Commit: 8ab8ee5e6e7e214bd5f9d325ad7894c86ddd7b76
Author: Vincent Le Ligeour <yo...@us...>
Date: Thu Jan 13 12:02:34 2011 +0100
Hacked some visualization stuff
---
pitchvis.cc | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/pitchvis.cc b/pitchvis.cc
index 2124fb4..441db92 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -38,6 +38,7 @@ PitchVis::PitchVis(std::string const& filename): height(1024) {
analyzer.input(data.begin() + x * step, data.begin() + (x + 1) * step);
analyzer.process();
+ /*
Analyzer::Peaks peaks = analyzer.getPeaks();
for (unsigned i = 0; i < peaks.size(); ++i) {
unsigned y = height - static_cast<unsigned>(16.0 * scale.getNote(peaks[i].freq));
@@ -52,19 +53,33 @@ PitchVis::PitchVis(std::string const& filename): height(1024) {
(*this)(x, y + 1) += p;
(*this)(x, y - 1) += p;
}
+ */
Analyzer::Tones tones = analyzer.getTones();
- for (Analyzer::Tones::const_iterator it = tones.begin(), itend = tones.end(); it != itend; ++it) {
- unsigned y = height - static_cast<unsigned>(16.0 * scale.getNote(it->freq));
+ unsigned int i = 0;
+ for (Analyzer::Tones::const_iterator it = tones.begin(), itend = tones.end(); it != itend && i < 3; ++it) {
+ unsigned y = height - static_cast<unsigned>(16.0 * scale.getNoteId(it->freq));
if (y == 0 || y >= height - 1) continue;
float value = 0.003 * (it->db + 80.0);
if (value <= 0.0) continue;
Pixel p(value, value, value);
+ switch(i) {
+ case 0:
+ p.r = 0.0; p.g = 1.0; p.b = 0.0;
+ break;
+ case 1:
+ p.r = 0.0; p.g = 0.5; p.b = 0.0;
+ break;
+ case 2:
+ p.r = 0.0; p.g = 0.3; p.b = 0.0;
+ break;
+ }
(*this)(x, y) += p;
p.r *= 0.5;
p.g *= 0.5;
p.b *= 0.5;
(*this)(x, y + 1) += p;
(*this)(x, y - 1) += p;
+ ++i;
}
}
progress.setValue(width);
|
|
From: Tapio V. <aa...@us...> - 2011-01-13 02:17:33
|
Module: editor Branch: master Commit: 67e27fe2b99021a2afe87e513b61c02cc4a397a0 Author: Tapio Vierros <tap...@gm...> Date: Thu Jan 13 04:14:47 2011 +0200 Undo implementation. * User can now undo most operations. * There is still a lot to tweak and test. * No redo. --- editorapp.cc | 48 ++++++++++++++++++++---- editorapp.hh | 4 +- notegraphwidget.cc | 103 +++++++++++++++++++++++++++++++++++++++++++--------- notegraphwidget.hh | 7 +++- notelabel.cc | 2 + notelabel.hh | 2 +- operation.cc | 4 -- operation.hh | 55 ++++++++++++++++++++++++---- 8 files changed, 183 insertions(+), 42 deletions(-) |
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-12 23:00:53
|
Module: editor Branch: master Commit: f7b1e6ea616b2624349d752b18750c92bb1a8a08 Author: Lasse Kärkkäinen <tronic+ndrm at trn.iki.fi> Date: Thu Jan 13 00:00:20 2011 +0100 Maximize the window by default --- editorapp.cc | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/editorapp.cc b/editorapp.cc index c802a36..2dd22ad 100644 --- a/editorapp.cc +++ b/editorapp.cc @@ -7,6 +7,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent) { + showMaximized(); ui.setupUi(this); noteGraph = new NoteGraphWidget(NULL); |
|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-12 23:00:50
|
Module: editor Branch: master Commit: 39bb5d581bbe3257273c6472e4a7a76f5c109440 Author: Lasse Kärkkäinen <tronic+ndrm at trn.iki.fi> Date: Wed Jan 12 23:53:50 2011 +0100 Build fix --- CMakeLists.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce4791f..77e4f92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif(NOT CMAKE_BUILD_TYPE) -find_package(Boost 1.36 REQUIRED COMPONENTS regex filesystem) +find_package(Boost 1.36 REQUIRED COMPONENTS regex filesystem system) include_directories(${Boost_INCLUDE_DIRS}) list(APPEND LIBS ${Boost_LIBRARIES}) |
|
From: Tapio V. <aa...@us...> - 2011-01-12 21:13:57
|
Module: editor
Branch: master
Commit: ceb5d72598034d08bbae4429df50c68da6552006
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 23:13:29 2011 +0200
Fix mouse panning.
---
notegraphwidget.cc | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 5b1a54a..f39e4cf 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -272,8 +272,8 @@ void NoteGraphWidget::mouseMoveEvent(QMouseEvent *event)
if (!m_panHotSpot.isNull()) {
setCursor(QCursor(Qt::ClosedHandCursor));
QScrollArea *scrollArea = NULL;
- if (parentWidget() && parentWidget()->parent())
- scrollArea = qobject_cast<QScrollArea*>(parentWidget()->parent()->parent());
+ if (parentWidget())
+ scrollArea = qobject_cast<QScrollArea*>(parentWidget()->parent());
if (scrollArea) {
QPoint diff = event->pos() - m_panHotSpot;
QScrollBar *scrollHor = scrollArea->horizontalScrollBar();
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 21:11:25
|
Module: editor
Branch: master
Commit: 353581cb45902e7db321b3c7c4ab4e3f04b310b7
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 23:10:31 2011 +0200
Use pitch info from TXT (hack).
---
notegraphwidget.cc | 6 +++---
songparser-txt.cc | 4 +---
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index dffe5eb..5b1a54a 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -92,13 +92,13 @@ void NoteGraphWidget::setLyrics(const Notes ¬es)
clear();
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
// TODO: Implement proper seconds-to-pixels mapping and note height thingy
- const float sec2pix = 100;
+ const float sec2pix = 200;
if (it->type == Note::NORMAL || it->type == Note::GOLDEN || it->type == Note::FREESTYLE)
- m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, 2 * noteYStep),
+ m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, height() - it->note * noteYStep),
QSize((it->end - it->begin)*sec2pix, 0), false));
}
- finalizeNewLyrics();
+ updateNotes();
}
void NoteGraphWidget::finalizeNewLyrics()
diff --git a/songparser-txt.cc b/songparser-txt.cc
index e622846..6854f2a 100644
--- a/songparser-txt.cc
+++ b/songparser-txt.cc
@@ -148,10 +148,8 @@ bool SongParser::txtParseNote(std::string line, VocalTrack &vocal) {
if (n.type == Note::SLEEP) {
if (notes.empty()) return true; // Ignore sleeps at song beginning
n.begin = n.end = prevtime; // Normalize sleep notes
+ notes.back().lineBreak = true; // lineBreak flag for notes preceding SLEEPs
}
- // Add lineBreak flag for notes preceding SLEEPs
- if (notes.size() > 0 && n.type == Note::SLEEP)
- n.lineBreak = true;
notes.push_back(n);
return true;
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 20:39:15
|
Module: editor
Branch: master
Commit: bbf036daec004528a51ec2139a8ee777ca208ee3
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 22:37:51 2011 +0200
Only show normal, golden and freestyle notes.
---
notegraphwidget.cc | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 42ae63f..dffe5eb 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -93,8 +93,9 @@ void NoteGraphWidget::setLyrics(const Notes ¬es)
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
// TODO: Implement proper seconds-to-pixels mapping and note height thingy
const float sec2pix = 100;
- m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, 2 * noteYStep),
- QSize((it->end - it->begin)*sec2pix, 0), false));
+ if (it->type == Note::NORMAL || it->type == Note::GOLDEN || it->type == Note::FREESTYLE)
+ m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, 2 * noteYStep),
+ QSize((it->end - it->begin)*sec2pix, 0), false));
}
finalizeNewLyrics();
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 20:39:12
|
Module: editor
Branch: master
Commit: f547f4197e94fd607c43589e44b1d529872209cd
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 22:37:39 2011 +0200
Add lineBreak flags to notes parsed from US TXT.
---
songparser-txt.cc | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/songparser-txt.cc b/songparser-txt.cc
index 072389e..e622846 100644
--- a/songparser-txt.cc
+++ b/songparser-txt.cc
@@ -149,6 +149,9 @@ bool SongParser::txtParseNote(std::string line, VocalTrack &vocal) {
if (notes.empty()) return true; // Ignore sleeps at song beginning
n.begin = n.end = prevtime; // Normalize sleep notes
}
+ // Add lineBreak flag for notes preceding SLEEPs
+ if (notes.size() > 0 && n.type == Note::SLEEP)
+ n.lineBreak = true;
notes.push_back(n);
return true;
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 20:39:09
|
Module: editor
Branch: master
Commit: eeafe315792a6446a094ff9d98b778972c0b2388
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 22:30:22 2011 +0200
Restore note type changing through UI.
---
editorapp.cc | 7 +++----
notelabel.hh | 2 +-
notes.cc | 26 +++++++++++++++++++++++---
notes.hh | 9 ++++++---
4 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index f354fee..c802a36 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -50,7 +50,7 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.valNoteDuration->setText(QString::number(note->width()));
ui.valNote->setText(QString::number(note->y() / NoteGraphWidget::noteYStep));
ui.cmbNoteType->setEnabled(true);
- // FIXME: ui.cmbNoteType->setCurrentIndex(note->note().type);
+ ui.cmbNoteType->setCurrentIndex(note->note().getTypeInt());
ui.chkFloating->setEnabled(true);
ui.chkFloating->setChecked(note->isFloating());
} else {
@@ -209,9 +209,8 @@ void EditorApp::on_actionAbout_triggered()
void EditorApp::on_cmbNoteType_currentIndexChanged(int index)
{
- // FIXME: Fix this
- //if (noteGraph->selectedNote())
- // noteGraph->selectedNote()->setType(index);
+ if (noteGraph->selectedNote())
+ noteGraph->selectedNote()->setType(index);
}
void EditorApp::on_chkFloating_stateChanged(int state)
diff --git a/notelabel.hh b/notelabel.hh
index b02bdbe..c19631d 100644
--- a/notelabel.hh
+++ b/notelabel.hh
@@ -29,7 +29,7 @@ public:
bool isFloating() const { return m_floating; }
void setFloating(bool state) { m_floating = state; createPixmap(size()); }
- void setType(Note::Type newtype) { m_note.type = Note::Type(newtype); createPixmap(size()); }
+ void setType(int newtype) { m_note.type = Note::types[newtype]; createPixmap(size()); }
void startResizing(int dir);
void startDragging(const QPoint& point);
diff --git a/notes.cc b/notes.cc
index ba98255..beb5442 100644
--- a/notes.cc
+++ b/notes.cc
@@ -1,6 +1,7 @@
#include "notes.hh"
#include "util.hh"
+#include <QtGlobal>
#include <cmath>
#include <sstream>
#include <stdexcept>
@@ -54,14 +55,33 @@ double MusicalScale::getNoteOffset(double freq) const {
Duration::Duration(): begin(getNaN()), end(getNaN()) {}
+
+const Note::Type Note::types[] = { NORMAL, GOLDEN, FREESTYLE, SLIDE, SLEEP, TAP, HOLDBEGIN, HOLDEND, ROLL, MINE, LIFT };
+
Note::Note(std::string lyric): syllable(lyric), begin(), end(), phase(getNaN()), type(NORMAL), note(), notePrev(), lineBreak() {}
double Note::diff(double note, double n) { return remainder(n - note, 12.0); }
+int Note::getTypeInt() const {
+ switch (type) {
+ case NORMAL: return 0;
+ case GOLDEN: return 1;
+ case FREESTYLE: return 2;
+ case SLIDE: return 3;
+ case SLEEP: return 4;
+ default: return 255;
+ }
+}
+
std::string Note::typeString() const {
- static const std::string typenames[] = { "Normal", "Bonus", "Freestyle" };
- return typenames[0]; // FIXME: Handle notetypes properly
- //return typenames[type];
+ switch (type) {
+ case NORMAL: return QT_TR_NOOP("Normal");
+ case GOLDEN: return QT_TR_NOOP("Bonus");
+ case FREESTYLE: return QT_TR_NOOP("Freestyle");
+ case SLIDE: return QT_TR_NOOP("Slide");
+ case SLEEP: return QT_TR_NOOP("Sleep");
+ default: return QT_TR_NOOP("Unknown");
+ }
}
diff --git a/notes.hh b/notes.hh
index 601808f..e5f8b9e 100644
--- a/notes.hh
+++ b/notes.hh
@@ -48,13 +48,16 @@ typedef std::map<int, Durations> NoteMap;
/// note read from songfile
struct Note {
Note(std::string lyric = "");
+ /// note type - NOTE! Keep the types array below in sync with the enum!
+ enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-',
+ TAP = '1', HOLDBEGIN = '2', HOLDEND = '3', ROLL = '4', MINE = 'M', LIFT = 'L'} type;
+ static const Type types[];
+ int getTypeInt() const;
+
//Duration duration; ///< note begin/end
double begin; // FIXME: Should use duration but it is pain to change everywhere
double end;
double phase; ///< position within a measure, [0, 1)
- /// note type
- enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-',
- TAP = '1', HOLDBEGIN = '2', HOLDEND = '3', ROLL = '4', MINE = 'M', LIFT = 'L'} type;
int note; ///< MIDI pitch of the note (at the end for slide notes)
int notePrev; ///< MIDI pitch of the previous note (should be same as note for everything but SLIDE)
std::string syllable; ///< lyrics syllable for that note
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 20:09:58
|
Module: editor
Branch: master
Commit: acdf61ef9e9838680d9211cb9ea6892a0f4f746a
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 22:09:16 2011 +0200
Nice MessageBox tells about song loading error.
---
editorapp.cc | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 193b207..f354fee 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -98,12 +98,9 @@ void EditorApp::on_actionOpen_triggered()
QFileInfo finfo(fileName);
try {
song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
- VocalTrack vt = song->getVocalTrack();
noteGraph->setLyrics(song->getVocalTrack().notes);
} catch (const std::exception& e) {
- // TODO: Error handling
- std::cerr << "Error loading song: " << finfo.filePath().toStdString() << std::endl;
- std::cerr << " --> " << e.what() << std::endl;
+ QMessageBox::critical(this, tr("Error loading file!"), e.what());
}
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 19:58:19
|
Module: editor
Branch: master
Commit: 223adc8ab367bd7b4c14cb4c7f70a5b21d590555
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 21:57:45 2011 +0200
Load notes from UltraStar TXT. Kind of. Partially.
* Breaks UI handling of note types
* No pitch info
* Phony seconds-to-pixels mapping
---
editorapp.cc | 23 +++++++++++++++++------
editorapp.hh | 2 ++
notegraphwidget.cc | 5 ++++-
notelabel.hh | 2 +-
notes.cc | 3 ++-
notes.hh | 3 ++-
songparser.cc | 32 ++++++++++++++++++--------------
7 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/editorapp.cc b/editorapp.cc
index 68b61b7..193b207 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -1,5 +1,5 @@
#include <QtGui>
-#include <cstdlib>
+#include <iostream>
#include "editorapp.hh"
#include "notelabel.hh"
#include "notegraphwidget.hh"
@@ -50,7 +50,7 @@ void EditorApp::updateNoteInfo(NoteLabel *note)
ui.valNoteDuration->setText(QString::number(note->width()));
ui.valNote->setText(QString::number(note->y() / NoteGraphWidget::noteYStep));
ui.cmbNoteType->setEnabled(true);
- ui.cmbNoteType->setCurrentIndex(note->note().type);
+ // FIXME: ui.cmbNoteType->setCurrentIndex(note->note().type);
ui.chkFloating->setEnabled(true);
ui.chkFloating->setChecked(note->isFloating());
} else {
@@ -95,7 +95,17 @@ void EditorApp::on_actionOpen_triggered()
);
if (!fileName.isNull()) {
- // TODO: Spawn a parser
+ QFileInfo finfo(fileName);
+ try {
+ song.reset(new Song(QString(finfo.path()+"/").toStdString(), finfo.fileName().toStdString()));
+ VocalTrack vt = song->getVocalTrack();
+ noteGraph->setLyrics(song->getVocalTrack().notes);
+ } catch (const std::exception& e) {
+ // TODO: Error handling
+ std::cerr << "Error loading song: " << finfo.filePath().toStdString() << std::endl;
+ std::cerr << " --> " << e.what() << std::endl;
+ }
+
}
}
@@ -142,7 +152,7 @@ void EditorApp::on_actionMusicFile_triggered()
if (!fileName.isNull()) {
ui.valMusicFile->setText(fileName);
ui.tabWidget->setCurrentIndex(1);
- // TODO: Do something the file
+ // TODO: Do something with the file
}
}
@@ -202,8 +212,9 @@ void EditorApp::on_actionAbout_triggered()
void EditorApp::on_cmbNoteType_currentIndexChanged(int index)
{
- if (noteGraph->selectedNote())
- noteGraph->selectedNote()->setType(index);
+ // FIXME: Fix this
+ //if (noteGraph->selectedNote())
+ // noteGraph->selectedNote()->setType(index);
}
void EditorApp::on_chkFloating_stateChanged(int state)
diff --git a/editorapp.hh b/editorapp.hh
index 0595dd6..d622616 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -2,6 +2,7 @@
#include "ui_editor.h"
#include "operation.hh"
+#include "song.hh"
class NoteLabel;
class NoteGraphWidget;
@@ -44,4 +45,5 @@ private:
Ui::EditorApp ui;
NoteGraphWidget* noteGraph;
OperationStack opStack;
+ QScopedPointer<Song> song;
};
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 5747ef2..42ae63f 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -91,7 +91,10 @@ void NoteGraphWidget::setLyrics(const Notes ¬es)
{
clear();
for (Notes::const_iterator it = notes.begin(); it != notes.end(); ++it) {
- m_notes.push_back(new NoteLabel(*it, this, QPoint(0, 2 * noteYStep)));
+ // TODO: Implement proper seconds-to-pixels mapping and note height thingy
+ const float sec2pix = 100;
+ m_notes.push_back(new NoteLabel(*it, this, QPoint(it->begin*sec2pix, 2 * noteYStep),
+ QSize((it->end - it->begin)*sec2pix, 0), false));
}
finalizeNewLyrics();
diff --git a/notelabel.hh b/notelabel.hh
index b36e0d0..b02bdbe 100644
--- a/notelabel.hh
+++ b/notelabel.hh
@@ -29,7 +29,7 @@ public:
bool isFloating() const { return m_floating; }
void setFloating(bool state) { m_floating = state; createPixmap(size()); }
- void setType(int newtype) { m_note.type = Note::Type(newtype); createPixmap(size()); }
+ void setType(Note::Type newtype) { m_note.type = Note::Type(newtype); createPixmap(size()); }
void startResizing(int dir);
void startDragging(const QPoint& point);
diff --git a/notes.cc b/notes.cc
index d846de2..ba98255 100644
--- a/notes.cc
+++ b/notes.cc
@@ -60,7 +60,8 @@ double Note::diff(double note, double n) { return remainder(n - note, 12.0); }
std::string Note::typeString() const {
static const std::string typenames[] = { "Normal", "Bonus", "Freestyle" };
- return typenames[type];
+ return typenames[0]; // FIXME: Handle notetypes properly
+ //return typenames[type];
}
diff --git a/notes.hh b/notes.hh
index abf5d77..601808f 100644
--- a/notes.hh
+++ b/notes.hh
@@ -53,7 +53,8 @@ struct Note {
double end;
double phase; ///< position within a measure, [0, 1)
/// note type
- enum Type { NORMAL = 0, GOLDEN = 1, FREESTYLE = 2, SLEEP } type;
+ enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-',
+ TAP = '1', HOLDBEGIN = '2', HOLDEND = '3', ROLL = '4', MINE = 'M', LIFT = 'L'} type;
int note; ///< MIDI pitch of the note (at the end for slide notes)
int notePrev; ///< MIDI pitch of the previous note (should be same as note for everything but SLIDE)
std::string syllable; ///< lyrics syllable for that note
diff --git a/songparser.cc b/songparser.cc
index 930c00a..b52724a 100644
--- a/songparser.cc
+++ b/songparser.cc
@@ -65,20 +65,7 @@ SongParser::SongParser(Song& s):
m_ss.write(&data[0], size);
}
// FIXME: convertToUTF8(m_ss, s.path + s.filename);
- // Header already parsed?
- if (s.loadStatus == Song::HEADER) {
- try {
- if (type == TXT) txtParse();
- else if (type == INI) iniParse();
- else if (type == SM) smParse();
- } catch (std::runtime_error& e) {
- throw SongParserException(e.what(), m_linenum);
- }
- finalize(); // Do some adjusting to the notes
- s.loadStatus = Song::FULL;
- return;
- }
- // Parse only header to speed up loading and conserve memory
+ // Header parsing
try {
if (type == TXT) txtParseHeader();
else if (type == INI) iniParseHeader();
@@ -112,6 +99,23 @@ SongParser::SongParser(Song& s):
}
}
s.loadStatus = Song::HEADER;
+
+ // Note: The full parser invocation below should actually be above header parsing
+ // if two-phase parsing is wanted
+
+ // Header already parsed?
+ if (s.loadStatus == Song::HEADER) {
+ try {
+ if (type == TXT) txtParse();
+ else if (type == INI) iniParse();
+ else if (type == SM) smParse();
+ } catch (std::runtime_error& e) {
+ throw SongParserException(e.what(), m_linenum);
+ }
+ finalize(); // Do some adjusting to the notes
+ s.loadStatus = Song::FULL;
+ return; // FIXME: Header-only parsing is disabled
+ }
}
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 18:39:30
|
Module: editor
Branch: master
Commit: 1f1c4294ca6303695fdc8764d1e8eca8d8eeb737
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 17:50:56 2011 +0200
Another progress dialog for actual pitch rendering.
---
notegraphwidget.cc | 7 +++++++
pitchvis.cc | 2 +-
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index 799cda4..5747ef2 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -13,14 +13,21 @@ NoteGraphWidget::NoteGraphWidget(QWidget *parent)
: QLabel(parent), m_panHotSpot(), m_selectedNote(), m_selectedAction(NONE), m_pitch("music.raw")
{
unsigned width = m_pitch.width(), height = m_pitch.height;
+ QProgressDialog progress(tr("Rendering pitch data..."), tr("&Abort"), 0, width, this);
+ progress.setWindowModality(Qt::WindowModal);
+
QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
unsigned* rgba = reinterpret_cast<unsigned*>(image.bits());
for (unsigned x = 0; x < width; ++x) {
+ progress.setValue(x);
+ if (progress.wasCanceled()) break;
+
for (unsigned y = 0; y < height; ++y) {
rgba[y * width + x] = m_pitch(x, y).rgba();
}
}
setPixmap(QPixmap::fromImage(image));
+ progress.setValue(width);
// FIXME: Width should come from song length * pixPerSec
setFixedSize(std::max(width, (unsigned)1024), height);
diff --git a/pitchvis.cc b/pitchvis.cc
index ca04b8e..2124fb4 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -29,7 +29,7 @@ PitchVis::PitchVis(std::string const& filename): height(1024) {
img.resize(width * height);
Analyzer analyzer(44100, "");
MusicalScale scale;
- QProgressDialog progress(tr("Analyzing and rendering pitch data..."), tr("&Abort"), 0, width, this);
+ QProgressDialog progress(tr("Analyzing pitch data..."), tr("&Abort"), 0, width, this);
progress.setWindowModality(Qt::WindowModal);
for (unsigned x = 0; x < width; ++x) {
|
|
From: Tapio V. <aa...@us...> - 2011-01-12 14:49:45
|
Module: editor Branch: master Commit: ac3571f3ab71cb34cd62c4520490e84e38d7b647 Author: Tapio Vierros <tap...@gm...> Date: Wed Jan 12 16:46:06 2011 +0200 Import classes from Performous in preparation of UltraStar parsing. Required some changes: * Boost dependency introduced - Qt could handle those, but I'm too lazy to convert for now * Note class went back to not using Duration - Too much stuff to change in parser * Unicode stuff is removed (Qt could probably be used for this) * Other hackery. --- CMakeLists.txt | 6 ++- notes.cc | 2 +- notes.hh | 16 ++---- song.cc | 108 +++++++++++++++++++++++++++++++++++++ song.hh | 140 +++++++++++++++++++++++++++++++++++++++++++++++ songparser-txt.cc | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ songparser.cc | 140 +++++++++++++++++++++++++++++++++++++++++++++++ songparser.hh | 90 +++++++++++++++++++++++++++++++ 8 files changed, 645 insertions(+), 12 deletions(-) |
|
From: Tapio V. <aa...@us...> - 2011-01-12 14:12:27
|
Module: editor
Branch: master
Commit: b35bdf99aaa35536ac2eaca82c23a3830d40446d
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 16:11:23 2011 +0200
Early draft of operation abstraction and partial undo implementation.
---
editor.ui | 3 +++
editorapp.cc | 21 +++++++++++++++++++++
editorapp.hh | 6 ++++++
notegraphwidget.cc | 13 +++++++++++--
notegraphwidget.hh | 4 ++++
operation.cc | 6 ++++++
operation.hh | 20 ++++++++++++++++++++
7 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/editor.ui b/editor.ui
index 52f041d..c71a596 100644
--- a/editor.ui
+++ b/editor.ui
@@ -382,6 +382,9 @@
</property>
</action>
<action name="actionRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>&Redo</string>
</property>
diff --git a/editorapp.cc b/editorapp.cc
index bcdc9d1..68b61b7 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -17,6 +17,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
ui.splitter->setSizes(ss);
// Custom signals/slots
+ connect(noteGraph, SIGNAL(operationDone(const Operation&)), this, SLOT(operationDone(const Operation&)));
connect(noteGraph, SIGNAL(updateNoteInfo(NoteLabel*)), this, SLOT(updateNoteInfo(NoteLabel*)));
updateNoteInfo(NULL);
@@ -36,6 +37,11 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
}
+void EditorApp::operationDone(const Operation& op)
+{
+ opStack.push(op);
+}
+
void EditorApp::updateNoteInfo(NoteLabel *note)
{
if (note) {
@@ -112,6 +118,21 @@ void EditorApp::on_actionExit_triggered()
}
}
+void EditorApp::on_actionUndo_triggered()
+{
+ // TODO: Move popped to redo stack
+ opStack.pop();
+ noteGraph->close();
+ noteGraph = new NoteGraphWidget(NULL);
+ ui.noteGraphScroller->setWidget(noteGraph);
+ // Re-apply all operations in the stack
+ for (OperationStack::const_iterator opit = opStack.begin(); opit != opStack.end(); ++opit) {
+ // FIXME: This should check from the operation what class will implement it
+ // and call the appropriate object. QObject meta info could be very useful.
+ noteGraph->doOperation(*opit, Operation::NO_EMIT);
+ }
+}
+
void EditorApp::on_actionMusicFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
diff --git a/editorapp.hh b/editorapp.hh
index eaa9fa2..0595dd6 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -1,6 +1,7 @@
#pragma once
#include "ui_editor.h"
+#include "operation.hh"
class NoteLabel;
class NoteGraphWidget;
@@ -13,6 +14,7 @@ public:
EditorApp(QWidget *parent = 0);
public slots:
+ void operationDone(const Operation& op);
void updateNoteInfo(NoteLabel* note);
// Automatic slots
@@ -22,6 +24,9 @@ public slots:
void on_actionOpen_triggered();
void on_actionExit_triggered();
+ // Edit menu
+ void on_actionUndo_triggered();
+
// Insert menu
void on_actionMusicFile_triggered();
void on_actionLyricsFromFile_triggered();
@@ -38,4 +43,5 @@ public slots:
private:
Ui::EditorApp ui;
NoteGraphWidget* noteGraph;
+ OperationStack opStack;
};
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index e94f743..799cda4 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -247,8 +247,8 @@ void NoteGraphWidget::mouseDoubleClickEvent(QMouseEvent *event)
// Spawn an input dialog
bool ok;
QString text = QInputDialog::getText(this, tr("Edit lyric"),
- tr("Lyric:"), QLineEdit::Normal,
- child->lyric(), &ok);
+ tr("Lyric:"), QLineEdit::Normal,
+ child->lyric(), &ok);
if (ok && !text.isEmpty()) {
child->setLyric(text);
child->createPixmap(child->size());
@@ -314,6 +314,15 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
}
}
+void NoteGraphWidget::doOperation(const Operation& op, Operation::OperationFlags flags)
+{
+ if (!(flags & Operation::NO_EXEC)) {
+ // TODO: This should perform the operation
+ }
+ if (!(flags & Operation::NO_EMIT))
+ emit operationDone(op);
+}
+
void FloatingGap::addNote(NoteLabel* n)
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index f9bc4c7..e7fdb5a 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -2,6 +2,7 @@
#include "pitchvis.hh"
#include "notes.hh"
+#include "operation.hh"
#include <QLabel>
#include <list>
@@ -26,8 +27,11 @@ public:
void selectNote(NoteLabel* note);
NoteLabel* selectedNote() const { return m_selectedNote; }
+ void doOperation(const Operation& op, Operation::OperationFlags flags = Operation::NORMAL);
+
signals:
void updateNoteInfo(NoteLabel*);
+ void operationDone(const Operation&);
protected:
void mousePressEvent(QMouseEvent *event);
diff --git a/operation.cc b/operation.cc
new file mode 100644
index 0000000..16faca5
--- /dev/null
+++ b/operation.cc
@@ -0,0 +1,6 @@
+#include "operation.hh"
+
+Operation::Operation(QString opString)
+{
+ (void)opString;
+}
diff --git a/operation.hh b/operation.hh
new file mode 100644
index 0000000..6f516c6
--- /dev/null
+++ b/operation.hh
@@ -0,0 +1,20 @@
+#pragma once
+#include <QString>
+#include <QStack>
+
+///! This is class is draft and subject to change
+
+struct Operation
+{
+ enum OperationFlags { NORMAL = 0, NO_EXEC = 1, NO_EMIT = 2 };
+
+ // FIXME: Somekind of nice serializable type for constructor
+ Operation(QString opString = "");
+
+ QString owner; /// Who performs the operation
+ unsigned id; /// E.g. a child id of the owner
+ unsigned action; /// Id of the action to-be-performed
+ void *data; /// User data
+};
+
+typedef QStack<Operation> OperationStack;
|