2 Commits 1534e90a39 ... e880e3cb2a

Author SHA1 Message Date
  IanCaio e880e3cb2a Changes AutomationPattern to use nodes instead of raw float values (#5712) 3 years ago
  cyber-bridge 05de59c085 Feature: PianoRoll Knife (#5845) 3 years ago

BIN
data/themes/classic/edit_draw_outvalue.png


BIN
data/themes/classic/edit_knife.png


+ 3 - 1
data/themes/classic/style.css

@@ -20,7 +20,8 @@ AutomationEditor {
 	background-color: rgb(0, 0, 0);
 	color: #e0e0e0;
 	qproperty-backgroundShade: rgba(255, 255, 255, 15);
-	qproperty-vertexColor: #ff77af;
+	qproperty-nodeInValueColor: rgba(255, 119, 175, 150);
+	qproperty-nodeOutValueColor: rgba(129, 231, 181, 150);
 	qproperty-crossColor: rgb( 255, 51, 51 );
 	/* Grid colors */
 	qproperty-lineColor: rgba(128, 128, 128, 80);
@@ -155,6 +156,7 @@ PianoRoll {
 	qproperty-ghostNoteBorders: true;
 	qproperty-barColor: #4afd85;
 	qproperty-markedSemitoneColor: rgba( 0, 255, 200, 60 );
+	qproperty-knifeCutLine: rgba(255, 0, 0, 255);
 	/* Piano keys */
 	qproperty-whiteKeyWidth: 64;
 	qproperty-whiteKeyActiveTextColor: #000;

BIN
data/themes/default/edit_draw_outvalue.png


BIN
data/themes/default/edit_knife.png


+ 3 - 1
data/themes/default/style.css

@@ -55,7 +55,8 @@ AutomationEditor {
 	color: #ffffff;
 	background-color: #141616;
 	qproperty-backgroundShade: rgba(255, 255, 255, 15);
-	qproperty-vertexColor: #6749C2;
+	qproperty-nodeInValueColor: rgba(103, 73, 194, 150);
+	qproperty-nodeOutValueColor: rgba(125, 40, 40, 150);
 	qproperty-crossColor: rgba(215, 210, 254, 150);
 	/* Grid colors */
 	qproperty-lineColor: #292929;
@@ -187,6 +188,7 @@ PianoRoll {
 	qproperty-ghostNoteBorders: false;
 	qproperty-barColor: #078f3a;
 	qproperty-markedSemitoneColor: rgba(255, 255, 255, 30);
+	qproperty-knifeCutLine: rgba(255, 0, 0, 255);
 	/* Piano keys */
 	qproperty-whiteKeyWidth: 64;
 	qproperty-whiteKeyActiveTextColor: #000;

+ 22 - 54
include/AutomationEditor.h

@@ -26,7 +26,6 @@
 #ifndef AUTOMATION_EDITOR_H
 #define AUTOMATION_EDITOR_H
 
-#include <QtCore/QMutex>
 #include <QVector>
 #include <QWidget>
 
@@ -52,14 +51,15 @@ class TimeLineWidget;
 class AutomationEditor : public QWidget, public JournallingObject
 {
 	Q_OBJECT
-	Q_PROPERTY(QColor barLineColor READ barLineColor WRITE setBarLineColor)
-	Q_PROPERTY(QColor beatLineColor READ beatLineColor WRITE setBeatLineColor)
-	Q_PROPERTY(QColor lineColor READ lineColor WRITE setLineColor)
-	Q_PROPERTY(QColor vertexColor READ vertexColor WRITE setVertexColor)
-	Q_PROPERTY(QBrush scaleColor READ scaleColor WRITE setScaleColor)
-	Q_PROPERTY(QBrush graphColor READ graphColor WRITE setGraphColor)
-	Q_PROPERTY(QColor crossColor READ crossColor WRITE setCrossColor)
-	Q_PROPERTY(QColor backgroundShade READ backgroundShade WRITE setBackgroundShade)
+	Q_PROPERTY(QColor barLineColor MEMBER m_barLineColor)
+	Q_PROPERTY(QColor beatLineColor MEMBER m_beatLineColor)
+	Q_PROPERTY(QColor lineColor MEMBER m_lineColor)
+	Q_PROPERTY(QColor nodeInValueColor MEMBER m_nodeInValueColor)
+	Q_PROPERTY(QColor nodeOutValueColor MEMBER m_nodeOutValueColor)
+	Q_PROPERTY(QBrush scaleColor MEMBER m_scaleColor)
+	Q_PROPERTY(QBrush graphColor MEMBER m_graphColor)
+	Q_PROPERTY(QColor crossColor MEMBER m_crossColor)
+	Q_PROPERTY(QColor backgroundShade MEMBER m_backgroundShade)
 public:
 	void setCurrentPattern(AutomationPattern * new_pattern);
 
@@ -80,30 +80,11 @@ public:
 		return "automationeditor";
 	}
 
-	// qproperty access methods
-	QColor barLineColor() const;
-	void setBarLineColor(const QColor & c);
-	QColor beatLineColor() const;
-	void setBeatLineColor(const QColor & c);
-	QColor lineColor() const;
-	void setLineColor(const QColor & c);
-	QBrush graphColor() const;
-	void setGraphColor(const QBrush & c);
-	QColor vertexColor() const;
-	void setVertexColor(const QColor & c);
-	QBrush scaleColor() const;
-	void setScaleColor(const QBrush & c);
-	QColor crossColor() const;
-	void setCrossColor(const QColor & c);
-	QColor backgroundShade() const;
-	void setBackgroundShade(const QColor & c);
-
 	enum EditModes
 	{
 		DRAW,
 		ERASE,
-		SELECT,
-		MOVE
+		DRAW_OUTVALUES
 	};
 
 public slots:
@@ -126,13 +107,11 @@ protected:
 	float getLevel( int y );
 	int xCoordOfTick( int tick );
 	float yCoordOfLevel( float level );
-	inline void drawLevelTick( QPainter & p, int tick, float value);// bool is_selected ); //NEEDS Change in CSS
-	void removeSelection();
-	void selectAll();
-	void getSelectedValues(timeMap & selected_values );
+	inline void drawLevelTick(QPainter & p, int tick, float value);
+
+	timeMap::iterator getNodeAt(int x, int y, bool outValue = false, int r = 5);
 
 	void drawLine( int x0, float y0, int x1, float y1 );
-	void removePoints( int x0, int x1 );
 
 protected slots:
 	void play();
@@ -148,11 +127,6 @@ protected slots:
 	void setProgressionType(int type);
 	void setTension();
 
-	void copySelectedValues();
-	void cutSelectedValues();
-	void pasteValues();
-	void deleteSelectedValues();
-
 	void updatePosition( const TimePos & t );
 
 	void zoomingXChanged();
@@ -167,8 +141,10 @@ private:
 	{
 		NONE,
 		MOVE_VALUE,
-		SELECT_VALUES,
-		MOVE_SELECTION
+		ERASE_VALUES,
+		MOVE_OUTVALUE,
+		RESET_OUTVALUES,
+		DRAW_LINE
 	} ;
 
 	// some constants...
@@ -187,7 +163,7 @@ private:
 
 	static QPixmap * s_toolDraw;
 	static QPixmap * s_toolErase;
-	static QPixmap * s_toolSelect;
+	static QPixmap * s_toolDrawOut;
 	static QPixmap * s_toolMove;
 	static QPixmap * s_toolYFlip;
 	static QPixmap * s_toolXFlip;
@@ -200,7 +176,6 @@ private:
 
 	FloatModel * m_tensionModel;
 
-	QMutex m_patternMutex;
 	AutomationPattern * m_pattern;
 	float m_minLevel;
 	float m_maxLevel;
@@ -219,13 +194,6 @@ private:
 
 	Actions m_action;
 
-	tick_t m_selectStartTick;
-	tick_t m_selectedTick;
-	float m_selectStartLevel;
-	float m_selectedLevels;
-
-	float m_moveStartLevel;
-	tick_t m_moveStartTick;
 	int m_moveXOffset;
 
 	float m_drawLastLevel;
@@ -235,9 +203,8 @@ private:
 	int m_y_delta;
 	bool m_y_auto;
 
-	timeMap m_valuesToCopy;
-	timeMap m_selValuesForMove;
-
+	// Time position (key) of automation node whose outValue is being dragged
+	int m_draggedOutValueKey;
 
 	EditModes m_editMode;
 
@@ -255,7 +222,8 @@ private:
 	QColor m_beatLineColor;
 	QColor m_lineColor;
 	QBrush m_graphColor;
-	QColor m_vertexColor;
+	QColor m_nodeInValueColor;
+	QColor m_nodeOutValueColor;
 	QBrush m_scaleColor;
 	QColor m_crossColor;
 	QColor m_backgroundShade;

+ 153 - 0
include/AutomationNode.h

@@ -0,0 +1,153 @@
+/*
+ * AutomationNode.h - Declaration of class AutomationNode, which contains
+ *                       all information about an automation node
+ *
+ * Copyright (c) 2020 Ian Caio <iancaio_dev/at/hotmail.com>
+ *
+ * This file is part of LMMS - https://lmms.io
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program (see COPYING); if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef AUTOMATION_NODE_H
+#define AUTOMATION_NODE_H
+
+// MACROs to help handling automation nodes
+#define INVAL(x) ((x).value().getInValue())
+#define OUTVAL(x) ((x).value().getOutValue())
+#define OFFSET(x) ((x).value().getValueOffset())
+#define INTAN(x) ((x).value().getInTangent())
+#define OUTTAN(x) ((x).value().getOutTangent())
+#define POS(x) ((x).key())
+
+class AutomationPattern;
+
+
+// Note: We use the default copy-assignment on the AutomationPattern constructor. It's
+// fine for now as we don't have dynamic allocated members, but if any are added we should
+// have an user-defined one to perform a deep-copy.
+class AutomationNode
+{
+public:
+	AutomationNode(); // Dummy constructor for the QMap
+	AutomationNode(AutomationPattern* pat, float value, int pos);
+	AutomationNode(AutomationPattern* pat, float inValue, float outValue, int pos);
+
+	AutomationNode& operator+=(float f)
+	{
+		m_inValue += f;
+		m_outValue += f;
+		return *this;
+	}
+	AutomationNode& operator-=(float f)
+	{
+		m_inValue -= f;
+		m_outValue -= f;
+		return *this;
+	}
+	AutomationNode& operator*=(float f)
+	{
+		m_inValue *= f;
+		m_outValue *= f;
+		return *this;
+	}
+	AutomationNode& operator/=(float f)
+	{
+		m_inValue /= f;
+		m_outValue /= f;
+		return *this;
+	}
+
+	inline const float getInValue() const
+	{
+		return m_inValue;
+	}
+	void setInValue(float value);
+
+	inline const float getOutValue() const
+	{
+		return m_outValue;
+	}
+	void setOutValue(float value);
+	void resetOutValue();
+
+	/**
+	 * @brief Gets the offset between inValue and outValue
+	 * @return Float representing the offset between inValue and outValue
+	 */
+	inline const float getValueOffset() const
+	{
+		return m_outValue - m_inValue;
+	}
+
+	/**
+	 * @brief Gets the tangent of the left side of the node
+	 * @return Float with the tangent from the inValue side
+	 */
+	inline const float getInTangent() const
+	{
+		return m_inTangent;
+	}
+
+	/**
+	 * @brief Sets the tangent of the left side of the node
+	 * @param Float with the tangent for the inValue side
+	 */
+	inline void setInTangent(float tangent)
+	{
+		m_inTangent = tangent;
+	}
+
+	/**
+	 * @brief Gets the tangent of the right side of the node
+	 * @return Float with the tangent from the outValue side
+	 */
+	inline const float getOutTangent() const
+	{
+		return m_outTangent;
+	}
+
+	/**
+	 * @brief Sets the tangent of the right side of the node
+	 * @param Float with the tangent for the outValue side
+	 */
+	inline void setOutTangent(float tangent)
+	{
+		m_outTangent = tangent;
+	}
+
+private:
+	// Pattern that this node belongs to
+	AutomationPattern* m_pattern;
+
+	// Time position of this node (matches the timeMap key)
+	int m_pos;
+
+	// Values of this node
+	float m_inValue;
+	float m_outValue;
+
+	// Slope at each point for calculating spline
+	// We might have discrete jumps between curves, so we possibly have
+	// two different tangents for each side of the curve. If inValue and
+	// outValue are equal, inTangent and outTangent are equal too.
+	float m_inTangent;
+	float m_outTangent;
+};
+
+
+#endif

+ 30 - 20
include/AutomationPattern.h

@@ -30,6 +30,7 @@
 #include <QtCore/QMap>
 #include <QtCore/QPointer>
 
+#include "AutomationNode.h"
 #include "TrackContentObject.h"
 
 
@@ -49,8 +50,8 @@ public:
 		CubicHermiteProgression
 	} ;
 
-	typedef QMap<int, float> timeMap;
-	typedef QVector<QPointer<AutomatableModel> > objectVector;
+	typedef QMap<int, AutomationNode> timeMap;
+	typedef QVector<QPointer<AutomatableModel>> objectVector;
 
 	AutomationPattern( AutomationTrack * _auto_track );
 	AutomationPattern( const AutomationPattern & _pat_to_copy );
@@ -77,12 +78,25 @@ public:
 	TimePos timeMapLength() const;
 	void updateLength();
 
-	TimePos putValue( const TimePos & time,
-				const float value,
-				const bool quantPos = true,
-				const bool ignoreSurroundingPoints = true );
+	TimePos putValue(
+		const TimePos & time,
+		const float value,
+		const bool quantPos = true,
+		const bool ignoreSurroundingPoints = true
+	);
+
+	TimePos putValues(
+		const TimePos & time,
+		const float inValue,
+		const float outValue,
+		const bool quantPos = true,
+		const bool ignoreSurroundingPoints = true
+	);
 
-	void removeValue( const TimePos & time );
+	void removeNode(const TimePos & time);
+	void removeNodes(const int tick0, const int tick1);
+
+	void resetNodes(const int tick0, const int tick1);
 
 	void recordValue(TimePos time, float value);
 
@@ -109,16 +123,6 @@ public:
 		return m_timeMap;
 	}
 
-	inline const timeMap & getTangents() const
-	{
-		return m_tangents;
-	}
-
-	inline timeMap & getTangents()
-	{
-		return m_tangents;
-	}
-
 	inline float getMin() const
 	{
 		return firstObject()->minValue<float>();
@@ -170,21 +174,26 @@ public slots:
 private:
 	void cleanObjects();
 	void generateTangents();
-	void generateTangents( timeMap::const_iterator it, int numToGenerate );
+	void generateTangents(timeMap::iterator it, int numToGenerate);
 	float valueAt( timeMap::const_iterator v, int offset ) const;
 
+	// Mutex to make methods involving automation patterns thread safe
+	// Mutable so we can lock it from const objects
+	mutable QMutex m_patternMutex;
+
 	AutomationTrack * m_autoTrack;
 	QVector<jo_id_t> m_idsToResolve;
 	objectVector m_objects;
 	timeMap m_timeMap;	// actual values
 	timeMap m_oldTimeMap;	// old values for storing the values before setDragValue() is called.
-	timeMap m_tangents;	// slope at each point for calculating spline
 	float m_tension;
 	bool m_hasAutomation;
 	ProgressionTypes m_progressionType;
 
 	bool m_dragging;
-	
+	bool m_dragKeepOutValue; // Should we keep the current dragged node's outValue?
+	float m_dragOutValue; // The outValue of the dragged node's
+
 	bool m_isRecording;
 	float m_lastRecordedValue;
 
@@ -194,6 +203,7 @@ private:
 	static const float DEFAULT_MAX_VALUE;
 
 	friend class AutomationPatternView;
+	friend class AutomationNode;
 
 } ;
 

+ 0 - 0
include/DataFile.h


Some files were not shown because too many files changed in this diff