]> git.donarmstrong.com Git - lilypond.git/commitdiff
Adds collision-voice-only property to beams.
authorMike Solomon <mike@apollinemike.com>
Fri, 8 Apr 2011 22:45:50 +0000 (18:45 -0400)
committerMike Solomon <mike@apollinemike.com>
Fri, 8 Apr 2011 22:45:50 +0000 (18:45 -0400)
The default is ##f, meaning that beams will attempt to not collide
with all of the grobs they cover.  Setting this to ##t only polices
collisions within a voice.

input/regression/beam-collision-voice-only.ly [new file with mode: 0644]
lily/beam-collision-engraver.cc
lily/beam.cc
lily/grob-info.cc
lily/include/grob-info.hh
scm/define-grob-properties.scm

diff --git a/input/regression/beam-collision-voice-only.ly b/input/regression/beam-collision-voice-only.ly
new file mode 100644 (file)
index 0000000..42755a4
--- /dev/null
@@ -0,0 +1,14 @@
+\version "2.13.59"
+\header {
+  texidoc = "Beam collision can be tweaked to only apply to the grobs
+within the beam's original voice."
+}
+
+\relative c' {
+  \time 5/4
+  << { c8[ s c ] } \\ { s8 c' s8 } >>
+  c,[ des' ]
+  \override Staff . Beam #'collision-voice-only = ##t
+  << { c,8[ s c ] } \\ { s8 c' s8 } >>
+  c,[ des'! ]
+}
index bdaa557570eb6963574043778779b18fd617fbd1..0f89eac89e8dc69484f7bfe336023981a4840536 100644 (file)
@@ -26,8 +26,8 @@
 class Beam_collision_engraver : public Engraver
 {
 protected:
-  vector<Grob *> beams_;
-  vector<Grob *> covered_grobs_;
+  vector<Grob_info> beams_;
+  vector<Grob_info> covered_grobs_;
 
   DECLARE_ACKNOWLEDGER (note_head);
   DECLARE_ACKNOWLEDGER (accidental);
@@ -67,41 +67,51 @@ Beam_collision_engraver::finalize ()
   if (!covered_grobs_.size ())
     return;
 
-  vector_sort (covered_grobs_, Grob::less);
-  vector_sort (beams_, Grob::less);
+  vector_sort (covered_grobs_, Grob_info::less);
+  vector_sort (beams_, Grob_info::less);
   vsize start = 0;
 
   for (vsize i = 0; i < beams_.size (); i++)
     {
-      Interval_t<int> beam_spanned_rank_ = beams_[i]->spanned_rank_interval ();
+      Grob *beam_grob = beams_[i].grob ();
+      Context *beam_context = beams_[i].context ();
+
+      Interval_t<int> beam_spanned_rank_ = beam_grob->spanned_rank_interval ();
       // Start considering grobs at the first grob whose end falls at or after the beam's beginning.
-      while (covered_grobs_[start]->spanned_rank_interval ()[RIGHT] < beam_spanned_rank_[LEFT])
+      while (covered_grobs_[start].grob ()->spanned_rank_interval ()[RIGHT] < beam_spanned_rank_[LEFT])
         start++;
 
       // Stop when the grob's beginning comes after the beam's end.
       for (vsize j = start; j < covered_grobs_.size (); j++)
         {
-          Interval_t<int> covered_grob_spanned_rank = covered_grobs_[j]->spanned_rank_interval ();
+          Grob *covered_grob = covered_grobs_[j].grob ();
+          Context *covered_grob_context = covered_grobs_[j].context ();
+
+          Interval_t<int> covered_grob_spanned_rank = covered_grob->spanned_rank_interval ();
           if ((covered_grob_spanned_rank[LEFT] > beam_spanned_rank_[RIGHT]
-              || !covered_grob_has_interface (covered_grobs_[j], beams_[i])))
+              || !covered_grob_has_interface (covered_grob, beam_grob)))
             break;
           /*
              Only consider grobs whose end falls at or after the beam's beginning.
-             If the grob is a beam, it cannot start before beams_[i]
+             If the grob is a beam, it cannot start before beams_[i].
+             Also, if the user wants to check for collisions only in the beam's voice,
+             then make sure the beam and the covered_grob are in the same voice.
           */
           if ((covered_grob_spanned_rank[RIGHT] >= beam_spanned_rank_[LEFT])
-              && !(Beam::has_interface (covered_grobs_[j])
+              && !(to_boolean (beam_grob->get_property ("collision-voice-only"))
+                   && (covered_grob_context != beam_context))
+              && !(Beam::has_interface (covered_grob)
                    && (covered_grob_spanned_rank[LEFT] <= beam_spanned_rank_[LEFT])))
             {
               // Do not consider note heads attached to the beam.
               bool my_beam = false;
-              if (Grob *stem = unsmob_grob (covered_grobs_[j]->get_object ("stem")))
+              if (Grob *stem = unsmob_grob (covered_grob->get_object ("stem")))
                 if (Grob *beam = unsmob_grob (stem->get_object ("beam")))
-                  if (beam == beams_[i])
+                  if (beam == beam_grob)
                     my_beam = true;
 
               if (!my_beam)
-                Pointer_group_interface::add_grob (beams_[i], ly_symbol2scm ("covered-grobs"), covered_grobs_[j]);
+                Pointer_group_interface::add_grob (beam_grob, ly_symbol2scm ("covered-grobs"), covered_grob);
             }
         }
     }
@@ -110,39 +120,39 @@ Beam_collision_engraver::finalize ()
 void
 Beam_collision_engraver::acknowledge_note_head (Grob_info i)
 {
-  covered_grobs_.push_back (i.grob ());
+  covered_grobs_.push_back (i);
 }
 
 void
 Beam_collision_engraver::acknowledge_accidental (Grob_info i)
 {
   if (i.grob ()->internal_has_interface (ly_symbol2scm ("inline-accidental-interface")))
-    covered_grobs_.push_back (i.grob ());
+    covered_grobs_.push_back (i);
 }
 
 void
 Beam_collision_engraver::acknowledge_clef (Grob_info i)
 {
-  covered_grobs_.push_back (i.grob ());
+  covered_grobs_.push_back (i);
 }
 
 void
 Beam_collision_engraver::acknowledge_key_signature (Grob_info i)
 {
-  covered_grobs_.push_back (i.grob ());
+  covered_grobs_.push_back (i);
 }
 
 void
 Beam_collision_engraver::acknowledge_time_signature (Grob_info i)
 {
-  covered_grobs_.push_back (i.grob ());
+  covered_grobs_.push_back (i);
 }
 
 void
 Beam_collision_engraver::acknowledge_beam (Grob_info i)
 {
-  beams_.push_back (i.grob ());
-  covered_grobs_.push_back (i.grob ());
+  beams_.push_back (i);
+  covered_grobs_.push_back (i);
 }
 
 #include "translator.icc"
index 6ae2ed4819bd43d75c03869a5be7085abf56b9ee..f39bf9f62c06e55f0914bf5e83004ad775b96bde 100644 (file)
@@ -1819,6 +1819,7 @@ ADD_INTERFACE (Beam,
               "clip-edges "
               "concaveness "
               "collision-interfaces "
+              "collision-voice-only "
               "covered-grobs "
               "damping "
               "details "
index fb1f366b9e26b794b0a231c21ce92055522a4ff1..f02e836e75389b80d601e7ddb9c12981682fb46d 100644 (file)
@@ -94,3 +94,9 @@ Grob_info::ultimate_event_cause () const
     }
   return unsmob_stream_event (cause);
 }
+
+bool
+Grob_info::less (Grob_info i, Grob_info j)
+{
+  return Grob::less (i.grob (), j.grob ());
+}
index cbe5a5f9df8852b35a35e79a05c011ebfd77b9f7..f9390fff446d16cede3c5345c766c97db75cbd2e 100644 (file)
@@ -48,6 +48,7 @@ public:
 
   Item *item () const;
   Spanner *spanner () const;
+  static bool less (Grob_info i, Grob_info j);
 };
 
 #endif // STAFFELEMINFO_HH
index 62d7cf070c14fab3791b193a90c262c266a17c21..3381cb9e27ed2858ea1decc3e88b31e4c1d5b97f 100644 (file)
@@ -172,6 +172,8 @@ edges of beams?")
 delimiter.  If equal or smaller, the bracket/brace/line is removed.")
      (collision-interfaces ,list? "A list of interfaces for which
 automatic beam-collision resolution is run.")
+     (collision-voice-only ,boolean? "Does automatic beam collsion apply
+only to the voice in which the beam was created?")
      (color ,color? "The color of this grob.")
      (common-shortest-duration ,ly:moment? "The most common shortest
 note length.  This is used in spacing.  Enlarging this sets the score