Here's the fixed version:
waiting for feedbacks!
(Again and again: I write these snippets really in a hurry, in these days.
A more "structured" collaboration is getting necessary for me, at this
point)
Any Javascript volunteer?
On Tue, Dec 17, 2019 at 1:24 AM Paolo Prete <[email protected]> wrote:
> I'm just noting that there's a bug with more than one Beam. I'm fixing it.
> Have a bit of patience please ;-)
>
> On Mon, Dec 16, 2019 at 11:55 PM Paolo Prete <[email protected]> wrote:
>
>> Hello everybody,
>>
>> here is another snippet that uses the system that I previously
>> implemented. This time for the tuning of the beams.
>> This is too a very tedious operation to do with just the code and for
>> this I believe that this tool is also useful.
>> As you can see, the code is not only shorter than the previous one, but
>> it recycles the whole template of the previous snippet, which I'm making
>> more and more generic.
>> In short, the goal is to have Lilypond itself automatically create a GUI
>> tool for the tuning of the main properties of the grobs.
>>
>> This is somewhat crazy: Lilypond used as a factory for WYSIWYG editors!
>> :-)
>>
>> HTH
>>
>> Paolo
>>
>> P.S) I don't know why the browser's viewer messes up the indentation of
>> these attachments.
>> If so, I ask if are there volunteers to fix that and re-post the snippet
>> (I see correct indentation if I paste the code to any online js editor)
>>
>>
\version "2.19.45"
JSSVGBeamTuner = #(define-void-function (body) (string?)
(let* ((mod (resolve-module '(scm framework-svg)))
(svg-end (module-ref mod 'svg-end #f)))
(if (procedure? svg-end)
(module-define! mod 'svg-end (lambda () (string-join
(list "<script type=\"text/javascript\"><![CDATA["
body "]]></script>" (svg-end)) "\n"))))))
JSSVGBeamTunerScript = #"
rootNode = document.querySelector('svg')
pixelsX = rootNode.getAttribute('width').replace('mm', '') * 96 / 25.4
pixelsY = rootNode.getAttribute('height').replace('mm', '') * 96 / 25.4
scaleX = rootNode.getAttribute('viewBox').split(' ')[2] / pixelsX
scaleY = rootNode.getAttribute('viewBox').split(' ')[3] / pixelsY
var beamId = 0
var currGrob = null
function pointsArrToStr(points)
{
pointsStr = ''
for (var i = 0; i< 8; i++) {
pointsStr += points[i] + ' '
}
return pointsStr.substring(0, pointsStr.length - 1)
}
function initBeam(n1) {
n1.setAttribute('id', beamId)
for (n2 = n1.firstChild; n2 !== null; n2 = n2.nextSibling) {
if (n2.nodeName == 'polygon') {
//TODO Ugly parsering, replace with a proper and safer one
transf = n2.getAttribute('transform')
// TODO: check backspaces?
// TODO: check if it doesn't have transform attr?
translateX = transf.replace('translate(', '').split(',')[0]
translateY = transf.split(',')[1].trim().replace(')', '')
points = n2.getAttribute('points').split(' ')
//alert(translateX)
for (var i = 0; i<7; i = i+2) {
points[i] = Number(points[i]) + Number(translateX)
}
for (var i = 1; i<8; i = i+2) {
points[i] = Number(points[i]) + Number(translateY)
}
pointsStr = pointsArrToStr(points)
n2.setAttribute('points', pointsStr)
n2.setAttribute('origPoints', pointsStr)
n2.setAttribute('id', 'lilyBeamPoly_'+beamId)
n2.setAttribute('onmousedown', 'selectGrob(this)')
n2.removeAttribute('transform')
n2.setAttribute('anchor', '')
}
}
beamId++
}
function selectGrob(grob) {
if (!grob.hasAttribute('id'))
return
if (!detectLeftButton(event)) {
event.preventDefault()
showGrobModifyExpr(grob)
return
}
grob.setAttribute('color', 'cyan')
points = grob.getAttribute('points').split(' ')
leftX = Number(points[4])
rightX = Number(points[0])
distanceFromRightSide = Math.abs(event.pageX * scaleX - rightX)
distanceFromLeftSide = Math.abs(event.pageX * scaleX - leftX)
distanceFromCenter = Math.abs(event.pageX * scaleX -
(leftX + (rightX - leftX)/2))
minDistance = Math.min(distanceFromLeftSide,
distanceFromCenter,
distanceFromRightSide)
switch(minDistance)
{
case distanceFromRightSide:
grob.setAttribute('anchor','right')
break;
case distanceFromLeftSide:
grob.setAttribute('anchor','left')
break;
case distanceFromCenter:
grob.setAttribute('anchor','center')
break;
}
grob.setAttribute('yScreenPrev', event.pageY * scaleY)
currGrob = grob
}
function detectLeftButton(evt) {
evt = evt || window.event
if ('buttons' in evt) {
return evt.buttons == 1
}
var button = evt.which || evt.button
return button == 1
}
function unselectGrob() {
if (currGrob)
currGrob.setAttribute('color', 'black')
currGrob = null
}
function moveGrob() {
if (!currGrob)
return
points = currGrob.getAttribute('points').split(' ')
origPoints = currGrob.getAttribute('origPoints').split(' ')
idx1 = 1
idx2 = 8
if (currGrob.getAttribute('anchor') == 'left') {
idx1 = 5
}
else if (currGrob.getAttribute('anchor') == 'right') {
idx2 = 5
}
for (var i = idx1; i < idx2; i = i + 2) {
points[i] = Number(points[i]) +
event.pageY * scaleY -
Number(currGrob.getAttribute('yScreenPrev'))
}
currGrob.setAttribute('yScreenPrev', event.pageY * scaleY)
currGrob.setAttribute('points', pointsArrToStr(points))
}
window.oncontextmenu = function(evt) {
evt.preventDefault()
}
function showGrobModifyExpr(grob) {
angleLeft = +((grob.getAttribute('origPoints').split(' ')[5] -
grob.getAttribute('points').split(' ')[5]).toFixed(3))
angleRight = +((grob.getAttribute('origPoints').split(' ')[1] -
grob.getAttribute('points').split(' ')[1]).toFixed(3))
lilyExpr = '-\\\\offset positions ' +
'#\\'(' + angleLeft + ' . ' + angleRight + ')'
alert(lilyExpr)
}
var as = document.querySelectorAll('a')
//Remove all 'a' tags
for (var i = 0; i < as.length; i++) {
as[i].replaceWith(...as[i].childNodes)
}
beams = document.querySelectorAll('svg .lilyBeam')
for (var i = 0; i < beams.length; i++) {
initBeam(beams[i])
}
document.addEventListener('mouseup', unselectGrob)
document.addEventListener('mousemove', moveGrob)
"
addJSSVGBeamTuner = \JSSVGBeamTuner \JSSVGBeamTunerScript
addSVGBeamHandler = {
\override Beam.output-attributes = #'((class . "lilyBeam"))
}
\score
{
{
\addSVGBeamHandler
% How-to:
% 1) move with the left mouse button the angles or the vertical position
% of the beam in the SVG output file.
% 2) right-click and replace the line below with the output string in this way:
% a8-\offset positions #'(y1 . y2)[ c' c' c'] c' d' e' f'
a8[ c' c' c']
c'[ d' e' f']
c'''[ e''' c''' c''']
c'''[ e''' c''' c''']
}
}
\addJSSVGBeamTuner