public override void Render(DrawArgs drawArgs) { if (!isOn) { return; } if (!isInitialized) { Initialize(drawArgs); } m_pointSprites.Clear(); int closestIconDistanceSquared = int.MaxValue; PointIcon closestIcon = null; // build list of all points in view foreach (PointIcon point in m_points.Values) { try { // don't bother to do anything else if we aren't even in view if (drawArgs.WorldCamera.ViewFrustum.ContainsPoint(point.Position)) { Vector3 translationVector = new Vector3( (float)(point.PositionD.X - drawArgs.WorldCamera.ReferenceCenter.X), (float)(point.PositionD.Y - drawArgs.WorldCamera.ReferenceCenter.Y), (float)(point.PositionD.Z - drawArgs.WorldCamera.ReferenceCenter.Z)); Vector3 projectedPoint = drawArgs.WorldCamera.Project(translationVector); // check if inside bounding box of icon int dx = DrawArgs.LastMousePosition.X - (int)projectedPoint.X; int dy = DrawArgs.LastMousePosition.Y - (int)projectedPoint.Y; if (SelectionRectangle.Contains(dx, dy)) { // Mouse is over, check whether this icon is closest int distanceSquared = dx * dx + dy * dy; if (distanceSquared < closestIconDistanceSquared) { closestIconDistanceSquared = distanceSquared; closestIcon = point; } } PointSpriteVertex pv = new PointSpriteVertex(translationVector.X, translationVector.Y, translationVector.Z, point.Size, point.Color.ToArgb()); m_pointSprites.Add(pv); } } catch { } finally { } } // render point sprites if any in the list try { if (m_pointSprites.Count > 0) { // save device state Texture origTexture = drawArgs.device.GetTexture(0); VertexFormats origVertexFormat = drawArgs.device.VertexFormat; float origPointScaleA = drawArgs.device.RenderState.PointScaleA; float origPointScaleB = drawArgs.device.RenderState.PointScaleB; float origPointScaleC = drawArgs.device.RenderState.PointScaleC; bool origPointSpriteEnable = drawArgs.device.RenderState.PointSpriteEnable; bool origPointScaleEnable = drawArgs.device.RenderState.PointScaleEnable; Blend origSourceBlend = drawArgs.device.RenderState.SourceBlend; Blend origDestBlend = drawArgs.device.RenderState.DestinationBlend; // set device to do point sprites drawArgs.device.SetTexture(0, m_pointTexture.Texture); drawArgs.device.VertexFormat = VertexFormats.Position | VertexFormats.PointSize | VertexFormats.Diffuse; drawArgs.device.RenderState.PointScaleA = 1f; drawArgs.device.RenderState.PointScaleB = 0f; drawArgs.device.RenderState.PointScaleC = 0f; drawArgs.device.RenderState.PointSpriteEnable = true; drawArgs.device.RenderState.PointScaleEnable = true; //drawArgs.device.RenderState.SourceBlend = Blend.One; //drawArgs.device.RenderState.DestinationBlend = Blend.BlendFactor; drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorOperation, (int)TextureOperation.Modulate); drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorArgument1, (int)TextureArgument.TextureColor); drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorArgument2, (int)TextureArgument.Diffuse); // Draw all visible points drawArgs.device.DrawUserPrimitives(PrimitiveType.PointList, m_pointSprites.Count, m_pointSprites.ToArray()); // Draw label and description of mouseover point if (closestIcon != null) { } // restore device state drawArgs.device.SetTexture(0, origTexture); drawArgs.device.VertexFormat = origVertexFormat; drawArgs.device.RenderState.PointScaleA = origPointScaleA; drawArgs.device.RenderState.PointScaleB = origPointScaleB; drawArgs.device.RenderState.PointScaleC = origPointScaleC; drawArgs.device.RenderState.PointSpriteEnable = origPointSpriteEnable; drawArgs.device.RenderState.PointScaleEnable = origPointScaleEnable; drawArgs.device.RenderState.SourceBlend = origSourceBlend; drawArgs.device.RenderState.DestinationBlend = origDestBlend; } } catch { } }
/// <summary> /// This used to be done in the World class but moved here so folks could override a ROL's behavior. /// /// NOTE: Everything under an Icons is rendered using RenderPriority.Icons. If you put any other kind of /// ROL in here it (and it's children) probably wont render. /// </summary> /// <param name="drawArgs"></param> /// <param name="priority"></param> public override void RenderChildren(DrawArgs drawArgs, RenderPriority priority) { //Respect icon set temporal extents if (TimeKeeper.CurrentTimeUtc < EarliestTime || TimeKeeper.CurrentTimeUtc > LatestTime) { return; } if (!isOn) { return; } if (!isInitialized) { return; } if (priority != RenderPriority.Icons) { return; } // render ourselves this.Render(drawArgs); if (m_canUsePointSprites) { pointSprites.Clear(); } // First render everything except icons - we need to do this twice since the other loop is INSIDE the // sprite.begin which can mess up the rendering of other ROs. This is why prerender is in this loop. m_childrenRWLock.AcquireReaderLock(Timeout.Infinite); try { foreach (RenderableObject ro in m_children) { if (!ro.IsOn) { continue; } if (ro is Icon) // && (priority == RenderPriority.Icons)) { Icon icon = ro as Icon; if (icon == null) { continue; } // do this once for both passes icon.DistanceToIcon = Vector3.Length(icon.Position - drawArgs.WorldCamera.Position); // do PreRender regardless of everything else // note that mouseover actions happen one render cycle after mouse is over icon icon.PreRender(drawArgs, (mouseOverIcon != null) && (icon == mouseOverIcon)); } else if (ro is RenderableObjectList) { (ro as RenderableObjectList).RenderChildren(drawArgs, priority); } //// hack to render both surface images and terrain mapped images. //else if (priority == RenderPriority.TerrainMappedImages) //{ // if (ro.RenderPriority == RenderPriority.SurfaceImages || ro.RenderPriority == RenderPriority.TerrainMappedImages) // { // ro.Render(drawArgs); // } //} else // if (ro.RenderPriority == priority) { ro.Render(drawArgs); } } } catch (Exception ex) { Log.Write(ex); } finally { m_childrenRWLock.ReleaseReaderLock(); } m_labelRectangles.Clear(); int closestIconDistanceSquared = int.MaxValue; Icon closestIcon = null; if (priority == RenderPriority.Icons) { try { m_sprite.Begin(SpriteFlags.AlphaBlend); // Now render just the icons m_childrenRWLock.AcquireReaderLock(Timeout.Infinite); try { foreach (RenderableObject ro in m_children) { if (!ro.IsOn) { continue; } Icon icon = ro as Icon; if (icon == null) { continue; } // don't try to render if we aren't in view or too far away if ((drawArgs.WorldCamera.ViewFrustum.ContainsPoint(icon.Position)) && (icon.DistanceToIcon <= icon.MaximumDisplayDistance) && (icon.DistanceToIcon >= icon.MinimumDisplayDistance)) { Vector3 translationVector = new Vector3( (float)(icon.PositionD.X - drawArgs.WorldCamera.ReferenceCenter.X), (float)(icon.PositionD.Y - drawArgs.WorldCamera.ReferenceCenter.Y), (float)(icon.PositionD.Z - drawArgs.WorldCamera.ReferenceCenter.Z)); Vector3 projectedPoint = drawArgs.WorldCamera.Project(translationVector); // check if inside bounding box of icon int dx = DrawArgs.LastMousePosition.X - (int)projectedPoint.X; int dy = DrawArgs.LastMousePosition.Y - (int)projectedPoint.Y; if (icon.SelectionRectangle.Contains(dx, dy)) { // Mouse is over, check whether this icon is closest int distanceSquared = dx * dx + dy * dy; if (distanceSquared < closestIconDistanceSquared) { closestIconDistanceSquared = distanceSquared; closestIcon = icon; } } // mouseover is always one render cycle behind...we mark that an icon is the mouseover // icon and render it normally. On the NEXT pass it renders as a mouseover icon if (icon != mouseOverIcon) { // Note: Always render hooked icons as a real icon rather than a sprite. if (icon.UsePointSprite && (icon.DistanceToIcon > icon.PointSpriteDistance) && m_canUsePointSprites && !icon.IsHooked) { PointSpriteVertex pv = new PointSpriteVertex(translationVector.X, translationVector.Y, translationVector.Z, icon.PointSpriteSize, icon.PointSpriteColor.ToArgb()); pointSprites.Add(pv); } else { // add pointsprite anyway if (icon.UsePointSprite && icon.AlwaysRenderPointSprite) { PointSpriteVertex pv = new PointSpriteVertex(translationVector.X, translationVector.Y, translationVector.Z, icon.PointSpriteSize, icon.PointSpriteColor.ToArgb()); pointSprites.Add(pv); } icon.FastRender(drawArgs, m_sprite, projectedPoint, false, m_labelRectangles); } } } else { // do whatever we're supposed to do if we're not in view or too far away icon.NoRender(drawArgs); } // do post rendering even if we don't render // note that mouseover actions happen one render cycle after mouse is over icon icon.PostRender(drawArgs, icon == mouseOverIcon); } } catch (Exception ex) { System.Console.WriteLine(ex.Message.ToString()); } finally { m_childrenRWLock.ReleaseReaderLock(); } // Clear the rectangles so that mouseover label always appears m_labelRectangles.Clear(); // Render the mouse over icon last (on top) if (mouseOverIcon != null) { Vector3 translationVector = new Vector3( (float)(mouseOverIcon.PositionD.X - drawArgs.WorldCamera.ReferenceCenter.X), (float)(mouseOverIcon.PositionD.Y - drawArgs.WorldCamera.ReferenceCenter.Y), (float)(mouseOverIcon.PositionD.Z - drawArgs.WorldCamera.ReferenceCenter.Z)); Vector3 projectedPoint = drawArgs.WorldCamera.Project(translationVector); if (mouseOverIcon.UsePointSprite && mouseOverIcon.AlwaysRenderPointSprite && m_canUsePointSprites) { // add pointsprite anyway PointSpriteVertex pv = new PointSpriteVertex(translationVector.X, translationVector.Y, translationVector.Z, mouseOverIcon.PointSpriteSize, mouseOverIcon.PointSpriteColor.ToArgb()); pointSprites.Add(pv); } mouseOverIcon.FastRender(drawArgs, m_sprite, projectedPoint, true, m_labelRectangles); } // set new mouseover icon mouseOverIcon = closestIcon; } catch (Exception ex) { System.Console.WriteLine(ex.Message.ToString()); } finally { m_sprite.End(); } // render point sprites if any in the list try { if (pointSprites.Count > 0) { // save device state Texture origTexture = drawArgs.device.GetTexture(0); VertexFormats origVertexFormat = drawArgs.device.VertexFormat; float origPointScaleA = drawArgs.device.RenderState.PointScaleA; float origPointScaleB = drawArgs.device.RenderState.PointScaleB; float origPointScaleC = drawArgs.device.RenderState.PointScaleC; bool origPointSpriteEnable = drawArgs.device.RenderState.PointSpriteEnable; bool origPointScaleEnable = drawArgs.device.RenderState.PointScaleEnable; Blend origSourceBlend = drawArgs.device.RenderState.SourceBlend; Blend origDestBlend = drawArgs.device.RenderState.DestinationBlend; // set device to do point sprites drawArgs.device.SetTexture(0, m_pointTexture.Texture); drawArgs.device.VertexFormat = VertexFormats.Position | VertexFormats.PointSize | VertexFormats.Diffuse; drawArgs.device.RenderState.PointScaleA = 1f; drawArgs.device.RenderState.PointScaleB = 0f; drawArgs.device.RenderState.PointScaleC = 0f; //drawArgs.device.RenderState.PointScaleA = 0f; //drawArgs.device.RenderState.PointScaleB = 0f; //drawArgs.device.RenderState.PointScaleC = .0000000000001f; drawArgs.device.RenderState.PointSpriteEnable = true; drawArgs.device.RenderState.PointScaleEnable = true; drawArgs.device.RenderState.SourceBlend = Blend.One; drawArgs.device.RenderState.DestinationBlend = Blend.InvSourceAlpha; drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorOperation, (int)TextureOperation.Modulate); drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorArgument1, (int)TextureArgument.TextureColor); drawArgs.device.SetTextureStageState(0, TextureStageStates.ColorArgument2, (int)TextureArgument.Diffuse); drawArgs.device.DrawUserPrimitives(PrimitiveType.PointList, pointSprites.Count, pointSprites.ToArray()); // restore device state drawArgs.device.SetTexture(0, origTexture); drawArgs.device.VertexFormat = origVertexFormat; drawArgs.device.RenderState.PointScaleA = origPointScaleA; drawArgs.device.RenderState.PointScaleB = origPointScaleB; drawArgs.device.RenderState.PointScaleC = origPointScaleC; drawArgs.device.RenderState.PointSpriteEnable = origPointSpriteEnable; drawArgs.device.RenderState.PointScaleEnable = origPointScaleEnable; drawArgs.device.RenderState.SourceBlend = origSourceBlend; drawArgs.device.RenderState.DestinationBlend = origDestBlend; } } catch (Exception ex) { System.Console.WriteLine(ex.Message.ToString()); } } }