Lua Skript für Legatobögen per Tastatur

TGTools, Patterson Plug-Ins, Forza! und andere Plug-Ins von Drittanbietern
Antworten
mas82
Beiträge: 38
Registriert: Mo Mai 08, 2017 10:00 pm

Lua Skript für Legatobögen per Tastatur

Beitrag von mas82 » Sa Okt 27, 2018 8:55 pm

Hallo zusammen!

Trotz intensiver Beschäftigung mit Lua stehe ich immer noch auf dem Schlauch und mach keinen einzigen Schritt vorwärts:
Es geht darum, dass ich gerne ein Skript schreiben möchte, um einer Auswahl an Noten einen Legatobogen hinzuzufügen.

Mit Dynamikgabeln klappt das mittlerweile wunderbar dank eines tollen Skriptes von Harald:
viewtopic.php?f=9&t=5225


Da Legatobögen note-attached sind, versuche ich nun, Haralds Skript als Leitfaden zu nehmen und anzupassen aber ich komme überhaupt nicht weiter und bitte um Korrektur meines Gedankenganges:

- In Zeile 44 auf finale.SMARTSHAPE_SLURAUTO ändern
- Ich setze :SetEntryBased(true) aus FCSmartShape() in Zeile 19
- Ich erzeuge mit :SetEntryNumber aus FCSmartShapeSegment das Segment (Zeile 34f statt :SetMeasure), einmal links, einmal rechts
- Nun brauch ich nur noch die Daten für :SetEntryNumber. in FCMusicRegion finde ich zwar StartMeasure und StartMeasurePos... aber nichts für Noten.
- Also sehe ich nach bei FCSmartShapeEntryMark und finde Methods wie :GetNoteEntry und :CalcLeftMark und Ähnliches aber hier strande ich...

Jetzt ist die Verwirrung komplett. Hab verschiedene Varianten ausprobiert - keine Syntax-Fehler, immerhin - aber ich stecke fest....
Muss ich mit den Methods aus der Class "FCSmartShapeEntryMark" die Daten für das Segment bekommen?
Oder reicht doch :GetTerminateSegmentLeft() aus FCSmartShapeSegment? (passiert aber nichts)
Oder bin ich ganz falsch? (wahrscheinlich...)
Hallo! Mein PC:
Windows 10 64bit
Finale 25.5.0.290

Benutzeravatar
Harald
Beiträge: 153
Registriert: Sa Aug 30, 2003 6:43 pm

Re: Lua Skript für Legatobögen per Tastatur

Beitrag von Harald » So Okt 28, 2018 12:55 pm

Auf der JWLua-Mailingliste wurde das im Juni 2016 schonmal hier diskutiert. Ich kopiere den Code mal hier rein, damit alles zusammen ist...:

Code: Alles auswählen

Chris marcel.denio at gmail.com 
Tue Jun 28 20:57:13 CEST 2016
Previous message (by thread): [JW Lua] Attaching a new entry-based custom smart line to a	score
Next message (by thread): [JW Lua] Attaching a new entry-based custom smart line to a	score
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Jan

Here is an example that works with 2 half-notes in the first measure.
There are 2 important things :
-  LineID : that is the index of the smartline (it's possible to have 
any line for glissando- but how do you know which one is right)
- NoteID : that is the position of the note in the chord

-----------------------------------------
local function createSmartShape(staff,measure,leftnoteentry,rightnoteentry)
     local smartshape = finale.FCSmartShape()
     smartshape.ShapeType = finale.SMARTSHAPE_GLISSANDO
     smartshape.EntryBased = true
     smartshape.MakeHorizontal = false
     smartshape.BeatAttached= false
     smartshape.PresetShape = true
     smartshape.Visible = true
     smartshape.LineID= 1

     local leftseg = smartshape:GetTerminateSegmentLeft()
     leftseg:SetMeasure(measure)
     leftseg.Staff = staff
     leftseg:SetEntry(leftnoteentry)
     leftseg.NoteID = 1

     local rightseg = smartshape:GetTerminateSegmentRight()
     rightseg:SetMeasure(measure)
     rightseg.Staff = staff
     rightseg:SetEntry(rightnoteentry)
     rightseg.NoteID = 1

     smartshape:SaveNewEverything(NULL,NULL)
end

local noteentrycell = finale.FCNoteEntryCell(1, 1)
noteentrycell:Load()
local leftnoteentry = noteentrycell:FindEntryStartPosition(0,1)
local rightnoteentry = noteentrycell:FindEntryStartPosition(2048,1)

createSmartShape(1,1,leftnoteentry,rightnoteentry)

-----------------------------------------


Chris
Wo ich aber selbst überlege ist, warum FCSmartShapeEntryMark nicht verwendet wird - dabei besagt doch die Dokumentation "A slur (and other note-attached smart shapes) would normally have two FCSmartShapeEntryMark records; one for the start entry and one for the end entry.". Ein Versuch, FCSmartShapeEntryMark zu verwenden, brachte mir eben Finale zum Absturz :|

Harald
Finale 3.0-25.5 / Windows 7

mas82
Beiträge: 38
Registriert: Mo Mai 08, 2017 10:00 pm

Re: Lua Skript für Legatobögen per Tastatur

Beitrag von mas82 » So Okt 28, 2018 10:18 pm

Vielen Dank, Harald! Der Tipp war super!

Ich hab nun das Script erneuert und es funktioniert... fast!

Ich kann die Bögen erzeugen allerdings immer nur bis zum Taktende und es muss mindestens ein Takt ausgewählt sein.
- liegt an ":IsLastMeasure()" in Zeile 42.

Code: Alles auswählen

local function createSmartShape(smeasure,sstaff,emeasure,estaff,leftnoteentry,rightnoteentry)
     local smartshape = finale.FCSmartShape()
     smartshape.ShapeType = finale.SMARTSHAPE_SLURAUTO
     smartshape.EntryBased = true
     smartshape.MakeHorizontal = false
     smartshape.BeatAttached= false
     smartshape.PresetShape = true
     smartshape.Visible = true
     smartshape.LineID= 1

     local leftseg = smartshape:GetTerminateSegmentLeft()
     leftseg:SetMeasure(smeasure)
     leftseg.Staff = sstaff
     leftseg:SetEntry(leftnoteentry)
     leftseg.NoteID = 1

     local rightseg = smartshape:GetTerminateSegmentRight()
     rightseg:SetMeasure(emeasure)
     rightseg.Staff = estaff
     rightseg:SetEntry(rightnoteentry)
     rightseg.NoteID = 1

     smartshape:SaveNewEverything(NULL,NULL)
end

function ebene()
	for noteentrylayer in eachentrysaved(finenv.Region()) do
	   return noteentrylayer.LayerNumber  -- Read-only property
	end
end

function erstenote()
	for noteeins in eachentrysaved(finenv.Region()) do
		
		return noteeins.MeasurePos  -- Read-only property
		
	end
end

function letztenote()
	for note in eachentrysaved(finenv.Region()) do
		if note:IsLastInMeasure() then 
		return note.MeasurePos  -- Read-only property
		end
	end
end

sm = finenv.Region().StartMeasure
ss = finenv.Region().StartStaff
em = finenv.Region().EndMeasure
es = finenv.Region().EndStaff

local noteentrycella = finale.FCNoteEntryCell(sm, ss)
noteentrycella:Load()
local noteentrycellb = finale.FCNoteEntryCell(em, es)
noteentrycellb:Load()
local leftnoteentry = noteentrycella:FindEntryStartPosition(erstenote(),ebene())
local rightnoteentry = noteentrycellb:FindEntryStartPosition(letztenote(),ebene())

createSmartShape(sm,ss,em,es,leftnoteentry,rightnoteentry)
Das Problem ist mir bekannt aber ich komme auf keine Lösung: In der Class FCNoteEntry kann ich eben nur den letzten Eintrag innerhalb eines Taktes anpeilen, in FCMusicRegion hingegen bekomme ich mit EndMeasurePos die Dauer der gesamten Auswahl und nicht die Endposition des letzten Eintrages. Wie bekomme ich den letzten NoteEntry am Ende der Auswahl?
Hallo! Mein PC:
Windows 10 64bit
Finale 25.5.0.290

Benutzeravatar
Harald
Beiträge: 153
Registriert: Sa Aug 30, 2003 6:43 pm

Re: Lua Skript für Legatobögen per Tastatur

Beitrag von Harald » Mo Okt 29, 2018 12:00 am

mas82 hat geschrieben:
So Okt 28, 2018 10:18 pm
Ich hab nun das Script erneuert und es funktioniert... fast!
Gratuliere :) !

Zum ersten und letzten Entry einer angewählten Region: man kann die aufwändige Lösung machen:

Code: Alles auswählen

-- Dieses JWLua-Skript sucht den ersten (=oben links) und letzten (=unten rechts) Entry in einer Auswahl
-- Alle Layer werden berücksichtigt
-- "NEC" = "NoteEntryCell"
local FirstNoteNEC = finale.FCNoteEntryCell(finenv.Region().StartMeasure, finenv.Region().StartStaff)
FirstNoteNEC:Load()
-- FindEntryStartPosition und FindNextEntryPos in Kombination erlauben unpräzise Anwahl des Start-Entries
local FirstEntryInRegion = FirstNoteNEC:FindEntryStartPosition(finenv.Region().StartMeasurePos, -1)
if ( FirstEntryInRegion == NULL) then
    FirstEntryInRegion = FirstNoteNEC:FindNextEntryPos(finenv.Region().StartMeasurePos)
end

local LastNoteNEC = finale.FCNoteEntryCell(finenv.Region().EndMeasure, finenv.Region().EndStaff)
LastNoteNEC:Load()
local RegionRightMeasurePos = finenv.Region().EndMeasurePos
-- Grenzt die Auswahl an den rechten Taktstrich? Dann die Taktdauer als RegionRightMeasurePos nehmen
if ( finenv.Region():IsAbsoluteEndMeasurePos() == true) then
    em = finale.FCMeasure()
    em:Load(finenv.Region().EndMeasure)
    RegionRightMeasurePos = em:GetDuration()
end
LastEntryInRegion = LastNoteNEC:FindPreviousEntryPos( RegionRightMeasurePos )


-- ToDo: Abfangen von NULL-Werten, falls kein First oder Last Entry gefunden wurde
-- Das kann passieren, falls im Anfangs- oder Endtakt keine Entries enthalten sind
print("FirstEntryInRegion  = ",FirstEntryInRegion.EntryNumber)
print("LastEntryInRegion = ",LastEntryInRegion.EntryNumber)
Es geht aber auch einfacher (und robuster!), worauf ich erst später gekommen bin 8) :

Code: Alles auswählen

local FirstEntry , LastEntry
for noteentry in eachentry(finenv.Region()) do
    if not FirstEntry then FirstEntry = noteentry end
    LastEntry = noteentry
end

if FirstEntry then print("First: ", FirstEntry.EntryNumber) end
if LastEntry then print("Last: ", LastEntry.EntryNumber) end
Finale 3.0-25.5 / Windows 7

Benutzeravatar
Harald
Beiträge: 153
Registriert: Sa Aug 30, 2003 6:43 pm

Re: Lua Skript für Legatobögen per Tastatur

Beitrag von Harald » Mo Okt 29, 2018 9:50 am

So funktioniert es bei mir und entspricht der Dokumentation, soweit ich es überblicke:

Code: Alles auswählen

function plugindef()
   finaleplugin.RequireSelection = true
   finaleplugin.MinFinaleVersion = "2025"
   finaleplugin.Author = "Harald Schollmeyer"
   finaleplugin.Version = "1.0"
   finaleplugin.Date = "29.10.2018"
   finaleplugin.AuthorEmail = "hschollm@gmx.net"
   finaleplugin.CategoryTags = "Measure, Region, Smartshape"
   return "AddSlur", "AddSlur", "Adds a slur spanning the selection"
end

-- function to create and assign an entry-attached slur
function MakeSlur( StartEntry, EndEntry)
    local smartshape = finale.FCSmartShape()
    smartshape.ShapeType = finale.SMARTSHAPE_SLURAUTO
    smartshape.EntryBased = true
    smartshape.BeatAttached= false
    smartshape.MakeHorizontal = false
    smartshape.PresetShape = true
    smartshape.Visible = true
    smartshape:SetSlurFlags( true )

    local leftseg = smartshape:GetTerminateSegmentLeft()
    leftseg.Measure = StartEntry.Measure
    leftseg.Staff = StartEntry.Staff
    leftseg:SetEntry(StartEntry)

    local rightseg = smartshape:GetTerminateSegmentRight()
    rightseg.Measure = EndEntry.Measure
    rightseg.Staff = EndEntry.Staff
    rightseg:SetEntry(EndEntry)

    smartshape:SaveNewEverything( StartEntry,EndEntry )
end

-- main program starts here
-- search first and last entry in selected region
local FirstEntry, LastEntry = nil, nil
for noteentry in eachentry(finenv.Region()) do
    if not FirstEntry then FirstEntry = noteentry end
    LastEntry = noteentry
end

-- if existing and not-identical entries are found, call function to add smart shape
if FirstEntry and LastEntry and (FirstEntry ~= LastEntry) then
MakeSlur( FirstEntry, LastEntry)
end
Ich stelle hier - und gleich auch auf der JWLua-Mailingliste - das Skript mit folgenden Fragen zur Diskussion:
1. obviously, FCSmartShapeEntryMark() isn't needed, although I would have thought, it would be necessary. What's it for?
2. smartshape:SaveNewEverything( NULL, NULL ) saves the smartshape as well as smartshape:SaveNewEverything( StartEntry,EndEntry ) although according to the documentation, only the second version would be correct
3. the FCSmartShape:SaveNewEverything documentation says: "For note-attached smart shapes, the frame collection that contains the entries need to be saved after the successful return from this method.". How do I save a frame collection? Using e.g. FCCellFrameHold (obviously more aimed at clef changes)?
4. FCSmartShape::SetSlurFlags( bool entrybased) says: "Configures the basic smart shape flags required for a slur.". What are these flags, are they of any importance for controlling slurs in JWLua scripts?

Harald
Finale 3.0-25.5 / Windows 7

mas82
Beiträge: 38
Registriert: Mo Mai 08, 2017 10:00 pm

Re: Lua Skript für Legatobögen per Tastatur

Beitrag von mas82 » Mo Okt 29, 2018 2:14 pm

Ich muss mich wieder mal verneigen... Danke vielmals!
Mit Shortcuts lassen sich Dynamikgabeln und nun auch die Bögen ruckzuck einfügen!
Macht viel Spaß!!

Das Skript zum Wählen des ersten und letzten Eintrags ist sehr nützlich! Werde ich in Ehren halten und häufig nutzen!
Wenn man das Skript so liest, dann wirkt die Lösung ganz naheliegend aber ich wäre trotzdem wohl nie darauf gekommen,
einen if-not-loop zum Aussieben des ersten Eintrages zu verwenden.

Jedenfalls wird meine wilde function-Konstruktion überflüssig, obwohl sie funktioniert. Immerhin: hab einiges dazugelernt in den letzten Tagen :wink:

Die Mailing-List ist noch ein sehr guter Hinweis - habe ich bis jetzt sträflich vernachlässigt. Das werde ich ändern und mich damit beschäftigen.

Jedenfalls möchte ich mich nochmals für deine großartige Hilfe bedanken, lieber Harald! Ohne sie würde ich immer noch auf der Stelle treten!
Hallo! Mein PC:
Windows 10 64bit
Finale 25.5.0.290

Antworten