User Tools

Site Tools


jwlua:harpglisssample

This is an old revision of the document!


Using JW Lua - Create Harp Glissando

harpgliss.lua
-- CHANGE THESE 2 VALUES IF YOU WANT OTHER VALUES
StemLength = 84   -- Stem Length of the first note in EVPUs
SmallNoteResize = 70   -- Resize % of small notes
 
function plugindef()
   -- This function and the 'finaleplugin' namespace
   -- are both reserved for the plug-in definition.
   finaleplugin.RequireSelection = true
   finaleplugin.MinFinaleVersion = "2012"
   finaleplugin.Author = "Jari Williamsson"
   finaleplugin.Version = "0.01"
   finaleplugin.Notes = [[
This script will only process 7-tuplets that appears on staves that has been defined as "Harp" in the Score Manager.
]]
   finaleplugin.CategoryTags = "Idiomatic, Note, Pluckedstrings, Region, Tuplet, Woodwinds"
   return "Harp gliss (from 7-tuplet)", "Harp gliss", "Transforms 7-tuplets to harp gliss notation."
end
 
 
-- Sets the beam width to 0 and resizes the stem for the first note (by moving
-- the primary beam)
-- This is a sub-function to ChangePrimaryBeam()
function ChangeBeamInfo(primarybeam, entry)
    local currentlength = entry:CalcStemLength()
    primarybeam.Thickness = 0  
    if entry:CalcStemUp() then
        primarybeam.LeftVerticalOffset = primarybeam.LeftVerticalOffset + StemLength - currentlength
    else
        primarybeam.LeftVerticalOffset = primarybeam.LeftVerticalOffset - StemLength + currentlength
    end
end
 
-- Changes a primary beam for and entry
function ChangePrimaryBeam(entry)    
    local primarybeams = finale.FCPrimaryBeamMods(entry)
    primarybeams:LoadAll()
    if primarybeams.Count > 0 then
        -- Modify the existing beam modification record to hide the beam
        local primarybeam = primarybeams:GetItemAt(0)        
        ChangeBeamInfo(primarybeam, entry)        
        primarybeam:Save()
    else
        -- Create a beam modification record and hide the beam
        local primarybeam = finale.FCBeamMod(false)
        primarybeam:SetNoteEntry(entry)
        ChangeBeamInfo(primarybeam, entry)         
        primarybeam:SaveNew()
    end
end
 
-- Assures that the entries that spans the entries are
-- considered "valid" for a harp gliss. Rests and too few
-- notes in the tuplet are things that aren't ok.
-- This is a sub-function to GetMatchingTuplet()
function VerifyEntries(entry, tuplet)
    local entrystaffspec = finale.FCCurrentStaffSpec()
    entrystaffspec:LoadForEntry(entry)
    if entrystaffspec.InstrumentUUID ~= finale.FFUUID_HARP then return false end
    local symbolicduration = 0
    local firstentry = entry
    for i = 0, 6 do
        if entry == nil then return false end
        if entry:IsRest() then return false end
        if entry.Duration >= finale.QUARTER_NOTE then return false end
        if entry.Staff ~= firstentry.Staff then return false end
        if entry.Layer ~= firstentry.Layer then return false end
        symbolicduration = symbolicduration + entry.Duration
        entry = entry:Next()
    end
    return (symbolicduration == tuplet:CalcFullSymbolicDuration())
end
 
-- If a "valid" harp tuplet is found for an entry, this method returns it.
function GetMatchingTuplet(entry)    
    local tuplets = entry:CreateTuplets()
    for t in each(tuplets) do
        if t.SymbolicNumber == 7 and VerifyEntries(entry, t) then return t end
    end
    return nil
end
 
-- Hides a tuplet (both by visibility and appearance)
function HideTuplet(t)    
    t.ShapeStyle = finale.TUPLETSHAPE_NONE
    t.NumberStyle = finale.TUPLETNUMBER_NONE
    t.Visible = false
    t:Save()
end
 
-- Hide stems for the small notes in the gliss. If the "full" note has a long
-- enough duration to not have a stem, the first entry also gets a hidden stem.
function HideStems(entry, tuplet)
    local hidefirstentry = (tuplet:CalcFullReferenceDuration() >= finale.WHOLE_NOTE)
    for i = 0, 6 do        
        if i > 0 or hidefirstentry then
            local stem = finale.FCCustomStemMod()        
            stem:SetNoteEntry(entry)
            stem:UseUpStemData(entry:CalcStemUp())
            if stem:LoadFirst() then
                stem.ShapeID = 0    
                stem:Save()
            else
                stem.ShapeID = 0
                stem:SaveNew()
            end            
        end
        entry = entry:Next()
    end
end
 
-- Change the notehead shapes and notehead sizes
function SetNoteheads(entry, tuplet)
    for i = 0, 6 do        
        for chordnote in each(entry) do
            local notehead = finale.FCNoteheadMod()                        
            if i == 0 then
                local fullrefdur = tuplet:CalcFullReferenceDuration()
                if fullrefdur >= finale.WHOLE_NOTE then
                    notehead.CustomChar = 119   -- Whole note character
                elseif fullrefdur >= finale.HALF_NOTE then
                    notehead.CustomChar = 250   -- Half note character
                end
            else
                notehead.Resize = SmallNoteResize
            end                    
            notehead:SaveAt(chordnote)                
        end
        entry = entry:Next()
    end
end
 
-- If the tuplet spans a duration that is dotted, modify the
-- rhythm at the beginning of the tuplet
function ChangeDottedFirstEntry(entry, tuplet)
    local refdur = tuplet:CalcFullReferenceDuration()
    local tupletdots = finale.FCNoteEntry.CalcDotsForDuration(refdur)
    local entrydots = entry:CalcDots()    
    if tupletdots == 0 then return end
    if tupletdots > 3 then return end  -- Don't support too complicated gliss rhythm values
    if entrydots > 0 then return end
    -- Create dotted rhythm
    local nextentry = entry:Next()
    local nextduration = nextentry.Duration / 2    
    for i = 1, tupletdots do
        entry.Duration = entry.Duration + nextduration
        nextentry.Duration = nextentry.Duration - nextduration
        nextduration = nextduration / 2
    end
end
 
-- *** THE SCRIPT EXECUTION STARTS HERE ***
 
-- Make sure the harp tuplets are beamed
for entry in eachentrysaved(finenv.Region()) do
    local harptuplet = GetMatchingTuplet(entry)
    if harptuplet then
        harp_tuplets_exist = true
        for  i = 1, 6 do
            entry = entry:Next()
            entry.BeamBeat = false
        end
    end
end
 
if harp_tuplets_exist == nil then return end
 
-- Since the entries might change direction when they are beamed,
-- tell Finale to update the entry metric data info
finale.FCNoteEntry.MarkEntryMetricsForUpdate()
 
-- Change the harp tuplets
for entry in eachentrysaved(finenv.Region()) do
    local harptuplet = GetMatchingTuplet(entry)
    if harptuplet then
        ChangeDottedFirstEntry(entry, harptuplet)
        ChangePrimaryBeam(entry)
        HideTuplet(harptuplet)
        HideStems(entry, harptuplet)
        SetNoteheads(entry, harptuplet)
    end        
end
jwlua/harpglisssample.1381219840.txt.gz · Last modified: 2013/10/08 08:10 by jariw