[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