2018-02-27 00:33:41 +00:00
|
|
|
/*
|
2018-06-04 19:04:53 +00:00
|
|
|
|
|
|
|
Copyright (C) 2017 Xenakios
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 3 of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License (version 3) for more details.
|
|
|
|
|
|
|
|
www.gnu.org/licenses
|
|
|
|
|
|
|
|
*/
|
2018-02-27 00:33:41 +00:00
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
#include "envelope_component.h"
|
|
|
|
|
2018-02-27 13:21:36 +00:00
|
|
|
EnvelopeComponent::EnvelopeComponent(CriticalSection* cs) : m_cs(cs)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
|
|
|
OnEnvelopeEdited = [](breakpoint_envelope*) {};
|
|
|
|
setWantsKeyboardFocus(true);
|
2018-07-08 11:38:50 +00:00
|
|
|
YFromNormalized = [](double x) { return x; };
|
|
|
|
XFromNormalized = [](double x) { return x; };
|
2018-02-26 23:59:22 +00:00
|
|
|
addChildComponent(&m_bubble);
|
|
|
|
setOpaque(true);
|
2022-04-14 07:26:26 +00:00
|
|
|
|
2022-04-15 18:29:23 +00:00
|
|
|
#if JUCE_IOS
|
2022-04-14 07:26:26 +00:00
|
|
|
m_menubutton.setButtonText("...");
|
|
|
|
m_menubutton.onClick = [this]() {
|
|
|
|
showPopupMenu();
|
|
|
|
};
|
|
|
|
addAndMakeVisible(&m_menubutton);
|
2022-04-15 18:29:23 +00:00
|
|
|
#endif
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EnvelopeComponent::~EnvelopeComponent()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-17 10:06:07 +00:00
|
|
|
void EnvelopeComponent::show_bubble(int x, int y, const envelope_point& node)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
double scaledtime = XFromNormalized(node.pt_x);
|
|
|
|
double scaledvalue = YFromNormalized(node.pt_y);
|
2018-02-26 23:59:22 +00:00
|
|
|
x -= 50;
|
|
|
|
if (x < 0)
|
|
|
|
x = 0;
|
|
|
|
if (x + 100 > getWidth())
|
|
|
|
x = getWidth() - 100;
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
|
|
|
if (y + 20 > getHeight())
|
|
|
|
y = getHeight() - 20;
|
|
|
|
AttributedString temp(String::formatted("%.2f %.2f", scaledtime, scaledvalue));
|
|
|
|
temp.setColour(Colours::white);
|
|
|
|
m_bubble.showAt({ x,y,100,20 }, temp , 5000);
|
|
|
|
}
|
|
|
|
|
2022-04-14 07:26:26 +00:00
|
|
|
void EnvelopeComponent::resized()
|
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
#if JUCE_IOS
|
2022-04-14 07:26:26 +00:00
|
|
|
int butw = 38;
|
2022-04-18 19:11:22 +00:00
|
|
|
int buth = 34;
|
|
|
|
m_menubutton.setBounds((getWidth() - butw)/2, 1, butw, buth);
|
|
|
|
#endif
|
2022-04-14 07:26:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
void EnvelopeComponent::paint(Graphics& g)
|
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
float targsize = 10.0;
|
2022-04-12 22:47:43 +00:00
|
|
|
#if JUCE_IOS
|
|
|
|
targsize = 16.0;
|
|
|
|
#endif
|
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
if (!EnvelopeUnderlayDraw)
|
|
|
|
{
|
|
|
|
g.fillAll(Colours::black);
|
|
|
|
g.setColour(Colours::white.darker());
|
|
|
|
juce::Rectangle<int> rect(0, 0, getWidth(), getHeight());
|
|
|
|
|
|
|
|
g.setFont(15.0);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g.saveState();
|
|
|
|
EnvelopeUnderlayDraw(this, g);
|
|
|
|
g.restoreState();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_envelope == nullptr)
|
|
|
|
{
|
|
|
|
g.drawText("No envelope set", 10, 10, getWidth(), getHeight(), Justification::centred);
|
|
|
|
return;
|
|
|
|
}
|
2020-12-11 02:02:36 +00:00
|
|
|
if (m_envelope.use_count() == 1)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
|
|
|
g.drawText("Envelope is orphaned (may be a bug)", 10, 10, getWidth(), getHeight(), Justification::centred);
|
|
|
|
return;
|
|
|
|
}
|
2022-04-15 18:29:23 +00:00
|
|
|
|
|
|
|
int freqdivs = jmax(2, jmin(10, (int) (getWidth() / 60.0f)));
|
|
|
|
int divwidth = getWidth() / freqdivs;
|
|
|
|
|
|
|
|
for (int i = 0; i < freqdivs; ++i)
|
2018-02-27 17:44:35 +00:00
|
|
|
{
|
2022-04-15 18:29:23 +00:00
|
|
|
double norm = 1.0 / freqdivs * i;
|
2018-07-08 11:38:50 +00:00
|
|
|
double hz = XFromNormalized(norm);
|
2022-04-15 18:29:23 +00:00
|
|
|
int xcor = divwidth * i;
|
|
|
|
g.drawFittedText(String(hz, 1), xcor, getHeight() - 20, divwidth, 20, Justification::topLeft, 1);
|
|
|
|
}
|
2018-02-28 02:30:28 +00:00
|
|
|
String name = m_envelope->GetName();
|
2018-02-26 23:59:22 +00:00
|
|
|
if (name.isEmpty() == true)
|
|
|
|
name = "Untitled envelope";
|
|
|
|
g.drawText(name, 10, 10, getWidth(), getHeight(), Justification::topLeft);
|
2018-02-28 11:04:44 +00:00
|
|
|
auto draw_env = [this, &g](Colour envcolor, bool drawTransformed, float linethickness)
|
2018-02-27 21:11:03 +00:00
|
|
|
{
|
2018-02-28 11:04:44 +00:00
|
|
|
g.setColour(envcolor);
|
|
|
|
double y0 = 0.0;
|
|
|
|
if (drawTransformed==false)
|
2018-10-17 10:14:07 +00:00
|
|
|
y0 = m_envelope->GetInterpolatedEnvelopeValue(0.0);
|
2018-02-28 11:04:44 +00:00
|
|
|
else y0 = m_envelope->getTransformedValue(0.0);
|
|
|
|
const int drawstep = 1;
|
2018-02-27 22:05:35 +00:00
|
|
|
for (int i = 1; i < getWidth(); ++i)
|
|
|
|
{
|
|
|
|
double env_x = 1.0 / getWidth()*i;
|
2018-02-28 11:04:44 +00:00
|
|
|
double y1 = 0.0;
|
|
|
|
if (drawTransformed==false)
|
2018-10-17 10:14:07 +00:00
|
|
|
y1 = m_envelope->GetInterpolatedEnvelopeValue(env_x);
|
2018-02-28 11:04:44 +00:00
|
|
|
else y1 = m_envelope->getTransformedValue(env_x);
|
2018-02-27 22:05:35 +00:00
|
|
|
double foo_y0 = (double)getHeight() - jmap<double>(y0, m_view_start_value, m_view_end_value, 0.0, getHeight());
|
|
|
|
double foo_y1 = (double)getHeight() - jmap<double>(y1, m_view_start_value, m_view_end_value, 0.0, getHeight());
|
|
|
|
g.drawLine((float)i, foo_y0, (float)i + 1, foo_y1, linethickness);
|
|
|
|
y0 = y1;
|
|
|
|
}
|
2018-02-28 11:04:44 +00:00
|
|
|
};
|
|
|
|
draw_env(m_env_color, false, 1.0f);
|
|
|
|
draw_env(Colours::aquamarine.darker(), true, 1.0f);
|
2018-10-17 10:14:07 +00:00
|
|
|
for (int i = 0; i < m_envelope->GetNumPoints(); ++i)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
const envelope_point& pt = m_envelope->GetNodeAtIndex(i);
|
|
|
|
double xcor = jmap(pt.pt_x, m_view_start_time, m_view_end_time, 0.0, (double)getWidth());
|
|
|
|
double ycor = (double)getHeight() - jmap(pt.pt_y, m_view_start_value, m_view_end_value, 0.0, (double)getHeight());
|
2018-02-26 23:59:22 +00:00
|
|
|
g.setColour(Colours::white);
|
2018-02-27 21:11:03 +00:00
|
|
|
if (pt.Status == 0)
|
2022-04-12 22:47:43 +00:00
|
|
|
g.drawRect((float)xcor - targsize*0.5f, (float)ycor - targsize*0.5f, targsize, targsize, 1.0f);
|
|
|
|
else g.fillRect((float)xcor - targsize*0.5f, (float)ycor - targsize*0.5f, targsize, targsize);
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::changeListenerCallback(ChangeBroadcaster*)
|
|
|
|
{
|
|
|
|
repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::timerCallback(int)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::set_envelope(std::shared_ptr<breakpoint_envelope> env, String name)
|
|
|
|
{
|
|
|
|
m_envelope = env;
|
|
|
|
m_name = name;
|
|
|
|
repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::mouseDrag(const MouseEvent& ev)
|
|
|
|
{
|
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return;
|
|
|
|
if (m_segment_drag_info.first >= 0 && ev.mods.isAltDown())
|
|
|
|
{
|
|
|
|
double dist = jmap<double>(ev.getDistanceFromDragStartX(), -300.0, 300.0, -1.0, 1.0);
|
2018-10-17 10:06:07 +00:00
|
|
|
m_envelope->performRelativeTransformation([dist, this](int index, envelope_point& point)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
|
|
|
if (index == m_segment_drag_info.first)
|
|
|
|
{
|
|
|
|
point.ShapeParam1 += dist;
|
|
|
|
m_segment_drag_info.second = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
repaint();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_segment_drag_info.first >= 0)
|
|
|
|
{
|
|
|
|
double dist = jmap<double>(ev.getDistanceFromDragStartY(), -getHeight(), getHeight(), -1.0, 1.0);
|
|
|
|
m_envelope->adjustEnvelopeSegmentValues(m_segment_drag_info.first, -dist);
|
2018-02-28 16:34:34 +00:00
|
|
|
m_envelope->updateMinMaxValues();
|
2018-02-26 23:59:22 +00:00
|
|
|
repaint();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_node_to_drag >= 0)
|
|
|
|
{
|
|
|
|
//Logger::writeToLog("trying to move pt " + String(m_node_to_drag));
|
2018-10-17 10:06:07 +00:00
|
|
|
envelope_point& pt = m_envelope->GetNodeAtIndex(m_node_to_drag);
|
2018-02-26 23:59:22 +00:00
|
|
|
double left_bound = m_view_start_time;
|
|
|
|
double right_bound = m_view_end_time;
|
|
|
|
if (m_node_to_drag > 0 )
|
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
left_bound = m_envelope->GetNodeAtIndex(m_node_to_drag - 1).pt_x;
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
2018-10-17 10:14:07 +00:00
|
|
|
if (m_node_to_drag < m_envelope->GetNumPoints() - 1)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
right_bound = m_envelope->GetNodeAtIndex(m_node_to_drag + 1).pt_x;
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
double normx = jmap((double)ev.x - m_touch_offset.x, 0.0, (double)getWidth(), m_view_start_time, m_view_end_time);
|
|
|
|
double normy = jmap((double)getHeight() - (ev.y - m_touch_offset.y ), 0.0, (double)getHeight(), m_view_start_value, m_view_end_value);
|
2018-10-17 10:06:07 +00:00
|
|
|
pt.pt_x=jlimit(left_bound+0.001, right_bound - 0.001, normx);
|
|
|
|
pt.pt_y=jlimit(0.0,1.0,normy);
|
2018-02-28 16:34:34 +00:00
|
|
|
m_envelope->updateMinMaxValues();
|
2018-10-17 10:06:07 +00:00
|
|
|
m_last_tip = String(pt.pt_x, 2) + " " + String(pt.pt_y, 2);
|
2018-02-26 23:59:22 +00:00
|
|
|
show_bubble(ev.x, ev.y, pt);
|
|
|
|
m_node_that_was_dragged = m_node_to_drag;
|
|
|
|
repaint();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::mouseMove(const MouseEvent & ev)
|
|
|
|
{
|
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return;
|
|
|
|
m_node_to_drag = find_hot_envelope_point(ev.x, ev.y);
|
|
|
|
if (m_node_to_drag >= 0)
|
|
|
|
{
|
|
|
|
if (m_mouse_down == false)
|
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
#if !JUCE_IOS
|
2018-02-26 23:59:22 +00:00
|
|
|
show_bubble(ev.x, ev.y, m_envelope->GetNodeAtIndex(m_node_to_drag));
|
|
|
|
setMouseCursor(MouseCursor::PointingHandCursor);
|
2022-04-18 19:11:22 +00:00
|
|
|
#endif
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-02-28 14:01:16 +00:00
|
|
|
int temp = findHotEnvelopeSegment(ev.x, ev.y, true);
|
|
|
|
if (temp>=0)
|
|
|
|
setMouseCursor(MouseCursor::UpDownResizeCursor);
|
|
|
|
else
|
|
|
|
setMouseCursor(MouseCursor::NormalCursor);
|
2018-02-26 23:59:22 +00:00
|
|
|
m_bubble.setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-14 07:26:26 +00:00
|
|
|
void EnvelopeComponent::showPopupMenu()
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2022-04-14 07:26:26 +00:00
|
|
|
PopupMenu menu;
|
|
|
|
PopupMenu::Options opts;
|
|
|
|
menu.addItem(1, "Reset");
|
2022-04-18 19:11:22 +00:00
|
|
|
menu.addItem(5, "Delete selected");
|
2022-04-14 07:26:26 +00:00
|
|
|
menu.addItem(2, "Invert");
|
|
|
|
menu.addItem(3, "Wrap envelope X transform", true, m_envelope->m_transform_wrap_x);
|
|
|
|
menu.addItem(4, "Envelope Y random linear interpolation", true, m_envelope->m_transform_y_random_linear_interpolation);
|
|
|
|
#if JUCE_IOS
|
|
|
|
opts = opts.withStandardItemHeight(34);
|
|
|
|
#endif
|
|
|
|
auto callback = [this] (int r) {
|
|
|
|
if (r == 1)
|
|
|
|
{
|
|
|
|
ScopedLock locker(*m_cs);
|
|
|
|
m_envelope->ResetEnvelope();
|
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
else if (r == 2)
|
2022-04-14 07:26:26 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < m_envelope->GetNumPoints(); ++i)
|
2022-04-02 16:45:02 +00:00
|
|
|
{
|
2022-04-14 07:26:26 +00:00
|
|
|
double val = 1.0 - m_envelope->GetNodeAtIndex(i).pt_y;
|
|
|
|
m_envelope->GetNodeAtIndex(i).pt_y = val;
|
2022-04-02 16:45:02 +00:00
|
|
|
}
|
2022-04-11 17:23:10 +00:00
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
else if (r == 3)
|
2022-04-14 07:26:26 +00:00
|
|
|
{
|
|
|
|
toggleBool(m_envelope->m_transform_wrap_x);
|
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
else if (r == 4)
|
2022-04-14 07:26:26 +00:00
|
|
|
{
|
|
|
|
toggleBool(m_envelope->m_transform_y_random_linear_interpolation);
|
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
else if (r == 5)
|
|
|
|
{
|
|
|
|
deleteSelectedNodes();
|
|
|
|
}
|
2022-04-14 07:26:26 +00:00
|
|
|
repaint();
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!JUCEApplicationBase::isStandaloneApp()) {
|
|
|
|
opts = opts.withParentComponent(this);
|
|
|
|
}
|
2022-04-11 17:23:10 +00:00
|
|
|
|
|
|
|
|
2022-04-14 07:26:26 +00:00
|
|
|
menu.showMenuAsync(opts, callback);
|
|
|
|
}
|
2022-04-02 16:45:02 +00:00
|
|
|
|
2022-04-14 07:26:26 +00:00
|
|
|
void EnvelopeComponent::mouseDown(const MouseEvent & ev)
|
|
|
|
{
|
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return;
|
|
|
|
if (ev.mods.isRightButtonDown() == true)
|
|
|
|
{
|
|
|
|
showPopupMenu();
|
2022-04-02 16:45:02 +00:00
|
|
|
return;
|
2018-02-26 23:59:22 +00:00
|
|
|
}
|
|
|
|
m_node_to_drag = find_hot_envelope_point(ev.x, ev.y);
|
2022-04-18 19:11:22 +00:00
|
|
|
m_touch_offset = {0, 0};
|
2018-02-26 23:59:22 +00:00
|
|
|
m_mouse_down = true;
|
|
|
|
m_segment_drag_info = { findHotEnvelopeSegment(ev.x, ev.y, true),false };
|
|
|
|
if (m_segment_drag_info.first >= 0)
|
|
|
|
{
|
|
|
|
m_envelope->beginRelativeTransformation();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_node_to_drag >= 0 && ev.mods.isAltDown() == true)
|
|
|
|
{
|
2018-10-17 10:14:07 +00:00
|
|
|
if (m_envelope->GetNumPoints() < 2)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
|
|
|
m_bubble.showAt({ ev.x,ev.y, 0,0 }, AttributedString("Can't remove last node"), 3000, false, false);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-27 13:21:36 +00:00
|
|
|
m_cs->enter();
|
2018-02-26 23:59:22 +00:00
|
|
|
m_envelope->DeleteNode(m_node_to_drag);
|
2018-02-27 13:21:36 +00:00
|
|
|
m_cs->exit();
|
2018-02-28 16:34:34 +00:00
|
|
|
m_envelope->updateMinMaxValues();
|
2018-02-26 23:59:22 +00:00
|
|
|
m_node_to_drag = -1;
|
|
|
|
OnEnvelopeEdited(m_envelope.get());
|
|
|
|
repaint();
|
|
|
|
return;
|
|
|
|
}
|
2022-04-18 19:11:22 +00:00
|
|
|
if (m_node_to_drag >= 0)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
const envelope_point& pt = m_envelope->GetNodeAtIndex(m_node_to_drag);
|
|
|
|
double xcor = jmap(pt.pt_x, m_view_start_time, m_view_end_time, 0.0, (double)getWidth());
|
|
|
|
double ycor = (double)getHeight() - jmap(pt.pt_y, m_view_start_value, m_view_end_value, 0.0, (double)getHeight());
|
|
|
|
m_touch_offset = { ev.x - (int)xcor , ev.y - (int)ycor };
|
|
|
|
|
|
|
|
if (!ev.mods.isShiftDown()) {
|
|
|
|
m_envelope->SetNodeStatusForAll(0);
|
|
|
|
}
|
|
|
|
int oldstatus = m_envelope->GetNodeAtIndex(m_node_to_drag).Status;
|
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
if (oldstatus==0)
|
|
|
|
m_envelope->GetNodeAtIndex(m_node_to_drag).Status=1;
|
|
|
|
else m_envelope->GetNodeAtIndex(m_node_to_drag).Status=0;
|
|
|
|
repaint();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_node_to_drag == -1)
|
|
|
|
{
|
|
|
|
double normx = jmap((double)ev.x, 0.0, (double)getWidth(), m_view_start_time, m_view_end_time);
|
|
|
|
double normy = jmap((double)getHeight() - ev.y, 0.0, (double)getHeight(), m_view_start_value, m_view_end_value);
|
2018-02-27 13:21:36 +00:00
|
|
|
m_cs->enter();
|
2018-02-26 23:59:22 +00:00
|
|
|
m_envelope->AddNode ({ normx,normy, 0.5});
|
|
|
|
m_envelope->SortNodes();
|
2018-02-27 13:21:36 +00:00
|
|
|
m_cs->exit();
|
2018-02-28 16:34:34 +00:00
|
|
|
m_envelope->updateMinMaxValues();
|
2022-04-14 07:26:26 +00:00
|
|
|
|
|
|
|
m_node_to_drag = find_hot_envelope_point(ev.x, ev.y);
|
2022-04-18 19:11:22 +00:00
|
|
|
// deselect all
|
|
|
|
m_envelope->SetNodeStatusForAll(0);
|
|
|
|
m_envelope->GetNodeAtIndex(m_node_to_drag).Status=1; // select it
|
|
|
|
|
2022-04-14 07:26:26 +00:00
|
|
|
//m_mouse_down = false;
|
2018-02-26 23:59:22 +00:00
|
|
|
OnEnvelopeEdited(m_envelope.get());
|
|
|
|
repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnvelopeComponent::mouseUp(const MouseEvent &ev)
|
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
#if JUCE_IOS
|
|
|
|
m_bubble.setVisible(false);
|
|
|
|
#endif
|
|
|
|
if (ev.mods == ModifierKeys::noModifiers) {
|
|
|
|
m_bubble.setVisible(false);
|
|
|
|
}
|
2018-02-26 23:59:22 +00:00
|
|
|
if (m_node_that_was_dragged >= 0 || m_segment_drag_info.second==true)
|
|
|
|
{
|
|
|
|
OnEnvelopeEdited(m_envelope.get());
|
|
|
|
}
|
|
|
|
m_mouse_down = false;
|
|
|
|
m_node_that_was_dragged = -1;
|
|
|
|
m_node_to_drag = -1;
|
|
|
|
if (m_segment_drag_info.second == true)
|
|
|
|
{
|
|
|
|
m_segment_drag_info = { -1,false };
|
|
|
|
m_envelope->endRelativeTransformation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-18 19:11:22 +00:00
|
|
|
void EnvelopeComponent::deleteSelectedNodes()
|
|
|
|
{
|
|
|
|
m_node_to_drag = -1;
|
|
|
|
{
|
|
|
|
ScopedLock locker(*m_cs);
|
|
|
|
m_envelope->removePointsConditionally([](const envelope_point& pt) { return pt.Status == 1; });
|
|
|
|
if (m_envelope->GetNumPoints() == 0)
|
|
|
|
m_envelope->AddNode({ 0.0,0.5 });
|
|
|
|
}
|
|
|
|
OnEnvelopeEdited(m_envelope.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
bool EnvelopeComponent::keyPressed(const KeyPress & ev)
|
|
|
|
{
|
2018-02-27 22:05:35 +00:00
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return false;
|
2018-02-27 23:16:30 +00:00
|
|
|
auto f = [this](auto& env_var, double amt)
|
|
|
|
{
|
|
|
|
env_var+=amt;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
bool r = false;
|
|
|
|
if (ev == 'Q')
|
|
|
|
r = f(m_envelope->m_transform_x_shift,-0.01);
|
|
|
|
if (ev == 'W')
|
|
|
|
r = f(m_envelope->m_transform_x_shift,0.01);
|
2018-02-27 22:05:35 +00:00
|
|
|
if (ev == 'E')
|
2018-02-27 23:16:30 +00:00
|
|
|
r = f(m_envelope->m_transform_y_shift,0.01);
|
2018-02-27 22:05:35 +00:00
|
|
|
if (ev == 'D')
|
2018-02-27 23:16:30 +00:00
|
|
|
r = f(m_envelope->m_transform_y_shift,-0.01);
|
2018-02-27 22:32:18 +00:00
|
|
|
if (ev == 'R')
|
2018-02-27 23:16:30 +00:00
|
|
|
r = f(m_envelope->m_transform_y_scale,0.05);
|
2018-02-27 22:32:18 +00:00
|
|
|
if (ev == 'F')
|
2018-02-27 23:16:30 +00:00
|
|
|
r = f(m_envelope->m_transform_y_scale,-0.05);
|
2018-02-28 00:14:27 +00:00
|
|
|
if (ev == 'T')
|
|
|
|
r = f(m_envelope->m_transform_y_sinus,0.01);
|
|
|
|
if (ev == 'G')
|
|
|
|
r = f(m_envelope->m_transform_y_sinus,-0.01);
|
2018-02-28 03:38:19 +00:00
|
|
|
if (ev == 'Y')
|
|
|
|
r = f(m_envelope->m_transform_y_tilt,0.02);
|
|
|
|
if (ev == 'H')
|
|
|
|
r = f(m_envelope->m_transform_y_tilt,-0.02);
|
2018-02-28 03:58:22 +00:00
|
|
|
if (ev == 'V')
|
|
|
|
r = f(m_envelope->m_transform_y_sinus_freq,1.0);
|
|
|
|
if (ev == 'B')
|
|
|
|
r = f(m_envelope->m_transform_y_sinus_freq,-1.0);
|
|
|
|
m_envelope->m_transform_y_sinus_freq = jlimit(1.0,64.0, m_envelope->m_transform_y_sinus_freq);
|
2018-02-28 03:38:19 +00:00
|
|
|
if (r==true)
|
2018-02-27 23:16:30 +00:00
|
|
|
{
|
|
|
|
repaint();
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-28 12:20:26 +00:00
|
|
|
if (ev == 'A')
|
|
|
|
{
|
|
|
|
m_envelope->m_transform_x_shift = 0.0;
|
|
|
|
m_envelope->m_transform_y_scale = 1.0;
|
|
|
|
m_envelope->m_transform_y_shift = 0.0;
|
|
|
|
m_envelope->m_transform_y_sinus = 0.0;
|
|
|
|
repaint();
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-27 22:05:35 +00:00
|
|
|
|
|
|
|
if (ev == KeyPress::deleteKey)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
deleteSelectedNodes();
|
|
|
|
repaint();
|
2018-02-26 23:59:22 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EnvelopeComponent::find_hot_envelope_point(double xcor, double ycor)
|
|
|
|
{
|
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return -1;
|
2018-10-17 10:14:07 +00:00
|
|
|
for (int i = 0; i < m_envelope->GetNumPoints(); ++i)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
const envelope_point& pt = m_envelope->GetNodeAtIndex(i);
|
|
|
|
double ptxcor = jmap(pt.pt_x, m_view_start_time, m_view_end_time, 0.0, (double)getWidth());
|
|
|
|
double ptycor = (double)getHeight() - jmap(pt.pt_y, m_view_start_value, m_view_end_value, 0.0, (double)getHeight());
|
2022-04-18 19:11:22 +00:00
|
|
|
float targsize = 10.0;
|
2022-04-12 22:47:43 +00:00
|
|
|
#if JUCE_IOS
|
2022-04-14 07:26:26 +00:00
|
|
|
targsize = 20;
|
2022-04-12 22:47:43 +00:00
|
|
|
#endif
|
|
|
|
juce::Rectangle<double> target(ptxcor - targsize*0.5f, ptycor - targsize*0.5, targsize, targsize);
|
2018-02-26 23:59:22 +00:00
|
|
|
if (target.contains(xcor, ycor) == true)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EnvelopeComponent::findHotEnvelopeSegment(double xcor, double ycor, bool detectsegment)
|
|
|
|
{
|
2022-04-18 19:11:22 +00:00
|
|
|
float targsize = 10.0;
|
2022-04-12 22:47:43 +00:00
|
|
|
#if JUCE_IOS
|
2022-04-14 07:26:26 +00:00
|
|
|
targsize = 20.0;
|
2022-04-12 22:47:43 +00:00
|
|
|
#endif
|
|
|
|
|
2018-02-26 23:59:22 +00:00
|
|
|
if (m_envelope == nullptr)
|
|
|
|
return -1;
|
2018-10-17 10:14:07 +00:00
|
|
|
for (int i = 0; i < m_envelope->GetNumPoints()-1; ++i)
|
2018-02-26 23:59:22 +00:00
|
|
|
{
|
2018-10-17 10:06:07 +00:00
|
|
|
const envelope_point& pt0 = m_envelope->GetNodeAtIndex(i);
|
|
|
|
const envelope_point& pt1 = m_envelope->GetNodeAtIndex(i+1);
|
|
|
|
float xcor0 = (float)jmap<double>(pt0.pt_x, m_view_start_time, m_view_end_time, 0.0, getWidth());
|
|
|
|
float xcor1 = (float)jmap<double>(pt1.pt_x, m_view_start_time, m_view_end_time, 0.0, getWidth());
|
2018-02-26 23:59:22 +00:00
|
|
|
float segwidth = xcor1 - xcor0;
|
2022-04-18 19:11:22 +00:00
|
|
|
juce::Rectangle<float> segrect(xcor0+targsize, 0.0f, segwidth-2*targsize, (float)getHeight());
|
2018-02-26 23:59:22 +00:00
|
|
|
if (segrect.contains((float)xcor, (float)ycor))
|
|
|
|
{
|
|
|
|
if (detectsegment == false)
|
|
|
|
return i;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double normx = jmap<double>(xcor, 0.0, getWidth(), m_view_start_time, m_view_end_time);
|
2018-10-17 10:14:07 +00:00
|
|
|
double yval = m_envelope->GetInterpolatedEnvelopeValue(normx);
|
2018-02-26 23:59:22 +00:00
|
|
|
float ycor0 = (float)(getHeight()-jmap<double>(yval, 0.0, 1.0, 0.0, getHeight()));
|
2018-02-28 14:01:16 +00:00
|
|
|
juce::Rectangle<float> segrect2((float)(xcor - 20), (float)(ycor - 10), 40, 20);
|
2018-02-26 23:59:22 +00:00
|
|
|
if (segrect2.contains((float)xcor, ycor0))
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|