/// <summary> /// Notifies this refresh manager that an area of the corresponding ViewPort is hidden by another ViewPort. /// </summary> /// <param name="otherVPR"> /// The refresh manager of the other ViewPort that hides the given area from the ViewPort corresponding to this /// refresh manager. /// </param> /// <param name="area">The area that is hidden (in the Display coordinate system).</param> public void AddHiddenArea(ViewPortRefreshMgr otherVPR, Rectangle area) { for (int idx = 0; idx < this.dirtyRectsDC.Count; idx++) { if (area.Contains(this.dirtyRectsDC[idx])) { /// If the given area hides the current dirty rectangle, then it has to be /// removed from the refresh list because it is hidden. this.dirtyRectsDC[idx] = Rectangle.Empty; this.dirtyRectsVPC[idx] = Rectangle.Empty; } else { /// If the given area intersects the current dirty rectangle, then the intersection /// has to be added to the refresh list of the other refresh manager. Rectangle intersection = Rectangle.Intersect(this.dirtyRectsDC[idx], area); if (!intersection.IsEmpty) { otherVPR.dirtyRectsDC.Add(intersection); otherVPR.dirtyRectsVPC.Add(new Rectangle(intersection.X - otherVPR.targetVP.X, intersection.Y - otherVPR.targetVP.Y, intersection.Width, intersection.Height)); } } /// TODO: Here we could implement an optimalization: remove the parts of the current dirty /// rectangle that are hidden. This is difficult to implement as there are a lot of cases to /// handle but later we may implement this optimalization if necessary. } }
/// <summary> /// Sends the given ViewPort backward one step in the Z-order. /// </summary> /// <param name="vp">The ViewPort you want to send backward.</param> /// <remarks> /// If the given ViewPort is not registered or is the bottommost ViewPort of the Display then this function /// has no effect. /// Call this from the render thread. /// </remarks> private void SendViewPortBackward_i(ViewPort vp) { lock (this.viewPorts) { int vpIndex = this.viewPorts.IndexOf(vp); if (vpIndex > 0) { /// Swap the given ViewPort and the ViewPort behind it. ViewPortRefreshMgr vpr = this.vpRefreshers[vpIndex]; this.viewPorts[vpIndex] = this.viewPorts[vpIndex - 1]; this.viewPorts[vpIndex - 1] = vp; this.vpRefreshers[vpIndex] = this.vpRefreshers[vpIndex - 1]; this.vpRefreshers[vpIndex - 1] = vpr; } } }
/// <summary> /// Brings the given ViewPort forward one step in the Z-order. /// </summary> /// <param name="vp">The ViewPort you want to bring forward.</param> /// <remarks> /// If the given ViewPort is not registered or is the topmost ViewPort of the Display then this function /// has no effect. /// Call this from the render thread. /// </remarks> private void BringViewPortForward_i(ViewPort vp) { lock (this.viewPorts) { int vpIndex = this.viewPorts.IndexOf(vp); if (-1 != vpIndex && vpIndex < this.viewPorts.Count - 1) { /// Swap the given ViewPort and the ViewPort in front of it. ViewPortRefreshMgr vpr = this.vpRefreshers[vpIndex]; this.viewPorts[vpIndex] = this.viewPorts[vpIndex + 1]; this.viewPorts[vpIndex + 1] = vp; this.vpRefreshers[vpIndex] = this.vpRefreshers[vpIndex + 1]; this.vpRefreshers[vpIndex + 1] = vpr; } } }
/// <summary> /// Sends the given ViewPort to the bottom of the Z-order. /// </summary> /// <param name="vp">The ViewPort you want to send to the bottom.</param> /// <remarks> /// If the given ViewPort is not registered or is the bottommost ViewPort of the Display then this function /// has no effect. /// Call this from the render thread. /// </remarks> private void SendViewPortBottom_i(ViewPort vp) { lock (this.viewPorts) { int vpIndex = this.viewPorts.IndexOf(vp); if (vpIndex > 0) { ViewPortRefreshMgr vpr = this.vpRefreshers[vpIndex]; for (int i = vpIndex; i > 0; i--) { this.viewPorts[i] = this.viewPorts[i - 1]; this.vpRefreshers[i] = this.vpRefreshers[i - 1]; } this.viewPorts[0] = vp; this.vpRefreshers[0] = vpr; } } }
/// <summary> /// Brings the given ViewPort to the top of the Z-order. /// </summary> /// <param name="vp">The ViewPort you want to bring to the top.</param> /// <remarks> /// If the given ViewPort is not registered or is the topmost ViewPort of the Display then this function /// has no effect. /// Call this from the render thread. /// </remarks> private void BringViewPortTop_i(ViewPort vp) { lock (this.viewPorts) { int vpIndex = this.viewPorts.IndexOf(vp); if (-1 != vpIndex && vpIndex < this.viewPorts.Count - 1) { ViewPortRefreshMgr vpr = this.vpRefreshers[vpIndex]; for (int i = vpIndex; i < this.viewPorts.Count - 1; i++) { this.viewPorts[i] = this.viewPorts[i + 1]; this.vpRefreshers[i] = this.vpRefreshers[i + 1]; } this.viewPorts[this.viewPorts.Count - 1] = vp; this.vpRefreshers[this.vpRefreshers.Count - 1] = vpr; } } }
/// <summary> /// This function applies the current Z-order on the ViewPorts. This means that all refresh manager /// will be notified if any parts of it's corresponding ViewPort is covered by another ViewPort. /// </summary> private void ApplyZOrderOnViewPorts() { for (int currIdx = 0; currIdx < this.viewPorts.Count - 1; currIdx++) { ViewPort currVP = this.viewPorts[currIdx]; ViewPortRefreshMgr currVPR = this.vpRefreshers[currIdx]; for (int otherIdx = currIdx + 1; otherIdx < this.viewPorts.Count; otherIdx++) { ViewPort otherVP = this.viewPorts[otherIdx]; ViewPortRefreshMgr otherVPR = this.vpRefreshers[otherIdx]; Rectangle intersection = Rectangle.Intersect(currVP.Position, otherVP.Position); if (!intersection.IsEmpty) { currVPR.AddHiddenArea(otherVPR, intersection); } } } }