-- Version 0.2 -- Hist: 0.2 Corrected initial comment -- 0.3 Corrected bug with boundaries with unchecked lower/upper -- 0.4 Corrected bug when other user objects are around --[[-------------------------------------------------------------------------- This plugin will connect barlines with the staff below. You must specify if the current staff is Upper, Middle or Lower staff in order to draw connections correctly. --]]-------------------------------------------------------------------------- ---- Necessary testcases: ---- Legend: ---- B boundary u/l=with upper/lower value; r=reset ---- C connect f=staffsig<>None,n=staffsig=None,s=standard ---- S collapsible section s=start, f=forbid ---- # staff breaks ---- $ ending bar ---- | bar line ---- ... other things in staff ---- + expect correctly drawn connect lines ---- - expect no connect lines ---- ---- staffsig/standard working ---- TestC1: Cf ... +# ... +# ... +$ ---- TestC2: ... -# ... Cf ... +# ... +# ... +$ ---- TestC3: ... -# ... Cf ... +# ... +# ... Cn ... -# ... -$ ---- TestC4: ... -# ... -# ... Cs +| ... -| ... -# ... -$ ---- TestC5: ... -# ... Cf ... +# ... Cs +| ... -| ... +# ... Cn ... -# ... -$ ---- ---- boundary working ---- TestB1: Cf ... +# ... Bul(larger) ... +# ... +# ... +# ... +$ ---- TestB2: Cf ... +# ... Bul(larger) ... +# ... +# ... Br ... +# ... +$ ---- TestB3: Cf ... +# ... Bul(larger) ... +# ... Bul(larger) ... +# ... +$ ---- TestB4: Cf ... +# ... Bul(larger) ... +# ... Bul(smaller) ... +# ... +$ ---- TestB5: Cf ... +# ... Bul(larger) ... Bul(larger) ... +# ... +$ ---- TestB6: Cf ... +# ... Bul(larger) ... Bul(smaller) ... +# ... +$ ---- TestB7: Cf ... +# ... Bul(larger) ... +# ... +# ... Br ... Bul(larger) ... +# ... +$ ---- TestB8: Cf ... +# ... Bul(larger) ... +# ... +# ... Br ... Bul(smaller) ... +# ... +$ ---- TestB9: Cf ... +# ... Bu(larger) ... +# ... +# ... Br ... +# ... +$ ---- ---- collapsing ---- TestD1: Cf ... +# ... Sc ... +# ... Bul(larger) ... # ... Sf ... +# ... +# ... +$ ---- ---- TestD2: Cf ... +# ... Sc ... +# ... ... +# ... +# ... Sf ... +# ... +$ ---- Cf ... +# ... ... +# ... Cf(without conn to collapsed) ... +# ... +# ... Cf(conn to uncollapsed) ... +# ... +$ ---- ---- TestD3: Cf ... +# ... Sc ... +# ... +# ... Sf ... +# ... +$ ---- Cf ... +# ... Cf(without conn to collapsed) ... +# ... +# ... Cf(conn to uncollapsed) ... +# ... +$ ---- ---- top, bottom and middle working ---- TestE8: Like B8, with top & bottom ---- TestF8: Like B8, with top & middle & bottom local userObjTypeName = ... local drawpos = nwcdraw.user local printedStaffIterator = nwc.drawpos local fullScoreIterator = nwc.ntnidx.new() local barToEnlarge = nwc.drawpos.new() local object_spec = { { id='System', label='Staff Location', type='enum', default='Top Staff', list={'Top Staff', 'Middle Staff', 'Bottom Staff', 'None'}}, { id='Delayed', label='Active after next break (useful if other staff collapses)', type='bool', default=false}, } local function do_create(t) t.Class = 'StaffSig' end local function do_draw(t) ---- nwc.debug("c0") local isStaffSig = (t.Class == 'StaffSig') local w = nwc.toolbox.drawStaffSigLabel('ConnectBarLines') if not nwcdraw.isDrawing() then return w end ---- nwc.debug("c1") -- if nwcdraw.getTarget() ~= 'print' then return end ------ nwc.debug("c2") if drawpos:isHidden() then return end ---- nwc.debug("c3") local yPosTop local yPosBottom local setTopIfNil = function(value, offset) ---- nwc.debug("setTopIfNil", value) if not yPosTop and value then yPosTop = value + offset end end local setBottomIfNil = function(value, offset) ---- nwc.debug("setBottomIfNil", value) if not yPosBottom and value then yPosBottom = value + offset end end local setTopToMax = function(value, offset) ---- nwc.debug("setTopToMax", type(yPosTop), type(value), yPosTop, value) if value and yPosTop < value + offset then yPosTop = value + offset end end local setBottomToMax = function(value, offset) ---- nwc.debug("setBottomToMax", type(yPosBottom), type(value), yPosBottom, value) if value and yPosBottom < value + offset then yPosBottom = value + offset end end local setTopBottom = function(idx,setTop,setBottom) if idx:objType() == 'Boundary' and idx:objProp('Style') == 'NewSize' then ---- nwc.debug("setTopBottom1", idx:objProp('Upper'), idx:objProp('Lower')) setTop(idx:objProp('Upper'), 4) setBottom(idx:objProp('Lower'), 4) ---- nwc.debug("setTopBottom1r", yPosTop, yPosBottom) elseif idx:objType() == 'Boundary' and idx:objProp('Style') == 'Reset' then ---- nwc.debug("setTopBottom2", nwcdraw.getStaffProp('BoundaryTop'), nwcdraw.getStaffProp('BoundaryBottom')) setTop(nwcdraw.getStaffProp('BoundaryTop'), 0) setBottom(nwcdraw.getStaffProp('BoundaryBottom'), 0) ---- nwc.debug("setTopBottom2r", yPosTop, yPosBottom) elseif idx:objType() == 'Text' then ---- nwc.debug("t", idx:objProp('Text')) end end local me = nwcdraw.user -- don't do anything when hidden if me:isHidden() then return end ---- nwc.debug("c4") -- also don't do anything when explicitly delayed, and -- we are the "real" (not auto-inserted) one if t.Delayed and not me:isAutoInsert() then return end ---- nwc.debug("c5") -- the actual drawing of staffsig-controlled bar lines is defined by the -- *rightmost* staffsig ConnectBarLines in the printed staff; -- so if there is another staffsig item to the right of the current, we dont -- do anything (this makes e.g. "None" shut off bar line drawing, even though -- there is that autoInserted one at the beginning of the same printed staff) -- However, a "delayed" instance is ignored at its actual position (i.e., -- when it is not auto-inserted) printedStaffIterator:reset() while printedStaffIterator:find('next', user, userObjTypeName) do ---- nwc.debug("c5a", printedStaffIterator:objType()) if printedStaffIterator:userType() == userObjTypeName and printedStaffIterator:objProp('Class') == 'StaffSig' then if printedStaffIterator:objProp('Delayed') and not printedStaffIterator:isAutoInsert() then -- ignore it else -- there is an active one to the right - the current instance is not active return end end end ---- nwc.debug("c6") -- Algorithm for finding the right size to draw: -- a. Find boundary values at beginning of printed staff (by running back over score) -- b. Find largest values inside printed staff -- Step a. -- start from the start of the current printed staff printedStaffIterator:reset() -- now at current object (might be in middle of printed staff) printedStaffIterator:find('first', 'bar') -- now at beginning of printed staff -- run backwards to find nearest definitions of boundaries fullScoreIterator:find(printedStaffIterator) while fullScoreIterator:find('prior') do setTopBottom(fullScoreIterator,setTopIfNil,setBottomIfNil) end -- if none found, use staff sizes setTopIfNil(nwcdraw.getStaffProp('BoundaryTop'), 0) setBottomIfNil(nwcdraw.getStaffProp('BoundaryBottom'), 0) ---- nwc.debug("c7", yPosTop, yPosBottom) -- Step b. printedStaffIterator:reset() -- now at current object printedStaffIterator:find('last', 'bar') -- now at last bar but one printedStaffIterator:find('next', 'bar') -- now at last bar -- run over printed staff to find maximum while printedStaffIterator:find('prior') do setTopBottom(printedStaffIterator,setTopToMax,setBottomToMax) end -- yPosTop and yPosBottom are now correctly set -- Find the bar that is to be enlarged local found barToEnlarge:reset() -- now at current object if isStaffSig then barToEnlarge:find('last', 'bar') -- now at last bar but one found = barToEnlarge:find('next', 'bar') -- now at last bar else found = barToEnlarge:find('next', 'bar') -- now at next bar end if found then -- we found a bar - finally draw the enlargement lines local x,y = barToEnlarge:xyAnchor() local barType = barToEnlarge:objProp('Style') if t.System == 'Top Staff' then nwcdraw.moveTo(x,y) nwcdraw.barSegment(barType,y-4,y-yPosBottom) elseif t.System == 'Middle Staff' then nwcdraw.moveTo(x,y) nwcdraw.barSegment(barType,y+yPosTop,y+4) nwcdraw.moveTo(x,y) nwcdraw.barSegment(barType,y-4,y-yPosBottom) elseif t.System == 'Bottom Staff' then nwcdraw.moveTo(x,y) nwcdraw.barSegment(barType,y+yPosTop,y+4) end end end return { spec = object_spec, create = do_create, width = do_draw, draw = do_draw, }