mirror of https://github.com/AxioDL/amuse.git
More work on Amuse Editor
This commit is contained in:
parent
3f265cdb46
commit
f50ee6e8f1
|
@ -0,0 +1,7 @@
|
|||
#include "ADSREditor.hpp"
|
||||
|
||||
ADSREditor::ADSREditor(ProjectModel::ADSRNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef AMUSE_ADSR_EDITOR_HPP
|
||||
#define AMUSE_ADSR_EDITOR_HPP
|
||||
|
||||
#include "EditorWidget.hpp"
|
||||
|
||||
class ADSREditor : public EditorWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ADSREditor(ProjectModel::ADSRNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
#endif //AMUSE_ADSR_EDITOR_HPP
|
|
@ -28,15 +28,17 @@ add_executable(amuse-gui WIN32 MACOSX_BUNDLE
|
|||
Common.hpp Common.cpp
|
||||
MainWindow.ui MainWindow.hpp MainWindow.cpp
|
||||
KeyboardWidget.hpp KeyboardWidget.cpp
|
||||
StatusBarWidget.hpp StatusBarWidget.cpp
|
||||
StatusBarWidget.hpp
|
||||
ProjectModel.hpp ProjectModel.cpp
|
||||
ProjectStatistics.hpp ProjectStatistics.cpp
|
||||
EditorWidget.hpp EditorWidget.cpp
|
||||
SoundMacroEditor.hpp SoundMacroEditor.cpp
|
||||
ADSREditor.hpp ADSREditor.cpp
|
||||
CurveEditor.hpp CurveEditor.cpp
|
||||
KeymapEditor.hpp KeymapEditor.cpp
|
||||
LayersEditor.hpp LayersEditor.cpp
|
||||
SampleEditor.hpp SampleEditor.cpp
|
||||
SFXGroupEditor.hpp SFXGroupEditor.cpp
|
||||
SoundGroupEditor.hpp SoundGroupEditor.cpp
|
||||
SongGroupEditor.hpp SongGroupEditor.cpp
|
||||
AudioGroupModel.hpp AudioGroupModel.cpp
|
||||
resources/resources.qrc qrc_resources.cpp
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include "CurveEditor.hpp"
|
||||
|
||||
CurveEditor::CurveEditor(ProjectModel::CurveNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef AMUSE_CURVE_EDITOR_HPP
|
||||
#define AMUSE_CURVE_EDITOR_HPP
|
||||
|
||||
#include "EditorWidget.hpp"
|
||||
|
||||
class CurveEditor : public EditorWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CurveEditor(ProjectModel::CurveNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
#endif //AMUSE_CURVE_EDITOR_HPP
|
|
@ -2,12 +2,14 @@
|
|||
#define AMUSE_EDITOR_WIDGET_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include "ProjectModel.hpp"
|
||||
|
||||
class EditorWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EditorWidget(QWidget* parent = Q_NULLPTR);
|
||||
virtual bool valid() const { return true; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,203 @@
|
|||
#include "KeyboardWidget.hpp"
|
||||
#include <QHBoxLayout>
|
||||
#include <QSvgRenderer>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollArea>
|
||||
|
||||
/* Used for generating transform matrices to map coordinate space */
|
||||
static QTransform RectToRect(const QRectF& from, const QRectF& to)
|
||||
{
|
||||
QPolygonF orig(from);
|
||||
orig.pop_back();
|
||||
QPolygonF resize(to);
|
||||
resize.pop_back();
|
||||
QTransform ret;
|
||||
QTransform::quadToQuad(orig, resize, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const QString NaturalKeyNames[] =
|
||||
{
|
||||
QStringLiteral("C"),
|
||||
QStringLiteral("D"),
|
||||
QStringLiteral("E"),
|
||||
QStringLiteral("F"),
|
||||
QStringLiteral("G"),
|
||||
QStringLiteral("A"),
|
||||
QStringLiteral("B")
|
||||
};
|
||||
|
||||
static const QString SharpKeyNames[] =
|
||||
{
|
||||
QStringLiteral("Cs"),
|
||||
QStringLiteral("Ds"),
|
||||
QStringLiteral("Fs"),
|
||||
QStringLiteral("Gs"),
|
||||
QStringLiteral("As")
|
||||
};
|
||||
|
||||
static const QString KeyStrings[] =
|
||||
{
|
||||
QStringLiteral("C"),
|
||||
QStringLiteral("C#"),
|
||||
QStringLiteral("D"),
|
||||
QStringLiteral("D#"),
|
||||
QStringLiteral("E"),
|
||||
QStringLiteral("F"),
|
||||
QStringLiteral("F#"),
|
||||
QStringLiteral("G"),
|
||||
QStringLiteral("G#"),
|
||||
QStringLiteral("A"),
|
||||
QStringLiteral("A#"),
|
||||
QStringLiteral("B")
|
||||
};
|
||||
|
||||
static const int NaturalKeyNumbers[] =
|
||||
{
|
||||
0, 2, 4, 5, 7, 9, 11
|
||||
};
|
||||
|
||||
static const int SharpKeyNumbers[] =
|
||||
{
|
||||
1, 3, 6, 8, 10
|
||||
};
|
||||
|
||||
KeyboardOctave::KeyboardOctave(int octave, const QString& svgPath, QWidget* parent)
|
||||
: QSvgWidget(svgPath, parent), m_octave(octave)
|
||||
{
|
||||
for (int i = 0; i < 7; ++i)
|
||||
if (renderer()->elementExists(NaturalKeyNames[i]))
|
||||
m_natural[i] = renderer()->matrixForElement(NaturalKeyNames[i]).
|
||||
mapRect(renderer()->boundsOnElement(NaturalKeyNames[i]));
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
if (renderer()->elementExists(SharpKeyNames[i]))
|
||||
m_sharp[i] = renderer()->matrixForElement(SharpKeyNames[i]).
|
||||
mapRect(renderer()->boundsOnElement(SharpKeyNames[i]));
|
||||
|
||||
/* The parent keyboard manages all mouse events */
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
}
|
||||
|
||||
int KeyboardOctave::getKey(const QPoint& localPos) const
|
||||
{
|
||||
QPointF localPoint = m_widgetToSvg.map(localPos);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
if (m_sharp[i].contains(localPoint))
|
||||
return SharpKeyNumbers[i];
|
||||
for (int i = 0; i < 7; ++i)
|
||||
if (m_natural[i].contains(localPoint))
|
||||
return NaturalKeyNumbers[i];
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KeyboardOctave::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
m_widgetToSvg = RectToRect(rect(), renderer()->viewBoxF());
|
||||
}
|
||||
|
||||
KeyboardWidget::KeyboardWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(QMargins());
|
||||
layout->setSpacing(0);
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
m_widgets[i] = new KeyboardOctave(i, QStringLiteral(":/bg/keyboard.svg"), this);
|
||||
m_widgets[i]->setGeometry(QRect(0, 0, 141, 50));
|
||||
m_widgets[i]->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
|
||||
layout->addWidget(m_widgets[i]);
|
||||
}
|
||||
|
||||
m_widgets[10] = new KeyboardOctave(10, QStringLiteral(":/bg/keyboard_last.svg"), this);
|
||||
m_widgets[10]->setGeometry(QRect(0, 0, 101, 50));
|
||||
m_widgets[10]->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred));
|
||||
layout->addWidget(m_widgets[10]);
|
||||
|
||||
setLayout(layout);
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
std::pair<int, int> KeyboardWidget::_getOctaveAndKey(QMouseEvent* event) const
|
||||
{
|
||||
for (KeyboardOctave* oct : m_widgets)
|
||||
{
|
||||
QPoint localPos = oct->mapFromParent(event->pos());
|
||||
if (oct->rect().contains(localPos))
|
||||
return {oct->getOctave(), oct->getKey(localPos)};
|
||||
}
|
||||
return {-1, -1};
|
||||
}
|
||||
|
||||
void KeyboardWidget::_startKey(int octave, int key)
|
||||
{
|
||||
printf("START %d %d\n", octave, key);
|
||||
}
|
||||
|
||||
void KeyboardWidget::_stopKey()
|
||||
{
|
||||
printf("STOP\n");
|
||||
}
|
||||
|
||||
void KeyboardWidget::_moveOnKey(int octave, int key)
|
||||
{
|
||||
if (m_lastOctave != octave || m_lastKey != key)
|
||||
{
|
||||
m_lastOctave = octave;
|
||||
m_lastKey = key;
|
||||
if (m_statusFocus)
|
||||
m_statusFocus->setMessage(QStringLiteral("%1%2").arg(KeyStrings[key]).arg(octave - 1));
|
||||
if (m_holding)
|
||||
_startKey(octave, key);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardWidget::_pressOnKey(int octave, int key)
|
||||
{
|
||||
_moveOnKey(octave, key);
|
||||
m_holding = true;
|
||||
_startKey(octave, key);
|
||||
}
|
||||
|
||||
void KeyboardWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
std::pair<int, int> ok = _getOctaveAndKey(event);
|
||||
if (ok.first != -1 && ok.second != -1)
|
||||
_moveOnKey(ok.first, ok.second);
|
||||
}
|
||||
|
||||
void KeyboardWidget::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
std::pair<int, int> ok = _getOctaveAndKey(event);
|
||||
if (ok.first != -1 && ok.second != -1)
|
||||
_pressOnKey(ok.first, ok.second);
|
||||
}
|
||||
|
||||
void KeyboardWidget::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
_stopKey();
|
||||
m_holding = false;
|
||||
}
|
||||
|
||||
void KeyboardWidget::enterEvent(QEvent* event)
|
||||
{
|
||||
if (m_statusFocus)
|
||||
m_statusFocus->enter();
|
||||
}
|
||||
|
||||
void KeyboardWidget::leaveEvent(QEvent* event)
|
||||
{
|
||||
if (m_statusFocus)
|
||||
m_statusFocus->exit();
|
||||
}
|
||||
|
||||
void KeyboardWidget::showEvent(QShowEvent* event)
|
||||
{
|
||||
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
||||
{
|
||||
/* Scroll to C3 */
|
||||
scroll->ensureVisible(141 * 4 + scroll->width(), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,50 @@
|
|||
#define AMUSE_KEYBOARD_WIDGET_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSvgWidget>
|
||||
#include "StatusBarWidget.hpp"
|
||||
|
||||
class KeyboardWidget;
|
||||
|
||||
class KeyboardOctave : public QSvgWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
int m_octave;
|
||||
QRectF m_natural[7];
|
||||
QRectF m_sharp[5];
|
||||
QTransform m_widgetToSvg;
|
||||
public:
|
||||
explicit KeyboardOctave(int octave, const QString& svgPath, QWidget* parent = Q_NULLPTR);
|
||||
int getOctave() const { return m_octave; }
|
||||
int getKey(const QPoint& localPos) const;
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
};
|
||||
|
||||
class KeyboardWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
KeyboardOctave* m_widgets[11];
|
||||
StatusBarFocus* m_statusFocus = nullptr;
|
||||
int m_lastOctave = -1;
|
||||
int m_lastKey = -1;
|
||||
bool m_holding = false;
|
||||
|
||||
std::pair<int, int> _getOctaveAndKey(QMouseEvent* event) const;
|
||||
void _startKey(int octave, int key);
|
||||
void _stopKey();
|
||||
void _moveOnKey(int octave, int key);
|
||||
void _pressOnKey(int octave, int key);
|
||||
|
||||
public:
|
||||
explicit KeyboardWidget(QWidget* parent = Q_NULLPTR);
|
||||
void setStatusFocus(StatusBarFocus* statusFocus) { m_statusFocus = statusFocus; }
|
||||
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
void enterEvent(QEvent* event);
|
||||
void leaveEvent(QEvent* event);
|
||||
void showEvent(QShowEvent *event);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "KeymapEditor.hpp"
|
||||
|
||||
KeymapEditor::KeymapEditor(QWidget* parent)
|
||||
KeymapEditor::KeymapEditor(ProjectModel::KeymapNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class KeymapEditor : public EditorWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KeymapEditor(QWidget* parent = Q_NULLPTR);
|
||||
explicit KeymapEditor(ProjectModel::KeymapNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "LayersEditor.hpp"
|
||||
|
||||
LayersEditor::LayersEditor(QWidget* parent)
|
||||
LayersEditor::LayersEditor(ProjectModel::LayersNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class LayersEditor : public EditorWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LayersEditor(QWidget* parent = Q_NULLPTR);
|
||||
explicit LayersEditor(ProjectModel::LayersNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4,9 +4,18 @@
|
|||
#include <QLineEdit>
|
||||
#include <QInputDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QMouseEvent>
|
||||
#include <QtSvg/QtSvg>
|
||||
#include "amuse/ContainerRegistry.hpp"
|
||||
#include "Common.hpp"
|
||||
#include "SongGroupEditor.hpp"
|
||||
#include "SoundGroupEditor.hpp"
|
||||
#include "SoundGroupEditor.hpp"
|
||||
#include "SoundMacroEditor.hpp"
|
||||
#include "ADSREditor.hpp"
|
||||
#include "CurveEditor.hpp"
|
||||
#include "KeymapEditor.hpp"
|
||||
#include "LayersEditor.hpp"
|
||||
|
||||
static void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
|
||||
{
|
||||
|
@ -15,6 +24,7 @@ static void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
|
|||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent),
|
||||
m_treeDelegate(*this, this),
|
||||
m_mainMessenger(this),
|
||||
m_undoStack(new QUndoStack(this)),
|
||||
m_backgroundThread(this)
|
||||
|
@ -22,8 +32,11 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
m_backgroundThread.start();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
m_ui.projectOutline->setItemDelegate(&m_treeDelegate);
|
||||
connectMessenger(&m_mainMessenger, Qt::DirectConnection);
|
||||
|
||||
m_ui.keyboardContents->setStatusFocus(new StatusBarFocus(m_ui.statusbar));
|
||||
|
||||
m_ui.actionNew_Project->setShortcut(QKeySequence::New);
|
||||
connect(m_ui.actionNew_Project, SIGNAL(triggered()), this, SLOT(newAction()));
|
||||
m_ui.actionOpen_Project->setShortcut(QKeySequence::Open);
|
||||
|
@ -45,11 +58,21 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
m_ui.actionDelete->setShortcut(QKeySequence::Delete);
|
||||
onFocusChanged(nullptr, this);
|
||||
|
||||
m_ui.editorSvg->load(QStringLiteral(":/bg/FaceGrey.svg"));
|
||||
QGridLayout* faceLayout = new QGridLayout;
|
||||
QSvgWidget* faceSvg = new QSvgWidget(QStringLiteral(":/bg/FaceGrey.svg"));
|
||||
faceSvg->setGeometry(0, 0, 256, 256);
|
||||
faceSvg->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
faceLayout->addWidget(faceSvg);
|
||||
m_faceSvg = new QWidget;
|
||||
m_faceSvg->setLayout(faceLayout);
|
||||
m_ui.editorContents->addWidget(m_faceSvg);
|
||||
|
||||
connect(m_ui.actionNew_Subproject, SIGNAL(triggered()), this, SLOT(newSubprojectAction()));
|
||||
connect(m_ui.actionNew_SFX_Group, SIGNAL(triggered()), this, SLOT(newSFXGroupAction()));
|
||||
connect(m_ui.actionNew_Song_Group, SIGNAL(triggered()), this, SLOT(newSongGroupAction()));
|
||||
connect(m_ui.actionNew_Sound_Macro, SIGNAL(triggered()), this, SLOT(newSoundMacroAction()));
|
||||
connect(m_ui.actionNew_ADSR, SIGNAL(triggered()), this, SLOT(newADSRAction()));
|
||||
connect(m_ui.actionNew_Curve, SIGNAL(triggered()), this, SLOT(newCurveAction()));
|
||||
connect(m_ui.actionNew_Keymap, SIGNAL(triggered()), this, SLOT(newKeymapAction()));
|
||||
connect(m_ui.actionNew_Layers, SIGNAL(triggered()), this, SLOT(newLayersAction()));
|
||||
|
||||
|
@ -128,6 +151,9 @@ bool MainWindow::setProjectPath(const QString& path)
|
|||
m_ui.projectOutline->setModel(m_projectModel);
|
||||
m_ui.actionExport_GameCube_Groups->setEnabled(true);
|
||||
setWindowFilePath(path);
|
||||
#ifndef __APPLE__
|
||||
setWindowTitle(QString("Amuse - %1").arg(dir.dirName()));
|
||||
#endif
|
||||
setFocusAudioGroup(nullptr);
|
||||
onFocusChanged(nullptr, focusWidget());
|
||||
|
||||
|
@ -217,6 +243,88 @@ void MainWindow::startBackgroundTask(const QString& windowTitle, const QString&
|
|||
QMetaObject::invokeMethod(m_backgroundTask, "run", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
bool MainWindow::_setEditor(EditorWidget* editor)
|
||||
{
|
||||
while (m_ui.editorContents->currentWidget() != m_faceSvg)
|
||||
{
|
||||
m_ui.editorContents->currentWidget()->deleteLater();
|
||||
m_ui.editorContents->removeWidget(m_ui.editorContents->currentWidget());
|
||||
}
|
||||
if (!editor)
|
||||
return false;
|
||||
if (!editor->valid())
|
||||
{
|
||||
editor->deleteLater();
|
||||
return false;
|
||||
}
|
||||
m_ui.editorContents->addWidget(editor);
|
||||
m_ui.editorContents->setCurrentWidget(editor);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::SongGroupNode* node)
|
||||
{
|
||||
return _setEditor(new SongGroupEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::SoundGroupNode* node)
|
||||
{
|
||||
return _setEditor(new SoundGroupEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::SoundMacroNode* node)
|
||||
{
|
||||
return _setEditor(new SoundMacroEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::ADSRNode* node)
|
||||
{
|
||||
return _setEditor(new ADSREditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::CurveNode* node)
|
||||
{
|
||||
return _setEditor(new CurveEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::KeymapNode* node)
|
||||
{
|
||||
return _setEditor(new KeymapEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::LayersNode* node)
|
||||
{
|
||||
return _setEditor(new LayersEditor(node));
|
||||
}
|
||||
|
||||
bool MainWindow::openEditor(ProjectModel::INode* node)
|
||||
{
|
||||
switch (node->type())
|
||||
{
|
||||
case ProjectModel::INode::Type::SongGroup:
|
||||
return openEditor(static_cast<ProjectModel::SongGroupNode*>(node));
|
||||
case ProjectModel::INode::Type::SoundGroup:
|
||||
return openEditor(static_cast<ProjectModel::SoundGroupNode*>(node));
|
||||
case ProjectModel::INode::Type::SoundMacro:
|
||||
return openEditor(static_cast<ProjectModel::SoundMacroNode*>(node));
|
||||
case ProjectModel::INode::Type::ADSR:
|
||||
return openEditor(static_cast<ProjectModel::ADSRNode*>(node));
|
||||
case ProjectModel::INode::Type::Curve:
|
||||
return openEditor(static_cast<ProjectModel::CurveNode*>(node));
|
||||
case ProjectModel::INode::Type::Keymap:
|
||||
return openEditor(static_cast<ProjectModel::KeymapNode*>(node));
|
||||
case ProjectModel::INode::Type::Layer:
|
||||
return openEditor(static_cast<ProjectModel::LayersNode*>(node));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeEditor()
|
||||
{
|
||||
_setEditor(nullptr);
|
||||
}
|
||||
|
||||
void MainWindow::newAction()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("New Project"));
|
||||
|
@ -226,6 +334,9 @@ void MainWindow::newAction()
|
|||
return;
|
||||
if (!setProjectPath(path))
|
||||
return;
|
||||
|
||||
m_projectModel->clearProjectData();
|
||||
m_projectModel->ensureModelData();
|
||||
}
|
||||
|
||||
void MainWindow::openAction()
|
||||
|
@ -233,10 +344,41 @@ void MainWindow::openAction()
|
|||
QString path = QFileDialog::getExistingDirectory(this, tr("Open Project"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QDir dir(path);
|
||||
if (!dir.exists())
|
||||
{
|
||||
QString msg = QString(tr("The directory at '%1' does not exist.")).arg(path);
|
||||
QMessageBox::critical(this, tr("Bad Directory"), msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (QFileInfo(dir, QStringLiteral("!project.yaml")).exists() &&
|
||||
QFileInfo(dir, QStringLiteral("!pool.yaml")).exists())
|
||||
dir.cdUp();
|
||||
|
||||
if (!setProjectPath(path))
|
||||
return;
|
||||
|
||||
|
||||
ProjectModel* model = m_projectModel;
|
||||
startBackgroundTask(tr("Opening"), tr("Scanning Project"),
|
||||
[dir, model](BackgroundTask& task)
|
||||
{
|
||||
QStringList childDirs = dir.entryList(QDir::Dirs);
|
||||
for (const auto& chDir : childDirs)
|
||||
{
|
||||
if (task.isCanceled())
|
||||
return;
|
||||
QString chPath = dir.filePath(chDir);
|
||||
if (QFileInfo(chPath, QStringLiteral("!project.yaml")).exists() &&
|
||||
QFileInfo(chPath, QStringLiteral("!pool.yaml")).exists())
|
||||
{
|
||||
task.setLabelText(tr("Opening %1").arg(chDir));
|
||||
if (!model->openGroupData(chDir, task.uiMessenger()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::importAction()
|
||||
|
@ -372,6 +514,33 @@ void MainWindow::exportAction()
|
|||
|
||||
}
|
||||
|
||||
bool TreeDelegate::editorEvent(QEvent* event,
|
||||
QAbstractItemModel* _model,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index)
|
||||
{
|
||||
ProjectModel* model = static_cast<ProjectModel*>(_model);
|
||||
ProjectModel::INode* node = model->node(index);
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
if ((event->type() == QEvent::MouseButtonDblClick &&
|
||||
static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton) ||
|
||||
(event->type() == QEvent::KeyPress &&
|
||||
static_cast<QKeyEvent*>(event)->key() == Qt::Key_Enter))
|
||||
{
|
||||
// Open in editor
|
||||
return m_window.openEditor(node);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::newSubprojectAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::newSFXGroupAction()
|
||||
{
|
||||
|
||||
|
@ -387,6 +556,16 @@ void MainWindow::newSoundMacroAction()
|
|||
|
||||
}
|
||||
|
||||
void MainWindow::newADSRAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::newCurveAction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::newKeymapAction()
|
||||
{
|
||||
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
#include <QUndoStack>
|
||||
#include <QProgressDialog>
|
||||
#include <QThread>
|
||||
#include <QStyledItemDelegate>
|
||||
#include "ui_MainWindow.h"
|
||||
#include "amuse/Engine.hpp"
|
||||
#include "amuse/BooBackend.hpp"
|
||||
#include "boo/audiodev/IAudioVoiceEngine.hpp"
|
||||
#include "ProjectModel.hpp"
|
||||
#include "EditorWidget.hpp"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow;
|
||||
class AudioGroupModel;
|
||||
|
||||
class BackgroundTask : public QObject
|
||||
|
@ -41,13 +44,29 @@ public slots:
|
|||
void cancel() { m_cancelled = true; }
|
||||
};
|
||||
|
||||
class TreeDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
MainWindow& m_window;
|
||||
public:
|
||||
explicit TreeDelegate(MainWindow& window, QObject* parent = Q_NULLPTR)
|
||||
: QStyledItemDelegate(parent), m_window(window) {}
|
||||
|
||||
bool editorEvent(QEvent *event,
|
||||
QAbstractItemModel *model,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index);
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Ui::MainWindow m_ui;
|
||||
TreeDelegate m_treeDelegate;
|
||||
UIMessenger m_mainMessenger;
|
||||
ProjectModel* m_projectModel = nullptr;
|
||||
AudioGroupModel* m_focusAudioGroup = nullptr;
|
||||
QWidget* m_faceSvg;
|
||||
|
||||
std::unique_ptr<boo::IAudioVoiceEngine> m_voxEngine;
|
||||
std::unique_ptr<amuse::BooBackendVoiceAllocator> m_voxAllocator;
|
||||
|
@ -79,19 +98,34 @@ class MainWindow : public QMainWindow
|
|||
void startBackgroundTask(const QString& windowTitle, const QString& label,
|
||||
std::function<void(BackgroundTask&)>&& task);
|
||||
|
||||
bool _setEditor(EditorWidget* widget);
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = Q_NULLPTR);
|
||||
~MainWindow();
|
||||
|
||||
bool openEditor(ProjectModel::SongGroupNode* node);
|
||||
bool openEditor(ProjectModel::SoundGroupNode* node);
|
||||
bool openEditor(ProjectModel::SoundMacroNode* node);
|
||||
bool openEditor(ProjectModel::ADSRNode* node);
|
||||
bool openEditor(ProjectModel::CurveNode* node);
|
||||
bool openEditor(ProjectModel::KeymapNode* node);
|
||||
bool openEditor(ProjectModel::LayersNode* node);
|
||||
bool openEditor(ProjectModel::INode* node);
|
||||
void closeEditor();
|
||||
|
||||
public slots:
|
||||
void newAction();
|
||||
void openAction();
|
||||
void importAction();
|
||||
void exportAction();
|
||||
|
||||
void newSubprojectAction();
|
||||
void newSFXGroupAction();
|
||||
void newSongGroupAction();
|
||||
void newSoundMacroAction();
|
||||
void newADSRAction();
|
||||
void newCurveAction();
|
||||
void newKeymapAction();
|
||||
void newLayersAction();
|
||||
|
||||
|
|
|
@ -35,41 +35,25 @@
|
|||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="leftSplitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QTreeView" name="projectOutline">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QTreeView" name="projectOutline">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QTableView" name="propertyEditor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>2</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="rightSplitter">
|
||||
<property name="sizePolicy">
|
||||
|
@ -109,7 +93,7 @@
|
|||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="editorContents">
|
||||
<widget class="QStackedWidget" name="editorContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
|
@ -118,24 +102,6 @@
|
|||
<height>442</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSvgWidget" name="editorSvg" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>256</width>
|
||||
<height>256</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="keyboardScrollArea">
|
||||
|
@ -174,10 +140,22 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>540</width>
|
||||
<height>100</height>
|
||||
<width>1501</width>
|
||||
<height>85</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1501</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
|
@ -213,10 +191,14 @@
|
|||
<property name="title">
|
||||
<string>P&roject</string>
|
||||
</property>
|
||||
<addaction name="actionNew_Subproject"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionNew_SFX_Group"/>
|
||||
<addaction name="actionNew_Song_Group"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionNew_Sound_Macro"/>
|
||||
<addaction name="actionNew_ADSR"/>
|
||||
<addaction name="actionNew_Curve"/>
|
||||
<addaction name="actionNew_Keymap"/>
|
||||
<addaction name="actionNew_Layers"/>
|
||||
</widget>
|
||||
|
@ -418,6 +400,42 @@
|
|||
<string>Ctrl+E</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNew_Subproject">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/IconNewGroup.svg</normaloff>:/icons/IconNewGroup.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N&ew Subproject</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNew_ADSR">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/IconNewADSR.svg</normaloff>:/icons/IconNewADSR.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ne&w ADSR</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNew_Curve">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/icons/IconNewCurve.svg</normaloff>:/icons/IconNewCurve.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New &Curve</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -431,12 +449,6 @@
|
|||
<extends>QStatusBar</extends>
|
||||
<header>StatusBarWidget.hpp</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QSvgWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">QSvgWidget</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
@ -18,6 +18,25 @@ ProjectModel::ProjectModel(const QString& path, QObject* parent)
|
|||
SoundGroupNode::Icon = QIcon(":/icons/IconSoundGroup.svg");
|
||||
}
|
||||
|
||||
bool ProjectModel::clearProjectData()
|
||||
{
|
||||
m_projectDatabase = amuse::ProjectDatabase();
|
||||
m_groups.clear();
|
||||
|
||||
m_needsReset = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectModel::openGroupData(const QString& groupName, UIMessenger& messenger)
|
||||
{
|
||||
m_projectDatabase.setIdDatabases();
|
||||
QString path = QFileInfo(m_dir, groupName).filePath();
|
||||
m_groups.insert(std::make_pair(groupName, QStringToSysString(path)));
|
||||
|
||||
m_needsReset = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectModel::importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
|
||||
ImportMode mode, UIMessenger& messenger)
|
||||
{
|
||||
|
@ -89,12 +108,13 @@ void ProjectModel::_resetModelData()
|
|||
{
|
||||
it->second.setIdDatabases();
|
||||
GroupNode& gn = m_root->makeChild<GroupNode>(it);
|
||||
auto& songGroups = it->second.getProj().songGroups();
|
||||
auto& sfxGroups = it->second.getProj().sfxGroups();
|
||||
auto& soundMacros = it->second.getPool().soundMacros();
|
||||
auto& tables = it->second.getPool().tables();
|
||||
auto& keymaps = it->second.getPool().keymaps();
|
||||
auto& layers = it->second.getPool().layers();
|
||||
amuse::AudioGroup& group = it->second;
|
||||
auto& songGroups = group.getProj().songGroups();
|
||||
auto& sfxGroups = group.getProj().sfxGroups();
|
||||
auto& soundMacros = group.getPool().soundMacros();
|
||||
auto& tables = group.getPool().tables();
|
||||
auto& keymaps = group.getPool().keymaps();
|
||||
auto& layers = group.getPool().layers();
|
||||
gn.reserve(songGroups.size() + sfxGroups.size() + 4);
|
||||
for (const auto& grp : SortUnorderedMap(songGroups))
|
||||
gn.makeChild<SongGroupNode>(grp.first, grp.second.get());
|
||||
|
@ -106,7 +126,7 @@ void ProjectModel::_resetModelData()
|
|||
gn.makeChild<CollectionNode>(tr("Sound Macros"), QIcon(":/icons/IconSoundMacro.svg"));
|
||||
col.reserve(soundMacros.size());
|
||||
for (const auto& macro : SortUnorderedMap(soundMacros))
|
||||
col.makeChild<PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro>>(macro.first, macro.second.get());
|
||||
col.makeChild<SoundMacroNode>(macro.first, macro.second.get());
|
||||
}
|
||||
if (tables.size())
|
||||
{
|
||||
|
@ -130,7 +150,7 @@ void ProjectModel::_resetModelData()
|
|||
{
|
||||
amuse::ITable::Type tp = t.second.get()->Isa();
|
||||
if (tp == amuse::ITable::Type::ADSR || tp == amuse::ITable::Type::ADSRDLS)
|
||||
col.makeChild<PoolObjectNode<amuse::TableId, amuse::ITable>>(t.first, *t.second.get());
|
||||
col.makeChild<ADSRNode>(t.first, *t.second.get());
|
||||
}
|
||||
}
|
||||
if (curveCount)
|
||||
|
@ -142,7 +162,7 @@ void ProjectModel::_resetModelData()
|
|||
{
|
||||
amuse::ITable::Type tp = t.second.get()->Isa();
|
||||
if (tp == amuse::ITable::Type::Curve)
|
||||
col.makeChild<PoolObjectNode<amuse::TableId, amuse::Curve>>(t.first, static_cast<amuse::Curve&>(*t.second.get()));
|
||||
col.makeChild<CurveNode>(t.first, static_cast<amuse::Curve&>(*t.second.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +172,7 @@ void ProjectModel::_resetModelData()
|
|||
gn.makeChild<CollectionNode>(tr("Keymaps"), QIcon(":/icons/IconKeymap.svg"));
|
||||
col.reserve(keymaps.size());
|
||||
for (auto& keymap : SortUnorderedMap(keymaps))
|
||||
col.makeChild<PoolObjectNode<amuse::KeymapId, amuse::Keymap>>(keymap.first, keymap.second.get());
|
||||
col.makeChild<KeymapNode>(keymap.first, keymap.second.get());
|
||||
}
|
||||
if (layers.size())
|
||||
{
|
||||
|
@ -160,7 +180,7 @@ void ProjectModel::_resetModelData()
|
|||
gn.makeChild<CollectionNode>(tr("Layers"), QIcon(":/icons/IconLayers.svg"));
|
||||
col.reserve(layers.size());
|
||||
for (auto& keymap : SortUnorderedMap(layers))
|
||||
col.makeChild<PoolObjectNode<amuse::LayersId, std::vector<amuse::LayerMapping>>>(keymap.first, keymap.second.get());
|
||||
col.makeChild<LayersNode>(keymap.first, keymap.second.get());
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
|
@ -250,6 +270,13 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex& index) const
|
|||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
|
||||
ProjectModel::INode* ProjectModel::node(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return nullptr;
|
||||
return static_cast<INode*>(index.internalPointer());
|
||||
}
|
||||
|
||||
bool ProjectModel::canDelete() const
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -29,13 +29,16 @@ private:
|
|||
amuse::ProjectDatabase m_projectDatabase;
|
||||
std::map<QString, amuse::AudioGroupDatabase> m_groups;
|
||||
|
||||
public:
|
||||
class INode
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
Root,
|
||||
Group, // Top-level group
|
||||
SongGroup,
|
||||
SfxGroup,
|
||||
SoundGroup,
|
||||
Collection, // Classified object collection, one of the following:
|
||||
SoundMacro,
|
||||
ADSR,
|
||||
|
@ -43,6 +46,7 @@ private:
|
|||
Keymap,
|
||||
Layer
|
||||
};
|
||||
private:
|
||||
INode* m_parent;
|
||||
std::vector<std::unique_ptr<INode>> m_children;
|
||||
int m_row;
|
||||
|
@ -63,6 +67,7 @@ private:
|
|||
return static_cast<T&>(*m_children.back());
|
||||
}
|
||||
|
||||
virtual Type type() const = 0;
|
||||
virtual QString text() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
};
|
||||
|
@ -70,6 +75,7 @@ private:
|
|||
{
|
||||
RootNode() : INode(nullptr, 0) {}
|
||||
|
||||
Type type() const { return Type::Root; }
|
||||
QString text() const { return {}; }
|
||||
QIcon icon() const { return {}; }
|
||||
};
|
||||
|
@ -80,6 +86,7 @@ private:
|
|||
: INode(parent, row), m_it(it) {}
|
||||
|
||||
static QIcon Icon;
|
||||
Type type() const { return Type::Group; }
|
||||
QString text() const { return m_it->first; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
|
@ -92,6 +99,7 @@ private:
|
|||
: INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
|
||||
|
||||
static QIcon Icon;
|
||||
Type type() const { return Type::SongGroup; }
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
|
@ -104,6 +112,7 @@ private:
|
|||
: INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
|
||||
|
||||
static QIcon Icon;
|
||||
Type type() const { return Type::SoundGroup; }
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
|
@ -114,10 +123,11 @@ private:
|
|||
CollectionNode(INode* parent, int row, const QString& name, const QIcon& icon)
|
||||
: INode(parent, row), m_name(name), m_icon(icon) {}
|
||||
|
||||
Type type() const { return Type::Collection; }
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return m_icon; }
|
||||
};
|
||||
template <class ID, class T>
|
||||
template <class ID, class T, INode::Type TP>
|
||||
struct PoolObjectNode : INode
|
||||
{
|
||||
ID m_id;
|
||||
|
@ -126,9 +136,15 @@ private:
|
|||
PoolObjectNode(INode* parent, int row, ID id, T& obj)
|
||||
: INode(parent, row), m_id(id), m_name(ID::CurNameDB->resolveNameFromId(id).data()), m_obj(obj) {}
|
||||
|
||||
Type type() const { return TP; }
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return {}; }
|
||||
};
|
||||
using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>;
|
||||
using ADSRNode = PoolObjectNode<amuse::TableId, amuse::ITable, INode::Type::ADSR>;
|
||||
using CurveNode = PoolObjectNode<amuse::TableId, amuse::Curve, INode::Type::Curve>;
|
||||
using KeymapNode = PoolObjectNode<amuse::KeymapId, amuse::Keymap, INode::Type::Keymap>;
|
||||
using LayersNode = PoolObjectNode<amuse::LayersId, std::vector<amuse::LayerMapping>, INode::Type::Layer>;
|
||||
|
||||
std::unique_ptr<RootNode> m_root;
|
||||
|
||||
|
@ -138,6 +154,8 @@ private:
|
|||
public:
|
||||
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR);
|
||||
|
||||
bool clearProjectData();
|
||||
bool openGroupData(const QString& groupName, UIMessenger& messenger);
|
||||
bool importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
|
||||
ImportMode mode, UIMessenger& messenger);
|
||||
bool saveToFile(UIMessenger& messenger);
|
||||
|
@ -150,6 +168,7 @@ public:
|
|||
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
INode* node(const QModelIndex& index) const;
|
||||
|
||||
QString path() const { return m_dir.path(); }
|
||||
bool canDelete() const;
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#include "SFXGroupEditor.hpp"
|
||||
|
||||
SFXGroupEditor::SFXGroupEditor(QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef AMUSE_SFX_GROUP_EDITOR_HPP
|
||||
#define AMUSE_SFX_GROUP_EDITOR_HPP
|
||||
|
||||
#include "EditorWidget.hpp"
|
||||
|
||||
class SFXGroupEditor : public EditorWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SFXGroupEditor(QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
#endif //AMUSE_SFX_GROUP_EDITOR_HPP
|
|
@ -1,6 +1,6 @@
|
|||
#include "SongGroupEditor.hpp"
|
||||
|
||||
SongGroupEditor::SongGroupEditor(QWidget* parent)
|
||||
SongGroupEditor::SongGroupEditor(ProjectModel::SongGroupNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ class SongGroupEditor : public EditorWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SongGroupEditor(QWidget* parent = Q_NULLPTR);
|
||||
explicit SongGroupEditor(ProjectModel::SongGroupNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include "SoundGroupEditor.hpp"
|
||||
|
||||
SoundGroupEditor::SoundGroupEditor(ProjectModel::SoundGroupNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef AMUSE_SOUND_GROUP_EDITOR_HPP
|
||||
#define AMUSE_SOUND_GROUP_EDITOR_HPP
|
||||
|
||||
#include "EditorWidget.hpp"
|
||||
|
||||
class SoundGroupEditor : public EditorWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SoundGroupEditor(ProjectModel::SoundGroupNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
#endif //AMUSE_SOUND_GROUP_EDITOR_HPP
|
|
@ -1,7 +1,10 @@
|
|||
#include "SoundMacroEditor.hpp"
|
||||
#include <QLabel>
|
||||
|
||||
SoundMacroEditor::SoundMacroEditor(QWidget* parent)
|
||||
SoundMacroEditor::SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent)
|
||||
: EditorWidget(parent)
|
||||
{
|
||||
|
||||
QLabel* lab = new QLabel;
|
||||
lab->setText(node->m_name);
|
||||
lab->setParent(this);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ class SoundMacroEditor : public EditorWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SoundMacroEditor(QWidget* parent = Q_NULLPTR);
|
||||
explicit SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#include "StatusBarWidget.hpp"
|
||||
|
||||
StatusBarWidget::StatusBarWidget(QWidget* parent)
|
||||
: QStatusBar(parent)
|
||||
{
|
||||
|
||||
}
|
|
@ -2,13 +2,65 @@
|
|||
#define AMUSE_STATUSBAR_WIDGET_HPP
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QLabel>
|
||||
|
||||
class StatusBarFocus;
|
||||
|
||||
class StatusBarWidget : public QStatusBar
|
||||
{
|
||||
friend class StatusBarFocus;
|
||||
Q_OBJECT
|
||||
QLabel* m_normalMessage;
|
||||
StatusBarFocus* m_curFocus = nullptr;
|
||||
public:
|
||||
explicit StatusBarWidget(QWidget* parent = Q_NULLPTR);
|
||||
explicit StatusBarWidget(QWidget* parent = Q_NULLPTR) : QStatusBar(parent) {}
|
||||
void setNormalMessage(const QString& message) { m_normalMessage->setText(message); }
|
||||
};
|
||||
|
||||
class StatusBarFocus : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QString m_message;
|
||||
public:
|
||||
explicit StatusBarFocus(StatusBarWidget* statusWidget)
|
||||
: QObject(statusWidget) {}
|
||||
~StatusBarFocus() { exit(); }
|
||||
void setMessage(const QString& message)
|
||||
{
|
||||
m_message = message;
|
||||
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent()))
|
||||
{
|
||||
if (widget->m_curFocus == this)
|
||||
{
|
||||
if (m_message.isEmpty())
|
||||
widget->clearMessage();
|
||||
else
|
||||
widget->showMessage(m_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
void enter()
|
||||
{
|
||||
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent()))
|
||||
{
|
||||
widget->m_curFocus = this;
|
||||
if (m_message.isEmpty())
|
||||
widget->clearMessage();
|
||||
else
|
||||
widget->showMessage(m_message);
|
||||
}
|
||||
}
|
||||
void exit()
|
||||
{
|
||||
if (StatusBarWidget* widget = qobject_cast<StatusBarWidget*>(parent()))
|
||||
{
|
||||
if (widget->m_curFocus == this)
|
||||
{
|
||||
widget->clearMessage();
|
||||
widget->m_curFocus = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif //AMUSE_STATUSBAR_WIDGET_HPP
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="140"
|
||||
height="100"
|
||||
viewBox="0 0 37.041665 26.458336"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="keyboard.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="whiteKey">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4540" />
|
||||
<stop
|
||||
id="stop4552"
|
||||
offset="0.67000026"
|
||||
style="stop-color:#cecece;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4550"
|
||||
offset="0.68000031"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4542" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="blackKey">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4528" />
|
||||
<stop
|
||||
id="stop4538"
|
||||
offset="0.33333373"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4536"
|
||||
offset="0.36666706"
|
||||
style="stop-color:#313131;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4530" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534"
|
||||
x1="2.6458333"
|
||||
y1="286.41666"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.66145845)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-3"
|
||||
x1="2.645833"
|
||||
y1="286.41663"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(6.6145838,1.0903046e-5)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-6"
|
||||
x1="2.6458328"
|
||||
y1="286.41666"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(15.875001,7.6333333e-6)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-0"
|
||||
x1="2.645833"
|
||||
y1="286.41663"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(21.828126,1.4333333e-5)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-2"
|
||||
x1="2.645833"
|
||||
y1="286.41666"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(27.781251,7.7033334e-6)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#313131"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.4618283"
|
||||
inkscape:cx="44.115558"
|
||||
inkscape:cy="71.875845"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1286"
|
||||
inkscape:window-height="1176"
|
||||
inkscape:window-x="1170"
|
||||
inkscape:window-y="447"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4518"
|
||||
spacingx="0.13229167"
|
||||
spacingy="0.26458333"
|
||||
visible="false"
|
||||
empspacing="5"
|
||||
originx="0.13229165"
|
||||
originy="0.13228834" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0.13229166,-270.67394)">
|
||||
<path
|
||||
style="fill:#fdfdfd;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,270.54165 v 26.45833 H 5.2916666 V 286.41665 H 3.3072917 v -15.875 z"
|
||||
id="C"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:label="C" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 5.2916666,296.99998 H 10.583333 V 286.41665 H 9.2604166 v -15.875 H 7.2760419 v 15.875 H 5.2916666 Z"
|
||||
id="D"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:label="D" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.3072917,270.54165 v 15.875 h 3.9687499 v -15.875 z"
|
||||
id="Cs"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Cs" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.583333,296.99998 H 15.875 v -26.45833 h -2.645834 v 15.875 h -2.645833 z"
|
||||
id="E"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="E" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 15.875,296.99998 h 5.291666 v -10.58333 h -2.645833 v -15.875 H 15.875 Z"
|
||||
id="F"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="F" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 21.166666,296.99998 h 5.291667 v -10.58333 h -1.984374 v -15.875 h -1.984376 v 15.875 h -1.322917 z"
|
||||
id="G"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:label="G" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 26.458333,296.99998 H 31.75 v -10.58333 h -1.322917 v -15.875 h -1.984374 v 15.875 h -1.984376 z"
|
||||
id="A"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:label="A" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 31.75,296.99998 h 5.291666 v -10.58333 -15.875 h -2.645833 v 15.875 H 31.75 Z"
|
||||
id="B"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:label="B" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-3);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 9.260417,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="Ds"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Ds" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-6);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 18.520834,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="Fs"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Fs" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-0);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 24.473959,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="Gs"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Gs" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-2);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 30.427084,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="As"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="As" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.6 KiB |
|
@ -0,0 +1,174 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="101"
|
||||
height="100"
|
||||
viewBox="0 0 26.722915 26.458338"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="keyboard_last.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
id="blackKey">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4528" />
|
||||
<stop
|
||||
id="stop4538"
|
||||
offset="0.33333373"
|
||||
style="stop-color:#000000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop4536"
|
||||
offset="0.36666706"
|
||||
style="stop-color:#313131;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop4530" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534"
|
||||
x1="2.6458333"
|
||||
y1="286.41666"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0.66145845)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-3"
|
||||
x1="2.645833"
|
||||
y1="286.41663"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(6.6145838,1.0903046e-5)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blackKey"
|
||||
id="linearGradient4534-6"
|
||||
x1="2.6458328"
|
||||
y1="286.41666"
|
||||
x2="2.6458333"
|
||||
y2="270.54166"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(15.875001,7.6333333e-6)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#313131"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.25169"
|
||||
inkscape:cx="63.580658"
|
||||
inkscape:cy="56.621412"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1424"
|
||||
inkscape:window-height="1104"
|
||||
inkscape:window-x="2192"
|
||||
inkscape:window-y="236"
|
||||
inkscape:window-maximized="0"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4518"
|
||||
spacingx="0.13229167"
|
||||
spacingy="0.26458333"
|
||||
visible="false"
|
||||
empspacing="5"
|
||||
originx="0.13229164"
|
||||
originy="0.13228669" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0.13229166,-270.67394)">
|
||||
<path
|
||||
style="fill:#fdfdfd;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0,270.54165 v 26.45833 H 5.2916666 V 286.41665 H 3.3072917 v -15.875 z"
|
||||
id="C"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:label="C" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 5.2916666,296.99998 H 10.583333 V 286.41665 H 9.2604166 v -15.875 H 7.2760419 v 15.875 H 5.2916666 Z"
|
||||
id="D"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:label="D" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3.3072917,270.54165 v 15.875 h 3.9687499 v -15.875 z"
|
||||
id="Cs"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Cs" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 10.583333,296.99998 H 15.875 v -26.45833 h -2.645834 v 15.875 h -2.645833 z"
|
||||
id="E"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="E" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 15.875,296.99998 h 5.291666 v -10.58333 h -2.645833 v -15.875 H 15.875 Z"
|
||||
id="F"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="F" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 21.166666,296.99998 h 5.291667 c 0,0 1e-6,-26.45833 1e-6,-26.45833 h -3.968751 v 15.875 h -1.322917 z"
|
||||
id="G"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:label="G" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-3);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 9.260417,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="Ds"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Ds" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4534-6);fill-opacity:1;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 18.520834,270.54165 v 15.875 h 3.96875 v -15.875 z"
|
||||
id="Fs"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:label="Fs" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
|
@ -22,5 +22,7 @@
|
|||
</qresource>
|
||||
<qresource prefix="/bg">
|
||||
<file>FaceGrey.svg</file>
|
||||
<file>keyboard.svg</file>
|
||||
<file>keyboard_last.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -21,8 +21,12 @@ class AudioGroup
|
|||
|
||||
public:
|
||||
operator bool() const { return m_valid; }
|
||||
explicit AudioGroup(const AudioGroupData& data);
|
||||
explicit AudioGroup(SystemStringView groupPath);
|
||||
AudioGroup() = default;
|
||||
explicit AudioGroup(const AudioGroupData& data) { assign(data); }
|
||||
explicit AudioGroup(SystemStringView groupPath) { assign(groupPath); }
|
||||
|
||||
void assign(const AudioGroupData& data);
|
||||
void assign(SystemStringView groupPath);
|
||||
|
||||
const AudioGroupSampleDirectory::Entry* getSample(SampleId sfxId) const;
|
||||
const unsigned char* getSampleData(SampleId sfxId, const AudioGroupSampleDirectory::Entry* sample) const;
|
||||
|
@ -43,10 +47,16 @@ class AudioGroupDatabase : public AudioGroup
|
|||
amuse::NameDB m_layersDb;
|
||||
|
||||
public:
|
||||
AudioGroupDatabase() = default;
|
||||
explicit AudioGroupDatabase(const AudioGroupData& data)
|
||||
: AudioGroup(data) {}
|
||||
{
|
||||
assign(data);
|
||||
}
|
||||
explicit AudioGroupDatabase(SystemStringView groupPath)
|
||||
: AudioGroup(groupPath) {}
|
||||
{
|
||||
setIdDatabases();
|
||||
assign(groupPath);
|
||||
}
|
||||
|
||||
void setIdDatabases()
|
||||
{
|
||||
|
|
|
@ -118,6 +118,7 @@ struct SoundMacro
|
|||
MulVars,
|
||||
DivVars,
|
||||
AddIVars,
|
||||
SetVar,
|
||||
IfEqual = 0x70,
|
||||
IfLess,
|
||||
Invalid = 0xff
|
||||
|
@ -926,6 +927,17 @@ struct SoundMacro
|
|||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::AddIVars; }
|
||||
};
|
||||
struct CmdSetVar : ICmd
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<bool> varCtrlA;
|
||||
Value<atInt8> a;
|
||||
Seek<1, athena::Current> pad;
|
||||
Value<atInt16> imm;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
CmdOp Isa() const { return CmdOp::SetVar; }
|
||||
};
|
||||
struct CmdIfEqual : ICmd
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
|
@ -1149,10 +1161,10 @@ class AudioGroupPool
|
|||
std::unordered_map<KeymapId, Keymap> m_keymaps;
|
||||
std::unordered_map<LayersId, std::vector<LayerMapping>> m_layers;
|
||||
|
||||
AudioGroupPool() = default;
|
||||
template <athena::Endian DNAE>
|
||||
static AudioGroupPool _AudioGroupPool(athena::io::IStreamReader& r);
|
||||
public:
|
||||
AudioGroupPool() = default;
|
||||
static AudioGroupPool CreateAudioGroupPool(const AudioGroupData& data);
|
||||
static AudioGroupPool CreateAudioGroupPool(SystemStringView groupPath);
|
||||
|
||||
|
|
|
@ -183,7 +183,6 @@ class AudioGroupProject
|
|||
std::unordered_map<GroupId, SongGroupIndex> m_songGroups;
|
||||
std::unordered_map<GroupId, SFXGroupIndex> m_sfxGroups;
|
||||
|
||||
AudioGroupProject() = default;
|
||||
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
|
||||
template <athena::Endian DNAE>
|
||||
static AudioGroupProject _AudioGroupProject(athena::io::IStreamReader& r, bool absOffs);
|
||||
|
@ -192,6 +191,7 @@ class AudioGroupProject
|
|||
template <athena::Endian DNAE>
|
||||
static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs);
|
||||
public:
|
||||
AudioGroupProject() = default;
|
||||
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
|
||||
static AudioGroupProject CreateAudioGroupProject(SystemStringView groupPath);
|
||||
static void BootstrapObjectIDs(const AudioGroupData& data);
|
||||
|
|
|
@ -253,9 +253,8 @@ private:
|
|||
static void _extractCompressed(SampleId id, const Entry& ent, amuse::SystemStringView destDir,
|
||||
const unsigned char* samp);
|
||||
|
||||
AudioGroupSampleDirectory() = default;
|
||||
|
||||
public:
|
||||
AudioGroupSampleDirectory() = default;
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag);
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData, bool absOffs, N64DataTag);
|
||||
AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag);
|
||||
|
|
|
@ -4,19 +4,21 @@
|
|||
namespace amuse
|
||||
{
|
||||
|
||||
AudioGroup::AudioGroup(const AudioGroupData& data)
|
||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(data))
|
||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(data))
|
||||
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data))
|
||||
, m_samp(data.getSamp())
|
||||
{}
|
||||
|
||||
AudioGroup::AudioGroup(SystemStringView groupPath)
|
||||
: m_proj(AudioGroupProject::CreateAudioGroupProject(groupPath))
|
||||
, m_pool(AudioGroupPool::CreateAudioGroupPool(groupPath))
|
||||
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath))
|
||||
, m_groupPath(groupPath)
|
||||
{}
|
||||
void AudioGroup::assign(const AudioGroupData& data)
|
||||
{
|
||||
m_proj = AudioGroupProject::CreateAudioGroupProject(data);
|
||||
m_pool = AudioGroupPool::CreateAudioGroupPool(data);
|
||||
m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data);
|
||||
m_samp = data.getSamp();
|
||||
}
|
||||
void AudioGroup::assign(SystemStringView groupPath)
|
||||
{
|
||||
/* Reverse order when loading intermediates */
|
||||
m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath);
|
||||
m_pool = AudioGroupPool::CreateAudioGroupPool(groupPath);
|
||||
m_proj = AudioGroupProject::CreateAudioGroupProject(groupPath);
|
||||
m_samp = nullptr;
|
||||
}
|
||||
|
||||
const AudioGroupSampleDirectory::Entry* AudioGroup::getSample(SampleId sfxId) const
|
||||
{
|
||||
|
|
|
@ -134,7 +134,7 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
|
|||
if (!fi.hasError())
|
||||
{
|
||||
athena::io::YAMLDocReader r;
|
||||
if (r.parse(&fi) && r.ValidateClassType("amuse::Pool"))
|
||||
if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Pool"))
|
||||
{
|
||||
if (auto __r = r.enterSubRecord("soundMacros"))
|
||||
{
|
||||
|
@ -518,6 +518,8 @@ std::unique_ptr<SoundMacro::ICmd> SoundMacro::MakeCmd(R& r)
|
|||
cmd = _MakeCmd<CmdDivVars>(r); break;
|
||||
case CmdOp::AddIVars:
|
||||
cmd = _MakeCmd<CmdAddIVars>(r); break;
|
||||
case CmdOp::SetVar:
|
||||
cmd = _MakeCmd<CmdSetVar>(r); break;
|
||||
case CmdOp::IfEqual:
|
||||
cmd = _MakeCmd<CmdIfEqual>(r); break;
|
||||
case CmdOp::IfLess:
|
||||
|
@ -684,6 +686,8 @@ std::string_view SoundMacro::CmdOpToStr(CmdOp op)
|
|||
return "DivVars"sv;
|
||||
case CmdOp::AddIVars:
|
||||
return "AddIVars"sv;
|
||||
case CmdOp::SetVar:
|
||||
return "SetVar"sv;
|
||||
case CmdOp::IfEqual:
|
||||
return "IfEqual"sv;
|
||||
case CmdOp::IfLess:
|
||||
|
@ -845,6 +849,8 @@ SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op)
|
|||
return CmdOp::DivVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "AddIVars"))
|
||||
return CmdOp::AddIVars;
|
||||
else if (!CompareCaseInsensitive(op.data(), "SetVar"))
|
||||
return CmdOp::SetVar;
|
||||
else if (!CompareCaseInsensitive(op.data(), "IfEqual"))
|
||||
return CmdOp::IfEqual;
|
||||
else if (!CompareCaseInsensitive(op.data(), "IfLess"))
|
||||
|
|
|
@ -229,7 +229,7 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
|
|||
if (!fi.hasError())
|
||||
{
|
||||
athena::io::YAMLDocReader r;
|
||||
if (r.parse(&fi) && r.ValidateClassType("amuse::Project"))
|
||||
if (r.parse(&fi) && !r.readString("DNAType").compare("amuse::Project"))
|
||||
{
|
||||
if (auto __v = r.enterSubRecord("songGroups"))
|
||||
{
|
||||
|
@ -289,7 +289,7 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
|
|||
ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size());
|
||||
for (const auto& grp : r.getCurNode()->m_mapChildren)
|
||||
{
|
||||
if (auto __r = r.enterSubRecord(nullptr))
|
||||
if (auto __r = r.enterSubRecord(grp.first.c_str()))
|
||||
{
|
||||
uint16_t groupId;
|
||||
std::string groupName = ParseStringSlashId(grp.first, groupId);
|
||||
|
|
|
@ -1024,6 +1024,16 @@ bool SoundMacro::CmdAddIVars::Do(SoundMacroState& st, Voice& vox) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool SoundMacro::CmdSetVar::Do(SoundMacroState& st, Voice& vox) const
|
||||
{
|
||||
if (varCtrlA)
|
||||
vox.setCtrlValue(a, imm);
|
||||
else
|
||||
st.m_variables[a] = imm;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SoundMacro::CmdIfEqual::Do(SoundMacroState& st, Voice& vox) const
|
||||
{
|
||||
int32_t useA, useB;
|
||||
|
|
Loading…
Reference in New Issue