@@ -3,8 +3,8 @@ function plugindef()
33 finaleplugin .Author = " Carl Vine"
44 finaleplugin .AuthorURL = " https://carlvine.com/lua/"
55 finaleplugin .Copyright = " https://creativecommons.org/licenses/by/4.0/"
6- finaleplugin .Version = " 0.28 "
7- finaleplugin .Date = " 2024/02/07 "
6+ finaleplugin .Version = " 0.32 "
7+ finaleplugin .Date = " 2024/07/12 "
88 finaleplugin .MinJWLuaVersion = 0.70
99 finaleplugin .Notes = [[
1010 This script takes music from a nominated layer in the selected staff
@@ -14,48 +14,49 @@ function plugindef()
1414 If the destination measure is empty a whole-measure rest
1515 will be created as a reminder that the cue isn't played.
1616
17- Cue notes are often shown in a different octave to accommodate
18- the clef and transposition of the destination.
19- Use _Cue Octave Offset_ setting for this.
17+ Use __Cue Octave Offset__ to change the register of a cue to
18+ suit the clef and transposition of the destination.
2019 Cues can interact visually with "played" material in countless ways
2120 so settings probably need to change between scenarios.
2221
2322 The cue copy is reduced in size and muted, and can optionally duplicate
2423 articulations, expressions, lyrics and smart shapes.
25- "Note-based" smart shapes are copied, typically slurs and glissandos,
24+ __Note-based__ smart shapes are copied, typically slurs and glissandos,
2625 because they actually "attach" to the cued notes.
2726
28- This script stores cue names in a text expression category called _Cue Names_
29- which will be created automatically if needed.
27+ This script stores cue names in a text expression category called
28+ __Cue Names__ which will be created automatically if needed.
3029 Once created you can adjust its text and position parameters
3130 like any other expression category.
3231
3332 Rests in the cue will be offset by the value you have set
34- for layer 1 at _Document_ → _Document Options_ → _Layers_.
35- They will automatically offset in the same direction as
33+ for layer 1 at _Document_ → _Document Options_ → _Layers_.
34+ They will automatically be offset in the same direction as
3635 the nominated cue stem direction.
3736
3837 > __Command Keys__
39- > In the _Destination Staff_ window, hit the tab key to move the cursor
40- > into a numeric field and these key commands become available:
41-
42- > - __q__ - show these script notes
43- > - __w__ - flip [copy articulations]
44- > - __e__ - flip [copy expressions]
45- > - __r__ - flip [copy smartshapes]
46- > - __t__ - flip [copy lyrics]
47- > - __y__ - flip [mute cuenotes]
48- > - __a__ - check all options
49- > - __s__ - check no options
50- > - __d__ - select all staves
51- > - __f__ - select no staves
52- > - __g__ - select empty staves
53- > - __z (-)__ - octave -1
54- > - __x (+)__ - octave +1
55- > - __c__ - flip stem direction
56- > - __v__ - flip [destination stems opposite]
38+ > In the __Destination Staff__ window, highlight one of the
39+ > numeric fields and these key commands become available:
40+
41+ > - __q__: show script info
42+ > - __w__: toggle [copy articulations]
43+ > - __e__: toggle [copy expressions]
44+ > - __r__: toggle [copy smartshapes]
45+ > - __t__: toggle [copy lyrics]
46+ > - __y__: toggle [mute cuenotes]
47+ > - __a__: check all options
48+ > - __s__: check no options
49+ > - __d__: select all staves
50+ > - __f__: select no staves
51+ > - __g__: select empty staves
52+ > - __z (-)__: octave -1
53+ > - __x (+)__: octave +1
54+ > - __c__: toggle stem direction
55+ > - __v__: toggle [destination stems opposite]
5756 ]]
58- return " Cue Notes Overlay..." , " Cue Notes Overlay" , " Copy as cue notes to another staff"
57+ return " Cue Notes Overlay..." ,
58+ " Cue Notes Overlay" ,
59+ " Copy as cue notes to another staff"
5960end
6061
6162local config = { -- retained and over-written by the user's "settings" file
@@ -64,24 +65,46 @@ local config = { -- retained and over-written by the user's "settings" file
6465 copy_smartshapes = true ,
6566 copy_lyrics = false ,
6667 mute_cuenotes = true ,
67- cuenote_percent = 70 , -- (75% too big, 66% too small)
68- source_layer = 1 , -- layer the cue comes from
69- cuenote_layer = 4 , -- layer the cue ends up
70- stem_direction = 0 , -- "0" up, "1" down
68+ cuenote_percent = 70 , -- (75% too big, 66% too small)
69+ source_layer = 1 , -- layer the cue comes from
70+ cuenote_layer = 4 , -- layer the cue ends up
71+ stem_direction = 0 , -- "0" up, "1" down
7172 stems_oppose = true , -- destination stem direction opposite to cue stem
72- octave_offset = 0 , -- octave displacement (-5 to +5) of copied cue version
73+ octave_offset = 0 , -- octave displacement (-5 to +5) of copied cue version
7374 abbreviate = true , -- abbreviate staff names when creating new titles
7475 cuename_item = 0 , -- ItemNo of the last selected cue_name expression
7576 overwrite_layer = 4 , -- overriden by user
7677 -- not user accessible:
77- shift_expression_down = - 24 * 9 , -- when cue_name is below staff
78- shift_expression_left = - 24 , -- EVPUs; cue names generally need to be LEFT of music start
78+ shift_exp_up = 24 , -- cue_name above staff
79+ shift_exp_down = - 24 * 9 , -- cue_name below staff
80+ shift_exp_left = - 24 , -- EVPUs; cue names generally need to be LEFT of music start
7981 -- if creating a new "Cue Names" category ...
8082 cue_category_name = " Cue Names" ,
8183 cue_font_smaller = 1 , -- how many points smaller than the standard technique expression
8284 window_pos_x = false ,
8385 window_pos_y = false ,
8486}
87+ local hotkey = { -- customise
88+ show_info = " q" ,
89+ copy_articulations = " w" ,
90+ copy_expressions = " e" ,
91+ copy_smartshapes = " r" ,
92+ copy_lyrics = " t" ,
93+ mute_cuenotes = " y" ,
94+ --
95+ set_all = " a" ,
96+ clear_all = " s" ,
97+ all_staves = " d" ,
98+ no_staves = " f" ,
99+ empty_staves = " g" ,
100+ --
101+ octave_dn1 = " z" ,
102+ octave_dn2 = " -" ,
103+ octave_up1 = " x" ,
104+ octave_up2 = " +" ,
105+ stem_direction = " c" ,
106+ stems_oppose = " v" ,
107+ }
85108local options = {
86109 check = { " copy_articulations" , " copy_expressions" , " copy_smartshapes" , " copy_lyrics" , " mute_cuenotes" },
87110 integer = { " cuenote_percent" , " source_layer" , " cuenote_layer" }, -- integer edit boxes
@@ -149,11 +172,10 @@ end
149172local function get_staff_name (staff_num )
150173 local staff = finale .FCStaff () -- copy the source Staff Name
151174 staff :Load (staff_num )
152- local str = staff :CreateDisplayFullNameString ()
153- local name = { full = str .LuaString }
154- str = staff :CreateDisplayAbbreviatedNameString ()
155- name .abbrev = str .LuaString
156- return name
175+ return {
176+ full = staff :CreateDisplayFullNameString ().LuaString ,
177+ abbrev = staff :CreateDisplayAbbreviatedNameString ().LuaString
178+ }
157179end
158180
159181local function new_cue_name (source_staff )
@@ -187,7 +209,7 @@ local function choose_name_index(name_list, source_staff)
187209 dialog :CreateStatic (0 , 17 ):SetText (" Select cue name:" ):SetWidth (100 )
188210 make_info_button (dialog , 180 , 17 )
189211 local staff_list = dialog :CreateListBox (0 , 40 ):SetWidth (200 )
190- :AddString (" *** new name ***" ) -- menu item [0] is "*** new name ***"
212+ :AddString (" *** new cue name ***" ) -- menu item [0] is "*** new name ***"
191213 for i , v in ipairs (name_list ) do -- add all names in the extant list
192214 staff_list :AddString (v [1 ])
193215 if v [2 ] == config .cuename_item then staff_list :SetSelectedItem (i ) end
@@ -224,12 +246,12 @@ local function create_new_expression(exp_name, category_number)
224246end
225247
226248local function choose_destination_staff (source_staff )
227- local source_name
228249 local rgn = finale .FCMusicRegion ()
229250 rgn :SetCurrentSelection ()
230251 rgn :SetFullMeasureStack () -- scan the whole stack
231252
232253 -- assemble selected staves
254+ local source_name
233255 local staff_list = {} -- staff number; name
234256 for staff_number in eachstaff (rgn ) do
235257 local name = get_staff_name (staff_number )
@@ -306,21 +328,21 @@ local function choose_destination_staff(source_staff)
306328 or s :find (" [^0-9]" )
307329 )
308330 ) then
309- if s :find (" [q?] " ) then info_dialog ()
310- elseif s :find (" w " ) then flip_check (" copy_articulations " )
311- elseif s :find (" e " ) then flip_check ( " copy_expressions " )
312- elseif s :find (" r " ) then flip_check ( " copy_smartshapes " )
313- elseif s :find (" t " ) then flip_check ( " copy_lyrics " )
314- elseif s :find (" y " ) then flip_check ( " mute_cuenotes " )
315- elseif s :find (" a " ) then set_check_state ( 1 ) -- check all
316- elseif s :find (" s " ) then set_check_state ( 0 ) -- check none
317- elseif s :find (" d " ) then set_list_state ( 1 ) -- all staves
318- elseif s :find (" f " ) then set_list_state ( 0 ) -- no staves
319- elseif s :find (" g " ) then set_list_state ( - 1 ) -- empty staves
320- elseif s : find ( " [-z_] " ) then octave_change ( 1 ) -- octave - 1
321- elseif s : find ( " [+x=] " ) then octave_change ( - 1 ) -- octave + 1
322- elseif s :find (" c " ) then flip_direction () -- up/down stem
323- elseif s : find ( " v " ) then flip_check ( " stems_oppose " )
331+ if s :find (hotkey . show_info ) then info_dialog ()
332+ elseif s :find (hotkey . mute_cuenotes ) then flip_check (" mute_cuenotes " )
333+ elseif s :find (hotkey . set_all ) then set_check_state ( 1 )
334+ elseif s :find (hotkey . clear_all ) then set_check_state ( 0 )
335+ elseif s :find (hotkey . all_staves ) then set_list_state ( 1 )
336+ elseif s :find (hotkey . no_staves ) then set_list_state ( 0 )
337+ elseif s :find (hotkey . empty_staves ) then set_list_state ( - 1 ) -- empty staves
338+ elseif s :find (hotkey . octave_dn1 ) or s : find ( hotkey . octave_dn2 ) then octave_change ( 1 )
339+ elseif s :find (hotkey . octave_up1 ) or s : find ( hotkey . octave_up2 ) then octave_change ( - 1 )
340+ elseif s :find (hotkey . stem_direction ) then flip_direction ( ) -- up/down stem
341+ elseif s :find (hotkey . stems_oppose ) then flip_check ( " stems_oppose " )
342+ else
343+ for _ , v in ipairs ( options . check ) do
344+ if s :find (hotkey [ v ] ) then flip_check ( v ) break end
345+ end
324346 end
325347 ctl :SetText (saved [name ]):SetKeyboardFocus ()
326348 elseif s ~= " " then
@@ -425,12 +447,11 @@ local function choose_overwrite_layer(staff_name, empty_layers)
425447 dialog :CreateStatic (0 , 55 ):SetText (" Please confirm:" ):SetWidth (100 )
426448 local list = dialog :CreateListBox (0 , 75 ):SetWidth (wide ):SetHeight (70 )
427449 for i = 1 , layer .max_layers () do
428- local si = tostring (i )
429450 if i == config .cuenote_layer then
430- list :AddString (" overwrite CUENOTE layer " .. si )
451+ list :AddString (" overwrite CUENOTE layer " .. i )
431452 else
432453 msg = empty_layers [i ] and " use empty layer " or " overwrite layer "
433- list :AddString (msg .. si )
454+ list :AddString (msg .. i )
434455 end
435456 if i == config .overwrite_layer then list :SetSelectedItem (i - 1 ) end
436457 end
@@ -625,6 +646,18 @@ local function new_expression_category(new_name)
625646 return ok , (ok and new_category :GetID () or 0 )
626647end
627648
649+ local function find_first_non_rest (staff , measure )
650+ local nel = finale .FCNoteEntryLayer (config .source_layer - 1 , staff , measure , measure )
651+ nel :Load ()
652+ for i = 0 , (nel .Count - 1 ) do
653+ local e = nel :GetItemAt (i )
654+ if e ~= nil and e :IsNote () then
655+ return e .MeasurePos
656+ end
657+ end
658+ return 0
659+ end
660+
628661local function create_cue_notes ()
629662 configuration .get_user_settings (script_name , config , true )
630663 local cue_names = { } -- compile NAME/ItemNo of all pre-existing CUE_NAME expressions
@@ -686,22 +719,22 @@ local function create_cue_notes()
686719 return
687720 end
688721 -- make the cue copy
722+ local vert_shift = (config .stem_direction == 1 ) and config .shift_exp_down or config .shift_exp_up
723+ local measure_pos = find_first_non_rest (start_staff , source_region .StartMeasure )
689724 for _ , one_staff in ipairs (destination_staves ) do
690725 if notelayer_copy (source_region , one_staff ) then
691726 local cue_name = mixin .FCMExpression () -- "name" the cue
692727 cue_name :SetStaff (one_staff )
693728 :SetVisible (true )
694- :SetMeasurePos (0 )
729+ :SetMeasurePos (measure_pos )
730+ :SetLayerAssignment (config .cuenote_layer )
695731 :SetScaleWithEntry (false )
696732 :SetPartAssignment (true )
697733 :SetScoreAssignment (true )
698734 :SetID (config .cuename_item )
699- :SetHorizontalPos (config .shift_expression_left )
735+ :SetHorizontalPos (config .shift_exp_left )
736+ :SetVerticalPos (vert_shift )
700737 :SaveNewToCell (finale .FCCell (source_region .StartMeasure , one_staff ))
701- if config .stem_direction == 1 then -- downstem
702- cue_name .VerticalPos = config .shift_expression_down
703- cue_name :Save ()
704- end
705738 end
706739 end
707740 refocus ()
0 commit comments