[JW Lua] Piano keyboard diagram
Chris
marcel.denio at gmail.com
Fri Feb 14 15:37:33 CET 2014
Hello all
That may be an idea that can be developed (if someone is interested here).
(see attached script)
This script creates diagrams for keyboard.
You can change the size to the lines 29,30,31
For notes to mark, enter the first note and then
enterintervals in semitones separated by a space .
(I hope to improve it by entering intervals -> 3 5 b7)
And thank you for your advice, I am only an amateur programming
Chris
-------------- next part --------------
function plugindef()
-- This function and the 'finaleplugin' namespace
-- are both reserved for the plug-in definition.
finaleplugin.RequireSelection = true
finaleplugin.Author = "Chris"
return "Piano keyboard diagram", "Piano keyboard diagram", ""
end
-- initialize entries for UI
local selectNote = {"C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1","C2","C#2","D2","D#2","E2","F2","F#2","G2","G#2","A2","A#2","B2","C3"}
local selectFond = {"none","C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1","C2","C#2","D2","D#2","E2","F2","F#2","G2","G#2","A2","A#2","B2","C3"}
local dialog = finenv.UserValueInput()
dialog.Title = "Piano keyboard diagram"
dialog:SetTypes("String","String","String","String")
dialog:SetDescriptions("First Note :","Last Note :","First mark note","Intervals :")
dialog:SetInitValues("C1", "C3","none","")
dialog:SetLists(selectNote,selectNote,selectFond)
local returnvalues = dialog:Execute()
if returnvalues == nil then return end
local firstNote = returnvalues[1]
local lastNote = returnvalues[2]
local fondNote = returnvalues[3]
local inters = returnvalues[4]
-- constantes
local hBlanche = 8 -- hauteur d'une note blanche (hauteur du diagramme)
local wBlanche = 2 -- largeur d'une note blanche
local lineWidth = 10 -- epaisseur des lignes des notes blanches en pourcentage de la largeur
function convertMmEVPU(valeur)
-- converti les millimetres en EVPU
return 288 * valeur / 25.4
end
function convertEVPU_EFIX(valeur)
-- converti les EVPU en EFIX
return valeur * 64
end
function round(valeur)
if valeur >= 0 then return math.floor(valeur + 0.5)
else return math.ceil(valeur - 0.5) end
end
-- conversion des valeurs (et en entiers pour eviter erreurs d'arrondi)
hBlanche = round(convertMmEVPU(hBlanche))
local hNoire = round(hBlanche * 0.7 ) -- hauteur de la noire en fonction de la hauteur de la blanche
wBlanche = round(convertMmEVPU(wBlanche))
local wNoire = round(wBlanche * 0.73) -- largeur de la noire en fonction de la largeur de la blanche
lineWidth = round(wBlanche * lineWidth / 100)
-- variables
local notesVisibles = {}
local nBlanches = 0 -- nombre de notes blanches du diagramme
function isDiese(note)
return not(string.find(note,"#") == nil)
end
function CreerListeNotesVisibles()
local flDebut = false
local ind = 1 -- index de la nouvelle liste
local xPtr = lineWidth /2 -- touches blanches : gauche, touches noires : centre
local indFirstActive = -1 -- index de la 1ere note marquee
for key,value in pairs(selectNote) do
if value == firstNote then
flDebut = true
if isDiese(value) then xPtr = (wNoire /2) end
end
if flDebut then
local isDiese = isDiese(value)
notesVisibles[ind] = {diese = isDiese, x = xPtr, marque = false}
if not isDiese then
xPtr = xPtr + wBlanche
nBlanches = nBlanches + 1
end
if value == fondNote then -- 1ere note marquee
indFirstActive = ind
end
ind = ind +1
end
if value == lastNote then break end
end
-- positionner le champ "marque"
if indFirstActive ~= -1 then
notesVisibles[indFirstActive].marque =true
if #inters >0 then
strInters = finale.FCString()
strInters.LuaString= inters
tabInters = strInters:CreateParsedStrings(" ")
local ind = indFirstActive
for inter in each (tabInters) do
if inter:IsNumber() then
ind = ind + inter:GetInteger(0)
if ind > 0 and ind<= #notesVisibles then
notesVisibles[ind].marque =true
end
end
end
end
end
return #notesVisibles > 0
end
-- DEBUT DU PROGRAMME
if not CreerListeNotesVisibles() then
finenv.UI():AlertInfo("Donnees incorrectes","Diagramme de piano")
return
end
function LigneVerticaleYZero(instructions,originX,hauteur,wLine)
-- dessine du haut vers le bas (originX au centre de l'ýpaisseur)
local demiWLine = wLine / 2
local origin =finale.FCPoint(originX ,0)
local lefttop = finale.FCPoint(round(originX - demiWLine ),0)
local rightbottom= finale.FCPoint(round(originX + demiWLine) ,- hauteur)
instructions:AddStartObject(origin,lefttop,rightbottom,1000,1000,0)
instructions:AddRMoveTo(0,0)
instructions:AddLineWidth(wLine)
instructions:AddSolidLineStyle()
instructions:AddRLineTo(0,- hauteur)
instructions:AddStroke()
end
function Cercle(instructions,originX,originY,diametre,couleur)
-- couleur > 0:noir 100:blanc (origine en haut a gauche)
local origin =finale.FCPoint(originX ,originY)
local lefttop = finale.FCPoint(originX ,originY)
local rightbottom= finale.FCPoint(originX + diametre ,originY - diametre)
instructions:AddStartObject(origin,lefttop,rightbottom,1000,1000,0)
instructions:AddRMoveTo(0,0)
instructions:AddLineWidth(0)
instructions:AddSetGrey(couleur)
instructions:AddEllipse(diametre,diametre)
instructions:AddFillSolid()
end
function creerMarques(instructions)
local diametreMarque = round(wNoire * 0.8) -- 80% largeur noire
local offsetBlanche = (wBlanche - diametreMarque) /2 -- espace entre le cercle et le bord de la blanche
local offsetNoire = (wNoire - diametreMarque) /2 -- espace entre le cercle et le bord de la noire
local yBlanche = - (hBlanche - ((hBlanche - hNoire - diametreMarque) / 2))
local yNoire = -(hNoire - offsetNoire)
offsetNoire = offsetNoire - (wNoire / 2)
for key,value in pairs(notesVisibles) do
if value.marque then
local couleur,x,y
if value.diese then
x = value.x + offsetNoire
y = yNoire
couleur = 100
else
x = value.x + offsetBlanche
y = yBlanche
couleur = 0
end
Cercle(instructions, x, y, diametreMarque,couleur)
end
end
end
function creerDiagramme()
-- retourne l'ID de la shape
local shapedef =finale.FCShapeDef()
local instructions = shapedef:CreateInstructions()
local rectBlanches = (nBlanches * wBlanche) + lineWidth
local wDiagramme = rectBlanches
local xRectBlanches = 0
local lineWidthEFIX = convertEVPU_EFIX(lineWidth) -- unite EFIX
if notesVisibles[1].diese then -- 1ere note : diese
xRectBlanches = round((wNoire / 2) - (lineWidth /2))
wDiagramme = wDiagramme + xRectBlanches
end
if notesVisibles[#notesVisibles].diese then wDiagramme = wDiagramme + (wNoire /2) end
-- rectangle des blanches (epaisseur ligne vers l'interieur)
local origin =finale.FCPoint(0,0)
local lefttop =finale.FCPoint(0,0)
local rightbottom =finale.FCPoint(wDiagramme,- hBlanche)
instructions:AddStartObject(origin,lefttop,rightbottom,1000,1000,0)
instructions:AddRMoveTo(xRectBlanches,0)
instructions:AddLineWidth(lineWidthEFIX)
instructions:AddSolidLineStyle()
instructions:AddRectangle(rectBlanches,- hBlanche)
instructions:AddStroke()
-- blanches et noires(trait vertical epais)
local wNoireEFIX = convertEVPU_EFIX(wNoire)
for key,value in pairs(notesVisibles) do
if value.diese then -- diese
LigneVerticaleYZero(instructions,value.x ,hNoire, wNoireEFIX)
elseif key ~= 1 then -- blanches (trait vertical a l'interieur de rectangle)
LigneVerticaleYZero(instructions,value.x ,hBlanche,lineWidthEFIX)
end
end
creerMarques(instructions)
-- sauvegarde
shapedef:RebuildInstructions(instructions)
shapedef:SaveNewWithType(-1)
return shapedef.ItemNo
end
function creerExpression(idShape)
local shapeexpressiondef = finale.FCShapeExpressionDef()
shapeexpressiondef.ID = idShape
shapeexpressiondef.AllowHorizontalStretching = false
shapeexpressiondef:SaveNew()
local e = finale.FCExpression()
e.Shape = true
e.ID = shapeexpressiondef.ItemNo
local region = finenv.Region()
e:SaveNewToCell(finale.FCCell(region.StartMeasure,region.StartStaff))
end
-- DEBUT DU PROGRAMME
local idShape = creerDiagramme()
creerExpression(idShape)
More information about the JWLua
mailing list