Skip to content

Commit 921079a

Browse files
authored
Merge pull request #744 from MuseCraft-Studio/master
Create articulation_expression_swap
2 parents 0e8c065 + 2adc008 commit 921079a

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
function plugindef()
2+
finaleplugin.RequireSelection = false
3+
finaleplugin.Author = "CJ Garcia"
4+
finaleplugin.Copyright = "2024 MuseCraft Studio"
5+
finaleplugin.Version = "1.1"
6+
finaleplugin.Date = "7/20/2024"
7+
finaleplugin.MinJWLuaVersion = 0.66
8+
finaleplugin.RevisionNotes = [[
9+
May 27, 2024: Script work began with idea from Burt Goldstein
10+
May 28, 2024: Version 1.0
11+
July 20, 2024: Carl Vine edits integrated
12+
]]
13+
finaleplugin.CategoryTags = "Articulation, Expression"
14+
return "Articulation and Expression Swap...", "Articulation and Expression Swap",
15+
"Replaces the selected articulation with the selected expression (or vice versa) for the full document if a region is not selected."
16+
end
17+
18+
local config = {
19+
art_id = 0,
20+
exp_id = 0,
21+
show_result = true,
22+
}
23+
local configuration = require("library.configuration")
24+
local library = require("library.general_library")
25+
local script_name = library.calc_script_name()
26+
local name = plugindef():gsub("%.%.%.", "")
27+
configuration.get_user_settings(script_name, config, true)
28+
29+
local function assign_expression(exp_id, entry)
30+
local exp = finale.FCExpression()
31+
exp:SetStaff(entry.Staff)
32+
exp:SetVisible(true)
33+
exp:SetMeasurePos(entry:GetMeasurePos())
34+
exp:SetScaleWithEntry(true)
35+
exp:SetLayerAssignment(entry.LayerNumber)
36+
exp:SetID(exp_id)
37+
exp:SaveNewToCell(finale.FCCell(entry.Measure, entry.Staff))
38+
end
39+
40+
local function show_the_results(type, count, id)
41+
if config.show_result then
42+
if count ~= 0 then
43+
local msg = count > 1 and " occurances of " or " occurance of "
44+
msg = msg .. type .. " ID " .. id
45+
finenv.UI():AlertInfo("Replaced " .. count .. msg, name .. ": Success")
46+
else
47+
finenv.UI():AlertInfo("No occurances of " .. type .. " ID " .. id .. " were found",
48+
name .. ": Not found")
49+
end
50+
end
51+
end
52+
53+
local function run(art_id, exp_id, selected_item)
54+
local msg = {}
55+
if art_id == nil or art_id < 1 then
56+
table.insert(msg, "The Articulation ID must be a digit > 0")
57+
end
58+
if exp_id == nil or exp_id < 1 then
59+
table.insert(msg, "The Expression ID must be a digit > 0")
60+
end
61+
if #msg > 0 then
62+
table.insert(msg, "Exiting process.")
63+
finenv.UI():AlertInfo(table.concat(msg, "\n\n"), name .. ": Entry Error")
64+
return
65+
end
66+
67+
local function match_item(fc_defs, id)
68+
fc_defs:LoadAll()
69+
for a in each(fc_defs) do
70+
if a:GetItemNo() == id then return true end
71+
end
72+
return false
73+
end
74+
local has_art = match_item(finale.FCArticulationDefs(), art_id)
75+
local has_exp = match_item(finale.FCTextExpressionDefs(), exp_id)
76+
msg = {}
77+
if not has_art then
78+
table.insert(msg, "Articulation ID " .. art_id .. " could not be found.")
79+
end
80+
if not has_exp then
81+
table.insert(msg, "Expression ID " .. exp_id .. " could not be found.")
82+
end
83+
if #msg > 0 then
84+
table.insert(msg, "Exiting process.")
85+
finenv.UI():AlertInfo(table.concat(msg, "\n\n"), name .. ": Items not found")
86+
return
87+
end
88+
89+
local music_region = finenv.Region()
90+
if music_region:IsEmpty() then
91+
music_region = finale.FCMusicRegion()
92+
music_region:SetFullDocument()
93+
end
94+
95+
local count = 0
96+
if selected_item == 0 then
97+
-- replace articulation with expression
98+
for noteentry in eachentrysaved(music_region) do
99+
local arts = noteentry:CreateArticulations()
100+
for a in eachbackwards(arts) do
101+
if a:GetID() == art_id then
102+
count = count + 1
103+
a:DeleteData()
104+
assign_expression(exp_id, noteentry)
105+
end
106+
end
107+
end
108+
show_the_results("articulation", count, art_id)
109+
else
110+
-- replace expression with articulation
111+
for noteentry in eachentrysaved(music_region) do
112+
local pin_point = finale.FCMusicRegion()
113+
pin_point:SetStartStaff(noteentry:GetStaff())
114+
pin_point:SetEndStaff(noteentry:GetStaff())
115+
pin_point:SetStartMeasure(noteentry:GetMeasure())
116+
pin_point:SetEndMeasure(noteentry:GetMeasure())
117+
pin_point:SetStartMeasurePos(noteentry:GetMeasurePos())
118+
pin_point:SetEndMeasurePos(noteentry:GetMeasurePos())
119+
120+
local expressions = finale.FCExpressions()
121+
expressions:LoadAllForRegion(pin_point)
122+
for exp in eachbackwards(expressions) do
123+
local ted = exp:CreateTextExpressionDef()
124+
if ted:GetItemNo() == exp_id then
125+
count = count + 1
126+
exp:DeleteData()
127+
local art = finale.FCArticulation()
128+
art:SetNoteEntry(noteentry)
129+
art:SetID(art_id)
130+
art:SaveNew()
131+
end
132+
end
133+
end
134+
show_the_results("expression", count, exp_id)
135+
end
136+
end
137+
138+
local fs = finale.FCString
139+
local dialog = finale.FCCustomLuaWindow()
140+
dialog:SetTitle(fs(name))
141+
142+
local art_button = dialog:CreateButton(0, 45)
143+
art_button:SetText(fs("Select..."))
144+
local exp_button = dialog:CreateButton(150, 45)
145+
exp_button:SetText(fs("Select..."))
146+
147+
local art_text = dialog:CreateStatic(0, 0)
148+
art_text:SetText(fs("Articulation ID"))
149+
local art_box = dialog:CreateEdit(0, 16)
150+
art_box:SetInteger(config.art_id)
151+
152+
local exp_text = dialog:CreateStatic(150, 0)
153+
exp_text:SetText(fs("Expression ID"))
154+
local exp_box = dialog:CreateEdit(150, 16)
155+
exp_box:SetInteger(config.exp_id)
156+
157+
local radio_group = dialog:CreateRadioButtonGroup(0, 70, 2)
158+
local strs = finale.FCStrings()
159+
strs:CopyFromStringTable{
160+
"Find Articulation, Replace With Expression",
161+
"Find Expression, Replace With Articulation"
162+
}
163+
radio_group:SetText(strs)
164+
radio_group:SetWidth(240)
165+
local show_result = dialog:CreateCheckbox(0, 105)
166+
show_result:SetWidth(150)
167+
show_result:SetText(fs("Show Results"))
168+
show_result:SetCheck(config.show_result and 1 or 0)
169+
170+
dialog:CreateOkButton()
171+
dialog:CreateCancelButton()
172+
173+
local function get_user_selection(controller)
174+
if controller:GetControlID() == art_button:GetControlID() then
175+
art_box:SetInteger(finenv.UI():DisplayArticulationDialog(art_box:GetInteger()))
176+
elseif controller:GetControlID() == exp_button:GetControlID() then
177+
exp_box:SetInteger(finenv.UI():DisplayExpressionDialog(exp_box:GetInteger(), false))
178+
end
179+
end
180+
181+
dialog:RegisterHandleCommand(get_user_selection)
182+
183+
if dialog:ExecuteModal(nil) == finale.EXECMODAL_OK then
184+
config.art_id = art_box:GetInteger()
185+
config.exp_id = exp_box:GetInteger()
186+
config.show_result = (show_result:GetCheck() == 1)
187+
configuration.save_user_settings(script_name, config)
188+
run(config.art_id, config.exp_id, radio_group:GetSelectedItem())
189+
end

0 commit comments

Comments
 (0)