Initial ProjectModel implementation
|
@ -54,4 +54,4 @@ target_link_libraries(amuse-gui ${PLAT_LIBS}
|
|||
${Qt5Network_LIBRARIES}
|
||||
${Qt5Xml_LIBRARIES}
|
||||
${Qt5Svg_LIBRARIES}
|
||||
amuse boo ${BOO_SYS_LIBS} logvisor zeus athena-core athena-libyaml xxhash ${ZLIB_LIBRARIES} ${LZO_LIB})
|
||||
amuse boo ${BOO_SYS_LIBS} logvisor athena-core athena-libyaml xxhash ${ZLIB_LIBRARIES} ${LZO_LIB})
|
||||
|
|
|
@ -20,18 +20,18 @@ QString SysStringToQString(const boo::SystemString& str)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool MkPath(const QString& path, QWidget* parent)
|
||||
bool MkPath(const QString& path, UIMessenger& messenger)
|
||||
{
|
||||
QFileInfo fInfo(path);
|
||||
return MkPath(fInfo.dir(), fInfo.fileName(), parent);
|
||||
return MkPath(fInfo.dir(), fInfo.fileName(), messenger);
|
||||
}
|
||||
|
||||
bool MkPath(const QDir& dir, const QString& file, QWidget* parent)
|
||||
bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger)
|
||||
{
|
||||
if (!dir.mkpath(file))
|
||||
{
|
||||
QString msg = QString(parent->tr("A directory at '%1/%2' could not be created.")).arg(dir.path()).arg(file);
|
||||
QMessageBox::critical(parent, parent->tr("Unable to create directory"), msg);
|
||||
QString msg = QString(QObject::tr("A directory at '%1/%2' could not be created.")).arg(dir.path()).arg(file);
|
||||
messenger.critical(QObject::tr("Unable to create directory"), msg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -4,11 +4,33 @@
|
|||
#include "boo/System.hpp"
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
class UIMessenger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QObject::QObject;
|
||||
signals:
|
||||
QMessageBox::StandardButton information(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton question(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons =
|
||||
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton warning(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton critical(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
};
|
||||
|
||||
boo::SystemString QStringToSysString(const QString& str);
|
||||
QString SysStringToQString(const boo::SystemString& str);
|
||||
|
||||
bool MkPath(const QString& path, QWidget* parent);
|
||||
bool MkPath(const QDir& dir, const QString& file, QWidget* parent);
|
||||
bool MkPath(const QString& path, UIMessenger& messenger);
|
||||
bool MkPath(const QDir& dir, const QString& file, UIMessenger& messenger);
|
||||
|
||||
#endif //AMUSE_COMMON_HPP
|
||||
|
|
|
@ -3,15 +3,27 @@
|
|||
#include <QMessageBox>
|
||||
#include <QLineEdit>
|
||||
#include <QInputDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QtSvg/QtSvg>
|
||||
#include "amuse/ContainerRegistry.hpp"
|
||||
#include "Common.hpp"
|
||||
|
||||
static void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent),
|
||||
m_undoStack(new QUndoStack(this))
|
||||
m_mainMessenger(this),
|
||||
m_undoStack(new QUndoStack(this)),
|
||||
m_backgroundThread(this)
|
||||
{
|
||||
m_backgroundThread.start();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
connectMessenger(&m_mainMessenger, Qt::DirectConnection);
|
||||
|
||||
m_ui.actionNew_Project->setShortcut(QKeySequence::New);
|
||||
connect(m_ui.actionNew_Project, SIGNAL(triggered()), this, SLOT(newAction()));
|
||||
m_ui.actionOpen_Project->setShortcut(QKeySequence::Open);
|
||||
|
@ -55,9 +67,39 @@ MainWindow::MainWindow(QWidget* parent)
|
|||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
m_backgroundThread.quit();
|
||||
m_backgroundThread.wait();
|
||||
printf("IM DYING\n");
|
||||
}
|
||||
|
||||
void MainWindow::connectMessenger(UIMessenger* messenger, Qt::ConnectionType type)
|
||||
{
|
||||
connect(messenger, SIGNAL(information(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)),
|
||||
this, SLOT(msgInformation(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)), type);
|
||||
connect(messenger, SIGNAL(question(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)),
|
||||
this, SLOT(msgQuestion(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)), type);
|
||||
connect(messenger, SIGNAL(warning(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)),
|
||||
this, SLOT(msgWarning(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)), type);
|
||||
connect(messenger, SIGNAL(critical(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)),
|
||||
this, SLOT(msgCritical(const QString&,
|
||||
const QString&, QMessageBox::StandardButtons,
|
||||
QMessageBox::StandardButton)), type);
|
||||
}
|
||||
|
||||
bool MainWindow::setProjectPath(const QString& path)
|
||||
{
|
||||
if (m_projectModel && m_projectModel->path() == path)
|
||||
|
@ -138,14 +180,52 @@ void MainWindow::refreshMIDIIO()
|
|||
m_ui.menuMIDI->addAction(tr("No MIDI Devices Found"))->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::startBackgroundTask(const QString& windowTitle, const QString& label,
|
||||
std::function<void(BackgroundTask&)>&& task)
|
||||
{
|
||||
assert(m_backgroundTask == nullptr && "existing background process");
|
||||
setEnabled(false);
|
||||
|
||||
m_backgroundTask = new BackgroundTask(std::move(task));
|
||||
m_backgroundTask->moveToThread(&m_backgroundThread);
|
||||
|
||||
m_backgroundDialog = new QProgressDialog(this);
|
||||
m_backgroundDialog->setWindowTitle(windowTitle);
|
||||
m_backgroundDialog->setLabelText(label);
|
||||
m_backgroundDialog->setMinimumWidth(300);
|
||||
m_backgroundDialog->setAutoClose(false);
|
||||
m_backgroundDialog->setAutoReset(false);
|
||||
m_backgroundDialog->setMinimumDuration(0);
|
||||
m_backgroundDialog->setMinimum(0);
|
||||
m_backgroundDialog->setMaximum(0);
|
||||
m_backgroundDialog->setValue(0);
|
||||
|
||||
connect(m_backgroundTask, SIGNAL(setMinimum(int)),
|
||||
m_backgroundDialog, SLOT(setMinimum(int)), Qt::QueuedConnection);
|
||||
connect(m_backgroundTask, SIGNAL(setMaximum(int)),
|
||||
m_backgroundDialog, SLOT(setMaximum(int)), Qt::QueuedConnection);
|
||||
connect(m_backgroundTask, SIGNAL(setValue(int)),
|
||||
m_backgroundDialog, SLOT(setValue(int)), Qt::QueuedConnection);
|
||||
connect(m_backgroundTask, SIGNAL(setLabelText(const QString&)),
|
||||
m_backgroundDialog, SLOT(setLabelText(const QString&)), Qt::QueuedConnection);
|
||||
connect(m_backgroundTask, SIGNAL(finished()),
|
||||
this, SLOT(onBackgroundTaskFinished()), Qt::QueuedConnection);
|
||||
m_backgroundDialog->open(m_backgroundTask, SLOT(cancel()));
|
||||
|
||||
connectMessenger(&m_backgroundTask->uiMessenger(), Qt::BlockingQueuedConnection);
|
||||
|
||||
QMetaObject::invokeMethod(m_backgroundTask, "run", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void MainWindow::newAction()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(this, tr("New Project"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
if (!MkPath(path, this))
|
||||
if (!MkPath(path, m_mainMessenger))
|
||||
return;
|
||||
if (!setProjectPath(path))
|
||||
return;
|
||||
setProjectPath(path);
|
||||
}
|
||||
|
||||
void MainWindow::openAction()
|
||||
|
@ -153,7 +233,10 @@ void MainWindow::openAction()
|
|||
QString path = QFileDialog::getExistingDirectory(this, tr("Open Project"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
setProjectPath(path);
|
||||
if (!setProjectPath(path))
|
||||
return;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::importAction()
|
||||
|
@ -176,8 +259,8 @@ void MainWindow::importAction()
|
|||
int impMode = QMessageBox::question(this, tr("Sample Import Mode"),
|
||||
tr("Amuse can import samples as WAV files for ease of editing, "
|
||||
"import original compressed data for lossless repacking, or both. "
|
||||
"Exporting the project will prefer compressed files over WAVs, so "
|
||||
"be sure to delete the compressed version if you edit the WAV."),
|
||||
"Exporting the project will prefer whichever version was modified "
|
||||
"most recently."),
|
||||
tr("Import Compressed"), tr("Import WAVs"), tr("Import Both"));
|
||||
|
||||
switch (impMode)
|
||||
|
@ -189,6 +272,7 @@ void MainWindow::importAction()
|
|||
default:
|
||||
return;
|
||||
}
|
||||
ProjectModel::ImportMode importMode = ProjectModel::ImportMode(impMode);
|
||||
|
||||
/* Special handling for raw groups - gather sibling groups in filesystem */
|
||||
if (tp == amuse::ContainerRegistry::Type::Raw4)
|
||||
|
@ -211,12 +295,16 @@ void MainWindow::importAction()
|
|||
|
||||
QFileInfo fInfo(path);
|
||||
QString newPath = QFileInfo(fInfo.dir(), newName).filePath();
|
||||
if (!MkPath(fInfo.dir(), newName, this))
|
||||
if (!MkPath(fInfo.dir(), newName, m_mainMessenger))
|
||||
return;
|
||||
if (!setProjectPath(newPath))
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectModel* model = m_projectModel;
|
||||
startBackgroundTask(tr("Importing"), tr("Scanning Project"),
|
||||
[model, path, importMode](BackgroundTask& task)
|
||||
{
|
||||
QDir dir = QFileInfo(path).dir();
|
||||
QStringList filters;
|
||||
filters << "*.proj" << "*.pro";
|
||||
|
@ -225,11 +313,18 @@ void MainWindow::importAction()
|
|||
{
|
||||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(dir.filePath(fPath)).c_str());
|
||||
for (auto& p : data)
|
||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second)))
|
||||
{
|
||||
task.setLabelText(tr("Importing %1").arg(SysStringToQString(p.first)));
|
||||
if (task.isCanceled())
|
||||
return;
|
||||
if (!model->importGroupData(SysStringToQString(p.first), p.second,
|
||||
importMode, task.uiMessenger()))
|
||||
return;
|
||||
}
|
||||
m_projectModel->extractSamples(ProjectModel::ImportMode(impMode), this);
|
||||
m_projectModel->saveToFile(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
else if (scanMode == QMessageBox::No)
|
||||
|
@ -245,20 +340,31 @@ void MainWindow::importAction()
|
|||
{
|
||||
QFileInfo fInfo(path);
|
||||
QString newPath = QFileInfo(fInfo.dir(), fInfo.completeBaseName()).filePath();
|
||||
if (!MkPath(fInfo.dir(), fInfo.completeBaseName(), this))
|
||||
if (!MkPath(fInfo.dir(), fInfo.completeBaseName(), m_mainMessenger))
|
||||
return;
|
||||
if (!setProjectPath(newPath))
|
||||
return;
|
||||
}
|
||||
|
||||
ProjectModel* model = m_projectModel;
|
||||
startBackgroundTask(tr("Importing"), tr("Scanning Project"),
|
||||
[model, path, importMode](BackgroundTask& task)
|
||||
{
|
||||
/* Handle single container */
|
||||
auto data = amuse::ContainerRegistry::LoadContainer(QStringToSysString(path).c_str());
|
||||
task.setMaximum(int(data.size()));
|
||||
int curVal = 0;
|
||||
for (auto& p : data)
|
||||
if (!m_projectModel->importGroupData(SysStringToQString(p.first), std::move(p.second)))
|
||||
{
|
||||
task.setLabelText(tr("Importing %1").arg(SysStringToQString(p.first)));
|
||||
if (task.isCanceled())
|
||||
return;
|
||||
|
||||
m_projectModel->extractSamples(ProjectModel::ImportMode(impMode), this);
|
||||
m_projectModel->saveToFile(this);
|
||||
if (!model->importGroupData(SysStringToQString(p.first), p.second,
|
||||
importMode, task.uiMessenger()))
|
||||
return;
|
||||
task.setValue(++curVal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::exportAction()
|
||||
|
@ -395,3 +501,42 @@ void MainWindow::onTextDelete()
|
|||
le->del();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onBackgroundTaskFinished()
|
||||
{
|
||||
m_backgroundDialog->reset();
|
||||
m_backgroundDialog->deleteLater();
|
||||
m_backgroundDialog = nullptr;
|
||||
m_backgroundTask->deleteLater();
|
||||
m_backgroundTask = nullptr;
|
||||
m_projectModel->ensureModelData();
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton MainWindow::msgInformation(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
return QMessageBox::information(this, title, text, buttons, defaultButton);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton MainWindow::msgQuestion(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
return QMessageBox::question(this, title, text, buttons, defaultButton);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton MainWindow::msgWarning(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
return QMessageBox::warning(this, title, text, buttons, defaultButton);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton MainWindow::msgCritical(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
return QMessageBox::critical(this, title, text, buttons, defaultButton);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QUndoStack>
|
||||
#include <QProgressDialog>
|
||||
#include <QThread>
|
||||
#include "ui_MainWindow.h"
|
||||
#include "amuse/Engine.hpp"
|
||||
#include "amuse/BooBackend.hpp"
|
||||
|
@ -15,10 +17,35 @@ class MainWindow;
|
|||
|
||||
class AudioGroupModel;
|
||||
|
||||
class BackgroundTask : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
std::function<void(BackgroundTask&)> m_task;
|
||||
UIMessenger m_threadMessenger;
|
||||
bool m_cancelled = false;
|
||||
public:
|
||||
explicit BackgroundTask(std::function<void(BackgroundTask&)>&& task)
|
||||
: m_task(std::move(task)), m_threadMessenger(this) {}
|
||||
bool isCanceled() const { QCoreApplication::processEvents(); return m_cancelled; }
|
||||
UIMessenger& uiMessenger() { return m_threadMessenger; }
|
||||
|
||||
signals:
|
||||
void setMinimum(int minimum);
|
||||
void setMaximum(int maximum);
|
||||
void setValue(int value);
|
||||
void setLabelText(const QString& text);
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void run() { m_task(*this); emit finished(); }
|
||||
void cancel() { m_cancelled = true; }
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Ui::MainWindow m_ui;
|
||||
UIMessenger m_mainMessenger;
|
||||
ProjectModel* m_projectModel = nullptr;
|
||||
AudioGroupModel* m_focusAudioGroup = nullptr;
|
||||
|
||||
|
@ -38,11 +65,20 @@ class MainWindow : public QMainWindow
|
|||
QMetaObject::Connection m_deleteConn;
|
||||
QMetaObject::Connection m_canEditConn;
|
||||
|
||||
BackgroundTask* m_backgroundTask = nullptr;
|
||||
QProgressDialog* m_backgroundDialog = nullptr;
|
||||
QThread m_backgroundThread;
|
||||
|
||||
void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type);
|
||||
|
||||
bool setProjectPath(const QString& path);
|
||||
void setFocusAudioGroup(AudioGroupModel* group);
|
||||
void refreshAudioIO();
|
||||
void refreshMIDIIO();
|
||||
|
||||
void startBackgroundTask(const QString& windowTitle, const QString& label,
|
||||
std::function<void(BackgroundTask&)>&& task);
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = Q_NULLPTR);
|
||||
~MainWindow();
|
||||
|
@ -70,6 +106,22 @@ public slots:
|
|||
void onTextSelect();
|
||||
void onTextDelete();
|
||||
|
||||
void onBackgroundTaskFinished();
|
||||
|
||||
QMessageBox::StandardButton msgInformation(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton msgQuestion(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons =
|
||||
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton msgWarning(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
QMessageBox::StandardButton msgCritical(const QString &title,
|
||||
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@
|
|||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QTableView" name="propertyEditor">
|
||||
<property name="sizePolicy">
|
||||
|
|
|
@ -4,111 +4,250 @@
|
|||
#include "Common.hpp"
|
||||
#include "athena/YAMLDocWriter.hpp"
|
||||
|
||||
QIcon ProjectModel::GroupNode::Icon;
|
||||
QIcon ProjectModel::SongGroupNode::Icon;
|
||||
QIcon ProjectModel::SoundGroupNode::Icon;
|
||||
|
||||
ProjectModel::ProjectModel(const QString& path, QObject* parent)
|
||||
: QAbstractItemModel(parent), m_dir(path)
|
||||
{
|
||||
m_root = std::make_unique<RootNode>();
|
||||
|
||||
GroupNode::Icon = QIcon(":/icons/IconGroup.svg");
|
||||
SongGroupNode::Icon = QIcon(":/icons/IconSongGroup.svg");
|
||||
SoundGroupNode::Icon = QIcon(":/icons/IconSoundGroup.svg");
|
||||
}
|
||||
|
||||
ProjectModel::ProjectGroup::ProjectGroup(amuse::IntrusiveAudioGroupData&& data)
|
||||
: m_data(std::move(data)),
|
||||
m_proj(amuse::AudioGroupProject::CreateAudioGroupProject(m_data)),
|
||||
m_pool(amuse::AudioGroupPool::CreateAudioGroupPool(m_data)),
|
||||
m_sdir(amuse::AudioGroupSampleDirectory::CreateAudioGroupSampleDirectory(m_data))
|
||||
{}
|
||||
|
||||
bool ProjectModel::importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data)
|
||||
bool ProjectModel::importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
|
||||
ImportMode mode, UIMessenger& messenger)
|
||||
{
|
||||
setIdDatabases();
|
||||
m_projectDatabase.setIdDatabases();
|
||||
|
||||
ProjectGroup& grp = m_groups.insert(std::make_pair(groupName, std::move(data))).first->second;
|
||||
amuse::AudioGroupDatabase& grp = m_groups.insert(std::make_pair(groupName, data)).first->second;
|
||||
grp.setIdDatabases();
|
||||
amuse::AudioGroupProject::BootstrapObjectIDs(grp.m_data);
|
||||
amuse::AudioGroupProject::BootstrapObjectIDs(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectModel::extractSamples(ImportMode mode, QWidget* parent)
|
||||
{
|
||||
setIdDatabases();
|
||||
|
||||
if (!MkPath(m_dir.path(), parent))
|
||||
if (!MkPath(m_dir.path(), messenger))
|
||||
return false;
|
||||
|
||||
for (auto& g : m_groups)
|
||||
{
|
||||
g.second.setIdDatabases();
|
||||
|
||||
QDir dir(QFileInfo(m_dir, g.first).filePath());
|
||||
if (!MkPath(dir.path(), parent))
|
||||
QDir dir(QFileInfo(m_dir, groupName).filePath());
|
||||
if (!MkPath(dir.path(), messenger))
|
||||
return false;
|
||||
|
||||
amuse::SystemString sysDir = QStringToSysString(dir.path());
|
||||
switch (mode)
|
||||
{
|
||||
case ImportMode::Original:
|
||||
g.second.m_sdir.extractAllCompressed(sysDir, g.second.m_data.getSamp());
|
||||
grp.getSdir().extractAllCompressed(sysDir, data.getSamp());
|
||||
break;
|
||||
case ImportMode::WAVs:
|
||||
g.second.m_sdir.extractAllWAV(sysDir, g.second.m_data.getSamp());
|
||||
grp.getSdir().extractAllWAV(sysDir, data.getSamp());
|
||||
break;
|
||||
case ImportMode::Both:
|
||||
g.second.m_sdir.extractAllCompressed(sysDir, g.second.m_data.getSamp());
|
||||
g.second.m_sdir.extractAllWAV(sysDir, g.second.m_data.getSamp());
|
||||
grp.getSdir().extractAllWAV(sysDir, data.getSamp());
|
||||
grp.getSdir().extractAllCompressed(sysDir, data.getSamp());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
grp.getProj().toYAML(sysDir);
|
||||
grp.getPool().toYAML(sysDir);
|
||||
|
||||
m_needsReset = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectModel::saveToFile(QWidget* parent)
|
||||
bool ProjectModel::saveToFile(UIMessenger& messenger)
|
||||
{
|
||||
setIdDatabases();
|
||||
m_projectDatabase.setIdDatabases();
|
||||
|
||||
if (!MkPath(m_dir.path(), parent))
|
||||
if (!MkPath(m_dir.path(), messenger))
|
||||
return false;
|
||||
|
||||
for (auto& g : m_groups)
|
||||
{
|
||||
QDir dir(QFileInfo(m_dir, g.first).filePath());
|
||||
if (!MkPath(dir.path(), parent))
|
||||
if (!MkPath(dir.path(), messenger))
|
||||
return false;
|
||||
|
||||
g.second.setIdDatabases();
|
||||
amuse::SystemString groupPath = QStringToSysString(dir.path());
|
||||
g.second.m_proj.toYAML(groupPath);
|
||||
g.second.m_pool.toYAML(groupPath);
|
||||
g.second.getProj().toYAML(groupPath);
|
||||
g.second.getPool().toYAML(groupPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::index(int row, int column, const QModelIndex& parent) const
|
||||
void ProjectModel::_resetModelData()
|
||||
{
|
||||
return createIndex(row, column, nullptr);
|
||||
beginResetModel();
|
||||
m_projectDatabase.setIdDatabases();
|
||||
m_root = std::make_unique<RootNode>();
|
||||
m_root->reserve(m_groups.size());
|
||||
for (auto it = m_groups.begin() ; it != m_groups.end() ; ++it)
|
||||
{
|
||||
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();
|
||||
gn.reserve(songGroups.size() + sfxGroups.size() + 4);
|
||||
for (const auto& grp : SortUnorderedMap(songGroups))
|
||||
gn.makeChild<SongGroupNode>(grp.first, grp.second.get());
|
||||
for (const auto& grp : SortUnorderedMap(sfxGroups))
|
||||
gn.makeChild<SoundGroupNode>(grp.first, grp.second.get());
|
||||
if (soundMacros.size())
|
||||
{
|
||||
CollectionNode& col =
|
||||
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());
|
||||
}
|
||||
if (tables.size())
|
||||
{
|
||||
auto tablesSort = SortUnorderedMap(tables);
|
||||
size_t ADSRCount = 0;
|
||||
size_t curveCount = 0;
|
||||
for (auto& t : tablesSort)
|
||||
{
|
||||
amuse::ITable::Type tp = t.second.get()->Isa();
|
||||
if (tp == amuse::ITable::Type::ADSR || tp == amuse::ITable::Type::ADSRDLS)
|
||||
ADSRCount += 1;
|
||||
else if (tp == amuse::ITable::Type::Curve)
|
||||
curveCount += 1;
|
||||
}
|
||||
if (ADSRCount)
|
||||
{
|
||||
CollectionNode& col =
|
||||
gn.makeChild<CollectionNode>(tr("ADSRs"), QIcon(":/icons/IconADSR.svg"));
|
||||
col.reserve(ADSRCount);
|
||||
for (auto& t : tablesSort)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
if (curveCount)
|
||||
{
|
||||
CollectionNode& col =
|
||||
gn.makeChild<CollectionNode>(tr("Curves"), QIcon(":/icons/IconCurve.svg"));
|
||||
col.reserve(curveCount);
|
||||
for (auto& t : tablesSort)
|
||||
{
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keymaps.size())
|
||||
{
|
||||
CollectionNode& col =
|
||||
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());
|
||||
}
|
||||
if (layers.size())
|
||||
{
|
||||
CollectionNode& col =
|
||||
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());
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::parent(const QModelIndex& child) const
|
||||
void ProjectModel::ensureModelData()
|
||||
{
|
||||
return {};
|
||||
if (m_needsReset)
|
||||
{
|
||||
_resetModelData();
|
||||
m_needsReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
INode* parentItem;
|
||||
if (!parent.isValid())
|
||||
parentItem = m_root.get();
|
||||
else
|
||||
parentItem = static_cast<INode*>(parent.internalPointer());
|
||||
|
||||
INode* childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex ProjectModel::parent(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
INode* childItem = static_cast<INode*>(index.internalPointer());
|
||||
INode* parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == m_root.get())
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
int ProjectModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return 0;
|
||||
INode* parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = m_root.get();
|
||||
else
|
||||
parentItem = static_cast<INode*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
int ProjectModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
QVariant ProjectModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
INode* item = static_cast<INode*>(index.internalPointer());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return item->text();
|
||||
case Qt::DecorationRole:
|
||||
return item->icon();
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags ProjectModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
|
||||
bool ProjectModel::canDelete() const
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDir>
|
||||
#include <QIcon>
|
||||
#include <map>
|
||||
#include "Common.hpp"
|
||||
#include "amuse/AudioGroup.hpp"
|
||||
#include "amuse/AudioGroupData.hpp"
|
||||
#include "amuse/AudioGroupProject.hpp"
|
||||
#include "amuse/AudioGroupPool.hpp"
|
||||
|
@ -19,54 +22,134 @@ public:
|
|||
WAVs,
|
||||
Both
|
||||
};
|
||||
struct ProjectGroup
|
||||
{
|
||||
amuse::IntrusiveAudioGroupData m_data;
|
||||
amuse::AudioGroupProject m_proj;
|
||||
amuse::AudioGroupPool m_pool;
|
||||
amuse::AudioGroupSampleDirectory m_sdir;
|
||||
amuse::NameDB m_soundMacroDb;
|
||||
amuse::NameDB m_sampleDb;
|
||||
amuse::NameDB m_tableDb;
|
||||
amuse::NameDB m_keymapDb;
|
||||
amuse::NameDB m_layersDb;
|
||||
|
||||
explicit ProjectGroup(amuse::IntrusiveAudioGroupData&& data);
|
||||
void setIdDatabases()
|
||||
{
|
||||
amuse::SoundMacroId::CurNameDB = &m_soundMacroDb;
|
||||
amuse::SampleId::CurNameDB = &m_sampleDb;
|
||||
amuse::TableId::CurNameDB = &m_tableDb;
|
||||
amuse::KeymapId::CurNameDB = &m_keymapDb;
|
||||
amuse::LayersId::CurNameDB = &m_layersDb;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
QDir m_dir;
|
||||
|
||||
amuse::NameDB m_songDb;
|
||||
amuse::NameDB m_sfxDb;
|
||||
std::map<QString, ProjectGroup> m_groups;
|
||||
amuse::ProjectDatabase m_projectDatabase;
|
||||
std::map<QString, amuse::AudioGroupDatabase> m_groups;
|
||||
|
||||
void setIdDatabases()
|
||||
class INode
|
||||
{
|
||||
amuse::SongId::CurNameDB = &m_songDb;
|
||||
amuse::SFXId::CurNameDB = &m_sfxDb;
|
||||
enum class Type
|
||||
{
|
||||
Group, // Top-level group
|
||||
SongGroup,
|
||||
SfxGroup,
|
||||
Collection, // Classified object collection, one of the following:
|
||||
SoundMacro,
|
||||
ADSR,
|
||||
Curve,
|
||||
Keymap,
|
||||
Layer
|
||||
};
|
||||
INode* m_parent;
|
||||
std::vector<std::unique_ptr<INode>> m_children;
|
||||
int m_row;
|
||||
public:
|
||||
virtual ~INode() = default;
|
||||
INode(INode* parent, int row) : m_parent(parent), m_row(row) {}
|
||||
|
||||
int childCount() const { return int(m_children.size()); }
|
||||
INode* child(int row) const { return m_children[row].get(); }
|
||||
INode* parent() const { return m_parent; }
|
||||
int row() const { return m_row; }
|
||||
|
||||
void reserve(size_t sz) { m_children.reserve(sz); }
|
||||
template<class T, class... _Args>
|
||||
T& makeChild(_Args&&... args)
|
||||
{
|
||||
m_children.push_back(std::make_unique<T>(this, m_children.size(), std::forward<_Args>(args)...));
|
||||
return static_cast<T&>(*m_children.back());
|
||||
}
|
||||
|
||||
virtual QString text() const = 0;
|
||||
virtual QIcon icon() const = 0;
|
||||
};
|
||||
struct RootNode : INode
|
||||
{
|
||||
RootNode() : INode(nullptr, 0) {}
|
||||
|
||||
QString text() const { return {}; }
|
||||
QIcon icon() const { return {}; }
|
||||
};
|
||||
struct GroupNode : INode
|
||||
{
|
||||
std::map<QString, amuse::AudioGroupDatabase>::iterator m_it;
|
||||
GroupNode(INode* parent, int row, std::map<QString, amuse::AudioGroupDatabase>::iterator it)
|
||||
: INode(parent, row), m_it(it) {}
|
||||
|
||||
static QIcon Icon;
|
||||
QString text() const { return m_it->first; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
struct SongGroupNode : INode
|
||||
{
|
||||
amuse::GroupId m_id;
|
||||
QString m_name;
|
||||
amuse::SongGroupIndex& m_index;
|
||||
SongGroupNode(INode* parent, int row, amuse::GroupId id, amuse::SongGroupIndex& index)
|
||||
: INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
|
||||
|
||||
static QIcon Icon;
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
struct SoundGroupNode : INode
|
||||
{
|
||||
amuse::GroupId m_id;
|
||||
QString m_name;
|
||||
amuse::SFXGroupIndex& m_index;
|
||||
SoundGroupNode(INode* parent, int row, amuse::GroupId id, amuse::SFXGroupIndex& index)
|
||||
: INode(parent, row), m_id(id), m_name(amuse::GroupId::CurNameDB->resolveNameFromId(id).data()), m_index(index) {}
|
||||
|
||||
static QIcon Icon;
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return Icon; }
|
||||
};
|
||||
struct CollectionNode : INode
|
||||
{
|
||||
QString m_name;
|
||||
QIcon m_icon;
|
||||
CollectionNode(INode* parent, int row, const QString& name, const QIcon& icon)
|
||||
: INode(parent, row), m_name(name), m_icon(icon) {}
|
||||
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return m_icon; }
|
||||
};
|
||||
template <class ID, class T>
|
||||
struct PoolObjectNode : INode
|
||||
{
|
||||
ID m_id;
|
||||
QString m_name;
|
||||
T& m_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) {}
|
||||
|
||||
QString text() const { return m_name; }
|
||||
QIcon icon() const { return {}; }
|
||||
};
|
||||
|
||||
std::unique_ptr<RootNode> m_root;
|
||||
|
||||
bool m_needsReset = false;
|
||||
void _resetModelData();
|
||||
|
||||
public:
|
||||
explicit ProjectModel(const QString& path, QObject* parent = Q_NULLPTR);
|
||||
|
||||
bool importGroupData(const QString& groupName, amuse::IntrusiveAudioGroupData&& data);
|
||||
bool extractSamples(ImportMode mode, QWidget* parent);
|
||||
bool saveToFile(QWidget* parent);
|
||||
bool importGroupData(const QString& groupName, const amuse::AudioGroupData& data,
|
||||
ImportMode mode, UIMessenger& messenger);
|
||||
bool saveToFile(UIMessenger& messenger);
|
||||
|
||||
void ensureModelData();
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex& child) const;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
|
||||
QString path() const { return m_dir.path(); }
|
||||
bool canDelete() const;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconADSR.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="30.086227"
|
||||
inkscape:cx="7.2902772"
|
||||
inkscape:cy="8.0995259"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="267"
|
||||
inkscape:window-y="1022"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
visible="true"
|
||||
empspacing="1"
|
||||
id="grid4173"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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
|
||||
transform="translate(0,-292.76665)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
style="fill:#ff6600;fill-opacity:1;stroke:none;stroke-width:0.39687499;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="rect1235"
|
||||
width="3.7041667"
|
||||
height="3.7041805"
|
||||
x="0.26458335"
|
||||
y="293.03122" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.26458333,296.7354 1.0583334,293.47246 1.5875,294.35415 H 2.9104167 L 3.96875,296.7354"
|
||||
id="path1834"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
|
@ -0,0 +1,87 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconCurve.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="30.086227"
|
||||
inkscape:cx="-2.7199818"
|
||||
inkscape:cy="9.4290379"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="267"
|
||||
inkscape:window-y="1022"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
visible="true"
|
||||
empspacing="1"
|
||||
id="grid4173"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(0,-292.76665)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
style="fill:#00ffcc;fill-opacity:1;stroke:none;stroke-width:0.39687499;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="rect1235"
|
||||
width="3.7041667"
|
||||
height="3.7041805"
|
||||
x="0.26458335"
|
||||
y="293.03122" />
|
||||
<path
|
||||
style="fill:none;stroke:#808080;stroke-width:0.52916667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916666999999995;stroke-opacity:1;stroke-dashoffset:0"
|
||||
d="m 0.26458333,292.76665 0,3.96875 H 4.2333333"
|
||||
id="path1231"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 0,296.7354 c 2.0787582,0 3.96875,-2.11667 3.96875,-3.96875"
|
||||
id="path1233"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,74 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
sodipodi:docname="IconSoundGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="19.66"
|
||||
inkscape:cx="6.046968"
|
||||
inkscape:cy="6.9530957"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="231"
|
||||
inkscape:window-y="82"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="true"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4173"
|
||||
empspacing="1"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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,-292.76665)">
|
||||
<path
|
||||
style="opacity:1;fill:#fbd365;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
|
@ -14,7 +14,7 @@
|
|||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconLayers.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
|
@ -26,7 +26,7 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.92"
|
||||
inkscape:cx="19.961362"
|
||||
inkscape:cx="-13.575223"
|
||||
inkscape:cy="7.1823475"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
|
@ -34,8 +34,8 @@
|
|||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="131"
|
||||
inkscape:window-y="148"
|
||||
inkscape:window-x="1749"
|
||||
inkscape:window-y="677"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
|
@ -55,7 +55,7 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,86 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconNewADSR.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="30.086227"
|
||||
inkscape:cx="7.2902772"
|
||||
inkscape:cy="8.0995259"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="341"
|
||||
inkscape:window-y="1113"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
visible="true"
|
||||
empspacing="1"
|
||||
id="grid4173"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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
|
||||
transform="translate(0,-292.76665)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
style="fill:#ff6600;fill-opacity:1;stroke:none;stroke-width:0.39687499;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="rect1235"
|
||||
width="3.7041667"
|
||||
height="3.7041805"
|
||||
x="0.26458335"
|
||||
y="293.03122" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 0.26458333,296.7354 1.0583334,293.47246 1.5875,294.35415 H 2.9104167 L 3.96875,296.7354"
|
||||
id="path1834"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5323"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#df0000;stroke-width:0.26458332;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.8386428,295.34071 0.9362114,0.93622 m -0.9362104,-10e-6 0.9362094,-0.9362 m -1.1301062,0.4681 H 3.96875 m -0.6620015,0.662 v -1.324" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
|
@ -0,0 +1,92 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconNewCurve.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="30.086227"
|
||||
inkscape:cx="8.2484922"
|
||||
inkscape:cy="9.4290379"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="459"
|
||||
inkscape:window-y="172"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
visible="true"
|
||||
empspacing="1"
|
||||
id="grid4173"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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
|
||||
transform="translate(0,-292.76665)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
style="fill:#00ffcc;fill-opacity:1;stroke:none;stroke-width:0.39687499;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="rect1235"
|
||||
width="3.7041667"
|
||||
height="3.7041805"
|
||||
x="0.26458335"
|
||||
y="293.03122" />
|
||||
<path
|
||||
style="fill:none;stroke:#808080;stroke-width:0.52916667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.52916667, 0.52916666999999995;stroke-opacity:1;stroke-dashoffset:0"
|
||||
d="m 0.26458333,292.76665 0,3.96875 H 4.2333333"
|
||||
id="path1231"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.5291667;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 0,296.7354 c 2.0787582,0 3.96875,-2.11667 3.96875,-3.96875"
|
||||
id="path1233"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5323"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#df0000;stroke-width:0.26458332;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.8386428,295.34071 0.9362114,0.93622 m -0.9362104,-10e-6 0.9362094,-0.9362 m -1.1301062,0.4681 H 3.96875 m -0.6620015,0.662 v -1.324" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -0,0 +1,78 @@
|
|||
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
sodipodi:docname="NewSoundGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="19.66"
|
||||
inkscape:cx="6.046968"
|
||||
inkscape:cy="6.9530957"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="231"
|
||||
inkscape:window-y="82"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="true"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4173"
|
||||
empspacing="1"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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,-292.76665)">
|
||||
<path
|
||||
style="opacity:1;fill:#fbd365;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
<path
|
||||
id="path5876"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#df0000;stroke-width:0.26458332;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.8386428,295.07809 0.9362114,0.93622 m -0.9362104,-1e-5 0.9362094,-0.9362 m -1.1301062,0.4681 1.324003,0 m -0.6620015,0.662 0,-1.324" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
|
@ -14,8 +14,8 @@
|
|||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
sodipodi:docname="NewSongGroup.svg">
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconNewSongGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
|
@ -26,7 +26,7 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="29.730996"
|
||||
inkscape:cx="3.7002328"
|
||||
inkscape:cx="3.0052979"
|
||||
inkscape:cy="9.0045012"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
|
@ -35,7 +35,7 @@
|
|||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="23"
|
||||
inkscape:window-y="40"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
|
@ -55,7 +55,7 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -65,11 +65,16 @@
|
|||
id="layer1"
|
||||
transform="translate(0,-292.76665)">
|
||||
<path
|
||||
style="opacity:1;fill:#04e2ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
style="opacity:1;fill:#ff5599;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path868"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 1.8675862,295.87272 a 0.57456181,0.36088177 0 0 1 -0.5745618,0.36089 0.57456181,0.36088177 0 0 1 -0.57456172,-0.36089 0.57456181,0.36088177 0 0 1 0.57456172,-0.36088 0.57456181,0.36088177 0 0 1 0.5745618,0.36088 z m 1.3298265,-0.001 a 0.57456181,0.36088177 0 0 1 -0.5745619,0.36089 0.57456181,0.36088177 0 0 1 -0.5745618,-0.36089 0.57456181,0.36088177 0 0 1 0.5745618,-0.36088 0.57456181,0.36088177 0 0 1 0.5745619,0.36088 z m -0.253445,-1.78193 0.253445,0.006 v 1.77617 c -0.2177221,0.0701 -0.286996,-0.0173 -0.3755473,-0.1676 l 0.00387,-0.79478 H 1.868454 v 0.95424 c -0.2323614,-0.008 -0.2369279,-0.14254 -0.3755412,-0.22458 v -1.54879 z" />
|
||||
<path
|
||||
id="path5323"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#df0000;stroke-width:0.26458332;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
|
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.7 KiB |
|
@ -14,8 +14,8 @@
|
|||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
sodipodi:docname="NewSoundGroup.svg">
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconNewSoundGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
|
@ -25,17 +25,17 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="19.66"
|
||||
inkscape:cx="6.046968"
|
||||
inkscape:zoom="31.94"
|
||||
inkscape:cx="9.7896878"
|
||||
inkscape:cy="6.9530957"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="231"
|
||||
inkscape:window-y="82"
|
||||
inkscape:window-height="777"
|
||||
inkscape:window-x="2038"
|
||||
inkscape:window-y="1136"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="true"
|
||||
objecttolerance="4"
|
||||
|
@ -55,7 +55,7 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -65,11 +65,17 @@
|
|||
id="layer1"
|
||||
transform="translate(0,-292.76665)">
|
||||
<path
|
||||
style="opacity:1;fill:#fbd365;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
style="opacity:1;fill:#04e2ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
<path
|
||||
id="path1184"
|
||||
title="sin(x*4*pi)*sin(x*pi)"
|
||||
d="m 0.52916699,295.1479 c 0.11759258,-1.5e-4 0.23518516,-0.18652 0.35277774,-0.31191 0.11759258,-0.1254 0.23518517,-0.1236 0.35277777,0.10832 0.1175926,0.23193 0.2351851,0.66463 0.3527777,0.89812 0.1175926,0.23349 0.2351852,0.20457 0.3527778,-0.10832 0.1175925,-0.3129 0.2351851,-0.85907 0.3527777,-1.17242 0.1175926,-0.31334 0.2351852,-0.3414 0.3527777,-0.10832 0.1175926,0.23308 0.2351852,0.66584 0.3527778,0.89812 0.1175926,0.23228 0.2351851,0.23355 0.3527778,0.10832 0.1175925,-0.12522 0.235185,-0.31176 0.3527777,-0.31191"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path5876"
|
||||
style="fill:#ff0000;fill-rule:evenodd;stroke:#df0000;stroke-width:0.26458332;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
|
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.7 KiB |
|
@ -14,7 +14,7 @@
|
|||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconSongGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
|
@ -25,17 +25,17 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="29.730996"
|
||||
inkscape:cx="3.7002328"
|
||||
inkscape:cy="9.0045012"
|
||||
inkscape:zoom="34.350339"
|
||||
inkscape:cx="8.8858389"
|
||||
inkscape:cy="8.8343343"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="23"
|
||||
inkscape:window-x="1944"
|
||||
inkscape:window-y="288"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
|
@ -45,7 +45,7 @@
|
|||
type="xygrid"
|
||||
id="grid4173"
|
||||
empspacing="1"
|
||||
visible="false" />
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
|
@ -65,10 +65,19 @@
|
|||
id="layer1"
|
||||
transform="translate(0,-292.76665)">
|
||||
<path
|
||||
style="opacity:1;fill:#04e2ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
style="opacity:1;fill:#ff5599;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
<g
|
||||
aria-label="♬"
|
||||
style="font-style:normal;font-weight:normal;font-size:1.66674709px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.31251505"
|
||||
id="text820"
|
||||
transform="matrix(1.1529095,0,0,1.1529095,-0.32840767,-44.985003)" />
|
||||
<path
|
||||
id="path868"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 1.8675862,295.87272 a 0.57456183,0.36088178 0 0 1 -0.5745618,0.36089 0.57456183,0.36088178 0 0 1 -0.57456171,-0.36089 0.57456183,0.36088178 0 0 1 0.57456171,-0.36088 0.57456183,0.36088178 0 0 1 0.5745618,0.36088 z m 1.3298265,-0.001 a 0.57456183,0.36088178 0 0 1 -0.5745619,0.36089 0.57456183,0.36088178 0 0 1 -0.5745618,-0.36089 0.57456183,0.36088178 0 0 1 0.5745618,-0.36088 0.57456183,0.36088178 0 0 1 0.5745619,0.36088 z m -0.253445,-1.78193 0.253445,0.006 v 1.77617 c -0.2177221,0.0701 -0.286996,-0.0173 -0.3755473,-0.1676 l 0.00387,-0.79478 H 1.868454 v 0.95424 c -0.2323614,-0.008 -0.2369279,-0.14254 -0.3755412,-0.22458 v -1.54879 z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.6 KiB |
|
@ -14,10 +14,8 @@
|
|||
viewBox="0 0 4.2333332 4.2333335"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91+devel+osxmenu r12922"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="IconSoundGroup.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#393939"
|
||||
|
@ -25,28 +23,30 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="19.66"
|
||||
inkscape:cx="6.046968"
|
||||
inkscape:cy="6.9530957"
|
||||
inkscape:zoom="34.25"
|
||||
inkscape:cx="8.0808195"
|
||||
inkscape:cy="8.452632"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1260"
|
||||
inkscape:window-width="1258"
|
||||
inkscape:window-height="787"
|
||||
inkscape:window-x="231"
|
||||
inkscape:window-y="82"
|
||||
inkscape:window-x="1970"
|
||||
inkscape:window-y="1150"
|
||||
inkscape:window-maximized="0"
|
||||
showborder="true"
|
||||
showborder="false"
|
||||
objecttolerance="4"
|
||||
gridtolerance="4"
|
||||
guidetolerance="5">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4173"
|
||||
visible="true"
|
||||
empspacing="1"
|
||||
visible="true" />
|
||||
id="grid4173"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
|
@ -60,15 +60,21 @@
|
|||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-292.76665)"
|
||||
id="layer1"
|
||||
transform="translate(0,-292.76665)">
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
style="opacity:1;fill:#fbd365;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
id="rect4141"
|
||||
sodipodi:nodetypes="cccssssscccc"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccssssscccc" />
|
||||
id="rect4141"
|
||||
d="m 1.3229167,293.04538 c 0.2645833,0 0.5291666,0.25044 0.5291666,0.51502 l 0,0.26458 1.8488138,0.0102 c 0.3165926,0.002 0.5239173,0.20975 0.5245413,0.52471 l 0.00313,1.57936 c 6.239e-4,0.31495 -0.2079439,0.53411 -0.5245413,0.53411 l -3.17666623,0 C 0.21076252,296.47339 0,296.2566 0,295.94165 c 4.054e-5,-0.82258 0,-2.38125 0,-2.38125 0,-0.26458 0.26458333,-0.51612 0.52916667,-0.51612 z"
|
||||
style="opacity:1;fill:#04e2ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.67643285;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
id="path1184"
|
||||
title="sin(x*4*pi)*sin(x*pi)"
|
||||
d="m 0.52916698,295.1479 c 0.11759258,-1.5e-4 0.23518516,-0.18652 0.35277775,-0.31191 0.11759258,-0.1254 0.23518517,-0.1236 0.35277777,0.10832 0.1175926,0.23193 0.2351851,0.66463 0.3527777,0.89812 0.1175926,0.23349 0.2351852,0.20457 0.3527778,-0.10832 0.1175925,-0.3129 0.2351851,-0.85907 0.3527777,-1.17242 0.1175926,-0.31334 0.2351852,-0.3414 0.3527777,-0.10832 0.1175926,0.23308 0.2351852,0.66584 0.3527778,0.89812 0.1175926,0.23228 0.2351852,0.23355 0.3527777,0.10832 0.1175926,-0.12522 0.2351852,-0.31176 0.3527778,-0.31191"
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.396875;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linecap:round;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 3.3 KiB |
|
@ -13,6 +13,12 @@
|
|||
<file>IconSongGroup.svg</file>
|
||||
<file>IconSoundGroup.svg</file>
|
||||
<file>IconSoundMacro.svg</file>
|
||||
<file>IconGroup.svg</file>
|
||||
<file>IconNewGroup.svg</file>
|
||||
<file>IconADSR.svg</file>
|
||||
<file>IconNewADSR.svg</file>
|
||||
<file>IconCurve.svg</file>
|
||||
<file>IconNewCurve.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/bg">
|
||||
<file>FaceGrey.svg</file>
|
||||
|
|
|
@ -29,6 +29,48 @@ public:
|
|||
const AudioGroupProject& getProj() const { return m_proj; }
|
||||
const AudioGroupPool& getPool() const { return m_pool; }
|
||||
const AudioGroupSampleDirectory& getSdir() const { return m_sdir; }
|
||||
AudioGroupProject& getProj() { return m_proj; }
|
||||
AudioGroupPool& getPool() { return m_pool; }
|
||||
AudioGroupSampleDirectory& getSdir() { return m_sdir; }
|
||||
};
|
||||
|
||||
class AudioGroupDatabase : public AudioGroup
|
||||
{
|
||||
amuse::NameDB m_soundMacroDb;
|
||||
amuse::NameDB m_sampleDb;
|
||||
amuse::NameDB m_tableDb;
|
||||
amuse::NameDB m_keymapDb;
|
||||
amuse::NameDB m_layersDb;
|
||||
|
||||
public:
|
||||
explicit AudioGroupDatabase(const AudioGroupData& data)
|
||||
: AudioGroup(data) {}
|
||||
explicit AudioGroupDatabase(SystemStringView groupPath)
|
||||
: AudioGroup(groupPath) {}
|
||||
|
||||
void setIdDatabases()
|
||||
{
|
||||
amuse::SoundMacroId::CurNameDB = &m_soundMacroDb;
|
||||
amuse::SampleId::CurNameDB = &m_sampleDb;
|
||||
amuse::TableId::CurNameDB = &m_tableDb;
|
||||
amuse::KeymapId::CurNameDB = &m_keymapDb;
|
||||
amuse::LayersId::CurNameDB = &m_layersDb;
|
||||
}
|
||||
};
|
||||
|
||||
class ProjectDatabase
|
||||
{
|
||||
amuse::NameDB m_songDb;
|
||||
amuse::NameDB m_sfxDb;
|
||||
amuse::NameDB m_groupDb;
|
||||
|
||||
public:
|
||||
void setIdDatabases()
|
||||
{
|
||||
amuse::SongId::CurNameDB = &m_songDb;
|
||||
amuse::SFXId::CurNameDB = &m_sfxDb;
|
||||
amuse::GroupId::CurNameDB = &m_groupDb;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -664,7 +664,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -676,7 +676,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -688,7 +688,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -700,7 +700,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -712,7 +712,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -724,7 +724,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -736,7 +736,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -748,7 +748,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -760,7 +760,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -772,7 +772,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -784,7 +784,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -796,7 +796,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -808,7 +808,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -820,7 +820,7 @@ struct SoundMacro
|
|||
AT_DECL_DNAV
|
||||
Value<atUint8> midiControl;
|
||||
Value<atUint16> scalingPercentage;
|
||||
Value<bool> combine;
|
||||
Value<atInt8> combine;
|
||||
Value<bool> isVar;
|
||||
Value<atUint8> fineScaling;
|
||||
bool Do(SoundMacroState& st, Voice& vox) const;
|
||||
|
@ -1156,6 +1156,15 @@ public:
|
|||
static AudioGroupPool CreateAudioGroupPool(const AudioGroupData& data);
|
||||
static AudioGroupPool CreateAudioGroupPool(SystemStringView groupPath);
|
||||
|
||||
const std::unordered_map<SoundMacroId, SoundMacro>& soundMacros() const { return m_soundMacros; }
|
||||
const std::unordered_map<TableId, std::unique_ptr<ITable>>& tables() const { return m_tables; }
|
||||
const std::unordered_map<KeymapId, Keymap>& keymaps() const { return m_keymaps; }
|
||||
const std::unordered_map<LayersId, std::vector<LayerMapping>>& layers() const { return m_layers; }
|
||||
std::unordered_map<SoundMacroId, SoundMacro>& soundMacros() { return m_soundMacros; }
|
||||
std::unordered_map<TableId, std::unique_ptr<ITable>>& tables() { return m_tables; }
|
||||
std::unordered_map<KeymapId, Keymap>& keymaps() { return m_keymaps; }
|
||||
std::unordered_map<LayersId, std::vector<LayerMapping>>& layers() { return m_layers; }
|
||||
|
||||
const SoundMacro* soundMacro(ObjectId id) const;
|
||||
const Keymap* keymap(ObjectId id) const;
|
||||
const std::vector<LayerMapping>* layer(ObjectId id) const;
|
||||
|
@ -1164,6 +1173,11 @@ public:
|
|||
const Curve* tableAsCurves(ObjectId id) const;
|
||||
|
||||
bool toYAML(SystemStringView groupPath) const;
|
||||
|
||||
AudioGroupPool(const AudioGroupPool&) = delete;
|
||||
AudioGroupPool& operator=(const AudioGroupPool&) = delete;
|
||||
AudioGroupPool(AudioGroupPool&&) = default;
|
||||
AudioGroupPool& operator=(AudioGroupPool&&) = default;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ GroupHeader : BigDNA
|
|||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32, DNAEn> groupEndOff;
|
||||
Value<atUint16, DNAEn> groupId;
|
||||
GroupIdDNA<DNAEn> groupId;
|
||||
Value<GroupType, DNAEn> type;
|
||||
Value<atUint32, DNAEn> soundMacroIdsOff;
|
||||
Value<atUint32, DNAEn> samplIdsOff;
|
||||
|
@ -180,8 +180,8 @@ struct SFXGroupIndex : AudioGroupIndex
|
|||
/** Collection of SongGroup and SFXGroup indexes */
|
||||
class AudioGroupProject
|
||||
{
|
||||
std::unordered_map<int, SongGroupIndex> m_songGroups;
|
||||
std::unordered_map<int, SFXGroupIndex> m_sfxGroups;
|
||||
std::unordered_map<GroupId, SongGroupIndex> m_songGroups;
|
||||
std::unordered_map<GroupId, SFXGroupIndex> m_sfxGroups;
|
||||
|
||||
AudioGroupProject() = default;
|
||||
AudioGroupProject(athena::io::IStreamReader& r, GCNDataTag);
|
||||
|
@ -199,10 +199,17 @@ public:
|
|||
const SongGroupIndex* getSongGroupIndex(int groupId) const;
|
||||
const SFXGroupIndex* getSFXGroupIndex(int groupId) const;
|
||||
|
||||
const std::unordered_map<int, SongGroupIndex>& songGroups() const { return m_songGroups; }
|
||||
const std::unordered_map<int, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
|
||||
const std::unordered_map<GroupId, SongGroupIndex>& songGroups() const { return m_songGroups; }
|
||||
const std::unordered_map<GroupId, SFXGroupIndex>& sfxGroups() const { return m_sfxGroups; }
|
||||
std::unordered_map<GroupId, SongGroupIndex>& songGroups() { return m_songGroups; }
|
||||
std::unordered_map<GroupId, SFXGroupIndex>& sfxGroups() { return m_sfxGroups; }
|
||||
|
||||
bool toYAML(SystemStringView groupPath) const;
|
||||
|
||||
AudioGroupProject(const AudioGroupProject&) = delete;
|
||||
AudioGroupProject& operator=(const AudioGroupProject&) = delete;
|
||||
AudioGroupProject(AudioGroupProject&&) = default;
|
||||
AudioGroupProject& operator=(AudioGroupProject&&) = default;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,11 @@ public:
|
|||
void extractAllWAV(amuse::SystemStringView destDir, const unsigned char* samp) const;
|
||||
void extractCompressed(SampleId id, amuse::SystemStringView destDir, const unsigned char* samp) const;
|
||||
void extractAllCompressed(amuse::SystemStringView destDir, const unsigned char* samp) const;
|
||||
|
||||
AudioGroupSampleDirectory(const AudioGroupSampleDirectory&) = delete;
|
||||
AudioGroupSampleDirectory& operator=(const AudioGroupSampleDirectory&) = delete;
|
||||
AudioGroupSampleDirectory(AudioGroupSampleDirectory&&) = default;
|
||||
AudioGroupSampleDirectory& operator=(AudioGroupSampleDirectory&&) = default;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ DECL_ID_TYPE(KeymapId)
|
|||
DECL_ID_TYPE(LayersId)
|
||||
DECL_ID_TYPE(SongId)
|
||||
DECL_ID_TYPE(SFXId)
|
||||
DECL_ID_TYPE(GroupId)
|
||||
|
||||
/* MusyX has object polymorphism between Keymaps and Layers when
|
||||
* referenced by a song group's page object. When the upper bit is set,
|
||||
|
@ -417,12 +418,26 @@ struct PCDataTag
|
|||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
static std::vector<std::pair<typename T::key_type,
|
||||
std::reference_wrapper<typename T::mapped_type>>> SortUnorderedMap(T& um)
|
||||
{
|
||||
std::vector<std::pair<typename T::key_type, std::reference_wrapper<typename T::mapped_type>>> ret;
|
||||
ret.reserve(um.size());
|
||||
for (auto& p : um)
|
||||
ret.emplace_back(p.first, p.second);
|
||||
std::sort(ret.begin(), ret.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static std::vector<std::pair<typename T::key_type,
|
||||
std::reference_wrapper<const typename T::mapped_type>>> SortUnorderedMap(const T& um)
|
||||
{
|
||||
std::vector<std::pair<typename T::key_type,
|
||||
std::reference_wrapper<const typename T::mapped_type>>> ret(um.cbegin(), um.cend());
|
||||
std::vector<std::pair<typename T::key_type, std::reference_wrapper<const typename T::mapped_type>>> ret;
|
||||
ret.reserve(um.size());
|
||||
for (const auto& p : um)
|
||||
ret.emplace_back(p.first, p.second);
|
||||
std::sort(ret.begin(), ret.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
return ret;
|
||||
}
|
||||
|
@ -444,6 +459,7 @@ DECL_ID_HASH(KeymapId)
|
|||
DECL_ID_HASH(LayersId)
|
||||
DECL_ID_HASH(SongId)
|
||||
DECL_ID_HASH(SFXId)
|
||||
DECL_ID_HASH(GroupId)
|
||||
}
|
||||
|
||||
namespace amuse
|
||||
|
@ -458,6 +474,7 @@ struct NameDB
|
|||
Layer,
|
||||
Song,
|
||||
SFX,
|
||||
Group,
|
||||
Sample
|
||||
};
|
||||
|
||||
|
|
|
@ -210,6 +210,15 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(const AudioGroupDat
|
|||
}
|
||||
}
|
||||
|
||||
std::string ParseStringSlashId(const std::string& str, uint16_t& idOut)
|
||||
{
|
||||
size_t slashPos = str.find('/');
|
||||
if (slashPos == std::string::npos)
|
||||
return {};
|
||||
idOut = uint16_t(strtoul(str.data() + slashPos + 1, nullptr, 0));
|
||||
return {str.begin(), str.begin() + slashPos};
|
||||
}
|
||||
|
||||
AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView groupPath)
|
||||
{
|
||||
AudioGroupProject ret;
|
||||
|
@ -222,15 +231,20 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
|
|||
athena::io::YAMLDocReader r;
|
||||
if (r.parse(&fi) && r.ValidateClassType("amuse::Project"))
|
||||
{
|
||||
size_t songGroupCount;
|
||||
if (auto __v = r.enterSubVector("songGroups", songGroupCount))
|
||||
if (auto __v = r.enterSubRecord("songGroups"))
|
||||
{
|
||||
ret.m_songGroups.reserve(songGroupCount);
|
||||
for (int g = 0; g < songGroupCount; ++g)
|
||||
ret.m_songGroups.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()))
|
||||
{
|
||||
SongGroupIndex& idx = ret.m_songGroups[g];
|
||||
uint16_t groupId;
|
||||
std::string groupName = ParseStringSlashId(grp.first, groupId);
|
||||
if (groupName.empty() || groupId == 0xffff)
|
||||
continue;
|
||||
GroupId::CurNameDB->registerPair(groupName, groupId);
|
||||
|
||||
SongGroupIndex& idx = ret.m_songGroups[groupId];
|
||||
if (auto __v2 = r.enterSubRecord("normPages"))
|
||||
{
|
||||
idx.m_normPages.reserve(r.getCurNode()->m_mapChildren.size());
|
||||
|
@ -253,8 +267,12 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
|
|||
size_t chanCount;
|
||||
if (auto __v3 = r.enterSubVector(song.first.c_str(), chanCount))
|
||||
{
|
||||
ObjectId songId = SongId::CurNameDB->generateId(NameDB::Type::Song);
|
||||
SongId::CurNameDB->registerPair(song.first, songId);
|
||||
uint16_t songId;
|
||||
std::string songName = ParseStringSlashId(song.first, songId);
|
||||
if (songName.empty() || songId == 0xffff)
|
||||
continue;
|
||||
SongId::CurNameDB->registerPair(songName, songId);
|
||||
|
||||
std::array<SongGroupIndex::MIDISetup, 16>& setup = idx.m_midiSetups[songId];
|
||||
for (int i = 0; i < 16 && i < chanCount; ++i)
|
||||
if (auto __r2 = r.enterSubRecord(nullptr))
|
||||
|
@ -266,20 +284,28 @@ AudioGroupProject AudioGroupProject::CreateAudioGroupProject(SystemStringView gr
|
|||
}
|
||||
}
|
||||
|
||||
size_t sfxGroupCount;
|
||||
if (auto __v = r.enterSubVector("sfxGroups", sfxGroupCount))
|
||||
if (auto __v = r.enterSubRecord("sfxGroups"))
|
||||
{
|
||||
ret.m_sfxGroups.reserve(sfxGroupCount);
|
||||
for (int g = 0; g < sfxGroupCount; ++g)
|
||||
ret.m_sfxGroups.reserve(r.getCurNode()->m_mapChildren.size());
|
||||
for (const auto& grp : r.getCurNode()->m_mapChildren)
|
||||
{
|
||||
if (auto __r = r.enterSubRecord(nullptr))
|
||||
{
|
||||
SFXGroupIndex& idx = ret.m_sfxGroups[g];
|
||||
uint16_t groupId;
|
||||
std::string groupName = ParseStringSlashId(grp.first, groupId);
|
||||
if (groupName.empty() || groupId == 0xffff)
|
||||
continue;
|
||||
GroupId::CurNameDB->registerPair(groupName, groupId);
|
||||
|
||||
SFXGroupIndex& idx = ret.m_sfxGroups[groupId];
|
||||
for (const auto& sfx : r.getCurNode()->m_mapChildren)
|
||||
if (auto __r2 = r.enterSubRecord(sfx.first.c_str()))
|
||||
{
|
||||
ObjectId sfxId = SFXId::CurNameDB->generateId(NameDB::Type::SFX);
|
||||
SFXId::CurNameDB->registerPair(sfx.first, sfxId);
|
||||
uint16_t sfxId;
|
||||
std::string sfxName = ParseStringSlashId(sfx.first, sfxId);
|
||||
if (sfxName.empty() || sfxId == 0xffff)
|
||||
continue;
|
||||
SFXId::CurNameDB->registerPair(sfxName, sfxId);
|
||||
idx.m_sfxEntries[sfxId].read(r);
|
||||
}
|
||||
}
|
||||
|
@ -321,6 +347,8 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, GCNData
|
|||
GroupHeader<athena::Big> header;
|
||||
header.read(r);
|
||||
|
||||
GroupId::CurNameDB->registerPair(NameDB::generateName(header.groupId, NameDB::Type::Group), header.groupId);
|
||||
|
||||
/* Sound Macros */
|
||||
r.seek(header.soundMacroIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
|
@ -386,6 +414,8 @@ void AudioGroupProject::BootstrapObjectIDs(athena::io::IStreamReader& r, bool ab
|
|||
GroupHeader<DNAE> header;
|
||||
header.read(r);
|
||||
|
||||
GroupId::CurNameDB->registerPair(NameDB::generateName(header.groupId, NameDB::Type::Group), header.groupId);
|
||||
|
||||
/* Sound Macros */
|
||||
r.seek(subDataOff + header.soundMacroIdsOff, athena::Begin);
|
||||
while (!AtEnd16(r))
|
||||
|
@ -501,11 +531,13 @@ bool AudioGroupProject::toYAML(SystemStringView groupPath) const
|
|||
|
||||
if (!m_songGroups.empty())
|
||||
{
|
||||
if (auto __v = w.enterSubVector("songGroups"))
|
||||
if (auto __v = w.enterSubRecord("songGroups"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_songGroups))
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
char groupString[64];
|
||||
snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id));
|
||||
if (auto __r = w.enterSubRecord(groupString))
|
||||
{
|
||||
if (!p.second.get().m_normPages.empty())
|
||||
{
|
||||
|
@ -545,7 +577,9 @@ bool AudioGroupProject::toYAML(SystemStringView groupPath) const
|
|||
{
|
||||
for (const auto& song : SortUnorderedMap(p.second.get().m_midiSetups))
|
||||
{
|
||||
if (auto __v3 = w.enterSubVector(SongId::CurNameDB->resolveNameFromId(song.first).data()))
|
||||
char songString[64];
|
||||
snprintf(songString, 64, "%s/0x%04X", SongId::CurNameDB->resolveNameFromId(song.first).data(), int(song.first.id));
|
||||
if (auto __v3 = w.enterSubVector(songString))
|
||||
for (int i = 0; i < 16; ++i)
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
{
|
||||
|
@ -562,15 +596,19 @@ bool AudioGroupProject::toYAML(SystemStringView groupPath) const
|
|||
|
||||
if (!m_sfxGroups.empty())
|
||||
{
|
||||
if (auto __v = w.enterSubVector("sfxGroups"))
|
||||
if (auto __v = w.enterSubRecord("sfxGroups"))
|
||||
{
|
||||
for (const auto& p : SortUnorderedMap(m_sfxGroups))
|
||||
{
|
||||
if (auto __r = w.enterSubRecord(nullptr))
|
||||
char groupString[64];
|
||||
snprintf(groupString, 64, "%s/0x%04X", GroupId::CurNameDB->resolveNameFromId(p.first).data(), int(p.first.id));
|
||||
if (auto __r = w.enterSubRecord(groupString))
|
||||
{
|
||||
for (const auto& sfx : SortUnorderedMap(p.second.get().m_sfxEntries))
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(SFXId::CurNameDB->resolveNameFromId(sfx.first).data()))
|
||||
char sfxString[64];
|
||||
snprintf(sfxString, 64, "%s/0x%04X", SFXId::CurNameDB->resolveNameFromId(sfx.first).data(), int(sfx.first.id));
|
||||
if (auto __r2 = w.enterSubRecord(sfxString))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
sfx.second.get().write(w);
|
||||
|
|
|
@ -146,11 +146,23 @@ static uint32_t DSPNibbleToSample(uint32_t nibble)
|
|||
|
||||
void AudioGroupSampleDirectory::Entry::loadLooseData(SystemStringView basePath)
|
||||
{
|
||||
Sstat theStat;
|
||||
SystemString filePath = SystemString(basePath) + _S(".dsp");
|
||||
if (!Stat(filePath.c_str(), &theStat) && (!m_looseData || theStat.st_mtime > m_looseModTime))
|
||||
SystemString wavPath = SystemString(basePath) + _S(".wav");
|
||||
SystemString dspPath = SystemString(basePath) + _S(".dsp");
|
||||
Sstat wavStat, dspStat;
|
||||
bool wavValid = !Stat(wavPath.c_str(), &wavStat) && S_ISREG(wavStat.st_mode);
|
||||
bool dspValid = !Stat(dspPath.c_str(), &dspStat) && S_ISREG(dspStat.st_mode);
|
||||
|
||||
if (wavValid && dspValid)
|
||||
{
|
||||
athena::io::FileReader r(filePath);
|
||||
if (wavStat.st_mtime > dspStat.st_mtime)
|
||||
dspValid = false;
|
||||
else
|
||||
wavValid = false;
|
||||
}
|
||||
|
||||
if (dspValid && (!m_looseData || dspStat.st_mtime > m_looseModTime))
|
||||
{
|
||||
athena::io::FileReader r(dspPath);
|
||||
if (!r.hasError())
|
||||
{
|
||||
DSPADPCMHeader header;
|
||||
|
@ -175,13 +187,14 @@ void AudioGroupSampleDirectory::Entry::loadLooseData(SystemStringView basePath)
|
|||
m_looseData.reset(new uint8_t[dataLen]);
|
||||
r.readUBytesToBuf(m_looseData.get(), dataLen);
|
||||
|
||||
m_looseModTime = theStat.st_mtime;
|
||||
m_looseModTime = dspStat.st_mtime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Stat(filePath.c_str(), &theStat) && (!m_looseData || theStat.st_mtime > m_looseModTime))
|
||||
|
||||
if (wavValid && (!m_looseData || wavStat.st_mtime > m_looseModTime))
|
||||
{
|
||||
athena::io::FileReader r(filePath);
|
||||
athena::io::FileReader r(wavPath);
|
||||
if (!r.hasError())
|
||||
{
|
||||
atUint32 riffMagic = r.readUint32Little();
|
||||
|
@ -216,7 +229,6 @@ void AudioGroupSampleDirectory::Entry::loadLooseData(SystemStringView basePath)
|
|||
m_loopStartSample = loop.start;
|
||||
m_loopLengthSamples = loop.end - loop.start + 1;
|
||||
}
|
||||
|
||||
}
|
||||
else if (chunkMagic == SBIG('data'))
|
||||
{
|
||||
|
@ -227,7 +239,7 @@ void AudioGroupSampleDirectory::Entry::loadLooseData(SystemStringView basePath)
|
|||
r.seek(startPos + chunkSize, athena::Begin);
|
||||
}
|
||||
|
||||
m_looseModTime = theStat.st_mtime;
|
||||
m_looseModTime = wavStat.st_mtime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,7 @@ DEFINE_ID_TYPE(KeymapId, "keymap")
|
|||
DEFINE_ID_TYPE(LayersId, "layers")
|
||||
DEFINE_ID_TYPE(SongId, "song")
|
||||
DEFINE_ID_TYPE(SFXId, "sfx")
|
||||
DEFINE_ID_TYPE(GroupId, "group")
|
||||
|
||||
template<> template<>
|
||||
void PageObjectIdDNA<athena::Little>::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader)
|
||||
|
@ -225,6 +226,9 @@ std::string NameDB::generateName(ObjectId id, Type tp)
|
|||
case Type::SFX:
|
||||
snprintf(name, 32, "sfx%04X", id.id);
|
||||
break;
|
||||
case Type::Group:
|
||||
snprintf(name, 32, "group%04X", id.id);
|
||||
break;
|
||||
case Type::Sample:
|
||||
snprintf(name, 32, "sample%04X", id.id);
|
||||
break;
|
||||
|
|
|
@ -236,8 +236,8 @@ void Voice::_procSamplePre(int16_t& samp)
|
|||
float start = m_envelopeStart;
|
||||
float end = m_envelopeEnd;
|
||||
float t = clamp(0.f, float(m_envelopeTime / m_envelopeDur), 1.f);
|
||||
if (m_envelopeCurve)
|
||||
t = m_envelopeCurve->data.at(t * 127.f) / 127.f;
|
||||
if (m_envelopeCurve && m_envelopeCurve->data.size() >= 128)
|
||||
t = m_envelopeCurve->data[t * 127.f] / 127.f;
|
||||
m_curVol = clamp(0.f, (start * (1.0f - t)) + (end * t), 1.f);
|
||||
|
||||
// printf("%d %f\n", m_vid, m_curVol);
|
||||
|
|