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)
|
||||
{
|
||||
++m_cycleIdx;
|
||||
m_dragPoint = minDist;
|
||||
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 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)
|
||||
{
|
||||
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);
|
||||
ctrls->setDecayAndSustain(newDecay, newSustain * 100.0);
|
||||
ctrls->setDecayAndSustain(newDecay, newSustain * 100.0, m_cycleIdx);
|
||||
}
|
||||
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));
|
||||
ctrls->setRelease(newRelease, m_cycleIdx);
|
||||
ctrls->m_release->setValue(newRelease);
|
||||
}
|
||||
}
|
||||
|
@ -522,11 +524,13 @@ class ADSRAttackAndDecayUndoCommand : public EditorUndoCommand
|
|||
{
|
||||
double m_redoAttack, m_redoDecay;
|
||||
double m_undoAttack, m_undoDecay;
|
||||
uint64_t m_cycleCount;
|
||||
bool m_undid = false;
|
||||
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")),
|
||||
m_redoAttack(redoAttack), m_redoDecay(redoDecay) {}
|
||||
m_redoAttack(redoAttack), m_redoDecay(redoDecay), m_cycleCount(cycleCount) {}
|
||||
void undo()
|
||||
{
|
||||
m_undid = true;
|
||||
|
@ -569,7 +573,8 @@ public:
|
|||
}
|
||||
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_redoDecay = static_cast<const ADSRAttackAndDecayUndoCommand*>(other)->m_redoDecay;
|
||||
|
@ -580,7 +585,7 @@ public:
|
|||
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_attack->setValue(attack);
|
||||
|
@ -588,7 +593,8 @@ void ADSRControls::setAttackAndDecay(double attack, double decay)
|
|||
m_enableUpdate = true;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -596,11 +602,13 @@ class ADSRDecayAndSustainUndoCommand : public EditorUndoCommand
|
|||
{
|
||||
double m_redoDecay, m_redoSustain;
|
||||
double m_undoDecay, m_undoSustain;
|
||||
uint64_t m_cycleCount;
|
||||
bool m_undid = false;
|
||||
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")),
|
||||
m_redoDecay(redoDecay), m_redoSustain(redoSustain) {}
|
||||
m_redoDecay(redoDecay), m_redoSustain(redoSustain), m_cycleCount(cycleCount) {}
|
||||
void undo()
|
||||
{
|
||||
m_undid = true;
|
||||
|
@ -643,7 +651,8 @@ public:
|
|||
}
|
||||
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_redoSustain = static_cast<const ADSRDecayAndSustainUndoCommand*>(other)->m_redoSustain;
|
||||
|
@ -654,7 +663,7 @@ public:
|
|||
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_decay->setValue(decay);
|
||||
|
@ -662,18 +671,21 @@ void ADSRControls::setDecayAndSustain(double decay, double sustain)
|
|||
m_enableUpdate = true;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
class ADSRReleaseUndoCommand : public EditorUndoCommand
|
||||
{
|
||||
double m_redoVal, m_undoVal;
|
||||
uint64_t m_cycleCount;
|
||||
bool m_undid = false;
|
||||
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")),
|
||||
m_redoVal(redoVal) {}
|
||||
m_redoVal(redoVal), m_cycleCount(cycleCount) {}
|
||||
void undo()
|
||||
{
|
||||
m_undid = true;
|
||||
|
@ -710,7 +722,8 @@ public:
|
|||
}
|
||||
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;
|
||||
return true;
|
||||
|
@ -720,12 +733,23 @@ public:
|
|||
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)
|
||||
{
|
||||
if (m_enableUpdate)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Q_OBJECT
|
|||
QStaticText m_percentTexts[11];
|
||||
std::vector<QStaticText> m_timeTexts;
|
||||
int m_dragPoint = -1;
|
||||
uint64_t m_cycleIdx = 0;
|
||||
ADSREditor* getEditor() const;
|
||||
public:
|
||||
explicit ADSRView(QWidget* parent = Q_NULLPTR);
|
||||
|
@ -48,8 +49,9 @@ Q_OBJECT
|
|||
QDoubleSpinBox* m_keyToDecay;
|
||||
bool m_enableUpdate = true;
|
||||
ADSREditor* getEditor() const;
|
||||
void setAttackAndDecay(double attack, double decay);
|
||||
void setDecayAndSustain(double decay, double sustain);
|
||||
void setAttackAndDecay(double attack, double decay, uint64_t cycleCount);
|
||||
void setDecayAndSustain(double decay, double sustain, uint64_t cycleCount);
|
||||
void setRelease(double release, uint64_t cycleCount);
|
||||
public:
|
||||
explicit ADSRControls(QWidget* parent = Q_NULLPTR);
|
||||
void loadData();
|
||||
|
|
|
@ -85,3 +85,14 @@ QString ShowInGraphicalShellString()
|
|||
return MainWindow::tr("Show in Browser");
|
||||
#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()));
|
||||
}
|
||||
|
||||
/* Used for generating transform matrices to map SVG coordinate space */
|
||||
QTransform RectToRect(const QRectF& from, const QRectF& to);
|
||||
|
||||
#endif //AMUSE_COMMON_HPP
|
||||
|
|
|
@ -10,10 +10,12 @@ class CurveEditUndoCommand : public EditorUndoCommand
|
|||
{
|
||||
uint8_t m_redoData[128];
|
||||
uint8_t m_undoData[128];
|
||||
bool m_usedExpr;
|
||||
bool m_undid = false;
|
||||
public:
|
||||
CurveEditUndoCommand(const uint8_t* redoData, amuse::ObjToken<ProjectModel::CurveNode> node)
|
||||
: EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve"))
|
||||
CurveEditUndoCommand(const uint8_t* redoData, bool usedExpr,
|
||||
amuse::ObjToken<ProjectModel::CurveNode> node)
|
||||
: EditorUndoCommand(node.get(), CurveControls::tr("Edit Curve")), m_usedExpr(usedExpr)
|
||||
{
|
||||
std::memcpy(m_redoData, redoData, 128);
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ public:
|
|||
}
|
||||
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);
|
||||
return true;
|
||||
|
@ -153,7 +155,7 @@ void CurveView::mouseMoveEvent(QMouseEvent* ev)
|
|||
std::memcpy(newData, curve.data.data(), 128);
|
||||
newData[idx] = uint8_t(val);
|
||||
|
||||
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, m_node));
|
||||
g_MainWindow->pushUndoCommand(new CurveEditUndoCommand(newData, false, m_node));
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -227,7 +229,7 @@ void CurveControls::exprCommit()
|
|||
if (notANumber)
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "EditorWidget.hpp"
|
||||
#include "MainWindow.hpp"
|
||||
#include <QStandardItemModel>
|
||||
|
||||
EditorWidget::EditorWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
|
@ -16,3 +17,24 @@ void EditorUndoCommand::redo()
|
|||
{
|
||||
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 <QUndoCommand>
|
||||
#include <QApplication>
|
||||
#include <QSpinBox>
|
||||
#include <QComboBox>
|
||||
#include <QWheelEvent>
|
||||
#include "ProjectModel.hpp"
|
||||
|
||||
class EditorWidget : public QWidget
|
||||
|
@ -44,4 +47,36 @@ public:
|
|||
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
|
||||
|
|
|
@ -6,19 +6,7 @@
|
|||
#include <QApplication>
|
||||
#include <QScrollBar>
|
||||
|
||||
/* Used for generating transform matrices to map SVG coordinate space */
|
||||
static QTransform RectToRect(const QRectF& from, const QRectF& to)
|
||||
{
|
||||
QPolygonF orig(from);
|
||||
orig.pop_back();
|
||||
QPolygonF resize(to);
|
||||
resize.pop_back();
|
||||
QTransform ret;
|
||||
QTransform::quadToQuad(orig, resize, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const QString NaturalKeyNames[] =
|
||||
const QString NaturalKeyNames[] =
|
||||
{
|
||||
QStringLiteral("C"),
|
||||
QStringLiteral("D"),
|
||||
|
@ -29,7 +17,7 @@ static const QString NaturalKeyNames[] =
|
|||
QStringLiteral("B")
|
||||
};
|
||||
|
||||
static const QString SharpKeyNames[] =
|
||||
const QString SharpKeyNames[] =
|
||||
{
|
||||
QStringLiteral("Cs"),
|
||||
QStringLiteral("Ds"),
|
||||
|
@ -38,7 +26,7 @@ static const QString SharpKeyNames[] =
|
|||
QStringLiteral("As")
|
||||
};
|
||||
|
||||
static const QString KeyStrings[] =
|
||||
const QString KeyStrings[] =
|
||||
{
|
||||
QStringLiteral("C"),
|
||||
QStringLiteral("C#"),
|
||||
|
@ -54,12 +42,12 @@ static const QString KeyStrings[] =
|
|||
QStringLiteral("B")
|
||||
};
|
||||
|
||||
static const int NaturalKeyNumbers[] =
|
||||
const int NaturalKeyNumbers[] =
|
||||
{
|
||||
0, 2, 4, 5, 7, 9, 11
|
||||
};
|
||||
|
||||
static const int SharpKeyNumbers[] =
|
||||
const int SharpKeyNumbers[] =
|
||||
{
|
||||
1, 3, 6, 8, 10
|
||||
};
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
#include <QSlider>
|
||||
#include <QWheelEvent>
|
||||
#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;
|
||||
|
||||
|
|
|
@ -1,12 +1,600 @@
|
|||
#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)
|
||||
{
|
||||
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)
|
||||
: 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
|
||||
|
||||
#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
|
||||
{
|
||||
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:
|
||||
explicit KeymapEditor(QWidget* parent = Q_NULLPTR);
|
||||
bool loadData(ProjectModel::KeymapNode* node);
|
||||
void unloadData();
|
||||
ProjectModel::INode* currentNode() const;
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
};
|
||||
|
||||
|
||||
#endif //AMUSE_KEYMAP_EDITOR_HPP
|
||||
|
|
|
@ -110,8 +110,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>610</height>
|
||||
<width>1103</width>
|
||||
<height>606</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -151,6 +151,78 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</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>
|
||||
<widget class="QScrollArea" name="keyboardScrollArea">
|
||||
<property name="sizePolicy">
|
||||
|
@ -189,7 +261,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1501</width>
|
||||
<height>85</height>
|
||||
<height>80</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -213,78 +285,6 @@
|
|||
</widget>
|
||||
</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>
|
||||
<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>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -298,7 +298,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1360</width>
|
||||
<height>27</height>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
@ -325,7 +325,7 @@
|
|||
</widget>
|
||||
<widget class="QMenu" name="menuProject">
|
||||
<property name="title">
|
||||
<string>P&roject</string>
|
||||
<string>Pro&ject</string>
|
||||
</property>
|
||||
<addaction name="actionNew_Subproject"/>
|
||||
<addaction name="separator"/>
|
||||
|
|
|
@ -269,6 +269,10 @@ void ProjectModel::_resetModelData()
|
|||
col.reserve(keymaps.size());
|
||||
for (auto& keymap : SortUnorderedMap(keymaps))
|
||||
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 =
|
||||
|
|
|
@ -230,7 +230,7 @@ public:
|
|||
using SoundMacroNode = PoolObjectNode<amuse::SoundMacroId, amuse::SoundMacro, INode::Type::SoundMacro>;
|
||||
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 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 SampleNode = PoolObjectNode<amuse::SampleId, amuse::SampleEntry, INode::Type::Sample>;
|
||||
|
||||
|
|
|
@ -10,14 +10,6 @@
|
|||
#include <QApplication>
|
||||
#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)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
|
|
|
@ -17,37 +17,6 @@ class SoundMacroEditor;
|
|||
class SoundMacroListing;
|
||||
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
|
||||
{
|
||||
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>
|
||||
<name>ADSRControls</name>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="335"/>
|
||||
<location filename="../ADSREditor.cpp" line="337"/>
|
||||
<source>Change Attack</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="399"/>
|
||||
<location filename="../ADSREditor.cpp" line="401"/>
|
||||
<source>Change Decay</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="463"/>
|
||||
<location filename="../ADSREditor.cpp" line="465"/>
|
||||
<source>Change Sustain</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="528"/>
|
||||
<location filename="../ADSREditor.cpp" line="532"/>
|
||||
<source>Change Attack/Decay</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="602"/>
|
||||
<location filename="../ADSREditor.cpp" line="610"/>
|
||||
<source>Change Decay/Sustain</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="675"/>
|
||||
<location filename="../ADSREditor.cpp" line="687"/>
|
||||
<source>Change Release</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="765"/>
|
||||
<location filename="../ADSREditor.cpp" line="789"/>
|
||||
<source>Change DLS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="852"/>
|
||||
<location filename="../ADSREditor.cpp" line="876"/>
|
||||
<source>Change Vel To Attack</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="905"/>
|
||||
<location filename="../ADSREditor.cpp" line="929"/>
|
||||
<source>Change Key To Decay</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="970"/>
|
||||
<location filename="../ADSREditor.cpp" line="994"/>
|
||||
<source>Attack</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="978"/>
|
||||
<location filename="../ADSREditor.cpp" line="992"/>
|
||||
<location filename="../ADSREditor.cpp" line="1017"/>
|
||||
<location filename="../ADSREditor.cpp" line="1002"/>
|
||||
<location filename="../ADSREditor.cpp" line="1016"/>
|
||||
<location filename="../ADSREditor.cpp" line="1041"/>
|
||||
<source> sec</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="984"/>
|
||||
<location filename="../ADSREditor.cpp" line="1008"/>
|
||||
<source>Decay</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="998"/>
|
||||
<location filename="../ADSREditor.cpp" line="1022"/>
|
||||
<source>Sustain</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="1003"/>
|
||||
<location filename="../ADSREditor.cpp" line="1027"/>
|
||||
<source> %</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="1009"/>
|
||||
<location filename="../ADSREditor.cpp" line="1033"/>
|
||||
<source>Release</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="1023"/>
|
||||
<location filename="../ADSREditor.cpp" line="1047"/>
|
||||
<source>DLS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="1031"/>
|
||||
<location filename="../ADSREditor.cpp" line="1055"/>
|
||||
<source>Vel To Attack</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ADSREditor.cpp" line="1043"/>
|
||||
<location filename="../ADSREditor.cpp" line="1067"/>
|
||||
<source>Key To Decay</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -99,7 +99,7 @@
|
|||
<context>
|
||||
<name>CommandWidget</name>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="350"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="342"/>
|
||||
<source>Change %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -107,32 +107,80 @@
|
|||
<context>
|
||||
<name>CurveControls</name>
|
||||
<message>
|
||||
<location filename="../CurveEditor.cpp" line="16"/>
|
||||
<location filename="../CurveEditor.cpp" line="18"/>
|
||||
<source>Edit Curve</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../CurveEditor.cpp" line="228"/>
|
||||
<location filename="../CurveEditor.cpp" line="230"/>
|
||||
<source>Did not evaluate as a number</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../CurveEditor.cpp" line="253"/>
|
||||
<location filename="../CurveEditor.cpp" line="255"/>
|
||||
<source>Expression</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../CurveEditor.cpp" line="262"/>
|
||||
<location filename="../CurveEditor.cpp" line="264"/>
|
||||
<source>Apply</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</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>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
|
@ -153,7 +201,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../MainWindow.ui" line="328"/>
|
||||
<source>P&roject</source>
|
||||
<source>Pro&ject</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
|
@ -522,15 +570,23 @@
|
|||
<context>
|
||||
<name>ModulationSlider</name>
|
||||
<message>
|
||||
<location filename="../KeyboardWidget.cpp" line="267"/>
|
||||
<location filename="../KeyboardWidget.cpp" line="255"/>
|
||||
<source>Modulation: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</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>
|
||||
<name>PitchSlider</name>
|
||||
<message>
|
||||
<location filename="../KeyboardWidget.cpp" line="276"/>
|
||||
<location filename="../KeyboardWidget.cpp" line="264"/>
|
||||
<source>Pitch: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -558,17 +614,17 @@
|
|||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ProjectModel.cpp" line="275"/>
|
||||
<location filename="../ProjectModel.cpp" line="279"/>
|
||||
<source>Layers</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ProjectModel.cpp" line="282"/>
|
||||
<location filename="../ProjectModel.cpp" line="286"/>
|
||||
<source>Samples</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ProjectModel.cpp" line="434"/>
|
||||
<location filename="../ProjectModel.cpp" line="438"/>
|
||||
<source>Delete %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -647,72 +703,72 @@
|
|||
<context>
|
||||
<name>SoundMacroCatalogue</name>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="977"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="969"/>
|
||||
<source>Control</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="978"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="970"/>
|
||||
<source>Pitch</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="979"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="971"/>
|
||||
<source>Sample</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="980"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="972"/>
|
||||
<source>Setup</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="981"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="973"/>
|
||||
<source>Special</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="982"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="974"/>
|
||||
<source>Structure</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="983"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="975"/>
|
||||
<source>Volume</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="988"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="980"/>
|
||||
<source>Commands to control the voice</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="989"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="981"/>
|
||||
<source>Commands to control the voice's pitch</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="990"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="982"/>
|
||||
<source>Commands to control the voice's sample playback</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="991"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="983"/>
|
||||
<source>Commands to setup the voice's mixing process</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="992"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="984"/>
|
||||
<source>Miscellaneous commands</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="993"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="985"/>
|
||||
<source>Commands to control macro branching</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="994"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="986"/>
|
||||
<source>Commands to control the voice's volume</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -720,7 +776,7 @@
|
|||
<context>
|
||||
<name>SoundMacroDeleteButton</name>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="153"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="145"/>
|
||||
<source>Delete this SoundMacro</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -728,17 +784,17 @@
|
|||
<context>
|
||||
<name>SoundMacroListing</name>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="676"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="668"/>
|
||||
<source>Reorder %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="808"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="800"/>
|
||||
<source>Insert %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="861"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="853"/>
|
||||
<source>Delete %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -754,7 +810,7 @@
|
|||
<context>
|
||||
<name>TargetButton</name>
|
||||
<message>
|
||||
<location filename="../SoundMacroEditor.cpp" line="27"/>
|
||||
<location filename="../SoundMacroEditor.cpp" line="19"/>
|
||||
<source>Set step with target click</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -762,7 +818,7 @@
|
|||
<context>
|
||||
<name>VelocitySlider</name>
|
||||
<message>
|
||||
<location filename="../KeyboardWidget.cpp" line="258"/>
|
||||
<location filename="../KeyboardWidget.cpp" line="246"/>
|
||||
<source>Velocity: %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<file>IconSoundMacroTargetDisabled.svg</file>
|
||||
<file>IconKill.svg</file>
|
||||
<file>IconSample.svg</file>
|
||||
<file>IconPaintbrush.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/bg">
|
||||
<file>FaceGrey.svg</file>
|
||||
|
|
|
@ -1310,9 +1310,9 @@ struct Keymap : BigDNA
|
|||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SoundMacroIdDNA<athena::Big> macro;
|
||||
Value<atInt8> transpose;
|
||||
Value<atInt8> pan; /* -128 for surround-channel only */
|
||||
Value<atInt8> prioOffset;
|
||||
Value<atInt8> transpose = 0;
|
||||
Value<atInt8> pan = 64; /* -128 for surround-channel only */
|
||||
Value<atInt8> prioOffset = 0;
|
||||
|
||||
Keymap() = default;
|
||||
|
||||
|
@ -1331,6 +1331,11 @@ struct Keymap : BigDNA
|
|||
ret.prioOffset = prioOffset;
|
||||
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) */
|
||||
|
@ -1390,7 +1395,7 @@ class AudioGroupPool
|
|||
{
|
||||
std::unordered_map<SoundMacroId, ObjToken<SoundMacro>> m_soundMacros;
|
||||
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;
|
||||
|
||||
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<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; }
|
||||
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<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; }
|
||||
|
||||
const SoundMacro* soundMacro(ObjectId id) const;
|
||||
|
|
|
@ -152,10 +152,14 @@ AudioGroupPool AudioGroupPool::_AudioGroupPool(athena::io::IStreamReader& r)
|
|||
ObjectHeader<DNAE> objHead;
|
||||
atInt64 startPos = r.position();
|
||||
objHead.read(r);
|
||||
auto& km = ret.m_keymaps[objHead.objectId.id];
|
||||
km = MakeObj<std::array<Keymap, 128>>();
|
||||
for (int i = 0; i < 128; ++i)
|
||||
{
|
||||
KeymapDNA<DNAE> kmData;
|
||||
kmData.read(r);
|
||||
auto& km = ret.m_keymaps[objHead.objectId.id];
|
||||
km = MakeObj<Keymap>(kmData);
|
||||
(*km)[i] = kmData;
|
||||
}
|
||||
r.seek(startPos + objHead.size, athena::Begin);
|
||||
}
|
||||
}
|
||||
|
@ -311,11 +315,16 @@ AudioGroupPool AudioGroupPool::CreateAudioGroupPool(SystemStringView groupPath)
|
|||
{
|
||||
ret.m_keymaps.reserve(r.getCurNode()->m_mapChildren.size());
|
||||
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)];
|
||||
kmOut = MakeObj<Keymap>();
|
||||
kmOut->read(r);
|
||||
kmOut = MakeObj<std::array<Keymap, 128>>();
|
||||
for (int i = 0; i < mappingCount && i < 128; ++i)
|
||||
if (auto __r2 = r.enterSubRecord(nullptr))
|
||||
(*kmOut)[i].read(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +397,7 @@ const Keymap* AudioGroupPool::keymap(ObjectId id) const
|
|||
auto search = m_keymaps.find(id);
|
||||
if (search == m_keymaps.cend())
|
||||
return nullptr;
|
||||
return search->second.get();
|
||||
return search->second.get()->data();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
if (auto __v = w.enterSubRecord(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
if (auto __v = w.enterSubVector(KeymapId::CurNameDB->resolveNameFromId(p.first).data()))
|
||||
{
|
||||
for (const auto& km : *p.second.get())
|
||||
{
|
||||
if (auto __r2 = w.enterSubRecord(nullptr))
|
||||
{
|
||||
w.setStyle(athena::io::YAMLNodeStyle::Flow);
|
||||
p.second.get()->write(w);
|
||||
km.write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -811,8 +811,15 @@ bool Voice::_loadKeymap(const Keymap* keymap, double ticksPerSec,
|
|||
midiKey += km.transpose;
|
||||
bool ret = loadMacroObject(km.macro.id, 0, ticksPerSec, midiKey, midiVel, midiMod, pushPc);
|
||||
m_curVol = 1.f;
|
||||
if (km.pan == -128)
|
||||
{
|
||||
_setSurroundPan(1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_setPan((km.pan - 64) / 64.f);
|
||||
_setSurroundPan(-1.f);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue