~ubuntu-branches/debian/jessie/banshee-community-extensions/jessie

« back to all changes in this revision

Viewing changes to src/ClutterFlow/ClutterFlow/CoverManager.cs

  • Committer: Package Import Robot
  • Author(s): Chow Loong Jin
  • Date: 2011-09-20 18:45:46 UTC
  • mfrom: (1.2.9 upstream) (5.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20110920184546-3ahue2qplydc4t0e
Tags: 2.2.0-1
* [4940fab] Imported Upstream version 2.2.0
  + Notable bug fixes:
    - Karaoke: Fix crash when switching to Now Playing
    - Lyrics: Fix crash when switching to Now Playing

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
 
37
37
namespace ClutterFlow
38
38
{
 
39
    public delegate void ActorEventHandler<T>(T actor, EventArgs e) where T : ClutterFlowBaseActor;
39
40
 
40
 
        public delegate void ActorEventHandler<T>(T actor, EventArgs e) where T : ClutterFlowBaseActor;
41
 
                                
42
 
        public class CoverManager : Clutter.Group {
 
41
    public class CoverManager : Clutter.Group {
43
42
 
44
43
        #region Events
45
 
                public event ActorEventHandler<ClutterFlowBaseActor> ActorActivated;
46
 
                internal void InvokeActorActivated (ClutterFlowBaseActor cover)
47
 
        {
48
 
                        if (ActorActivated!=null) ActorActivated (cover, EventArgs.Empty);
49
 
                }
50
 
                
51
 
                public event ActorEventHandler<ClutterFlowBaseActor> NewCurrentCover;
52
 
                protected void InvokeNewCurrentCover (ClutterFlowBaseActor cover)
53
 
        {
54
 
                        if (NewCurrentCover!=null) NewCurrentCover(cover, EventArgs.Empty);
55
 
                }
56
 
                
57
 
                public event EventHandler<EventArgs> CoversChanged;
58
 
                protected void InvokeCoversChanged ()
59
 
        {
60
 
                        if (CoversChanged!=null) CoversChanged(this, EventArgs.Empty);
61
 
                }
62
 
                
63
 
                public event EventHandler<EventArgs> TargetIndexChanged;
64
 
                protected void InvokeTargetIndexChanged ()
65
 
        {
66
 
                        if (TargetIndexChanged!=null) TargetIndexChanged(this, EventArgs.Empty);
67
 
                }
68
 
 
69
 
        public event EventHandler TextureSizeChanged;
70
 
        protected void InvokeTextureSizeChanged ()
71
 
                {
72
 
             //TODO use a timeout here, if the function is called mutliple times shortly after another, we don't get endless recalculation
73
 
            if (TextureSizeChanged!=null) TextureSizeChanged (this, EventArgs.Empty);
 
44
        public event ActorEventHandler<ClutterFlowBaseActor> ActorActivated;
 
45
        internal void InvokeActorActivated (ClutterFlowBaseActor cover)
 
46
        {
 
47
            var handler = ActorActivated;
 
48
            if (handler != null) {
 
49
                handler (cover, EventArgs.Empty);
 
50
            }
 
51
        }
 
52
 
 
53
        public event ActorEventHandler<ClutterFlowBaseActor> NewCurrentCover;
 
54
        protected void InvokeNewCurrentCover (ClutterFlowBaseActor cover)
 
55
        {
 
56
            var handler = NewCurrentCover;
 
57
            if (handler != null) {
 
58
                handler (cover, EventArgs.Empty);
 
59
            }
 
60
        }
 
61
 
 
62
        public event EventHandler<EventArgs> CoversChanged;
 
63
        protected void InvokeCoversChanged ()
 
64
        {
 
65
            var handler = CoversChanged;
 
66
            if (handler != null) {
 
67
                handler (this, EventArgs.Empty);
 
68
            }
 
69
        }
 
70
 
 
71
        public event EventHandler<EventArgs> TargetIndexChanged;
 
72
        protected void InvokeTargetIndexChanged ()
 
73
        {
 
74
            var handler = TargetIndexChanged;
 
75
            if (handler != null) {
 
76
                handler (this, EventArgs.Empty);
 
77
            }
74
78
        }
75
79
 
76
80
        public event EventHandler<EventArgs> VisibleCoversChanged;
77
81
        protected void InvokeVisibleCoversChanged ()
78
 
                {
79
 
            if (VisibleCoversChanged!=null) VisibleCoversChanged(this, EventArgs.Empty);
80
 
        }
81
 
                
82
 
                public event EventHandler<EventArgs> LetterLookupChanged;
83
 
                protected void InvokeLetterLookupChanged ()
84
 
                {
85
 
                        if (LetterLookupChanged!=null) LetterLookupChanged(this, EventArgs.Empty);;
86
 
                }
 
82
        {
 
83
            var handler = VisibleCoversChanged;
 
84
            if (handler != null) {
 
85
                handler (this, EventArgs.Empty);
 
86
            }
 
87
        }
 
88
 
 
89
        public event EventHandler<EventArgs> LetterLookupChanged;
 
90
        protected void InvokeLetterLookupChanged ()
 
91
        {
 
92
            var handler = LetterLookupChanged;
 
93
            if (handler != null) {
 
94
                handler (this, EventArgs.Empty);
 
95
            }
 
96
        }
87
97
 
88
98
        #endregion
89
99
 
90
100
        #region Fields
91
 
                protected ClutterFlowTimeline timeline;
92
 
                public ClutterFlowTimeline Timeline {
93
 
                        get {
94
 
                if (timeline==null) {
 
101
        private static TextureHolder texture_holder;
 
102
        public static TextureHolder TextureHolder {
 
103
            get { return texture_holder; }
 
104
        }
 
105
 
 
106
        protected ClutterFlowTimeline timeline;
 
107
        public ClutterFlowTimeline Timeline {
 
108
            get {
 
109
                if (timeline == null) {
95
110
                    timeline = new ClutterFlowTimeline(this);
96
111
                    timeline.TargetMarkerReached += HandleTargetMarkerReached;
97
112
                }
98
 
                                return timeline;
99
 
                        }
100
 
                }
101
 
 
102
 
                protected IActorLoader actorLoader;     //Loads the actors (detaches ClutterFlow from Banshee related dependencies)
103
 
                public IActorLoader ActorLoader {
104
 
                        get { return actorLoader; }
105
 
                        internal set { actorLoader = value; }
106
 
                }
107
 
                
108
 
                public Dictionary<AlphabetChars, int> letter_lookup;
109
 
                public Dictionary<AlphabetChars, int> LetterLookup {
110
 
                        get { return letter_lookup; }
111
 
                }
112
 
                
113
 
                public void ResetLetterLookup () {
114
 
                        letter_lookup = new Dictionary<AlphabetChars, int>();
115
 
                        foreach (AlphabetChars key in Enum.GetValues(typeof(AlphabetChars)))
116
 
                                letter_lookup.Add(key, -1);
117
 
                }
118
 
                public void UpdateLetterLookup (ClutterFlowBaseActor actor) {
119
 
                        string label = actor.SortLabel.ToUpper ().Normalize (System.Text.NormalizationForm.FormKD);
120
 
                        char letter = label.Length>0 ? char.Parse(label.Substring (0,1)) : '?';
 
113
                return timeline;
 
114
            }
 
115
        }
 
116
 
 
117
        protected IActorLoader actor_loader;    //Loads the actors (detaches ClutterFlow from Banshee related dependencies)
 
118
        public IActorLoader ActorLoader {
 
119
            get { return actor_loader; }
 
120
        }
 
121
 
 
122
        public Dictionary<AlphabetChars, int> letter_lookup;
 
123
        public Dictionary<AlphabetChars, int> LetterLookup {
 
124
            get { return letter_lookup; }
 
125
        }
 
126
 
 
127
        public void ResetLetterLookup () {
 
128
            letter_lookup = new Dictionary<AlphabetChars, int>();
 
129
            foreach (AlphabetChars key in Enum.GetValues(typeof(AlphabetChars)))
 
130
                letter_lookup.Add(key, -1);
 
131
        }
 
132
        public void UpdateLetterLookup (ClutterFlowBaseActor actor) {
 
133
            string label = actor.SortLabel.ToUpper ().Normalize (System.Text.NormalizationForm.FormKD);
 
134
            char letter = label.Length>0 ? char.Parse(label.Substring (0,1)) : '?';
121
135
            AlphabetChars key;
122
 
                        if (char.IsLetter(letter))
123
 
                                key = (AlphabetChars) letter;
124
 
                        else
125
 
                                key = AlphabetChars.unknown;
126
 
                        if (letter_lookup.ContainsKey (key) && letter_lookup[key] == -1)
127
 
                                letter_lookup[key] = actor.Index;
128
 
                }
129
 
                
130
 
                protected FlowBehaviour behaviour;
131
 
                public FlowBehaviour Behaviour {
132
 
                        get { return behaviour; }
133
 
                }
 
136
            if (char.IsLetter(letter))
 
137
                key = (AlphabetChars) letter;
 
138
            else
 
139
                key = AlphabetChars.unknown;
 
140
            if (letter_lookup.ContainsKey (key) && letter_lookup[key] == -1)
 
141
                letter_lookup[key] = actor.Index;
 
142
        }
 
143
 
 
144
        protected FlowBehaviour behaviour;
 
145
        public FlowBehaviour Behaviour {
 
146
            get { return behaviour; }
 
147
        }
134
148
        #endregion
135
149
 
136
150
        #region Cover-related fields
137
151
 
138
 
                protected int textureSize = 128;
139
 
                public int TextureSize {
140
 
                        get { return textureSize; }
141
 
                        set {
142
 
                                if (textureSize!=value) {
143
 
                                        textureSize = value;
144
 
                    InvokeTextureSizeChanged ();
145
 
                                }
146
 
                        }
147
 
                }
148
 
                
149
 
                protected int visibleCovers = 17;
150
 
                public int VisibleCovers {
151
 
                        get { return visibleCovers; }
152
 
                        set {
153
 
                                if (value!=visibleCovers) {
154
 
                                        visibleCovers = value;
 
152
        protected int texture_size;
 
153
        public int TextureSize {
 
154
            get { return texture_size; }
 
155
            set { texture_size = value; }
 
156
        }
 
157
 
 
158
        protected int visibleCovers = 17;
 
159
        public int VisibleCovers {
 
160
            get { return visibleCovers; }
 
161
            set {
 
162
                if (value != visibleCovers) {
 
163
                    visibleCovers = value;
155
164
                    InvokeVisibleCoversChanged ();
156
 
                                }
157
 
                        }
158
 
                }
159
 
                public int HalfVisCovers {
160
 
                        get { return (int) ((visibleCovers-1) * 0.5); }
161
 
                }
 
165
                }
 
166
            }
 
167
        }
 
168
        public int HalfVisCovers {
 
169
            get { return (int) ((visibleCovers-1) * 0.5); }
 
170
        }
162
171
        #endregion
163
172
 
164
173
        #region Animation duration limits
165
 
                protected static uint maxAnimationSpan = 250; //maximal length of a single step in the animations in ms
166
 
                public static uint MaxAnimationSpan {
167
 
                        get { return maxAnimationSpan; }
168
 
                }
169
 
                
170
 
                protected static uint minAnimationSpan = 10; //minimal length of a single step in the animations in ms
171
 
                public static uint MinAnimationSpan {
172
 
                        get { return minAnimationSpan; }
173
 
                }
174
 
                
175
 
                protected static uint doubleClickTime = 200;
176
 
                public static uint DoubleClickTime {
177
 
                        get { return doubleClickTime; }
178
 
                        set { doubleClickTime = value; }
179
 
                }
 
174
        protected static uint maxAnimationSpan = 250; //maximal length of a single step in the animations in ms
 
175
        public static uint MaxAnimationSpan {
 
176
            get { return maxAnimationSpan; }
 
177
        }
 
178
 
 
179
        protected static uint minAnimationSpan = 10; //minimal length of a single step in the animations in ms
 
180
        public static uint MinAnimationSpan {
 
181
            get { return minAnimationSpan; }
 
182
        }
 
183
 
 
184
        protected static uint doubleClickTime = 200;
 
185
        public static uint DoubleClickTime {
 
186
            get { return doubleClickTime; }
 
187
            set { doubleClickTime = value; }
 
188
        }
180
189
        #endregion
181
190
 
182
191
        #region Target/Current index handling
183
 
                private int target_index = 0;                   // curent targetted cover index
184
 
                public int TargetIndex {
185
 
                        get { return target_index; }
186
 
                        set {
187
 
                                if (value >= TotalCovers) value = TotalCovers-1;
188
 
                                if (value < 0) value = 0;
189
 
                                if (value!=target_index) {
 
192
        private int target_index = 0;            // curent targetted cover index
 
193
        public int TargetIndex {
 
194
            get { return target_index; }
 
195
            set {
 
196
                if (value >= TotalCovers) {
 
197
                    value = TotalCovers - 1;
 
198
                }
 
199
                if (value < 0) {
 
200
                    value = 0;
 
201
                }
 
202
                if (value != target_index) {
190
203
                    //Console.WriteLine ("TargetIndex_set to " + value);
191
204
                    target_index = value;
192
 
                    current_cover = null; //to prevent clicks to load the old centered cover!
 
205
                    // To prevent clicks to load the old centered cover!
 
206
                    current_cover = null;
193
207
                    InvokeTargetIndexChanged();
194
 
                                }
195
 
                        }
196
 
                }
 
208
                }
 
209
            }
 
210
        }
197
211
 
198
 
                public ClutterFlowBaseActor TargetActor {
199
 
                        get {
200
 
                                if (covers.Count > TargetIndex)
201
 
                                        return covers[TargetIndex];
202
 
                                else
203
 
                                        return null;
204
 
                        }
205
 
                }
 
212
        public ClutterFlowBaseActor TargetActor {
 
213
            get {
 
214
                if (covers.Count > TargetIndex)
 
215
                    return covers[TargetIndex];
 
216
                else
 
217
                    return null;
 
218
            }
 
219
        }
206
220
 
207
221
        protected ClutterFlowFixedActor empty_actor;
208
222
        public ClutterFlowFixedActor EmptyActor {
209
223
            get {
210
 
                if (empty_actor==null)
211
 
                    empty_actor = new ClutterFlowFixedActor (this);
 
224
                if (empty_actor == null)
 
225
                    empty_actor = new ClutterFlowFixedActor ((uint)behaviour.CoverWidth);
212
226
                return empty_actor;
213
227
            }
214
228
        }
215
229
 
216
 
        internal List<ClutterFlowBaseActor> covers;     // list with cover actors
217
 
        public int TotalCovers  {               // number of covers or zero if null
 
230
        // list with cover actors
 
231
        private List<ClutterFlowBaseActor> covers;
 
232
        public List<ClutterFlowBaseActor> Covers {
 
233
            get { return covers; }
 
234
        }
 
235
 
 
236
        public int TotalCovers  {
218
237
            get { return (covers != null) ? covers.Count : 0; }
219
238
        }
220
239
 
221
 
        private ClutterFlowBaseActor current_cover = null; // currently centered cover
 
240
        // currently centered cover
 
241
        private ClutterFlowBaseActor current_cover = null;
222
242
        public ClutterFlowBaseActor CurrentCover {
223
243
            get { return current_cover; }
224
244
            set {
225
 
                if (value!=current_cover) {
 
245
                if (value != current_cover) {
226
246
                    current_cover = value;
227
247
                    InvokeNewCurrentCover (current_cover);
228
248
                }
230
250
        }
231
251
        #endregion
232
252
 
233
 
                protected bool needs_reloading = false;
234
 
                public bool NeedsReloading {
235
 
                        get { return needs_reloading; }
236
 
                        internal set { needs_reloading = value; }
237
 
                }
 
253
        protected bool needs_reloading = false;
 
254
        public bool NeedsReloading {
 
255
            get { return needs_reloading; }
 
256
            internal set { needs_reloading = value; }
 
257
        }
238
258
 
239
259
        #region Initialisation
240
 
                public CoverManager () : base ()
241
 
                {
242
 
                        behaviour = new FlowBehaviour (this);                   
243
 
                }
 
260
        public CoverManager (IActorLoader actor_loader, GetDefaultSurface get_default_surface, int texture_size) : base ()
 
261
        {
 
262
            this.actor_loader = actor_loader;
 
263
            this.texture_size = texture_size;
 
264
            behaviour = new FlowBehaviour (this);
 
265
            texture_holder = new TextureHolder (texture_size, get_default_surface);
 
266
        }
244
267
 
245
268
        public override void Dispose ()
246
269
        {
248
271
                GLib.Source.Remove (reload_timeout);
249
272
            }
250
273
 
251
 
            ActorLoader.Dispose ();
252
 
            Behaviour.Dispose ();
 
274
            behaviour.Dispose ();
253
275
            timeline.Dispose ();
254
276
 
255
277
            covers.Clear ();
266
288
        }*/
267
289
 
268
290
 
269
 
                public void UpdateBehaviour ()
270
 
                {
271
 
                        if (behaviour!=null && Stage!=null) {
272
 
                                behaviour.Height = Stage.Height;
273
 
                                behaviour.Width = Stage.Width;
274
 
                                //Console.WriteLine ("behaviour.CoverWidth = " + behaviour.CoverWidth + "behaviour.Height = " + behaviour.Height + " behaviour.Width = " + behaviour.Width);
275
 
                        }
276
 
                }
 
291
        public void UpdateBehaviour ()
 
292
        {
 
293
            if (behaviour != null && Stage != null) {
 
294
                behaviour.Height = Stage.Height;
 
295
                behaviour.Width = Stage.Width;
 
296
                //Console.WriteLine ("behaviour.CoverWidth = " + behaviour.CoverWidth + "behaviour.Height = " + behaviour.Height + " behaviour.Width = " + behaviour.Width);
 
297
            }
 
298
        }
277
299
 
278
 
                void HandleTargetMarkerReached(object sender, TargetReachedEventArgs args)
279
 
                {
280
 
                        if (args.Target==TargetIndex) {
281
 
                                if (covers.Count > args.Target)
 
300
        void HandleTargetMarkerReached(object sender, TargetReachedEventArgs args)
 
301
        {
 
302
            if (args.Target==TargetIndex) {
 
303
                if (covers.Count > args.Target) {
282
304
                    CurrentCover = covers[(int) args.Target];
283
 
                else
 
305
                } else {
284
306
                    CurrentCover = null;
285
 
                        }
286
 
                }
287
 
                
288
 
                private uint reload_timeout = 0;
289
 
                internal void ReloadCovers ()
290
 
                {
291
 
                        if (reload_timeout > 0)
292
 
                                GLib.Source.Remove(reload_timeout);
293
 
                        reload_timeout = GLib.Timeout.Add (MaxAnimationSpan, new GLib.TimeoutHandler (reload_covers));
294
 
                }
295
 
 
296
 
        private bool reload_covers ()
297
 
        {                       
298
 
                        if (Timeline!=null) Timeline.Pause ();
299
 
            HideAll (); Show ();
300
 
                        if (covers!=null && covers.Count!=0) {
301
 
                                Console.WriteLine("Reloading Covers");
302
 
                                
303
 
                                int old_target_index = CurrentCover!=null ? covers.IndexOf (CurrentCover) : 0;          // the old current index
304
 
                                int new_target_index = 0;                                       // the newly calculated index
305
 
                                bool keep_current = false;                                      // wether or not to keep the current cover centered
306
 
 
307
 
                                List<ClutterFlowBaseActor> old_covers = new List<ClutterFlowBaseActor>(SafeGetRange(covers, old_target_index - HalfVisCovers - 1, visibleCovers + 2));
308
 
                                foreach (ClutterFlowBaseActor actor in covers) {
309
 
                    if (actor.Data.ContainsKey ("isOldCover")) actor.Data.Remove ("isOldCover");
 
307
                }
 
308
            }
 
309
        }
 
310
 
 
311
        private uint reload_timeout = 0;
 
312
        public void ReloadCovers ()
 
313
        {
 
314
            if (reload_timeout > 0) {
 
315
                GLib.Source.Remove(reload_timeout);
 
316
            }
 
317
            reload_timeout = GLib.Timeout.Add (MaxAnimationSpan, new GLib.TimeoutHandler (reload_covers));
 
318
        }
 
319
 
 
320
         private bool reload_covers ()
 
321
         {
 
322
            if (Timeline != null) {
 
323
                Timeline.Pause ();
 
324
            }
 
325
            HideAll ();
 
326
            Show ();
 
327
            if (covers != null && covers.Count != 0) {
 
328
                Console.WriteLine("ClutterFlow - Reloading Covers");
 
329
 
 
330
                // the old current index
 
331
                int old_target_index = CurrentCover!=null ? covers.IndexOf (CurrentCover) : 0;
 
332
                // the newly calculated index
 
333
                int new_target_index = 0;
 
334
                // whether or not to keep the current cover centered
 
335
                bool keep_current = false;
 
336
 
 
337
                List<ClutterFlowBaseActor> old_covers = new List<ClutterFlowBaseActor> (
 
338
                    SafeGetRange (covers, old_target_index - HalfVisCovers - 1, visibleCovers + 2));
 
339
                foreach (ClutterFlowBaseActor actor in covers) {
 
340
                    if (actor.Data.ContainsKey ("isOldCover")) {
 
341
                        actor.Data.Remove ("isOldCover");
 
342
                    }
310
343
                    actor.Index = -1;
311
 
                    if (old_covers.Contains (actor))
 
344
                    if (old_covers.Contains (actor)) {
312
345
                        actor.Data.Add ("isOldCover", true);
313
 
                                }
 
346
                    }
 
347
                }
314
348
 
315
 
                                ResetLetterLookup ();
 
349
                ResetLetterLookup ();
316
350
                List<ClutterFlowBaseActor> persistent_covers = new List<ClutterFlowBaseActor>();
317
 
                        
318
 
                                covers = new List<ClutterFlowBaseActor>(actorLoader.GetActors (delegate (ClutterFlowBaseActor actor) {
319
 
                    if (actor.Data.ContainsKey ("isOldCover"))
 
351
 
 
352
                covers = actor_loader.GetActors (this);
 
353
                covers.ForEach (delegate (ClutterFlowBaseActor actor) {
 
354
                    if (actor.Data.ContainsKey ("isOldCover")) {
320
355
                        persistent_covers.Add (actor);
321
 
                    if (CurrentCover==actor) keep_current = true;
322
 
                                        
323
 
                                        UpdateLetterLookup (actor);
324
 
                                }));
325
 
                                InvokeLetterLookupChanged ();
326
 
                                
327
 
                if (covers.Count==0) {
 
356
                    }
 
357
                    if (CurrentCover==actor) {
 
358
                        keep_current = true;
 
359
                    }
 
360
 
 
361
                    UpdateLetterLookup (actor);
 
362
                });
 
363
                InvokeLetterLookupChanged ();
 
364
 
 
365
                if (covers.Count == 0) {
328
366
                    InstallEmptyActor ();
329
 
                                        if (old_covers.Contains(EmptyActor)) {
330
 
                                                EmptyActor.Show ();
331
 
                                                return false;
332
 
                                        }
333
 
                                        keep_current = true;
 
367
                    if (old_covers.Contains (EmptyActor)) {
 
368
                        EmptyActor.Show ();
 
369
                        return false;
 
370
                    }
 
371
                    keep_current = true;
334
372
                }
335
373
 
336
 
                                //recalculate timeline progression and the target index
337
 
                                if (covers.Count > 1) {
338
 
                                        if (keep_current)
339
 
                                                new_target_index = CurrentCover.Index;
340
 
                                        else {
341
 
                        if (persistent_covers.Count==0)
 
374
                //recalculate timeline progression and the target index
 
375
                if (covers.Count > 1) {
 
376
                    if (keep_current) {
 
377
                        new_target_index = CurrentCover.Index;
 
378
                    } else {
 
379
                        if (persistent_covers.Count==0) {
342
380
                            new_target_index = (int) Math.Round(Timeline.Progress * (covers.Count-1));
343
 
                        else if (persistent_covers.Count==1)
 
381
                        } else if (persistent_covers.Count==1) {
344
382
                            new_target_index = persistent_covers[0].Index;
345
 
                        else
 
383
                        } else {
346
384
                            new_target_index = persistent_covers[(int) (((float) persistent_covers.Count * 0.5f) - 1.0f)].Index;
 
385
                        }
347
386
                    }
348
 
                                }
 
387
                }
349
388
                TargetIndex = new_target_index;
350
389
                Timeline.JumpToTarget ();
351
390
 
352
391
                //Console.WriteLine ("Timeline progress set to " + Timeline.Progress + " Timeline.RelativeTarget is " + Timeline.RelativeTarget);
353
392
 
354
393
                List<ClutterFlowBaseActor> truly_pers = new List<ClutterFlowBaseActor> ();
355
 
                                List<ClutterFlowBaseActor> new_covers = new List<ClutterFlowBaseActor>(SafeGetRange(covers, new_target_index - HalfVisCovers - 1, visibleCovers + 2));
 
394
                List<ClutterFlowBaseActor> new_covers = new List<ClutterFlowBaseActor>(SafeGetRange(covers, new_target_index - HalfVisCovers - 1, visibleCovers + 2));
356
395
                foreach (ClutterFlowBaseActor actor in persistent_covers) {
357
 
                    if (actor!=null) {
358
 
                        if (actor.Data.ContainsKey ("isOldCover"))
 
396
                    if (actor != null) {
 
397
                        if (actor.Data.ContainsKey ("isOldCover")) {
359
398
                            actor.Data.Remove ("isOldCover");
 
399
                        }
360
400
                        if (new_covers.Contains (actor)) {
361
401
                            truly_pers.Add (actor);
362
402
                            new_covers.Remove (actor);
366
406
                    }
367
407
                }
368
408
                foreach (ClutterFlowBaseActor actor in old_covers) {
369
 
                    if (actor!=null) actor.Data.Remove ("isOldCover");
 
409
                    if (actor != null) {
 
410
                        actor.Data.Remove ("isOldCover");
 
411
                    }
370
412
                }
371
413
 
372
414
                /*Console.WriteLine ("old_covers          contains " + old_covers.Count + " elements:");
385
427
                };
386
428
 
387
429
                Behaviour.FadeCoversInAndOut (old_covers, truly_pers, new_covers, update_target);
388
 
                        } else {
389
 
                                //Console.WriteLine("Loading Covers");
390
 
                                ResetLetterLookup ();
391
 
                                covers = actorLoader.GetActors (UpdateLetterLookup);
392
 
                                InvokeLetterLookupChanged ();
 
430
            } else {
 
431
                Console.WriteLine("ClutterFlow - Loading Covers");
 
432
                ResetLetterLookup ();
 
433
                covers = actor_loader.GetActors (this);
 
434
                covers.ForEach (UpdateLetterLookup);
 
435
                InvokeLetterLookupChanged ();
393
436
                TargetIndex = 0;
394
437
                Timeline.JumpToTarget ();
395
438
                if (covers==null || covers.Count==0) {
396
439
                    InstallEmptyActor ();
397
 
                                        Behaviour.UpdateActors ();
 
440
                    Behaviour.UpdateActors ();
398
441
                    Behaviour.FadeInActor (EmptyActor);
399
442
                }
400
443
                Timeline.Play ();
401
 
                                InvokeCoversChanged ();
402
 
                        }
403
 
                        
404
 
                        return false;
405
 
                }
 
444
                InvokeCoversChanged ();
 
445
            }
 
446
 
 
447
            return false;
 
448
        }
406
449
 
407
450
        private void InstallEmptyActor ()
408
451
        {
410
453
            covers.Add (EmptyActor);
411
454
            CurrentCover = EmptyActor;
412
455
        }
413
 
                
414
456
 
415
 
                private IEnumerable<ClutterFlowBaseActor> SafeGetRange(List<ClutterFlowBaseActor> list, int index, int count) {
416
 
                        for (int i = index; i < index + count; i++) {
417
 
                                ClutterFlowBaseActor cover;
418
 
                                try {
419
 
                                        cover = list[i];
420
 
                    if (cover==null) throw new NullReferenceException();
421
 
                                } catch {
 
457
        private IEnumerable<ClutterFlowBaseActor> SafeGetRange (List<ClutterFlowBaseActor> list, int index, int count) {
 
458
            for (int i = index; i < index + count; i++) {
 
459
                ClutterFlowBaseActor cover = null;
 
460
                if (i >= 0 && i < list.Count) {
 
461
                    cover = list[i];
 
462
                }
 
463
                if (cover == null) {
422
464
                    continue;
423
 
                                }
 
465
                }
424
466
                yield return cover;
425
 
                        }
426
 
                        yield break;
427
 
                }
428
 
                
429
 
                public void ForSomeCovers(System.Action<ClutterFlowBaseActor> method_call, int lBound, int uBound) {
430
 
                        if (covers!=null && lBound <= uBound && lBound >= 0 && uBound < covers.Count) {
431
 
                                IEnumerator<ClutterFlowBaseActor> enumerator = covers.GetRange(lBound, uBound-lBound + 1).GetEnumerator();
432
 
                                while (enumerator.MoveNext())
433
 
                                        method_call(enumerator.Current);
434
 
                        }
435
 
                }
436
 
                
437
 
                public void ForEachCover(System.Action<ClutterFlowBaseActor> method_call) {
438
 
                        if (covers!=null) {
439
 
                                IEnumerator<ClutterFlowBaseActor> enumerator = covers.GetEnumerator();
440
 
                                while (enumerator.MoveNext())
441
 
                                        method_call(enumerator.Current);
442
 
                        }
443
 
                }
444
 
        }
445
 
}
 
 
b'\\ No newline at end of file'
 
467
            }
 
468
            yield break;
 
469
        }
 
470
 
 
471
        public void ForSomeCovers (System.Action<ClutterFlowBaseActor> method_call, int lBound, int uBound) {
 
472
            if (covers != null && lBound <= uBound && lBound >= 0 && uBound < covers.Count) {
 
473
                IEnumerator<ClutterFlowBaseActor> enumerator = covers.GetRange(lBound, uBound-lBound + 1).GetEnumerator();
 
474
                while (enumerator.MoveNext()) {
 
475
                    method_call(enumerator.Current);
 
476
                }
 
477
            }
 
478
        }
 
479
    }
 
480
}