More work on Amuse Editor

This commit is contained in:
Jack Andersen 2018-07-17 21:39:26 -10:00
parent 3f265cdb46
commit f50ee6e8f1
38 changed files with 1193 additions and 140 deletions

7
Editor/ADSREditor.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "ADSREditor.hpp"
ADSREditor::ADSREditor(ProjectModel::ADSRNode* node, QWidget* parent)
: EditorWidget(parent)
{
}

14
Editor/ADSREditor.hpp Normal file
View File

@ -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

View File

@ -28,15 +28,17 @@ add_executable(amuse-gui WIN32 MACOSX_BUNDLE
Common.hpp Common.cpp Common.hpp Common.cpp
MainWindow.ui MainWindow.hpp MainWindow.cpp MainWindow.ui MainWindow.hpp MainWindow.cpp
KeyboardWidget.hpp KeyboardWidget.cpp KeyboardWidget.hpp KeyboardWidget.cpp
StatusBarWidget.hpp StatusBarWidget.cpp StatusBarWidget.hpp
ProjectModel.hpp ProjectModel.cpp ProjectModel.hpp ProjectModel.cpp
ProjectStatistics.hpp ProjectStatistics.cpp ProjectStatistics.hpp ProjectStatistics.cpp
EditorWidget.hpp EditorWidget.cpp EditorWidget.hpp EditorWidget.cpp
SoundMacroEditor.hpp SoundMacroEditor.cpp SoundMacroEditor.hpp SoundMacroEditor.cpp
ADSREditor.hpp ADSREditor.cpp
CurveEditor.hpp CurveEditor.cpp
KeymapEditor.hpp KeymapEditor.cpp KeymapEditor.hpp KeymapEditor.cpp
LayersEditor.hpp LayersEditor.cpp LayersEditor.hpp LayersEditor.cpp
SampleEditor.hpp SampleEditor.cpp SampleEditor.hpp SampleEditor.cpp
SFXGroupEditor.hpp SFXGroupEditor.cpp SoundGroupEditor.hpp SoundGroupEditor.cpp
SongGroupEditor.hpp SongGroupEditor.cpp SongGroupEditor.hpp SongGroupEditor.cpp
AudioGroupModel.hpp AudioGroupModel.cpp AudioGroupModel.hpp AudioGroupModel.cpp
resources/resources.qrc qrc_resources.cpp resources/resources.qrc qrc_resources.cpp

7
Editor/CurveEditor.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "CurveEditor.hpp"
CurveEditor::CurveEditor(ProjectModel::CurveNode* node, QWidget* parent)
: EditorWidget(parent)
{
}

14
Editor/CurveEditor.hpp Normal file
View File

@ -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

View File

@ -2,12 +2,14 @@
#define AMUSE_EDITOR_WIDGET_HPP #define AMUSE_EDITOR_WIDGET_HPP
#include <QWidget> #include <QWidget>
#include "ProjectModel.hpp"
class EditorWidget : public QWidget class EditorWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit EditorWidget(QWidget* parent = Q_NULLPTR); explicit EditorWidget(QWidget* parent = Q_NULLPTR);
virtual bool valid() const { return true; }
}; };

View File

@ -1,7 +1,203 @@
#include "KeyboardWidget.hpp" #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) KeyboardWidget::KeyboardWidget(QWidget* parent)
: 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);
}
} }

View File

@ -2,12 +2,50 @@
#define AMUSE_KEYBOARD_WIDGET_HPP #define AMUSE_KEYBOARD_WIDGET_HPP
#include <QWidget> #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 class KeyboardWidget : public QWidget
{ {
Q_OBJECT 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: public:
explicit KeyboardWidget(QWidget* parent = Q_NULLPTR); 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);
}; };

View File

@ -1,6 +1,6 @@
#include "KeymapEditor.hpp" #include "KeymapEditor.hpp"
KeymapEditor::KeymapEditor(QWidget* parent) KeymapEditor::KeymapEditor(ProjectModel::KeymapNode* node, QWidget* parent)
: EditorWidget(parent) : EditorWidget(parent)
{ {

View File

@ -7,7 +7,7 @@ class KeymapEditor : public EditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit KeymapEditor(QWidget* parent = Q_NULLPTR); explicit KeymapEditor(ProjectModel::KeymapNode* node, QWidget* parent = Q_NULLPTR);
}; };

View File

@ -1,6 +1,6 @@
#include "LayersEditor.hpp" #include "LayersEditor.hpp"
LayersEditor::LayersEditor(QWidget* parent) LayersEditor::LayersEditor(ProjectModel::LayersNode* node, QWidget* parent)
: EditorWidget(parent) : EditorWidget(parent)
{ {

View File

@ -7,7 +7,7 @@ class LayersEditor : public EditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit LayersEditor(QWidget* parent = Q_NULLPTR); explicit LayersEditor(ProjectModel::LayersNode* node, QWidget* parent = Q_NULLPTR);
}; };

View File

@ -4,9 +4,18 @@
#include <QLineEdit> #include <QLineEdit>
#include <QInputDialog> #include <QInputDialog>
#include <QProgressDialog> #include <QProgressDialog>
#include <QMouseEvent>
#include <QtSvg/QtSvg> #include <QtSvg/QtSvg>
#include "amuse/ContainerRegistry.hpp" #include "amuse/ContainerRegistry.hpp"
#include "Common.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) static void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
{ {
@ -15,6 +24,7 @@ static void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
MainWindow::MainWindow(QWidget* parent) MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent), : QMainWindow(parent),
m_treeDelegate(*this, this),
m_mainMessenger(this), m_mainMessenger(this),
m_undoStack(new QUndoStack(this)), m_undoStack(new QUndoStack(this)),
m_backgroundThread(this) m_backgroundThread(this)
@ -22,8 +32,11 @@ MainWindow::MainWindow(QWidget* parent)
m_backgroundThread.start(); m_backgroundThread.start();
m_ui.setupUi(this); m_ui.setupUi(this);
m_ui.projectOutline->setItemDelegate(&m_treeDelegate);
connectMessenger(&m_mainMessenger, Qt::DirectConnection); connectMessenger(&m_mainMessenger, Qt::DirectConnection);
m_ui.keyboardContents->setStatusFocus(new StatusBarFocus(m_ui.statusbar));
m_ui.actionNew_Project->setShortcut(QKeySequence::New); m_ui.actionNew_Project->setShortcut(QKeySequence::New);
connect(m_ui.actionNew_Project, SIGNAL(triggered()), this, SLOT(newAction())); connect(m_ui.actionNew_Project, SIGNAL(triggered()), this, SLOT(newAction()));
m_ui.actionOpen_Project->setShortcut(QKeySequence::Open); m_ui.actionOpen_Project->setShortcut(QKeySequence::Open);
@ -45,11 +58,21 @@ MainWindow::MainWindow(QWidget* parent)
m_ui.actionDelete->setShortcut(QKeySequence::Delete); m_ui.actionDelete->setShortcut(QKeySequence::Delete);
onFocusChanged(nullptr, this); 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_SFX_Group, SIGNAL(triggered()), this, SLOT(newSFXGroupAction()));
connect(m_ui.actionNew_Song_Group, SIGNAL(triggered()), this, SLOT(newSongGroupAction())); 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_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_Keymap, SIGNAL(triggered()), this, SLOT(newKeymapAction()));
connect(m_ui.actionNew_Layers, SIGNAL(triggered()), this, SLOT(newLayersAction())); 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.projectOutline->setModel(m_projectModel);
m_ui.actionExport_GameCube_Groups->setEnabled(true); m_ui.actionExport_GameCube_Groups->setEnabled(true);
setWindowFilePath(path); setWindowFilePath(path);
#ifndef __APPLE__
setWindowTitle(QString("Amuse - %1").arg(dir.dirName()));
#endif
setFocusAudioGroup(nullptr); setFocusAudioGroup(nullptr);
onFocusChanged(nullptr, focusWidget()); onFocusChanged(nullptr, focusWidget());
@ -217,6 +243,88 @@ void MainWindow::startBackgroundTask(const QString& windowTitle, const QString&
QMetaObject::invokeMethod(m_backgroundTask, "run", Qt::QueuedConnection); 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() void MainWindow::newAction()
{ {
QString path = QFileDialog::getSaveFileName(this, tr("New Project")); QString path = QFileDialog::getSaveFileName(this, tr("New Project"));
@ -226,6 +334,9 @@ void MainWindow::newAction()
return; return;
if (!setProjectPath(path)) if (!setProjectPath(path))
return; return;
m_projectModel->clearProjectData();
m_projectModel->ensureModelData();
} }
void MainWindow::openAction() void MainWindow::openAction()
@ -233,10 +344,41 @@ void MainWindow::openAction()
QString path = QFileDialog::getExistingDirectory(this, tr("Open Project")); QString path = QFileDialog::getExistingDirectory(this, tr("Open Project"));
if (path.isEmpty()) if (path.isEmpty())
return; 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)) if (!setProjectPath(path))
return; 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() 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() void MainWindow::newSFXGroupAction()
{ {
@ -387,6 +556,16 @@ void MainWindow::newSoundMacroAction()
} }
void MainWindow::newADSRAction()
{
}
void MainWindow::newCurveAction()
{
}
void MainWindow::newKeymapAction() void MainWindow::newKeymapAction()
{ {

View File

@ -5,16 +5,19 @@
#include <QUndoStack> #include <QUndoStack>
#include <QProgressDialog> #include <QProgressDialog>
#include <QThread> #include <QThread>
#include <QStyledItemDelegate>
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include "amuse/Engine.hpp" #include "amuse/Engine.hpp"
#include "amuse/BooBackend.hpp" #include "amuse/BooBackend.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "ProjectModel.hpp" #include "ProjectModel.hpp"
#include "EditorWidget.hpp"
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
} }
class MainWindow;
class AudioGroupModel; class AudioGroupModel;
class BackgroundTask : public QObject class BackgroundTask : public QObject
@ -41,13 +44,29 @@ public slots:
void cancel() { m_cancelled = true; } 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 class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
Ui::MainWindow m_ui; Ui::MainWindow m_ui;
TreeDelegate m_treeDelegate;
UIMessenger m_mainMessenger; UIMessenger m_mainMessenger;
ProjectModel* m_projectModel = nullptr; ProjectModel* m_projectModel = nullptr;
AudioGroupModel* m_focusAudioGroup = nullptr; AudioGroupModel* m_focusAudioGroup = nullptr;
QWidget* m_faceSvg;
std::unique_ptr<boo::IAudioVoiceEngine> m_voxEngine; std::unique_ptr<boo::IAudioVoiceEngine> m_voxEngine;
std::unique_ptr<amuse::BooBackendVoiceAllocator> m_voxAllocator; std::unique_ptr<amuse::BooBackendVoiceAllocator> m_voxAllocator;
@ -79,19 +98,34 @@ class MainWindow : public QMainWindow
void startBackgroundTask(const QString& windowTitle, const QString& label, void startBackgroundTask(const QString& windowTitle, const QString& label,
std::function<void(BackgroundTask&)>&& task); std::function<void(BackgroundTask&)>&& task);
bool _setEditor(EditorWidget* widget);
public: public:
explicit MainWindow(QWidget* parent = Q_NULLPTR); explicit MainWindow(QWidget* parent = Q_NULLPTR);
~MainWindow(); ~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: public slots:
void newAction(); void newAction();
void openAction(); void openAction();
void importAction(); void importAction();
void exportAction(); void exportAction();
void newSubprojectAction();
void newSFXGroupAction(); void newSFXGroupAction();
void newSongGroupAction(); void newSongGroupAction();
void newSoundMacroAction(); void newSoundMacroAction();
void newADSRAction();
void newCurveAction();
void newKeymapAction(); void newKeymapAction();
void newLayersAction(); void newLayersAction();

View File

@ -35,10 +35,6 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QSplitter" name="leftSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeView" name="projectOutline"> <widget class="QTreeView" name="projectOutline">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -52,25 +48,13 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="animated">
<bool>true</bool>
</property>
<attribute name="headerVisible"> <attribute name="headerVisible">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
</widget> </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>
</widget>
<widget class="QSplitter" name="rightSplitter"> <widget class="QSplitter" name="rightSplitter">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@ -109,7 +93,7 @@
<property name="widgetResizable"> <property name="widgetResizable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<widget class="QWidget" name="editorContents"> <widget class="QStackedWidget" name="editorContents">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -118,24 +102,6 @@
<height>442</height> <height>442</height>
</rect> </rect>
</property> </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> </widget>
<widget class="QScrollArea" name="keyboardScrollArea"> <widget class="QScrollArea" name="keyboardScrollArea">
@ -174,10 +140,22 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>540</width> <width>1501</width>
<height>100</height> <height>85</height>
</rect> </rect>
</property> </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"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
@ -213,10 +191,14 @@
<property name="title"> <property name="title">
<string>P&amp;roject</string> <string>P&amp;roject</string>
</property> </property>
<addaction name="actionNew_Subproject"/>
<addaction name="separator"/>
<addaction name="actionNew_SFX_Group"/> <addaction name="actionNew_SFX_Group"/>
<addaction name="actionNew_Song_Group"/> <addaction name="actionNew_Song_Group"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionNew_Sound_Macro"/> <addaction name="actionNew_Sound_Macro"/>
<addaction name="actionNew_ADSR"/>
<addaction name="actionNew_Curve"/>
<addaction name="actionNew_Keymap"/> <addaction name="actionNew_Keymap"/>
<addaction name="actionNew_Layers"/> <addaction name="actionNew_Layers"/>
</widget> </widget>
@ -418,6 +400,42 @@
<string>Ctrl+E</string> <string>Ctrl+E</string>
</property> </property>
</action> </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&amp;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&amp;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 &amp;Curve</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
@ -431,12 +449,6 @@
<extends>QStatusBar</extends> <extends>QStatusBar</extends>
<header>StatusBarWidget.hpp</header> <header>StatusBarWidget.hpp</header>
</customwidget> </customwidget>
<customwidget>
<class>QSvgWidget</class>
<extends>QWidget</extends>
<header location="global">QSvgWidget</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -18,6 +18,25 @@ ProjectModel::ProjectModel(const QString& path, QObject* parent)
SoundGroupNode::Icon = QIcon(":/icons/IconSoundGroup.svg"); 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, bool ProjectModel::importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
ImportMode mode, UIMessenger& messenger) ImportMode mode, UIMessenger& messenger)
{ {
@ -89,12 +108,13 @@ void ProjectModel::_resetModelData()
{ {
it->second.setIdDatabases(); it->second.setIdDatabases();
GroupNode& gn = m_root->makeChild<GroupNode>(it); GroupNode& gn = m_root->makeChild<GroupNode>(it);
auto& songGroups = it->second.getProj().songGroups(); amuse::AudioGroup& group = it->second;
auto& sfxGroups = it->second.getProj().sfxGroups(); auto& songGroups = group.getProj().songGroups();
auto& soundMacros = it->second.getPool().soundMacros(); auto& sfxGroups = group.getProj().sfxGroups();
auto& tables = it->second.getPool().tables(); auto& soundMacros = group.getPool().soundMacros();
auto& keymaps = it->second.getPool().keymaps(); auto& tables = group.getPool().tables();
auto& layers = it->second.getPool().layers(); auto& keymaps = group.getPool().keymaps();
auto& layers = group.getPool().layers();
gn.reserve(songGroups.size() + sfxGroups.size() + 4); gn.reserve(songGroups.size() + sfxGroups.size() + 4);
for (const auto& grp : SortUnorderedMap(songGroups)) for (const auto& grp : SortUnorderedMap(songGroups))
gn.makeChild<SongGroupNode>(grp.first, grp.second.get()); 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")); gn.makeChild<CollectionNode>(tr("Sound Macros"), QIcon(":/icons/IconSoundMacro.svg"));
col.reserve(soundMacros.size()); col.reserve(soundMacros.size());
for (const auto& macro : SortUnorderedMap(soundMacros)) 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()) if (tables.size())
{ {
@ -130,7 +150,7 @@ void ProjectModel::_resetModelData()
{ {
amuse::ITable::Type tp = t.second.get()->Isa(); amuse::ITable::Type tp = t.second.get()->Isa();
if (tp == amuse::ITable::Type::ADSR || tp == amuse::ITable::Type::ADSRDLS) 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) if (curveCount)
@ -142,7 +162,7 @@ void ProjectModel::_resetModelData()
{ {
amuse::ITable::Type tp = t.second.get()->Isa(); amuse::ITable::Type tp = t.second.get()->Isa();
if (tp == amuse::ITable::Type::Curve) 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")); gn.makeChild<CollectionNode>(tr("Keymaps"), QIcon(":/icons/IconKeymap.svg"));
col.reserve(keymaps.size()); col.reserve(keymaps.size());
for (auto& keymap : SortUnorderedMap(keymaps)) 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()) if (layers.size())
{ {
@ -160,7 +180,7 @@ void ProjectModel::_resetModelData()
gn.makeChild<CollectionNode>(tr("Layers"), QIcon(":/icons/IconLayers.svg")); gn.makeChild<CollectionNode>(tr("Layers"), QIcon(":/icons/IconLayers.svg"));
col.reserve(layers.size()); col.reserve(layers.size());
for (auto& keymap : SortUnorderedMap(layers)) 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(); endResetModel();
@ -250,6 +270,13 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex& index) const
return QAbstractItemModel::flags(index); 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 bool ProjectModel::canDelete() const
{ {
return false; return false;

View File

@ -29,13 +29,16 @@ private:
amuse::ProjectDatabase m_projectDatabase; amuse::ProjectDatabase m_projectDatabase;
std::map<QString, amuse::AudioGroupDatabase> m_groups; std::map<QString, amuse::AudioGroupDatabase> m_groups;
public:
class INode class INode
{ {
public:
enum class Type enum class Type
{ {
Root,
Group, // Top-level group Group, // Top-level group
SongGroup, SongGroup,
SfxGroup, SoundGroup,
Collection, // Classified object collection, one of the following: Collection, // Classified object collection, one of the following:
SoundMacro, SoundMacro,
ADSR, ADSR,
@ -43,6 +46,7 @@ private:
Keymap, Keymap,
Layer Layer
}; };
private:
INode* m_parent; INode* m_parent;
std::vector<std::unique_ptr<INode>> m_children; std::vector<std::unique_ptr<INode>> m_children;
int m_row; int m_row;
@ -63,6 +67,7 @@ private:
return static_cast<T&>(*m_children.back()); return static_cast<T&>(*m_children.back());
} }
virtual Type type() const = 0;
virtual QString text() const = 0; virtual QString text() const = 0;
virtual QIcon icon() const = 0; virtual QIcon icon() const = 0;
}; };
@ -70,6 +75,7 @@ private:
{ {
RootNode() : INode(nullptr, 0) {} RootNode() : INode(nullptr, 0) {}
Type type() const { return Type::Root; }
QString text() const { return {}; } QString text() const { return {}; }
QIcon icon() const { return {}; } QIcon icon() const { return {}; }
}; };
@ -80,6 +86,7 @@ private:
: INode(parent, row), m_it(it) {} : INode(parent, row), m_it(it) {}
static QIcon Icon; static QIcon Icon;
Type type() const { return Type::Group; }
QString text() const { return m_it->first; } QString text() const { return m_it->first; }
QIcon icon() const { return Icon; } 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) {} : INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
static QIcon Icon; static QIcon Icon;
Type type() const { return Type::SongGroup; }
QString text() const { return m_name; } QString text() const { return m_name; }
QIcon icon() const { return Icon; } 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) {} : INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
static QIcon Icon; static QIcon Icon;
Type type() const { return Type::SoundGroup; }
QString text() const { return m_name; } QString text() const { return m_name; }
QIcon icon() const { return Icon; } QIcon icon() const { return Icon; }
}; };
@ -114,10 +123,11 @@ private:
CollectionNode(INode* parent, int row, const QString& name, const QIcon& icon) CollectionNode(INode* parent, int row, const QString& name, const QIcon& icon)
: INode(parent, row), m_name(name), m_icon(icon) {} : INode(parent, row), m_name(name), m_icon(icon) {}
Type type() const { return Type::Collection; }
QString text() const { return m_name; } QString text() const { return m_name; }
QIcon icon() const { return m_icon; } QIcon icon() const { return m_icon; }
}; };
template <class ID, class T> template <class ID, class T, INode::Type TP>
struct PoolObjectNode : INode struct PoolObjectNode : INode
{ {
ID m_id; ID m_id;
@ -126,9 +136,15 @@ private:
PoolObjectNode(INode* parent, int row, ID id, T& obj) 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) {} : 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; } QString text() const { return m_name; }
QIcon icon() const { return {}; } 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; std::unique_ptr<RootNode> m_root;
@ -138,6 +154,8 @@ private:
public: public:
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR); 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, bool importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
ImportMode mode, UIMessenger& messenger); ImportMode mode, UIMessenger& messenger);
bool saveToFile(UIMessenger& messenger); bool saveToFile(UIMessenger& messenger);
@ -150,6 +168,7 @@ public:
int columnCount(const QModelIndex& parent = QModelIndex()) const; int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex& index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
INode* node(const QModelIndex& index) const;
QString path() const { return m_dir.path(); } QString path() const { return m_dir.path(); }
bool canDelete() const; bool canDelete() const;

View File

@ -1,7 +0,0 @@
#include "SFXGroupEditor.hpp"
SFXGroupEditor::SFXGroupEditor(QWidget* parent)
: EditorWidget(parent)
{
}

View File

@ -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

View File

@ -1,6 +1,6 @@
#include "SongGroupEditor.hpp" #include "SongGroupEditor.hpp"
SongGroupEditor::SongGroupEditor(QWidget* parent) SongGroupEditor::SongGroupEditor(ProjectModel::SongGroupNode* node, QWidget* parent)
: EditorWidget(parent) : EditorWidget(parent)
{ {

View File

@ -7,7 +7,7 @@ class SongGroupEditor : public EditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SongGroupEditor(QWidget* parent = Q_NULLPTR); explicit SongGroupEditor(ProjectModel::SongGroupNode* node, QWidget* parent = Q_NULLPTR);
}; };

View File

@ -0,0 +1,7 @@
#include "SoundGroupEditor.hpp"
SoundGroupEditor::SoundGroupEditor(ProjectModel::SoundGroupNode* node, QWidget* parent)
: EditorWidget(parent)
{
}

View File

@ -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

View File

@ -1,7 +1,10 @@
#include "SoundMacroEditor.hpp" #include "SoundMacroEditor.hpp"
#include <QLabel>
SoundMacroEditor::SoundMacroEditor(QWidget* parent) SoundMacroEditor::SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent)
: EditorWidget(parent) : EditorWidget(parent)
{ {
QLabel* lab = new QLabel;
lab->setText(node->m_name);
lab->setParent(this);
} }

View File

@ -7,7 +7,7 @@ class SoundMacroEditor : public EditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SoundMacroEditor(QWidget* parent = Q_NULLPTR); explicit SoundMacroEditor(ProjectModel::SoundMacroNode* node, QWidget* parent = Q_NULLPTR);
}; };

View File

@ -1,7 +0,0 @@
#include "StatusBarWidget.hpp"
StatusBarWidget::StatusBarWidget(QWidget* parent)
: QStatusBar(parent)
{
}

View File

@ -2,13 +2,65 @@
#define AMUSE_STATUSBAR_WIDGET_HPP #define AMUSE_STATUSBAR_WIDGET_HPP
#include <QStatusBar> #include <QStatusBar>
#include <QLabel>
class StatusBarFocus;
class StatusBarWidget : public QStatusBar class StatusBarWidget : public QStatusBar
{ {
friend class StatusBarFocus;
Q_OBJECT Q_OBJECT
QLabel* m_normalMessage;
StatusBarFocus* m_curFocus = nullptr;
public: 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 #endif //AMUSE_STATUSBAR_WIDGET_HPP

View File

@ -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

View File

@ -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

View File

@ -22,5 +22,7 @@
</qresource> </qresource>
<qresource prefix="/bg"> <qresource prefix="/bg">
<file>FaceGrey.svg</file> <file>FaceGrey.svg</file>
<file>keyboard.svg</file>
<file>keyboard_last.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -21,8 +21,12 @@ class AudioGroup
public: public:
operator bool() const { return m_valid; } operator bool() const { return m_valid; }
explicit AudioGroup(const AudioGroupData& data); AudioGroup() = default;
explicit AudioGroup(SystemStringView groupPath); 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 AudioGroupSampleDirectory::Entry* getSample(SampleId sfxId) const;
const unsigned char* getSampleData(SampleId sfxId, const AudioGroupSampleDirectory::Entry* sample) const; const unsigned char* getSampleData(SampleId sfxId, const AudioGroupSampleDirectory::Entry* sample) const;
@ -43,10 +47,16 @@ class AudioGroupDatabase : public AudioGroup
amuse::NameDB m_layersDb; amuse::NameDB m_layersDb;
public: public:
AudioGroupDatabase() = default;
explicit AudioGroupDatabase(const AudioGroupData& data) explicit AudioGroupDatabase(const AudioGroupData& data)
: AudioGroup(data) {} {
assign(data);
}
explicit AudioGroupDatabase(SystemStringView groupPath) explicit AudioGroupDatabase(SystemStringView groupPath)
: AudioGroup(groupPath) {} {
setIdDatabases();
assign(groupPath);
}
void setIdDatabases() void setIdDatabases()
{ {

View File

@ -118,6 +118,7 @@ struct SoundMacro
MulVars, MulVars,
DivVars, DivVars,
AddIVars, AddIVars,
SetVar,
IfEqual = 0x70, IfEqual = 0x70,
IfLess, IfLess,
Invalid = 0xff Invalid = 0xff
@ -926,6 +927,17 @@ struct SoundMacro
bool Do(SoundMacroState& st, Voice& vox) const; bool Do(SoundMacroState& st, Voice& vox) const;
CmdOp Isa() const { return CmdOp::AddIVars; } 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 struct CmdIfEqual : ICmd
{ {
AT_DECL_DNA_YAML AT_DECL_DNA_YAML
@ -1149,10 +1161,10 @@ class AudioGroupPool
std::unordered_map<KeymapId, Keymap> m_keymaps; std::unordered_map<KeymapId, Keymap> m_keymaps;
std::unordered_map<LayersId, std::vector<LayerMapping>> m_layers; std::unordered_map<LayersId, std::vector<LayerMapping>> m_layers;
AudioGroupPool() = default;
template <athena::Endian DNAE> template <athena::Endian DNAE>
static AudioGroupPool _AudioGroupPool(athena::io::IStreamReader& r); static AudioGroupPool _AudioGroupPool(athena::io::IStreamReader& r);
public: public:
AudioGroupPool() = default;
static AudioGroupPool CreateAudioGroupPool(const AudioGroupData& data); static AudioGroupPool CreateAudioGroupPool(const AudioGroupData& data);
static AudioGroupPool CreateAudioGroupPool(SystemStringView groupPath); static AudioGroupPool CreateAudioGroupPool(SystemStringView groupPath);

View File

@ -183,7 +183,6 @@ class AudioGroupProject
std::unordered_map<GroupId, SongGroupIndex> m_songGroups; std::unordered_map<GroupId, SongGroupIndex> m_songGroups;
std::unordered_map<GroupId, SFXGroupIndex> m_sfxGroups; std::unordered_map<GroupId, SFXGroupIndex> m_sfxGroups;
AudioGroupProject() = default;
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag); AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
template <athena::Endian DNAE> template <athena::Endian DNAE>
static AudioGroupProject _AudioGroupProject(athena::io::IStreamReader& r, bool absOffs); static AudioGroupProject _AudioGroupProject(athena::io::IStreamReader& r, bool absOffs);
@ -192,6 +191,7 @@ class AudioGroupProject
template <athena::Endian DNAE> template <athena::Endian DNAE>
static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs); static void BootstrapObjectIDs(athena::io::IStreamReader& r, bool absOffs);
public: public:
AudioGroupProject() = default;
static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data); static AudioGroupProject CreateAudioGroupProject(const AudioGroupData& data);
static AudioGroupProject CreateAudioGroupProject(SystemStringView groupPath); static AudioGroupProject CreateAudioGroupProject(SystemStringView groupPath);
static void BootstrapObjectIDs(const AudioGroupData& data); static void BootstrapObjectIDs(const AudioGroupData& data);

View File

@ -253,9 +253,8 @@ private:
static void _extractCompressed(SampleId id, const Entry& ent, amuse::SystemStringView destDir, static void _extractCompressed(SampleId id, const Entry& ent, amuse::SystemStringView destDir,
const unsigned char* samp); const unsigned char* samp);
AudioGroupSampleDirectory() = default;
public: public:
AudioGroupSampleDirectory() = default;
AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag); AudioGroupSampleDirectory(athena::io::IStreamReader& r, GCNDataTag);
AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData, bool absOffs, N64DataTag); AudioGroupSampleDirectory(athena::io::IStreamReader& r, const unsigned char* sampData, bool absOffs, N64DataTag);
AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag); AudioGroupSampleDirectory(athena::io::IStreamReader& r, bool absOffs, PCDataTag);

View File

@ -4,19 +4,21 @@
namespace amuse namespace amuse
{ {
AudioGroup::AudioGroup(const AudioGroupData& data) void AudioGroup::assign(const AudioGroupData& data)
: m_proj(AudioGroupProject::CreateAudioGroupProject(data)) {
, m_pool(AudioGroupPool::CreateAudioGroupPool(data)) m_proj = AudioGroupProject::CreateAudioGroupProject(data);
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data)) m_pool = AudioGroupPool::CreateAudioGroupPool(data);
, m_samp(data.getSamp()) m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(data);
{} m_samp = data.getSamp();
}
AudioGroup::AudioGroup(SystemStringView groupPath) void AudioGroup::assign(SystemStringView groupPath)
: m_proj(AudioGroupProject::CreateAudioGroupProject(groupPath)) {
, m_pool(AudioGroupPool::CreateAudioGroupPool(groupPath)) /* Reverse order when loading intermediates */
, m_sdir(AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath)) m_sdir = AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(groupPath);
, m_groupPath(groupPath) m_pool = AudioGroupPool::CreateAudioGroupPool(groupPath);
{} m_proj = AudioGroupProject::CreateAudioGroupProject(groupPath);
m_samp = nullptr;
}
const AudioGroupSampleDirectory::Entry* AudioGroup::getSample(SampleId sfxId) const const AudioGroupSampleDirectory::Entry* AudioGroup::getSample(SampleId sfxId) const
{ {

View File

@ -134,7 +134,7 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
if (!fi.hasError()) if (!fi.hasError())
{ {
athena::io::YAMLDocReader r; 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")) if (auto __r = r.enterSubRecord("soundMacros"))
{ {
@ -518,6 +518,8 @@ std::unique_ptr<SoundMacro::ICmd> SoundMacro::MakeCmd(R& r)
cmd = _MakeCmd<CmdDivVars>(r); break; cmd = _MakeCmd<CmdDivVars>(r); break;
case CmdOp::AddIVars: case CmdOp::AddIVars:
cmd = _MakeCmd<CmdAddIVars>(r); break; cmd = _MakeCmd<CmdAddIVars>(r); break;
case CmdOp::SetVar:
cmd = _MakeCmd<CmdSetVar>(r); break;
case CmdOp::IfEqual: case CmdOp::IfEqual:
cmd = _MakeCmd<CmdIfEqual>(r); break; cmd = _MakeCmd<CmdIfEqual>(r); break;
case CmdOp::IfLess: case CmdOp::IfLess:
@ -684,6 +686,8 @@ std::string_view SoundMacro::CmdOpToStr(CmdOp op)
return "DivVars"sv; return "DivVars"sv;
case CmdOp::AddIVars: case CmdOp::AddIVars:
return "AddIVars"sv; return "AddIVars"sv;
case CmdOp::SetVar:
return "SetVar"sv;
case CmdOp::IfEqual: case CmdOp::IfEqual:
return "IfEqual"sv; return "IfEqual"sv;
case CmdOp::IfLess: case CmdOp::IfLess:
@ -845,6 +849,8 @@ SoundMacro::CmdOp SoundMacro::CmdStrToOp(std::string_view op)
return CmdOp::DivVars; return CmdOp::DivVars;
else if (!CompareCaseInsensitive(op.data(), "AddIVars")) else if (!CompareCaseInsensitive(op.data(), "AddIVars"))
return CmdOp::AddIVars; return CmdOp::AddIVars;
else if (!CompareCaseInsensitive(op.data(), "SetVar"))
return CmdOp::SetVar;
else if (!CompareCaseInsensitive(op.data(), "IfEqual")) else if (!CompareCaseInsensitive(op.data(), "IfEqual"))
return CmdOp::IfEqual; return CmdOp::IfEqual;
else if (!CompareCaseInsensitive(op.data(), "IfLess")) else if (!CompareCaseInsensitive(op.data(), "IfLess"))

View File

@ -229,7 +229,7 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
if (!fi.hasError()) if (!fi.hasError())
{ {
athena::io::YAMLDocReader r; 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")) if (auto __v = r.enterSubRecord("songGroups"))
{ {
@ -289,7 +289,7 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size()); ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size());
for (const auto& grp : r.getCurNode()->m_mapChildren) 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; uint16_t groupId;
std::string groupName = ParseStringSlashId(grp.first, groupId); std::string groupName = ParseStringSlashId(grp.first, groupId);

View File

@ -1024,6 +1024,16 @@ bool SoundMacro::CmdAddIVars::Do(SoundMacroState& st, Voice& vox) const
return false; 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 bool SoundMacro::CmdIfEqual::Do(SoundMacroState& st, Voice& vox) const
{ {
int32_t useA, useB; int32_t useA, useB;