mirror of https://github.com/AxioDL/amuse.git
Initial KeymapEditor implementation
This commit is contained in:
parent
2abed18784
commit
409d52c120
|
@ -195,6 +195,7 @@ void ADSRView::mousePressEvent(QMouseEvent* ev)
|
||||||
|
|
||||||
if (dists[minDist] < 10.0)
|
if (dists[minDist] < 10.0)
|
||||||
{
|
{
|
||||||
|
++m_cycleIdx;
|
||||||
m_dragPoint = minDist;
|
m_dragPoint = minDist;
|
||||||
mouseMoveEvent(ev);
|
mouseMoveEvent(ev);
|
||||||
}
|
}
|
||||||
|
@ -235,17 +236,18 @@ void ADSRView::mouseMoveEvent(QMouseEvent* ev)
|
||||||
{
|
{
|
||||||
qreal newAttack = std::max(0.0, (ev->localPos().x() - 30.0) / (width() - 30.0) * totalTime);
|
qreal newAttack = std::max(0.0, (ev->localPos().x() - 30.0) / (width() - 30.0) * totalTime);
|
||||||
qreal delta = newAttack - aTime;
|
qreal delta = newAttack - aTime;
|
||||||
ctrls->setAttackAndDecay(newAttack, std::max(0.0, ctrls->m_decay->value() - delta));
|
ctrls->setAttackAndDecay(newAttack, std::max(0.0, ctrls->m_decay->value() - delta), m_cycleIdx);
|
||||||
}
|
}
|
||||||
else if (m_dragPoint == 1)
|
else if (m_dragPoint == 1)
|
||||||
{
|
{
|
||||||
qreal newDecay = std::max(0.0, (ev->localPos().x() - 30.0) * totalTime / (width() - 30.0) - aTime);
|
qreal newDecay = std::max(0.0, (ev->localPos().x() - 30.0) * totalTime / (width() - 30.0) - aTime);
|
||||||
qreal newSustain = (-ev->localPos().y() + (height() - 16.0)) / (height() - 16.0);
|
qreal newSustain = (-ev->localPos().y() + (height() - 16.0)) / (height() - 16.0);
|
||||||
ctrls->setDecayAndSustain(newDecay, newSustain * 100.0);
|
ctrls->setDecayAndSustain(newDecay, newSustain * 100.0, m_cycleIdx);
|
||||||
}
|
}
|
||||||
else if (m_dragPoint == 2)
|
else if (m_dragPoint == 2)
|
||||||
{
|
{
|
||||||
qreal newRelease = std::max(0.0, (width() - 30.0) * (adTime + 1.0) / (ev->localPos().x() - 30.0) - (adTime + 1.0));
|
qreal newRelease = std::max(0.0, (width() - 30.0) * (adTime + 1.0) / (ev->localPos().x() - 30.0) - (adTime + 1.0));
|
||||||
|
ctrls->setRelease(newRelease, m_cycleIdx);
|
||||||
ctrls->m_release->setValue(newRelease);
|
ctrls->m_release->setValue(newRelease);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,11 +524,13 @@ class ADSRAttackAndDecayUndoCommand : public EditorUndoCommand
|
||||||
{
|
{
|
||||||
double m_redoAttack, m_redoDecay;
|
double m_redoAttack, m_redoDecay;
|
||||||
double m_undoAttack, m_undoDecay;
|
double m_undoAttack, m_undoDecay;
|
||||||
|
uint64_t m_cycleCount;
|
||||||
bool m_undid = false;
|
bool m_undid = false;
|
||||||
public:
|
public:
|
||||||
ADSRAttackAndDecayUndoCommand(double redoAttack, double redoDecay, amuse::ObjToken<ProjectModel::ADSRNode> node)
|
ADSRAttackAndDecayUndoCommand(double redoAttack, double redoDecay, uint64_t cycleCount,
|
||||||
|
amuse::ObjToken<ProjectModel::ADSRNode> node)
|
||||||
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Attack/Decay")),
|
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Attack/Decay")),
|
||||||
m_redoAttack(redoAttack), m_redoDecay(redoDecay) {}
|
m_redoAttack(redoAttack), m_redoDecay(redoDecay), m_cycleCount(cycleCount) {}
|
||||||
void undo()
|
void undo()
|
||||||
{
|
{
|
||||||
m_undid = true;
|
m_undid = true;
|
||||||
|
@ -569,7 +573,8 @@ public:
|
||||||
}
|
}
|
||||||
bool mergeWith(const QUndoCommand* other)
|
bool mergeWith(const QUndoCommand* other)
|
||||||
{
|
{
|
||||||
if (other->id() == id())
|
if (other->id() == id() && m_cycleCount ==
|
||||||
|
static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_cycleCount)
|
||||||
{
|
{
|
||||||
m_redoAttack = static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_redoAttack;
|
m_redoAttack = static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_redoAttack;
|
||||||
m_redoDecay = static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_redoDecay;
|
m_redoDecay = static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_redoDecay;
|
||||||
|
@ -580,7 +585,7 @@ public:
|
||||||
int id() const { return int(Id::ADSRAttackAndDecay); }
|
int id() const { return int(Id::ADSRAttackAndDecay); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void ADSRControls::setAttackAndDecay(double attack, double decay)
|
void ADSRControls::setAttackAndDecay(double attack, double decay, uint64_t cycleCount)
|
||||||
{
|
{
|
||||||
m_enableUpdate = false;
|
m_enableUpdate = false;
|
||||||
m_attack->setValue(attack);
|
m_attack->setValue(attack);
|
||||||
|
@ -588,7 +593,8 @@ void ADSRControls::setAttackAndDecay(double attack, double decay)
|
||||||
m_enableUpdate = true;
|
m_enableUpdate = true;
|
||||||
|
|
||||||
ADSRView* view = getEditor()->m_adsrView;
|
ADSRView* view = getEditor()->m_adsrView;
|
||||||
g_MainWindow->pushUndoCommand(new ADSRAttackAndDecayUndoCommand(attack, decay, view->m_node));
|
g_MainWindow->pushUndoCommand(new ADSRAttackAndDecayUndoCommand(m_attack->value(), m_decay->value(),
|
||||||
|
cycleCount, view->m_node));
|
||||||
view->update();
|
view->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,11 +602,13 @@ class ADSRDecayAndSustainUndoCommand : public EditorUndoCommand
|
||||||
{
|
{
|
||||||
double m_redoDecay, m_redoSustain;
|
double m_redoDecay, m_redoSustain;
|
||||||
double m_undoDecay, m_undoSustain;
|
double m_undoDecay, m_undoSustain;
|
||||||
|
uint64_t m_cycleCount;
|
||||||
bool m_undid = false;
|
bool m_undid = false;
|
||||||
public:
|
public:
|
||||||
ADSRDecayAndSustainUndoCommand(double redoDecay, double redoSustain, amuse::ObjToken<ProjectModel::ADSRNode> node)
|
ADSRDecayAndSustainUndoCommand(double redoDecay, double redoSustain, uint64_t cycleCount,
|
||||||
|
amuse::ObjToken<ProjectModel::ADSRNode> node)
|
||||||
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Decay/Sustain")),
|
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Decay/Sustain")),
|
||||||
m_redoDecay(redoDecay), m_redoSustain(redoSustain) {}
|
m_redoDecay(redoDecay), m_redoSustain(redoSustain), m_cycleCount(cycleCount) {}
|
||||||
void undo()
|
void undo()
|
||||||
{
|
{
|
||||||
m_undid = true;
|
m_undid = true;
|
||||||
|
@ -643,7 +651,8 @@ public:
|
||||||
}
|
}
|
||||||
bool mergeWith(const QUndoCommand* other)
|
bool mergeWith(const QUndoCommand* other)
|
||||||
{
|
{
|
||||||
if (other->id() == id())
|
if (other->id() == id() && m_cycleCount ==
|
||||||
|
static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_cycleCount)
|
||||||
{
|
{
|
||||||
m_redoDecay = static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_redoDecay;
|
m_redoDecay = static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_redoDecay;
|
||||||
m_redoSustain = static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_redoSustain;
|
m_redoSustain = static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_redoSustain;
|
||||||
|
@ -654,7 +663,7 @@ public:
|
||||||
int id() const { return int(Id::ADSRDecayAndSustain); }
|
int id() const { return int(Id::ADSRDecayAndSustain); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void ADSRControls::setDecayAndSustain(double decay, double sustain)
|
void ADSRControls::setDecayAndSustain(double decay, double sustain, uint64_t cycleCount)
|
||||||
{
|
{
|
||||||
m_enableUpdate = false;
|
m_enableUpdate = false;
|
||||||
m_decay->setValue(decay);
|
m_decay->setValue(decay);
|
||||||
|
@ -662,18 +671,21 @@ void ADSRControls::setDecayAndSustain(double decay, double sustain)
|
||||||
m_enableUpdate = true;
|
m_enableUpdate = true;
|
||||||
|
|
||||||
ADSRView* view = getEditor()->m_adsrView;
|
ADSRView* view = getEditor()->m_adsrView;
|
||||||
g_MainWindow->pushUndoCommand(new ADSRDecayAndSustainUndoCommand(decay, sustain / 100.0, view->m_node));
|
g_MainWindow->pushUndoCommand(new ADSRDecayAndSustainUndoCommand(m_decay->value(), m_sustain->value() / 100.0,
|
||||||
|
cycleCount, view->m_node));
|
||||||
view->update();
|
view->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ADSRReleaseUndoCommand : public EditorUndoCommand
|
class ADSRReleaseUndoCommand : public EditorUndoCommand
|
||||||
{
|
{
|
||||||
double m_redoVal, m_undoVal;
|
double m_redoVal, m_undoVal;
|
||||||
|
uint64_t m_cycleCount;
|
||||||
bool m_undid = false;
|
bool m_undid = false;
|
||||||
public:
|
public:
|
||||||
ADSRReleaseUndoCommand(double redoVal, amuse::ObjToken<ProjectModel::ADSRNode> node)
|
ADSRReleaseUndoCommand(double redoVal, uint64_t cycleCount,
|
||||||
|
amuse::ObjToken<ProjectModel::ADSRNode> node)
|
||||||
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Release")),
|
: EditorUndoCommand(node.get(), ADSRControls::tr("Change Release")),
|
||||||
m_redoVal(redoVal) {}
|
m_redoVal(redoVal), m_cycleCount(cycleCount) {}
|
||||||
void undo()
|
void undo()
|
||||||
{
|
{
|
||||||
m_undid = true;
|
m_undid = true;
|
||||||
|
@ -710,7 +722,8 @@ public:
|
||||||
}
|
}
|
||||||
bool mergeWith(const QUndoCommand* other)
|
bool mergeWith(const QUndoCommand* other)
|
||||||
{
|
{
|
||||||
if (other->id() == id())
|
if (other->id() == id() && m_cycleCount ==
|
||||||
|
static_cast<const ADSRReleaseUndoCommand*>(other)->m_cycleCount)
|
||||||
{
|
{
|
||||||
m_redoVal = static_cast<const ADSRReleaseUndoCommand*>(other)->m_redoVal;
|
m_redoVal = static_cast<const ADSRReleaseUndoCommand*>(other)->m_redoVal;
|
||||||
return true;
|
return true;
|
||||||
|
@ -720,12 +733,23 @@ public:
|
||||||
int id() const { return int(Id::ADSRRelease); }
|
int id() const { return int(Id::ADSRRelease); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ADSRControls::setRelease(double release, uint64_t cycleCount)
|
||||||
|
{
|
||||||
|
m_enableUpdate = false;
|
||||||
|
m_release->setValue(release);
|
||||||
|
m_enableUpdate = true;
|
||||||
|
|
||||||
|
ADSRView* view = getEditor()->m_adsrView;
|
||||||
|
g_MainWindow->pushUndoCommand(new ADSRReleaseUndoCommand(m_release->value(), cycleCount, view->m_node));
|
||||||
|
view->update();
|
||||||
|
}
|
||||||
|
|
||||||
void ADSRControls::releaseChanged(double val)
|
void ADSRControls::releaseChanged(double val)
|
||||||
{
|
{
|
||||||
if (m_enableUpdate)
|
if (m_enableUpdate)
|
||||||
{
|
{
|
||||||
ADSRView* view = getEditor()->m_adsrView;
|
ADSRView* view = getEditor()->m_adsrView;
|
||||||
g_MainWindow->pushUndoCommand(new ADSRReleaseUndoCommand(val, view->m_node));
|
g_MainWindow->pushUndoCommand(new ADSRReleaseUndoCommand(val, ~0ull, view->m_node));
|
||||||
view->update();
|
view->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ Q_OBJECT
|
||||||
QStaticText m_percentTexts[11];
|
QStaticText m_percentTexts[11];
|
||||||
std::vector<QStaticText> m_timeTexts;
|
std::vector<QStaticText> m_timeTexts;
|
||||||
int m_dragPoint = -1;
|
int m_dragPoint = -1;
|
||||||
|
uint64_t m_cycleIdx = 0;
|
||||||
ADSREditor* getEditor() const;
|
ADSREditor* getEditor() const;
|
||||||
public:
|
public:
|
||||||
explicit ADSRView(QWidget* parent = Q_NULLPTR);
|
explicit ADSRView(QWidget* parent = Q_NULLPTR);
|
||||||
|
@ -48,8 +49,9 @@ Q_OBJECT
|
||||||
QDoubleSpinBox* m_keyToDecay;
|
QDoubleSpinBox* m_keyToDecay;
|
||||||
bool m_enableUpdate = true;
|
bool m_enableUpdate = true;
|
||||||
ADSREditor* getEditor() const;
|
ADSREditor* getEditor() const;
|
||||||
void setAttackAndDecay(double attack, double decay);
|
void setAttackAndDecay(double attack, double decay, uint64_t cycleCount);
|
||||||
void setDecayAndSustain(double decay, double sustain);
|
void setDecayAndSustain(double decay, double sustain, uint64_t cycleCount);
|
||||||
|
void setRelease(double release, uint64_t cycleCount);
|
||||||
public:
|
public:
|
||||||
explicit ADSRControls(QWidget* parent = Q_NULLPTR);
|
explicit ADSRControls(QWidget* parent = Q_NULLPTR);
|
||||||
void loadData();
|
void loadData();
|
||||||
|
|
|
@ -85,3 +85,14 @@ QString ShowInGraphicalShellString()
|
||||||
return MainWindow::tr("Show in Browser");
|
return MainWindow::tr("Show in Browser");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -44,5 +44,7 @@ static QLatin1String StringViewToQString(std::string_view sv)
|
||||||
return QLatin1String(sv.data(), int(sv.size()));
|
return QLatin1String(sv.data(), int(sv.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Used for generating transform matrices to map SVG coordinate space */
|
||||||
|
QTransform RectToRect(const QRectF& from, const QRectF& to);
|
||||||
|
|
||||||
#endif //AMUSE_COMMON_HPP
|
#endif //AMUSE_COMMON_HPP
|
||||||
|
|
|
@ -10,10 +10,12 @@ class CurveEditUndoCommand : public EditorUndoCommand
|
||||||
{
|
{
|
||||||
uint8_t m_redoData[128];
|
uint8_t m_redoData[128];
|
||||||
uint8_t m_undoData[128];
|
uint8_t m_undoData[128];
|
||||||
|
bool m_usedExpr;
|
||||||
bool m_undid = false;
|
bool m_undid = false;
|
||||||
public:
|
public:
|
||||||
CurveEditUndoCommand(const uint8_t* redoData, amuse::ObjToken<ProjectModel::CurveNode> node)
|
CurveEditUndoCommand(const uint8_t* redoData, bool usedExpr,
|
||||||
: EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve"))
|
amuse::ObjToken<ProjectModel::CurveNode> node)
|
||||||
|
: EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve")), m_usedExpr(usedExpr)
|
||||||
{
|
{
|
||||||
std::memcpy(m_redoData, redoData, 128);
|
std::memcpy(m_redoData, redoData, 128);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +46,7 @@ public:
|
||||||
}
|
}
|
||||||
bool mergeWith(const QUndoCommand* other)
|
bool mergeWith(const QUndoCommand* other)
|
||||||
{
|
{
|
||||||
if (other->id() == id())
|
if (other->id() == id() && !m_usedExpr && !static_cast<const CurveEditUndoCommand*>(other)->m_usedExpr)
|
||||||
{
|
{
|
||||||
std::memcpy(m_redoData, static_cast<const CurveEditUndoCommand*>(other)->m_redoData, 128);
|
std::memcpy(m_redoData, static_cast<const CurveEditUndoCommand*>(other)->m_redoData, 128);
|
||||||
return true;
|
return true;
|
||||||
|
@ -153,7 +155,7 @@ void CurveView::mouseMoveEvent(QMouseEvent* ev)
|
||||||
std::memcpy(newData, curve.data.data(), 128);
|
std::memcpy(newData, curve.data.data(), 128);
|
||||||
newData[idx] = uint8_t(val);
|
newData[idx] = uint8_t(val);
|
||||||
|
|
||||||
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, m_node));
|
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, false, m_node));
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +229,7 @@ void CurveControls::exprCommit()
|
||||||
if (notANumber)
|
if (notANumber)
|
||||||
m_errLabel->setText(tr("Did not evaluate as a number"));
|
m_errLabel->setText(tr("Did not evaluate as a number"));
|
||||||
|
|
||||||
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, view->m_node));
|
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, true, view->m_node));
|
||||||
view->update();
|
view->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "EditorWidget.hpp"
|
#include "EditorWidget.hpp"
|
||||||
#include "MainWindow.hpp"
|
#include "MainWindow.hpp"
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
EditorWidget::EditorWidget(QWidget* parent)
|
EditorWidget::EditorWidget(QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
@ -16,3 +17,24 @@ void EditorUndoCommand::redo()
|
||||||
{
|
{
|
||||||
g_MainWindow->openEditor(m_node.get());
|
g_MainWindow->openEditor(m_node.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FieldProjectNode::FieldProjectNode(ProjectModel::CollectionNode* collection, QWidget* parent)
|
||||||
|
: FieldComboBox(parent)
|
||||||
|
{
|
||||||
|
setCollection(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FieldProjectNode::setCollection(ProjectModel::CollectionNode* collection)
|
||||||
|
{
|
||||||
|
m_collection = collection;
|
||||||
|
|
||||||
|
if (!collection)
|
||||||
|
{
|
||||||
|
setModel(new QStandardItemModel(0, 1, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectModel* model = g_MainWindow->projectModel();
|
||||||
|
setModel(model->getNullProxy());
|
||||||
|
setRootModelIndex(model->getNullProxy()->mapFromSource(model->index(collection)));
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QUndoCommand>
|
#include <QUndoCommand>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QWheelEvent>
|
||||||
#include "ProjectModel.hpp"
|
#include "ProjectModel.hpp"
|
||||||
|
|
||||||
class EditorWidget : public QWidget
|
class EditorWidget : public QWidget
|
||||||
|
@ -44,4 +47,36 @@ public:
|
||||||
void redo();
|
void redo();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FieldSpinBox : public QSpinBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FieldSpinBox(QWidget* parent = Q_NULLPTR)
|
||||||
|
: QSpinBox(parent) {}
|
||||||
|
|
||||||
|
/* Don't scroll */
|
||||||
|
void wheelEvent(QWheelEvent* event) { event->ignore(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FieldComboBox : public QComboBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FieldComboBox(QWidget* parent = Q_NULLPTR)
|
||||||
|
: QComboBox(parent) {}
|
||||||
|
|
||||||
|
/* Don't scroll */
|
||||||
|
void wheelEvent(QWheelEvent* event) { event->ignore(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class FieldProjectNode : public FieldComboBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
ProjectModel::CollectionNode* m_collection;
|
||||||
|
public:
|
||||||
|
explicit FieldProjectNode(ProjectModel::CollectionNode* collection = Q_NULLPTR, QWidget* parent = Q_NULLPTR);
|
||||||
|
void setCollection(ProjectModel::CollectionNode* collection);
|
||||||
|
ProjectModel::CollectionNode* collection() const { return m_collection; }
|
||||||
|
};
|
||||||
|
|
||||||
#endif //AMUSE_EDITOR_WIDGET_HPP
|
#endif //AMUSE_EDITOR_WIDGET_HPP
|
||||||
|
|
|
@ -6,19 +6,7 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
|
||||||
/* Used for generating transform matrices to map SVG coordinate space */
|
const QString NaturalKeyNames[] =
|
||||||
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("C"),
|
||||||
QStringLiteral("D"),
|
QStringLiteral("D"),
|
||||||
|
@ -29,7 +17,7 @@ static const QString NaturalKeyNames[] =
|
||||||
QStringLiteral("B")
|
QStringLiteral("B")
|
||||||
};
|
};
|
||||||
|
|
||||||
static const QString SharpKeyNames[] =
|
const QString SharpKeyNames[] =
|
||||||
{
|
{
|
||||||
QStringLiteral("Cs"),
|
QStringLiteral("Cs"),
|
||||||
QStringLiteral("Ds"),
|
QStringLiteral("Ds"),
|
||||||
|
@ -38,7 +26,7 @@ static const QString SharpKeyNames[] =
|
||||||
QStringLiteral("As")
|
QStringLiteral("As")
|
||||||
};
|
};
|
||||||
|
|
||||||
static const QString KeyStrings[] =
|
const QString KeyStrings[] =
|
||||||
{
|
{
|
||||||
QStringLiteral("C"),
|
QStringLiteral("C"),
|
||||||
QStringLiteral("C#"),
|
QStringLiteral("C#"),
|
||||||
|
@ -54,12 +42,12 @@ static const QString KeyStrings[] =
|
||||||
QStringLiteral("B")
|
QStringLiteral("B")
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int NaturalKeyNumbers[] =
|
const int NaturalKeyNumbers[] =
|
||||||
{
|
{
|
||||||
0, 2, 4, 5, 7, 9, 11
|
0, 2, 4, 5, 7, 9, 11
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int SharpKeyNumbers[] =
|
const int SharpKeyNumbers[] =
|
||||||
{
|
{
|
||||||
1, 3, 6, 8, 10
|
1, 3, 6, 8, 10
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
#include "StatusBarWidget.hpp"
|
#include "StatusBarWidget.hpp"
|
||||||
|
#include "Common.hpp"
|
||||||
|
|
||||||
|
extern const QString NaturalKeyNames[7];
|
||||||
|
extern const QString SharpKeyNames[5];
|
||||||
|
extern const QString KeyStrings[12];
|
||||||
|
extern const int NaturalKeyNumbers[7];
|
||||||
|
extern const int SharpKeyNumbers[5];
|
||||||
|
|
||||||
class KeyboardWidget;
|
class KeyboardWidget;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,600 @@
|
||||||
#include "KeymapEditor.hpp"
|
#include "KeymapEditor.hpp"
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
#include "KeyboardWidget.hpp"
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
static const int HueTable[] =
|
||||||
|
{
|
||||||
|
0, 30, 60, 80, 120, 170, 200, 240, 280, 320
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int SaturationTable[] =
|
||||||
|
{
|
||||||
|
255, 255, 255, 255, 255, 127, 127, 127, 127, 127, 63, 63, 63
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int ValueTable[] =
|
||||||
|
{
|
||||||
|
240, 200, 160, 120, 80, 240, 200, 160, 120, 80, 240, 200, 160
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QPoint PointTable[] =
|
||||||
|
{
|
||||||
|
{21, 180},
|
||||||
|
{41, 104},
|
||||||
|
{61, 180},
|
||||||
|
{86, 104},
|
||||||
|
{101, 180},
|
||||||
|
{141, 180},
|
||||||
|
{156, 104},
|
||||||
|
{181, 180},
|
||||||
|
{201, 104},
|
||||||
|
{221, 180},
|
||||||
|
{246, 104},
|
||||||
|
{261, 180}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int RadiusTable[] =
|
||||||
|
{
|
||||||
|
14,
|
||||||
|
10,
|
||||||
|
14,
|
||||||
|
10,
|
||||||
|
14,
|
||||||
|
14,
|
||||||
|
10,
|
||||||
|
14,
|
||||||
|
10,
|
||||||
|
14,
|
||||||
|
10,
|
||||||
|
14
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QColor PenColorTable[] =
|
||||||
|
{
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QColor NeutralColorTable[] =
|
||||||
|
{
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white,
|
||||||
|
Qt::black,
|
||||||
|
Qt::white
|
||||||
|
};
|
||||||
|
|
||||||
|
PaintButton::PaintButton(QWidget* parent)
|
||||||
|
: QPushButton(parent)
|
||||||
|
{
|
||||||
|
setIcon(QIcon(QStringLiteral(":/icons/IconPaintbrush.svg")));
|
||||||
|
setIconSize(QSize(26, 26));
|
||||||
|
setFixedSize(46, 46);
|
||||||
|
setToolTip(tr("Activate brush to apply values to keys"));
|
||||||
|
}
|
||||||
|
|
||||||
|
KeymapEditor* KeymapView::getEditor() const
|
||||||
|
{
|
||||||
|
return qobject_cast<KeymapEditor*>(parentWidget()->parentWidget()->parentWidget());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::loadData(ProjectModel::KeymapNode* node)
|
||||||
|
{
|
||||||
|
m_node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::unloadData()
|
||||||
|
{
|
||||||
|
m_node.reset();
|
||||||
|
std::fill(std::begin(m_keyPalettes), std::end(m_keyPalettes), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectModel::INode* KeymapView::currentNode() const
|
||||||
|
{
|
||||||
|
return m_node.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth,
|
||||||
|
const QColor* keyPalette, int o, int k) const
|
||||||
|
{
|
||||||
|
int keyIdx = o * 12 + k;
|
||||||
|
int keyPalIdx = m_keyPalettes[keyIdx];
|
||||||
|
painter.setPen(QPen(PenColorTable[k], penWidth));
|
||||||
|
painter.setBrush(keyPalIdx < 0 ? NeutralColorTable[k] : keyPalette[keyPalIdx]);
|
||||||
|
painter.drawEllipse(PointTable[k] + octaveRect.topLeft(), RadiusTable[k], RadiusTable[k]);
|
||||||
|
painter.setTransform(QTransform().translate(
|
||||||
|
PointTable[k].x() + octaveRect.left() - 13, PointTable[k].y() + octaveRect.top() - 20).rotate(-90.0));
|
||||||
|
painter.drawStaticText(QPointF{}, m_keyTexts[keyIdx]);
|
||||||
|
painter.setTransform(QTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::paintEvent(QPaintEvent* ev)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
const QColor* keyPalette = getEditor()->m_paintPalette;
|
||||||
|
|
||||||
|
qreal deviceRatio = devicePixelRatioF();
|
||||||
|
qreal penWidth = std::max(std::floor(deviceRatio), 1.0) / deviceRatio;
|
||||||
|
|
||||||
|
painter.setFont(m_keyFont);
|
||||||
|
int kbY = height() / 2 - 100;
|
||||||
|
for (int o = 0; o < 10; ++o)
|
||||||
|
{
|
||||||
|
QRect thisRect(o * 280, kbY, 280, 200);
|
||||||
|
if (ev->rect().intersects(thisRect))
|
||||||
|
{
|
||||||
|
m_octaveRenderer.render(&painter, thisRect);
|
||||||
|
for (int k = 0; k < 12; ++k)
|
||||||
|
drawKey(painter, thisRect, penWidth, keyPalette, o, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QRect thisRect(2800, kbY, 202, 200);
|
||||||
|
if (ev->rect().intersects(thisRect))
|
||||||
|
{
|
||||||
|
m_lastOctaveRenderer.render(&painter, thisRect);
|
||||||
|
for (int k = 0; k < 8; ++k)
|
||||||
|
drawKey(painter, thisRect, penWidth, keyPalette, 10, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::mousePressEvent(QMouseEvent* ev)
|
||||||
|
{
|
||||||
|
mouseMoveEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeymapView::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 KeymapView::mouseMoveEvent(QMouseEvent* ev)
|
||||||
|
{
|
||||||
|
int octave = ev->x() / 280;
|
||||||
|
int key = getKey(ev->pos() - QPoint(octave * 280, height() / 2 - 100));
|
||||||
|
if (octave >= 0 && key >= 0)
|
||||||
|
getEditor()->touchKey(octave * 12 + key, ev->modifiers() & Qt::ShiftModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapView::wheelEvent(QWheelEvent* event)
|
||||||
|
{
|
||||||
|
if (QScrollArea* scroll = qobject_cast<QScrollArea*>(parentWidget()->parentWidget()))
|
||||||
|
{
|
||||||
|
/* Send wheel event directly to the scroll bar */
|
||||||
|
QApplication::sendEvent(scroll->horizontalScrollBar(), event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeymapView::KeymapView(QWidget* parent)
|
||||||
|
: QWidget(parent), m_octaveRenderer(QStringLiteral(":/bg/keyboard.svg")),
|
||||||
|
m_lastOctaveRenderer(QStringLiteral(":/bg/keyboard_last.svg"))
|
||||||
|
{
|
||||||
|
setMinimumWidth(3002);
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < 11; ++i)
|
||||||
|
for (int j = 0; j < 12 && k < 128; ++j)
|
||||||
|
m_keyTexts[k++].setText(QStringLiteral("%1%2").arg(KeyStrings[j]).arg(i - 1));
|
||||||
|
m_keyFont.setPointSize(12);
|
||||||
|
std::fill(std::begin(m_keyPalettes), std::end(m_keyPalettes), -1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; ++i)
|
||||||
|
if (m_octaveRenderer.elementExists(NaturalKeyNames[i]))
|
||||||
|
m_natural[i] = m_octaveRenderer.matrixForElement(NaturalKeyNames[i]).
|
||||||
|
mapRect(m_octaveRenderer.boundsOnElement(NaturalKeyNames[i]));
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i)
|
||||||
|
if (m_octaveRenderer.elementExists(SharpKeyNames[i]))
|
||||||
|
m_sharp[i] = m_octaveRenderer.matrixForElement(SharpKeyNames[i]).
|
||||||
|
mapRect(m_octaveRenderer.boundsOnElement(SharpKeyNames[i]));
|
||||||
|
|
||||||
|
m_widgetToSvg = RectToRect(QRect(0, 0, 280, 200), m_octaveRenderer.viewBoxF());
|
||||||
|
}
|
||||||
|
|
||||||
|
KeymapEditor* KeymapControls::getEditor() const
|
||||||
|
{
|
||||||
|
return qobject_cast<KeymapEditor*>(parentWidget());
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::setPaintIdx(int idx)
|
||||||
|
{
|
||||||
|
QPalette palette = m_paintButton->palette();
|
||||||
|
if (idx < 0)
|
||||||
|
{
|
||||||
|
palette.setColor(QPalette::Background, QWidget::palette().color(QPalette::Background));
|
||||||
|
palette.setColor(QPalette::Button, QWidget::palette().color(QPalette::Button));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const QColor* keyPalette = getEditor()->m_paintPalette;
|
||||||
|
palette.setColor(QPalette::Background, keyPalette[idx]);
|
||||||
|
palette.setColor(QPalette::Button, keyPalette[idx].darker(300));
|
||||||
|
}
|
||||||
|
m_paintButton->setPalette(palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::setKeymap(const amuse::Keymap& km)
|
||||||
|
{
|
||||||
|
m_enableUpdate = false;
|
||||||
|
int idx = m_macro->collection()->indexOfId(km.macro.id);
|
||||||
|
m_macro->setCurrentIndex(idx + 1);
|
||||||
|
m_transpose->setValue(km.transpose);
|
||||||
|
if (km.pan == -128)
|
||||||
|
{
|
||||||
|
m_pan->setDisabled(true);
|
||||||
|
m_pan->setValue(true);
|
||||||
|
m_surround->setChecked(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pan->setEnabled(true);
|
||||||
|
m_pan->setValue(km.pan);
|
||||||
|
m_surround->setChecked(false);
|
||||||
|
}
|
||||||
|
m_prioOffset->setValue(km.prioOffset);
|
||||||
|
m_enableUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::loadData(ProjectModel::KeymapNode* node)
|
||||||
|
{
|
||||||
|
m_enableUpdate = false;
|
||||||
|
m_macro->setCollection(g_MainWindow->projectModel()->getGroupNode(node)->
|
||||||
|
getCollectionOfType(ProjectModel::INode::Type::SoundMacro));
|
||||||
|
m_macro->setDisabled(false);
|
||||||
|
m_transpose->setDisabled(false);
|
||||||
|
m_transpose->setValue(0);
|
||||||
|
m_pan->setDisabled(false);
|
||||||
|
m_pan->setValue(64);
|
||||||
|
m_surround->setDisabled(false);
|
||||||
|
m_surround->setChecked(false);
|
||||||
|
m_prioOffset->setDisabled(false);
|
||||||
|
m_prioOffset->setValue(0);
|
||||||
|
m_paintButton->setDisabled(false);
|
||||||
|
m_paintButton->setPalette(palette());
|
||||||
|
m_enableUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::unloadData()
|
||||||
|
{
|
||||||
|
m_enableUpdate = false;
|
||||||
|
m_macro->setCollection(nullptr);
|
||||||
|
m_macro->setDisabled(true);
|
||||||
|
m_transpose->setDisabled(true);
|
||||||
|
m_pan->setDisabled(true);
|
||||||
|
m_surround->setDisabled(true);
|
||||||
|
m_prioOffset->setDisabled(true);
|
||||||
|
m_paintButton->setDisabled(true);
|
||||||
|
m_paintButton->setPalette(palette());
|
||||||
|
m_enableUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::controlChanged()
|
||||||
|
{
|
||||||
|
if (m_enableUpdate)
|
||||||
|
{
|
||||||
|
amuse::Keymap km;
|
||||||
|
km.macro.id = m_macro->currentIndex() == 0 ? amuse::SoundMacroId{} :
|
||||||
|
m_macro->collection()->idOfIndex(m_macro->currentIndex() - 1);
|
||||||
|
km.transpose = int8_t(m_transpose->value());
|
||||||
|
km.pan = int8_t(m_pan->value());
|
||||||
|
if (m_surround->isChecked())
|
||||||
|
{
|
||||||
|
km.pan = -128;
|
||||||
|
m_pan->setDisabled(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_pan->setEnabled(true);
|
||||||
|
}
|
||||||
|
km.prioOffset = int8_t(m_prioOffset->value());
|
||||||
|
getEditor()->touchControl(km);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapControls::paintButtonPressed()
|
||||||
|
{
|
||||||
|
KeymapEditor* editor = getEditor();
|
||||||
|
if (!editor->m_inPaint)
|
||||||
|
{
|
||||||
|
editor->setCursor(QCursor(QPixmap(QStringLiteral(":/icons/IconPaintbrush.svg")), 2, 30));
|
||||||
|
editor->m_inPaint = true;
|
||||||
|
m_paintButton->setDown(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
editor->unsetCursor();
|
||||||
|
editor->m_inPaint = false;
|
||||||
|
m_paintButton->setDown(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeymapControls::KeymapControls(QWidget* parent)
|
||||||
|
: QFrame(parent)
|
||||||
|
{
|
||||||
|
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
|
setFixedHeight(100);
|
||||||
|
setFrameShape(QFrame::StyledPanel);
|
||||||
|
setFrameShadow(QFrame::Sunken);
|
||||||
|
setBackgroundRole(QPalette::Base);
|
||||||
|
setAutoFillBackground(true);
|
||||||
|
|
||||||
|
QPalette palette = QWidget::palette();
|
||||||
|
palette.setColor(QPalette::Base, palette.color(QPalette::Background));
|
||||||
|
|
||||||
|
QHBoxLayout* mainLayout = new QHBoxLayout;
|
||||||
|
|
||||||
|
QGridLayout* leftLayout = new QGridLayout;
|
||||||
|
|
||||||
|
leftLayout->addWidget(new QLabel(tr("SoundMacro")), 0, 0);
|
||||||
|
m_macro = new FieldProjectNode;
|
||||||
|
m_macro->setDisabled(true);
|
||||||
|
connect(m_macro, SIGNAL(currentIndexChanged(int)), this, SLOT(controlChanged()));
|
||||||
|
leftLayout->addWidget(m_macro, 1, 0);
|
||||||
|
|
||||||
|
leftLayout->addWidget(new QLabel(tr("Transpose")), 0, 1);
|
||||||
|
m_transpose = new QSpinBox;
|
||||||
|
m_transpose->setPalette(palette);
|
||||||
|
m_transpose->setDisabled(true);
|
||||||
|
m_transpose->setRange(-128, 127);
|
||||||
|
m_transpose->setToolTip(tr("Offset resulting MIDI note"));
|
||||||
|
connect(m_transpose, SIGNAL(valueChanged(int)), this, SLOT(controlChanged()));
|
||||||
|
leftLayout->addWidget(m_transpose, 1, 1);
|
||||||
|
|
||||||
|
leftLayout->addWidget(new QLabel(tr("Pan")), 0, 2);
|
||||||
|
m_pan = new QSpinBox;
|
||||||
|
m_pan->setPalette(palette);
|
||||||
|
m_pan->setDisabled(true);
|
||||||
|
m_pan->setRange(-127, 127);
|
||||||
|
m_pan->setToolTip(tr("Set initial pan"));
|
||||||
|
connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(controlChanged()));
|
||||||
|
leftLayout->addWidget(m_pan, 1, 2);
|
||||||
|
|
||||||
|
leftLayout->addWidget(new QLabel(tr("Surround")), 0, 3);
|
||||||
|
m_surround = new QCheckBox;
|
||||||
|
m_surround->setPalette(palette);
|
||||||
|
m_surround->setDisabled(true);
|
||||||
|
m_surround->setToolTip(tr("Initially play through surround channels"));
|
||||||
|
connect(m_surround, SIGNAL(stateChanged(int)), this, SLOT(controlChanged()));
|
||||||
|
leftLayout->addWidget(m_surround, 1, 3);
|
||||||
|
|
||||||
|
leftLayout->addWidget(new QLabel(tr("Prio Offset")), 0, 4);
|
||||||
|
m_prioOffset = new QSpinBox;
|
||||||
|
m_prioOffset->setPalette(palette);
|
||||||
|
m_prioOffset->setDisabled(true);
|
||||||
|
m_prioOffset->setRange(-128, 127);
|
||||||
|
m_prioOffset->setToolTip(tr("Offset resulting priority"));
|
||||||
|
connect(m_prioOffset, SIGNAL(valueChanged(int)), this, SLOT(controlChanged()));
|
||||||
|
leftLayout->addWidget(m_prioOffset, 1, 4);
|
||||||
|
|
||||||
|
leftLayout->setColumnMinimumWidth(0, 200);
|
||||||
|
leftLayout->setColumnMinimumWidth(1, 75);
|
||||||
|
leftLayout->setColumnMinimumWidth(2, 75);
|
||||||
|
leftLayout->setColumnMinimumWidth(3, 50);
|
||||||
|
leftLayout->setColumnMinimumWidth(4, 75);
|
||||||
|
leftLayout->setRowMinimumHeight(0, 22);
|
||||||
|
leftLayout->setRowMinimumHeight(1, 37);
|
||||||
|
leftLayout->setContentsMargins(10, 6, 0, 14);
|
||||||
|
|
||||||
|
QVBoxLayout* rightLayout = new QVBoxLayout;
|
||||||
|
|
||||||
|
m_paintButton = new PaintButton;
|
||||||
|
m_paintButton->setDisabled(true);
|
||||||
|
connect(m_paintButton, SIGNAL(pressed()), this, SLOT(paintButtonPressed()));
|
||||||
|
rightLayout->addWidget(m_paintButton);
|
||||||
|
rightLayout->setContentsMargins(0, 0, 10, 0);
|
||||||
|
|
||||||
|
mainLayout->addLayout(leftLayout);
|
||||||
|
mainLayout->addStretch(1);
|
||||||
|
mainLayout->addLayout(rightLayout);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::_touch()
|
||||||
|
{
|
||||||
|
if (m_controlKeymap.macro.id == 0xffff)
|
||||||
|
m_controls->setPaintIdx(-1);
|
||||||
|
else
|
||||||
|
m_controls->setPaintIdx(getConfigIdx(m_controlKeymap.configKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::touchKey(int key, bool bulk)
|
||||||
|
{
|
||||||
|
if (m_inPaint)
|
||||||
|
{
|
||||||
|
if (bulk)
|
||||||
|
{
|
||||||
|
uint64_t refKey = (*m_kmView->m_node->m_obj)[key].configKey();
|
||||||
|
for (int i = 0; i < 128; ++i)
|
||||||
|
{
|
||||||
|
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[i];
|
||||||
|
if (km.configKey() != refKey)
|
||||||
|
continue;
|
||||||
|
if (km.macro.id != 0xffff)
|
||||||
|
deallocateConfigIdx(km.configKey());
|
||||||
|
km = m_controlKeymap;
|
||||||
|
if (km.macro.id == 0xffff)
|
||||||
|
m_kmView->m_keyPalettes[i] = -1;
|
||||||
|
else
|
||||||
|
m_kmView->m_keyPalettes[i] = allocateConfigIdx(km.configKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key];
|
||||||
|
if (km.macro.id != 0xffff)
|
||||||
|
deallocateConfigIdx(km.configKey());
|
||||||
|
km = m_controlKeymap;
|
||||||
|
if (km.macro.id == 0xffff)
|
||||||
|
m_kmView->m_keyPalettes[key] = -1;
|
||||||
|
else
|
||||||
|
m_kmView->m_keyPalettes[key] = allocateConfigIdx(km.configKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_kmView->update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
amuse::Keymap& km = (*m_kmView->m_node->m_obj)[key];
|
||||||
|
m_controlKeymap = km;
|
||||||
|
m_controls->setKeymap(km);
|
||||||
|
_touch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::touchControl(const amuse::Keymap& km)
|
||||||
|
{
|
||||||
|
m_controlKeymap = km;
|
||||||
|
_touch();
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeymapEditor::allocateConfigIdx(uint64_t key)
|
||||||
|
{
|
||||||
|
auto search = m_configToIdx.find(key);
|
||||||
|
if (search != m_configToIdx.end())
|
||||||
|
{
|
||||||
|
++search->second.second;
|
||||||
|
return search->second.first;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 128; ++i)
|
||||||
|
if (!m_idxBitmap[i])
|
||||||
|
{
|
||||||
|
m_configToIdx[key] = std::make_pair(i, 1);
|
||||||
|
m_idxBitmap.set(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::deallocateConfigIdx(uint64_t key)
|
||||||
|
{
|
||||||
|
auto search = m_configToIdx.find(key);
|
||||||
|
if (search != m_configToIdx.end())
|
||||||
|
{
|
||||||
|
--search->second.second;
|
||||||
|
if (search->second.second == 0)
|
||||||
|
{
|
||||||
|
m_idxBitmap.reset(search->second.first);
|
||||||
|
m_configToIdx.erase(search);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeymapEditor::getConfigIdx(uint64_t key) const
|
||||||
|
{
|
||||||
|
auto search = m_configToIdx.find(key);
|
||||||
|
if (search != m_configToIdx.end())
|
||||||
|
return search->second.first;
|
||||||
|
for (int i = 0; i < 128; ++i)
|
||||||
|
if (!m_idxBitmap[i])
|
||||||
|
return i;
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
bool KeymapEditor::loadData(ProjectModel::KeymapNode* node)
|
bool KeymapEditor::loadData(ProjectModel::KeymapNode* node)
|
||||||
{
|
{
|
||||||
return false;
|
if (m_kmView->m_node.get() != node)
|
||||||
|
{
|
||||||
|
m_configToIdx.clear();
|
||||||
|
m_idxBitmap.reset();
|
||||||
|
|
||||||
|
for (int i = 0; i < 128; ++i)
|
||||||
|
{
|
||||||
|
amuse::Keymap& km = (*node->m_obj)[i];
|
||||||
|
if (km.macro.id == 0xffff)
|
||||||
|
m_kmView->m_keyPalettes[i] = -1;
|
||||||
|
else
|
||||||
|
m_kmView->m_keyPalettes[i] = allocateConfigIdx(km.configKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_controlKeymap = amuse::Keymap();
|
||||||
|
m_kmView->loadData(node);
|
||||||
|
m_controls->loadData(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_inPaint = false;
|
||||||
|
m_controls->m_paintButton->setDown(false);
|
||||||
|
unsetCursor();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::unloadData()
|
||||||
|
{
|
||||||
|
m_configToIdx.clear();
|
||||||
|
m_idxBitmap.reset();
|
||||||
|
m_kmView->unloadData();
|
||||||
|
m_controls->unloadData();
|
||||||
|
|
||||||
|
m_inPaint = false;
|
||||||
|
m_controls->m_paintButton->setDown(false);
|
||||||
|
unsetCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectModel::INode* KeymapEditor::currentNode() const
|
||||||
|
{
|
||||||
|
return m_kmView->currentNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeymapEditor::keyPressEvent(QKeyEvent* event)
|
||||||
|
{
|
||||||
|
if (event->key() == Qt::Key_Escape)
|
||||||
|
{
|
||||||
|
if (m_inPaint)
|
||||||
|
{
|
||||||
|
m_inPaint = false;
|
||||||
|
m_controls->m_paintButton->setDown(false);
|
||||||
|
unsetCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeymapEditor::KeymapEditor(QWidget* parent)
|
KeymapEditor::KeymapEditor(QWidget* parent)
|
||||||
: EditorWidget(parent)
|
: EditorWidget(parent), m_scrollArea(new QScrollArea),
|
||||||
|
m_kmView(new KeymapView), m_controls(new KeymapControls)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < 13; ++i)
|
||||||
|
for (int j = 0; j < 10 && k < 128; ++j)
|
||||||
|
m_paintPalette[k++].setHsv(HueTable[j], SaturationTable[i], ValueTable[i]);
|
||||||
|
|
||||||
|
m_scrollArea->setWidget(m_kmView);
|
||||||
|
m_scrollArea->setWidgetResizable(true);
|
||||||
|
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout;
|
||||||
|
layout->setContentsMargins(QMargins());
|
||||||
|
layout->setSpacing(1);
|
||||||
|
layout->addWidget(m_scrollArea);
|
||||||
|
layout->addWidget(m_controls);
|
||||||
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,108 @@
|
||||||
#define AMUSE_KEYMAP_EDITOR_HPP
|
#define AMUSE_KEYMAP_EDITOR_HPP
|
||||||
|
|
||||||
#include "EditorWidget.hpp"
|
#include "EditorWidget.hpp"
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QStaticText>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
class KeymapEditor;
|
||||||
|
|
||||||
|
class PaintButton : public QPushButton
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PaintButton(QWidget* parent = Q_NULLPTR);
|
||||||
|
void mouseReleaseEvent(QMouseEvent* event) { event->ignore(); }
|
||||||
|
void mouseMoveEvent(QMouseEvent* event) { event->ignore(); }
|
||||||
|
void focusOutEvent(QFocusEvent* event) { event->ignore(); }
|
||||||
|
void keyPressEvent(QKeyEvent* event) { event->ignore(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeymapView : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class KeymapControls;
|
||||||
|
friend class KeymapEditor;
|
||||||
|
amuse::ObjToken<ProjectModel::KeymapNode> m_node;
|
||||||
|
QSvgRenderer m_octaveRenderer;
|
||||||
|
QSvgRenderer m_lastOctaveRenderer;
|
||||||
|
QRectF m_natural[7];
|
||||||
|
QRectF m_sharp[5];
|
||||||
|
QTransform m_widgetToSvg;
|
||||||
|
QFont m_keyFont;
|
||||||
|
QStaticText m_keyTexts[128];
|
||||||
|
int m_keyPalettes[128];
|
||||||
|
KeymapEditor* getEditor() const;
|
||||||
|
int getKey(const QPoint& localPos) const;
|
||||||
|
void drawKey(QPainter& painter, const QRect& octaveRect, qreal penWidth,
|
||||||
|
const QColor* keyPalette, int o, int k) const;
|
||||||
|
public:
|
||||||
|
explicit KeymapView(QWidget* parent = Q_NULLPTR);
|
||||||
|
void loadData(ProjectModel::KeymapNode* node);
|
||||||
|
void unloadData();
|
||||||
|
ProjectModel::INode* currentNode() const;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent* ev);
|
||||||
|
void mousePressEvent(QMouseEvent* ev);
|
||||||
|
void mouseMoveEvent(QMouseEvent* ev);
|
||||||
|
void wheelEvent(QWheelEvent* event);
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeymapControls : public QFrame
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class KeymapView;
|
||||||
|
friend class KeymapEditor;
|
||||||
|
FieldProjectNode* m_macro;
|
||||||
|
QSpinBox* m_transpose;
|
||||||
|
QSpinBox* m_pan;
|
||||||
|
QCheckBox* m_surround;
|
||||||
|
QSpinBox* m_prioOffset;
|
||||||
|
PaintButton* m_paintButton;
|
||||||
|
bool m_enableUpdate = true;
|
||||||
|
KeymapEditor* getEditor() const;
|
||||||
|
void setPaintIdx(int idx);
|
||||||
|
void setKeymap(const amuse::Keymap& km);
|
||||||
|
public:
|
||||||
|
explicit KeymapControls(QWidget* parent = Q_NULLPTR);
|
||||||
|
void loadData(ProjectModel::KeymapNode* node);
|
||||||
|
void unloadData();
|
||||||
|
public slots:
|
||||||
|
void controlChanged();
|
||||||
|
void paintButtonPressed();
|
||||||
|
};
|
||||||
|
|
||||||
class KeymapEditor : public EditorWidget
|
class KeymapEditor : public EditorWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
friend class KeymapView;
|
||||||
|
friend class KeymapControls;
|
||||||
|
QScrollArea* m_scrollArea;
|
||||||
|
KeymapView* m_kmView;
|
||||||
|
KeymapControls* m_controls;
|
||||||
|
QColor m_paintPalette[128];
|
||||||
|
amuse::Keymap m_controlKeymap;
|
||||||
|
std::unordered_map<uint64_t, std::pair<int, int>> m_configToIdx;
|
||||||
|
std::bitset<128> m_idxBitmap;
|
||||||
|
bool m_inPaint = false;
|
||||||
|
void _touch();
|
||||||
|
void touchKey(int key, bool bulk = false);
|
||||||
|
void touchControl(const amuse::Keymap& km);
|
||||||
|
int allocateConfigIdx(uint64_t key);
|
||||||
|
void deallocateConfigIdx(uint64_t key);
|
||||||
|
int getConfigIdx(uint64_t key) const;
|
||||||
public:
|
public:
|
||||||
explicit KeymapEditor(QWidget* parent = Q_NULLPTR);
|
explicit KeymapEditor(QWidget* parent = Q_NULLPTR);
|
||||||
bool loadData(ProjectModel::KeymapNode* node);
|
bool loadData(ProjectModel::KeymapNode* node);
|
||||||
|
void unloadData();
|
||||||
|
ProjectModel::INode* currentNode() const;
|
||||||
|
void keyPressEvent(QKeyEvent* event);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //AMUSE_KEYMAP_EDITOR_HPP
|
#endif //AMUSE_KEYMAP_EDITOR_HPP
|
||||||
|
|
|
@ -110,8 +110,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1100</width>
|
<width>1103</width>
|
||||||
<height>610</height>
|
<height>606</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -151,6 +151,78 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="PitchSlider" name="pitchSlider">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-2048</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>2048</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ModulationSlider" name="modulationSlider">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>127</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="VelocitySlider" name="velocitySlider">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>127</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>90</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QScrollArea" name="keyboardScrollArea">
|
<widget class="QScrollArea" name="keyboardScrollArea">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -189,7 +261,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1501</width>
|
<width>1501</width>
|
||||||
<height>85</height>
|
<height>80</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -213,78 +285,6 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="VelocitySlider" name="velocitySlider">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>127</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>90</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ModulationSlider" name="modulationSlider">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>127</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="PitchSlider" name="pitchSlider">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>-2048</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>2048</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -298,7 +298,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1360</width>
|
<width>1360</width>
|
||||||
<height>27</height>
|
<height>34</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
|
@ -325,7 +325,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuProject">
|
<widget class="QMenu" name="menuProject">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>P&roject</string>
|
<string>Pro&ject</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionNew_Subproject"/>
|
<addaction name="actionNew_Subproject"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
|
|
@ -269,6 +269,10 @@ void ProjectModel::_resetModelData()
|
||||||
col.reserve(keymaps.size());
|
col.reserve(keymaps.size());
|
||||||
for (auto& keymap : SortUnorderedMap(keymaps))
|
for (auto& keymap : SortUnorderedMap(keymaps))
|
||||||
col.makeChild<KeymapNode>(keymap.first, keymap.second.get());
|
col.makeChild<KeymapNode>(keymap.first, keymap.second.get());
|
||||||
|
amuse::KeymapId id = 42;
|
||||||
|
amuse::KeymapId::CurNameDB->registerPair("test", id);
|
||||||
|
auto km = amuse::MakeObj<std::array<amuse::Keymap, 128>>();
|
||||||
|
col.makeChild<KeymapNode>(id, km);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
CollectionNode& col =
|
CollectionNode& col =
|
||||||
|
|
|
@ -230,7 +230,7 @@ public:
|
||||||
using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>;
|
using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>;
|
||||||
using ADSRNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::ADSR>;
|
using ADSRNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::ADSR>;
|
||||||
using CurveNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::Curve>;
|
using CurveNode = PoolObjectNode<amuse::TableId, std::unique_ptr<amuse::ITable>, INode::Type::Curve>;
|
||||||
using KeymapNode = PoolObjectNode<amuse::KeymapId, amuse::Keymap, INode::Type::Keymap>;
|
using KeymapNode = PoolObjectNode<amuse::KeymapId, std::array<amuse::Keymap, 128>, INode::Type::Keymap>;
|
||||||
using LayersNode = PoolObjectNode<amuse::LayersId, std::vector<amuse::LayerMapping>, INode::Type::Layer>;
|
using LayersNode = PoolObjectNode<amuse::LayersId, std::vector<amuse::LayerMapping>, INode::Type::Layer>;
|
||||||
using SampleNode = PoolObjectNode<amuse::SampleId, amuse::SampleEntry, INode::Type::Sample>;
|
using SampleNode = PoolObjectNode<amuse::SampleId, amuse::SampleEntry, INode::Type::Sample>;
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,6 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
|
||||||
FieldProjectNode::FieldProjectNode(ProjectModel::CollectionNode* collection, QWidget* parent)
|
|
||||||
: FieldComboBox(parent), m_collection(collection)
|
|
||||||
{
|
|
||||||
ProjectModel* model = g_MainWindow->projectModel();
|
|
||||||
setModel(model->getNullProxy());
|
|
||||||
setRootModelIndex(model->getNullProxy()->mapFromSource(model->index(collection)));
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetButton::TargetButton(QWidget* parent)
|
TargetButton::TargetButton(QWidget* parent)
|
||||||
: QPushButton(parent)
|
: QPushButton(parent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,37 +17,6 @@ class SoundMacroEditor;
|
||||||
class SoundMacroListing;
|
class SoundMacroListing;
|
||||||
class CatalogueItem;
|
class CatalogueItem;
|
||||||
|
|
||||||
class FieldSpinBox : public QSpinBox
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FieldSpinBox(QWidget* parent = Q_NULLPTR)
|
|
||||||
: QSpinBox(parent) {}
|
|
||||||
|
|
||||||
/* Don't scroll */
|
|
||||||
void wheelEvent(QWheelEvent* event) { event->ignore(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class FieldComboBox : public QComboBox
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FieldComboBox(QWidget* parent = Q_NULLPTR)
|
|
||||||
: QComboBox(parent) {}
|
|
||||||
|
|
||||||
/* Don't scroll */
|
|
||||||
void wheelEvent(QWheelEvent* event) { event->ignore(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
class FieldProjectNode : public FieldComboBox
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
ProjectModel::CollectionNode* m_collection;
|
|
||||||
public:
|
|
||||||
explicit FieldProjectNode(ProjectModel::CollectionNode* collection, QWidget* parent = Q_NULLPTR);
|
|
||||||
ProjectModel::CollectionNode* collection() const { return m_collection; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class TargetButton : public QPushButton
|
class TargetButton : public QPushButton
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?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="32"
|
||||||
|
height="32"
|
||||||
|
viewBox="0 0 8.4666664 8.4666672"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||||
|
sodipodi:docname="IconPaintbrush.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#353535"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="39.33"
|
||||||
|
inkscape:cx="14.81887"
|
||||||
|
inkscape:cy="20.680873"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
units="px"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2079"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="40"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
gridtolerance="10"
|
||||||
|
showguides="false"
|
||||||
|
showborder="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid817"
|
||||||
|
empspacing="0"
|
||||||
|
spacingx="0.52916666"
|
||||||
|
spacingy="0.52916666"
|
||||||
|
visible="true" />
|
||||||
|
</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,-288.53332)">
|
||||||
|
<path
|
||||||
|
style="fill:#333333;fill-opacity:1;stroke:#ffffff;stroke-width:0.26458334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 7.9375067,289.06249 c 0.2663267,0.26632 -4.2333372,5.29165 -4.2333372,5.29165 l -1.0583343,-1.05832 c 0,0 5.0253447,-4.49967 5.2916715,-4.23333 z"
|
||||||
|
id="path846"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="zccz" />
|
||||||
|
<path
|
||||||
|
style="fill:#333333;fill-opacity:1;stroke:#ffffff;stroke-width:0.26458334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 3.7041695,294.35414 c 0.7934571,0.79347 -2.1166685,2.11668 -3.17500284,2.11668 0,-1.05833 1.32960554,-3.96208 2.11666854,-3.175 z"
|
||||||
|
id="path848"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:0.26458334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 2.7321623,293.41165 c 0,0 -1.1446613,0.94249 -2.20299564,3.05917"
|
||||||
|
id="path850"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:0.26458334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 3.6041925,294.27028 c 0,0 -0.9583573,1.14221 -3.07502584,2.20054"
|
||||||
|
id="path852"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:0.26458334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 3.1750023,293.82499 -2.64583564,2.64583"
|
||||||
|
id="path854"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#fffffd;fill-opacity:1;stroke:none;stroke-width:0.26458356px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 3.4564631,292.56098 0.9825481,0.98255 -0.7348417,0.81061 -1.0583343,-1.05832 z"
|
||||||
|
id="path1960"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
|
@ -4,94 +4,94 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ADSRControls</name>
|
<name>ADSRControls</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="335"/>
|
<location filename="../ADSREditor.cpp" line="337"/>
|
||||||
<source>Change Attack</source>
|
<source>Change Attack</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="399"/>
|
<location filename="../ADSREditor.cpp" line="401"/>
|
||||||
<source>Change Decay</source>
|
<source>Change Decay</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="463"/>
|
<location filename="../ADSREditor.cpp" line="465"/>
|
||||||
<source>Change Sustain</source>
|
<source>Change Sustain</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="528"/>
|
<location filename="../ADSREditor.cpp" line="532"/>
|
||||||
<source>Change Attack/Decay</source>
|
<source>Change Attack/Decay</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="602"/>
|
<location filename="../ADSREditor.cpp" line="610"/>
|
||||||
<source>Change Decay/Sustain</source>
|
<source>Change Decay/Sustain</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="675"/>
|
<location filename="../ADSREditor.cpp" line="687"/>
|
||||||
<source>Change Release</source>
|
<source>Change Release</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="765"/>
|
<location filename="../ADSREditor.cpp" line="789"/>
|
||||||
<source>Change DLS</source>
|
<source>Change DLS</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="852"/>
|
<location filename="../ADSREditor.cpp" line="876"/>
|
||||||
<source>Change Vel To Attack</source>
|
<source>Change Vel To Attack</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="905"/>
|
<location filename="../ADSREditor.cpp" line="929"/>
|
||||||
<source>Change Key To Decay</source>
|
<source>Change Key To Decay</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="970"/>
|
<location filename="../ADSREditor.cpp" line="994"/>
|
||||||
<source>Attack</source>
|
<source>Attack</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="978"/>
|
<location filename="../ADSREditor.cpp" line="1002"/>
|
||||||
<location filename="../ADSREditor.cpp" line="992"/>
|
<location filename="../ADSREditor.cpp" line="1016"/>
|
||||||
<location filename="../ADSREditor.cpp" line="1017"/>
|
<location filename="../ADSREditor.cpp" line="1041"/>
|
||||||
<source> sec</source>
|
<source> sec</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="984"/>
|
<location filename="../ADSREditor.cpp" line="1008"/>
|
||||||
<source>Decay</source>
|
<source>Decay</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="998"/>
|
<location filename="../ADSREditor.cpp" line="1022"/>
|
||||||
<source>Sustain</source>
|
<source>Sustain</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="1003"/>
|
<location filename="../ADSREditor.cpp" line="1027"/>
|
||||||
<source> %</source>
|
<source> %</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="1009"/>
|
<location filename="../ADSREditor.cpp" line="1033"/>
|
||||||
<source>Release</source>
|
<source>Release</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="1023"/>
|
<location filename="../ADSREditor.cpp" line="1047"/>
|
||||||
<source>DLS</source>
|
<source>DLS</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="1031"/>
|
<location filename="../ADSREditor.cpp" line="1055"/>
|
||||||
<source>Vel To Attack</source>
|
<source>Vel To Attack</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ADSREditor.cpp" line="1043"/>
|
<location filename="../ADSREditor.cpp" line="1067"/>
|
||||||
<source>Key To Decay</source>
|
<source>Key To Decay</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>CommandWidget</name>
|
<name>CommandWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="350"/>
|
<location filename="../SoundMacroEditor.cpp" line="342"/>
|
||||||
<source>Change %1</source>
|
<source>Change %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -107,32 +107,80 @@
|
||||||
<context>
|
<context>
|
||||||
<name>CurveControls</name>
|
<name>CurveControls</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../CurveEditor.cpp" line="16"/>
|
<location filename="../CurveEditor.cpp" line="18"/>
|
||||||
<source>Edit Curve</source>
|
<source>Edit Curve</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../CurveEditor.cpp" line="228"/>
|
<location filename="../CurveEditor.cpp" line="230"/>
|
||||||
<source>Did not evaluate as a number</source>
|
<source>Did not evaluate as a number</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../CurveEditor.cpp" line="253"/>
|
<location filename="../CurveEditor.cpp" line="255"/>
|
||||||
<source>Expression</source>
|
<source>Expression</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../CurveEditor.cpp" line="262"/>
|
<location filename="../CurveEditor.cpp" line="264"/>
|
||||||
<source>Apply</source>
|
<source>Apply</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../CurveEditor.cpp" line="286"/>
|
<location filename="../CurveEditor.cpp" line="288"/>
|
||||||
<source>Expression interpreter mapping x:[0,1] to y:[0,1] with the following constants and functions available:
|
<source>Expression interpreter mapping x:[0,1] to y:[0,1] with the following constants and functions available:
|
||||||
</source>
|
</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>KeymapControls</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="356"/>
|
||||||
|
<source>SoundMacro</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="362"/>
|
||||||
|
<source>Transpose</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="367"/>
|
||||||
|
<source>Offset resulting MIDI note</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="371"/>
|
||||||
|
<source>Pan</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="376"/>
|
||||||
|
<source>Set initial pan</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="380"/>
|
||||||
|
<source>Surround</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="384"/>
|
||||||
|
<source>Initially play through surround channels</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="388"/>
|
||||||
|
<source>Prio Offset</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="393"/>
|
||||||
|
<source>Offset resulting priority</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
|
@ -153,7 +201,7 @@
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../MainWindow.ui" line="328"/>
|
<location filename="../MainWindow.ui" line="328"/>
|
||||||
<source>P&roject</source>
|
<source>Pro&ject</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
|
@ -522,15 +570,23 @@
|
||||||
<context>
|
<context>
|
||||||
<name>ModulationSlider</name>
|
<name>ModulationSlider</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../KeyboardWidget.cpp" line="267"/>
|
<location filename="../KeyboardWidget.cpp" line="255"/>
|
||||||
<source>Modulation: %1</source>
|
<source>Modulation: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>PaintButton</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../KeymapEditor.cpp" line="93"/>
|
||||||
|
<source>Activate brush to apply values to keys</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PitchSlider</name>
|
<name>PitchSlider</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../KeyboardWidget.cpp" line="276"/>
|
<location filename="../KeyboardWidget.cpp" line="264"/>
|
||||||
<source>Pitch: %1</source>
|
<source>Pitch: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -558,17 +614,17 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ProjectModel.cpp" line="275"/>
|
<location filename="../ProjectModel.cpp" line="279"/>
|
||||||
<source>Layers</source>
|
<source>Layers</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ProjectModel.cpp" line="282"/>
|
<location filename="../ProjectModel.cpp" line="286"/>
|
||||||
<source>Samples</source>
|
<source>Samples</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ProjectModel.cpp" line="434"/>
|
<location filename="../ProjectModel.cpp" line="438"/>
|
||||||
<source>Delete %1</source>
|
<source>Delete %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -647,72 +703,72 @@
|
||||||
<context>
|
<context>
|
||||||
<name>SoundMacroCatalogue</name>
|
<name>SoundMacroCatalogue</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="977"/>
|
<location filename="../SoundMacroEditor.cpp" line="969"/>
|
||||||
<source>Control</source>
|
<source>Control</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="978"/>
|
<location filename="../SoundMacroEditor.cpp" line="970"/>
|
||||||
<source>Pitch</source>
|
<source>Pitch</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="979"/>
|
<location filename="../SoundMacroEditor.cpp" line="971"/>
|
||||||
<source>Sample</source>
|
<source>Sample</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="980"/>
|
<location filename="../SoundMacroEditor.cpp" line="972"/>
|
||||||
<source>Setup</source>
|
<source>Setup</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="981"/>
|
<location filename="../SoundMacroEditor.cpp" line="973"/>
|
||||||
<source>Special</source>
|
<source>Special</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="982"/>
|
<location filename="../SoundMacroEditor.cpp" line="974"/>
|
||||||
<source>Structure</source>
|
<source>Structure</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="983"/>
|
<location filename="../SoundMacroEditor.cpp" line="975"/>
|
||||||
<source>Volume</source>
|
<source>Volume</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="988"/>
|
<location filename="../SoundMacroEditor.cpp" line="980"/>
|
||||||
<source>Commands to control the voice</source>
|
<source>Commands to control the voice</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="989"/>
|
<location filename="../SoundMacroEditor.cpp" line="981"/>
|
||||||
<source>Commands to control the voice's pitch</source>
|
<source>Commands to control the voice's pitch</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="990"/>
|
<location filename="../SoundMacroEditor.cpp" line="982"/>
|
||||||
<source>Commands to control the voice's sample playback</source>
|
<source>Commands to control the voice's sample playback</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="991"/>
|
<location filename="../SoundMacroEditor.cpp" line="983"/>
|
||||||
<source>Commands to setup the voice's mixing process</source>
|
<source>Commands to setup the voice's mixing process</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="992"/>
|
<location filename="../SoundMacroEditor.cpp" line="984"/>
|
||||||
<source>Miscellaneous commands</source>
|
<source>Miscellaneous commands</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="993"/>
|
<location filename="../SoundMacroEditor.cpp" line="985"/>
|
||||||
<source>Commands to control macro branching</source>
|
<source>Commands to control macro branching</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="994"/>
|
<location filename="../SoundMacroEditor.cpp" line="986"/>
|
||||||
<source>Commands to control the voice's volume</source>
|
<source>Commands to control the voice's volume</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -720,7 +776,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>SoundMacroDeleteButton</name>
|
<name>SoundMacroDeleteButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="153"/>
|
<location filename="../SoundMacroEditor.cpp" line="145"/>
|
||||||
<source>Delete this SoundMacro</source>
|
<source>Delete this SoundMacro</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -728,17 +784,17 @@
|
||||||
<context>
|
<context>
|
||||||
<name>SoundMacroListing</name>
|
<name>SoundMacroListing</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="676"/>
|
<location filename="../SoundMacroEditor.cpp" line="668"/>
|
||||||
<source>Reorder %1</source>
|
<source>Reorder %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="808"/>
|
<location filename="../SoundMacroEditor.cpp" line="800"/>
|
||||||
<source>Insert %1</source>
|
<source>Insert %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="861"/>
|
<location filename="../SoundMacroEditor.cpp" line="853"/>
|
||||||
<source>Delete %1</source>
|
<source>Delete %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -754,7 +810,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>TargetButton</name>
|
<name>TargetButton</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../SoundMacroEditor.cpp" line="27"/>
|
<location filename="../SoundMacroEditor.cpp" line="19"/>
|
||||||
<source>Set step with target click</source>
|
<source>Set step with target click</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -762,7 +818,7 @@
|
||||||
<context>
|
<context>
|
||||||
<name>VelocitySlider</name>
|
<name>VelocitySlider</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../KeyboardWidget.cpp" line="258"/>
|
<location filename="../KeyboardWidget.cpp" line="246"/>
|
||||||
<source>Velocity: %1</source>
|
<source>Velocity: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<file>IconSoundMacroTargetDisabled.svg</file>
|
<file>IconSoundMacroTargetDisabled.svg</file>
|
||||||
<file>IconKill.svg</file>
|
<file>IconKill.svg</file>
|
||||||
<file>IconSample.svg</file>
|
<file>IconSample.svg</file>
|
||||||
|
<file>IconPaintbrush.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/bg">
|
<qresource prefix="/bg">
|
||||||
<file>FaceGrey.svg</file>
|
<file>FaceGrey.svg</file>
|
||||||
|
|
|
@ -1310,9 +1310,9 @@ struct Keymap : BigDNA
|
||||||
{
|
{
|
||||||
AT_DECL_DNA_YAML
|
AT_DECL_DNA_YAML
|
||||||
SoundMacroIdDNA<athena::Big> macro;
|
SoundMacroIdDNA<athena::Big> macro;
|
||||||
Value<atInt8> transpose;
|
Value<atInt8> transpose = 0;
|
||||||
Value<atInt8> pan; /* -128 for surround-channel only */
|
Value<atInt8> pan = 64; /* -128 for surround-channel only */
|
||||||
Value<atInt8> prioOffset;
|
Value<atInt8> prioOffset = 0;
|
||||||
|
|
||||||
Keymap() = default;
|
Keymap() = default;
|
||||||
|
|
||||||
|
@ -1331,6 +1331,11 @@ struct Keymap : BigDNA
|
||||||
ret.prioOffset = prioOffset;
|
ret.prioOffset = prioOffset;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t configKey() const
|
||||||
|
{
|
||||||
|
return uint64_t(macro.id) | (uint64_t(transpose) << 16) | (uint64_t(pan) << 24) | (uint64_t(prioOffset) << 32);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
|
/** Maps ranges of MIDI keys to sound-entity (macro-voice, keymap, layer) */
|
||||||
|
@ -1390,7 +1395,7 @@ class AudioGroupPool
|
||||||
{
|
{
|
||||||
std::unordered_map<SoundMacroId, ObjToken<SoundMacro>> m_soundMacros;
|
std::unordered_map<SoundMacroId, ObjToken<SoundMacro>> m_soundMacros;
|
||||||
std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>> m_tables;
|
std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>> m_tables;
|
||||||
std::unordered_map<KeymapId, ObjToken<Keymap>> m_keymaps;
|
std::unordered_map<KeymapId, ObjToken<std::array<Keymap, 128>>> m_keymaps;
|
||||||
std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>> m_layers;
|
std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>> m_layers;
|
||||||
|
|
||||||
template <athena::Endian DNAE>
|
template <athena::Endian DNAE>
|
||||||
|
@ -1402,11 +1407,11 @@ public:
|
||||||
|
|
||||||
const std::unordered_map<SoundMacroId, ObjToken<SoundMacro>>& soundMacros() const { return m_soundMacros; }
|
const std::unordered_map<SoundMacroId, ObjToken<SoundMacro>>& soundMacros() const { return m_soundMacros; }
|
||||||
const std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>>& tables() const { return m_tables; }
|
const std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>>& tables() const { return m_tables; }
|
||||||
const std::unordered_map<KeymapId, ObjToken<Keymap>>& keymaps() const { return m_keymaps; }
|
const std::unordered_map<KeymapId, ObjToken<std::array<Keymap, 128>>>& keymaps() const { return m_keymaps; }
|
||||||
const std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>>& layers() const { return m_layers; }
|
const std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>>& layers() const { return m_layers; }
|
||||||
std::unordered_map<SoundMacroId, ObjToken<SoundMacro>>& soundMacros() { return m_soundMacros; }
|
std::unordered_map<SoundMacroId, ObjToken<SoundMacro>>& soundMacros() { return m_soundMacros; }
|
||||||
std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>>& tables() { return m_tables; }
|
std::unordered_map<TableId, ObjToken<std::unique_ptr<ITable>>>& tables() { return m_tables; }
|
||||||
std::unordered_map<KeymapId, ObjToken<Keymap>>& keymaps() { return m_keymaps; }
|
std::unordered_map<KeymapId, ObjToken<std::array<Keymap, 128>>>& keymaps() { return m_keymaps; }
|
||||||
std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>>& layers() { return m_layers; }
|
std::unordered_map<LayersId, ObjToken<std::vector<LayerMapping>>>& layers() { return m_layers; }
|
||||||
|
|
||||||
const SoundMacro* soundMacro(ObjectId id) const;
|
const SoundMacro* soundMacro(ObjectId id) const;
|
||||||
|
|
|
@ -152,10 +152,14 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
||||||
ObjectHeader<DNAE> objHead;
|
ObjectHeader<DNAE> objHead;
|
||||||
atInt64 startPos = r.position();
|
atInt64 startPos = r.position();
|
||||||
objHead.read(r);
|
objHead.read(r);
|
||||||
KeymapDNA<DNAE> kmData;
|
|
||||||
kmData.read(r);
|
|
||||||
auto& km = ret.m_keymaps[objHead.objectId.id];
|
auto& km = ret.m_keymaps[objHead.objectId.id];
|
||||||
km = MakeObj<Keymap>(kmData);
|
km = MakeObj<std::array<Keymap, 128>>();
|
||||||
|
for (int i = 0; i < 128; ++i)
|
||||||
|
{
|
||||||
|
KeymapDNA<DNAE> kmData;
|
||||||
|
kmData.read(r);
|
||||||
|
(*km)[i] = kmData;
|
||||||
|
}
|
||||||
r.seek(startPos + objHead.size, athena::Begin);
|
r.seek(startPos + objHead.size, athena::Begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,12 +315,17 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
|
||||||
{
|
{
|
||||||
ret.m_keymaps.reserve(r.getCurNode()->m_mapChildren.size());
|
ret.m_keymaps.reserve(r.getCurNode()->m_mapChildren.size());
|
||||||
for (const auto& k : r.getCurNode()->m_mapChildren)
|
for (const auto& k : r.getCurNode()->m_mapChildren)
|
||||||
if (auto __v = r.enterSubRecord(k.first.c_str()))
|
{
|
||||||
|
size_t mappingCount;
|
||||||
|
if (auto __v = r.enterSubVector(k.first.c_str(), mappingCount))
|
||||||
{
|
{
|
||||||
auto& kmOut = ret.m_keymaps[KeymapId::CurNameDB->resolveIdFromName(k.first)];
|
auto& kmOut = ret.m_keymaps[KeymapId::CurNameDB->resolveIdFromName(k.first)];
|
||||||
kmOut = MakeObj<Keymap>();
|
kmOut = MakeObj<std::array<Keymap, 128>>();
|
||||||
kmOut->read(r);
|
for (int i = 0; i < mappingCount && i < 128; ++i)
|
||||||
|
if (auto __r2 = r.enterSubRecord(nullptr))
|
||||||
|
(*kmOut)[i].read(r);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto __r = r.enterSubRecord("layers"))
|
if (auto __r = r.enterSubRecord("layers"))
|
||||||
|
@ -388,7 +397,7 @@ const Keymap* AudioGroupPool::keymap(ObjectId id) const
|
||||||
auto search = m_keymaps.find(id);
|
auto search = m_keymaps.find(id);
|
||||||
if (search == m_keymaps.cend())
|
if (search == m_keymaps.cend())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return search->second.get();
|
return search->second.get()->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<LayerMapping>* AudioGroupPool::layer(ObjectId id) const
|
const std::vector<LayerMapping>* AudioGroupPool::layer(ObjectId id) const
|
||||||
|
@ -991,10 +1000,16 @@ bool AudioGroupPool::toYAML(SystemStringView groupPath) const
|
||||||
{
|
{
|
||||||
for (const auto& p : SortUnorderedMap(m_keymaps))
|
for (const auto& p : SortUnorderedMap(m_keymaps))
|
||||||
{
|
{
|
||||||
if (auto __v = w.enterSubRecord(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
|
if (auto __v = w.enterSubVector(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||||
{
|
{
|
||||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
for (const auto& km : *p.second.get())
|
||||||
p.second.get()->write(w);
|
{
|
||||||
|
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||||
|
{
|
||||||
|
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||||
|
km.write(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -811,8 +811,15 @@ bool Voice::_loadKeymap(const Keymap* keymap, double ticksPerSec,
|
||||||
midiKey += km.transpose;
|
midiKey += km.transpose;
|
||||||
bool ret = loadMacroObject(km.macro.id, 0, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
bool ret = loadMacroObject(km.macro.id, 0, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||||
m_curVol = 1.f;
|
m_curVol = 1.f;
|
||||||
_setPan((km.pan - 64) / 64.f);
|
if (km.pan == -128)
|
||||||
_setSurroundPan(-1.f);
|
{
|
||||||
|
_setSurroundPan(1.f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_setPan((km.pan - 64) / 64.f);
|
||||||
|
_setSurroundPan(-1.f);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue