Skip to content

Commit

Permalink
add measure/line breaks
Browse files Browse the repository at this point in the history
  • Loading branch information
hlorenzi committed May 15, 2017
1 parent 6f3fb0c commit 296bee8
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 5 deletions.
17 changes: 17 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,22 @@
<button class="toolboxButton" onClick="handleButtonInsertMeterChange();">Insert</button>
</td>
</tr>
<tr>
<td>
<span class="toolboxLabel">Measure Break:</span>
</td>
<td>
<button class="toolboxButton" onClick="handleButtonInsertMeasureBreak();">Insert</button>
</td>
</tr>
<tr>
<td>
<span class="toolboxLabel">Line Break:</span>
</td>
<td>
<button class="toolboxButton" onClick="handleButtonInsertLineBreak();">Insert</button>
</td>
</tr>
</table>
</td>

Expand Down Expand Up @@ -200,6 +216,7 @@
<script src="src/song/chord.js"></script>
<script src="src/song/meter.js"></script>
<script src="src/song/key.js"></script>
<script src="src/song/measurebreak.js"></script>

<script src="src/editor/editor.js"></script>
<script src="src/editor/editor_interaction.js"></script>
Expand Down
86 changes: 83 additions & 3 deletions src/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,30 @@ Editor.prototype.insertMeterChange = function(numerator, denominator)
}


Editor.prototype.insertMeasureBreak = function()
{
this.selectNone();
this.eraseForcedMeasuresAt(this.cursorTick1, this.cursorTick1);
this.song.forcedMeasures.insert(
new SongMeasureBreak(this.cursorTick1.clone(), false, { selected: true }));
this.cursorSetTickBoth(this.cursorTick1.clone().min(this.cursorTick2));
this.refresh();
this.setUnsavedChanges(true);
}


Editor.prototype.insertLineBreak = function()
{
this.selectNone();
this.eraseForcedMeasuresAt(this.cursorTick1, this.cursorTick1);
this.song.forcedMeasures.insert(
new SongMeasureBreak(this.cursorTick1.clone(), true, { selected: true }));
this.cursorSetTickBoth(this.cursorTick1.clone().min(this.cursorTick2));
this.refresh();
this.setUnsavedChanges(true);
}


Editor.prototype.updateSvgCursor = function(node, visible, tick, track1, track2)
{
if (!visible)
Expand Down Expand Up @@ -554,7 +578,10 @@ Editor.prototype.refreshRow = function(rowTickStart, rowYStart)
var currentBlockStart = rowTickStart.clone();
var currentKeyChange = this.song.keyChanges.findPrevious(rowTickStart);
var currentMeterChange = this.song.meterChanges.findPrevious(rowTickStart);
var currentForcedMeasure = this.song.forcedMeasures.findPrevious(rowTickStart);
var currentMeasureStart = currentMeterChange.tick.clone();
if (currentForcedMeasure != null)
currentMeasureStart.max(currentForcedMeasure.tick);

// Also find the lowest and highest pitch rows for notes in this row.
var pitchRowMin = Theory.getPitchRow({ scaleIndex: 0, tonicMidiPitch: 0, accidentalOffset: 0 }, 12 * 5, that.usePopularNotation);
Expand All @@ -574,13 +601,17 @@ Editor.prototype.refreshRow = function(rowTickStart, rowYStart)

var nextKeyChange = this.song.keyChanges.findNext(currentBlockStart);
var nextMeterChange = this.song.meterChanges.findNext(currentBlockStart);
var nextForcedMeasure = this.song.forcedMeasures.findNext(currentBlockStart);

if (nextKeyChange != null && nextKeyChange.tick.compare(nextBlockEnd) < 0)
nextBlockEnd = nextKeyChange.tick.clone();

if (nextMeterChange != null && nextMeterChange.tick.compare(nextBlockEnd) < 0)
nextBlockEnd = nextMeterChange.tick.clone();

if (nextForcedMeasure != null && nextForcedMeasure.tick.compare(nextBlockEnd) < 0)
nextBlockEnd = nextForcedMeasure.tick.clone();

if (this.song.length.compare(nextBlockEnd) < 0)
nextBlockEnd = this.song.length.clone();

Expand All @@ -596,12 +627,13 @@ Editor.prototype.refreshRow = function(rowTickStart, rowYStart)
{
tickStart: currentBlockStart.clone(),
tickEnd: nextBlockEnd.clone(),
measureStartTick: currentMeterChange.tick.clone(),
measureStartTick: currentMeasureStart,
x: x + scaleLabelsOffset,
y: rowYStart,
width: width,
key: currentKeyChange,
meter: currentMeterChange,
forcedMeasure: nextForcedMeasure,
drawScaleLabels: drawScaleLabels
};

Expand All @@ -628,6 +660,19 @@ Editor.prototype.refreshRow = function(rowTickStart, rowYStart)
currentMeasureStart = currentMeterChange.tick.clone();
}

if (nextForcedMeasure != null && nextForcedMeasure.tick.compare(nextBlockEnd) == 0)
{
currentForcedMeasure = nextForcedMeasure;
currentMeasureStart = currentForcedMeasure.tick.clone();

if (nextForcedMeasure.isLineBreak)
break;
}

currentMeasureStart = currentMeterChange.tick.clone();
if (currentForcedMeasure != null)
currentMeasureStart.max(currentForcedMeasure.tick);

if (this.song.length.compare(nextBlockEnd) == 0)
break;
}
Expand Down Expand Up @@ -687,7 +732,7 @@ Editor.prototype.refreshBlock = function(
rowHasKeyChange, rowHasMeterChange)
{
var that = this;

// Add block layout to master list.
// This is used for mouse interaction.
block.elements = [];
Expand All @@ -698,7 +743,10 @@ Editor.prototype.refreshBlock = function(
block.trackMeterChangeYStart = block.trackKeyChangeYEnd;
block.trackMeterChangeYEnd = block.trackMeterChangeYStart + (rowHasMeterChange ? 20 : 0);

block.trackNoteYStart = block.trackMeterChangeYEnd;
block.trackForcedMeasureYStart = block.trackMeterChangeYEnd;
block.trackForcedMeasureYEnd = block.trackForcedMeasureYStart;

block.trackNoteYStart = block.trackForcedMeasureYEnd;
block.trackNoteYEnd = block.trackNoteYStart + (pitchRowMax + 1 - pitchRowMin) * this.noteHeight;

block.trackChordYStart = block.trackNoteYEnd;
Expand Down Expand Up @@ -1108,6 +1156,38 @@ Editor.prototype.refreshBlock = function(
});
}

// Render forced measure.
if (block.forcedMeasure != null &&
block.forcedMeasure.tick.compare(block.tickEnd) == 0)
{
this.addSvgNode("editorForcedMeasureLine", "line",
{
x1: block.x + block.width,
y1: block.y + (block.trackForcedMeasureYStart + block.trackForcedMeasureYEnd) / 2,
x2: block.x + block.width,
y2: block.y + block.trackChordYEnd
});

this.addSvgNode(
"editorForcedMeasureHandle" + (block.forcedMeasure.editorData.selected ? "Selected" : ""),
"rect",
{
x: block.x + block.width - this.handleSize / 2,
y: block.y + (block.trackForcedMeasureYStart + block.trackForcedMeasureYEnd) / 2 - 1 - this.handleSize,
width: this.handleSize,
height: this.handleSize
});

block.elements.push(
{
forcedMeasure: block.forcedMeasure,
x: block.x + block.width - this.handleSize,
y: block.y + (block.trackForcedMeasureYStart + block.trackForcedMeasureYEnd) / 2 - 1 - this.handleSize,
width: this.handleSize * 2,
height: this.handleSize
});
}


return block;
}
Expand Down
12 changes: 12 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ function handleButtonInsertMeterChange()
}


function handleButtonInsertMeasureBreak()
{
g_Editor.insertMeasureBreak();
}


function handleButtonInsertLineBreak()
{
g_Editor.insertLineBreak();
}


function handleSelectChordKindsChange()
{
var selectedIndex = document.getElementById("selectChordKinds").selectedIndex;
Expand Down
14 changes: 14 additions & 0 deletions src/song/measurebreak.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function SongMeasureBreak(tick, isLineBreak, editorData = null)
{
this.tick = tick;
this.isLineBreak = isLineBreak;
this.editorData = editorData;
}


SongMeasureBreak.prototype.clone = function()
{
return new SongMeasureBreak(
this.tick.clone(),
this.isLineBreak);
}
57 changes: 55 additions & 2 deletions src/song/song.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function Song()
{
this.CURRENT_TEXT_VERSION = 1;
this.CURRENT_BINARY_VERSION = 1;
this.CURRENT_TEXT_VERSION = 2;
this.CURRENT_BINARY_VERSION = 2;

this.length = new Rational(4);

Expand Down Expand Up @@ -112,10 +112,14 @@ Song.prototype.feedSynth = function(synth, startTick, useChordPatterns = true)

var meter = that.meterChanges.findPrevious(chord.startTick);
var meterBeatLength = meter.getBeatLength();
var measureBreak = that.forcedMeasures.findPrevious(chord.startTick);

var pattern = Theory.getChordStrummingPattern(meter);

var tick = meter.tick.clone();
if (measureBreak != null)
tick.max(measureBreak.tick);

var skipTick = new Rational(0);
var patternIndex = 0;
var mustPlayFirstBeat = false;
Expand Down Expand Up @@ -298,6 +302,23 @@ Song.prototype.saveJSON = function()
json += "\n";
}

json += " ],\n";
json += " \"measureBreaks\": [\n";

for (var i = 0; i < this.forcedMeasures.items.length; i++)
{
var measureBreak = this.forcedMeasures.items[i];

json += " ";
json += "[ " + measureBreak.tick.toString() + ", ";
json += measureBreak.isLineBreak.toString() + " ]";

if (i < this.forcedMeasures.items.length - 1)
json += ",";

json += "\n";
}

json += " ]\n}";

return json;
Expand Down Expand Up @@ -370,6 +391,16 @@ Song.prototype.loadJSON = function(jsonStr)
song.meterChanges[i][2]));
}

if (song.version >= 2)
{
for (var i = 0; i < song.measureBreaks.length; i++)
{
this.forcedMeasures.insert(new SongMeasureBreak(
Rational.fromArray(song.measureBreaks[i][0]),
song.measureBreaks[i][1]));
}
}

this.setLengthAuto();
this.sanitize();
}
Expand Down Expand Up @@ -491,6 +522,16 @@ Song.prototype.saveBinary = function()
writer.writeInteger(meterCh.denominator);
}

// Write measure break data.
writer.writeInteger(this.forcedMeasures.items.length);
for (var i = 0; i < this.forcedMeasures.items.length; i++)
{
var measureBreak = this.forcedMeasures.items[i];

writer.writeRational(measureBreak.tick);
writer.writeInteger(measureBreak.isLineBreak ? 1 : 0);
}

// Compress data.
var data = writer.data;
data = pako.deflateRaw(data, { to: "string" });
Expand Down Expand Up @@ -651,6 +692,18 @@ Song.prototype.loadBinary = function(base64str)
reader.readInteger()));
}

// Read meter change data.
if (version >= 2)
{
var measureBreakNum = reader.readInteger();
for (var i = 0; i < measureBreakNum; i++)
{
this.forcedMeasures.insert(new SongMeasureBreak(
reader.readRational(),
reader.readInteger() == 1 ? true : false));
}
}

this.setLengthAuto();
this.sanitize();
}
19 changes: 19 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,25 @@ body
alignment-baseline: middle;
}

.editorForcedMeasureHandle
{
fill: #000;
stroke-width: 0px;
}

.editorForcedMeasureHandleSelected
{
stroke: #000;
stroke-width: 2px;
fill: #ddd;
}

.editorForcedMeasureLine
{
stroke: #000;
stroke-width: 2px;
}

.editorCursor
{
stroke: blue;
Expand Down

0 comments on commit 296bee8

Please sign in to comment.