This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
jwlua:harpglisssample [2013/10/08 08:06] jariw created |
jwlua:harpglisssample [2013/10/08 14:19] (current) jariw [Step 1 - Download and Install JW Lua] |
||
---|---|---|---|
Line 1: | Line 1: | ||
===== Using JW Lua - Create Harp Glissando ===== | ===== Using JW Lua - Create Harp Glissando ===== | ||
+ | If you have never used //JW Lua// to run scripts before, this is a good page to start. At the bottom of the page is a full script that will automatically create a harp gliss from a 7-tuplet that you might want to test (the script works on Finale 2012 and later versions). | ||
+ | This wiki page is based on **beta version 0.07** of //JW Lua//, but it should hopefully work with any later version as well. | ||
+ | |||
+ | ==== Step 1 - Download and Install JW Lua ==== | ||
+ | |||
+ | The beta versions of JW Lua are available for download at this page: | ||
+ | http://finaletips.nu/index.php?option=com_phocadownload&view=category&id=28:beta-version&Itemid=2 | ||
+ | |||
+ | Install the plug-in as any other third party Finale plug-in. The Windows version contains a DLL file as well, which must be put in the same location as the plug-in .fxt file. | ||
+ | |||
+ | ==== Step 2 - Start JW Lua ==== | ||
+ | |||
+ | Once the JW Lua plug-in has been installed and Finale has been restarted, select //JW Lua...// in Finale's //Plug-ins// menu. | ||
+ | |||
+ | ==== Step 3 - Create a script group ==== | ||
+ | |||
+ | To organize the scripts into a workflow, a script need to be put in a group. | ||
+ | |||
+ | - Select the **Manager** page | ||
+ | - Click the **New...** button to the top right, which will open the //Edit Plug-in Group// dialog box. | ||
+ | - Enter a **Group Name** (such as "Harp Editing", "Plucked Strings", "Note Editing", "Client X", etc) where you want to put your script. | ||
+ | - Enter a **Description** with a text that is a more detailed description of what the group will contain. | ||
+ | - Leave everything else as it is and press the **OK** button. | ||
+ | ==== Step 4 - Add the script to the group ==== | ||
+ | |||
+ | Download the ''harpgliss.lua'' file below, if you haven't done so already. Make sure to store the JW Lua scripts at a good location on your computer. These scripts can be put anywhere on the hard drive, they don't need to be related to the Finale installation. | ||
+ | |||
+ | To add the script to the group: | ||
+ | - Make sure that the group is selected in the //top list// on the //Manager// page. | ||
+ | - Press the **New...** button next to the **bottom list**. | ||
+ | - In the dialog box that appears, locate the script on your computer and select it to add to the group. | ||
+ | |||
+ | When you exit Finale, the changes made on the //Manager// page will be saved. | ||
+ | ==== Step 5 - Refresh the plug-in list ==== | ||
+ | |||
+ | Select the **Explorer** page and press the **Refresh All** button. The group should now appear with the script inside. | ||
+ | |||
+ | ==== Step 6 - Run ==== | ||
+ | |||
+ | On the **Explorer** page, open your group container and select the script. Press the **Run** button. | ||
+ | |||
+ | ==== The Harp Glissando script ==== | ||
+ | |||
+ | The harp glissado script will transform 7-tuplets with seven undotted notes (of a "flagged" note duration) in the selected region into graphical harp glissando start note that spans the duration of the tuplet. | ||
+ | {{ :wiki:jwlua:jwlua-harpgliss.jpg?nolink |}} | ||
+ | |||
+ | The script will only modify staves that are defined a ''Harp'' in Finale's //Score Manager// - so if a 7-tuplet is for example found on a violin staff, nothing will be processed. It will also handle situations such as when the tuplet duration spans a half note or more. The original notes in the tuplet doesn't need to be beamed. | ||
+ | |||
+ | Note that at the very start of the script are 2 values (''StemLength'' and ''SmallNoteResize'') that you might want to modify. To do that, select the **Development** page and open/edit/save the file there. | ||
+ | |||
+ | (Click on the ''harpgliss.lua'' text to download the script.) | ||
+ | |||
+ | <code lua 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 | ||
+ | if entry:CalcDots() > 0 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</code> |