private void Draw(DrawState state, Vector2 scale, byte clipDepth) { Element parent = this.parent; Matrix matrix; GraphicsDevice device = null; if (parent == null) { if (state.DrawTarget.MultiSampleType != MultiSampleType.None) { device = state.BeginGetGraphicsDevice(StateFlag.None); device.RenderState.MultiSampleAntiAlias = false; } this.clipTestActive = false; DeviceRenderState rstate = new DeviceRenderState(); rstate.DepthColourCull.DepthWriteEnabled = false; rstate.DepthColourCull.DepthTestEnabled = false; state.PushRenderState(ref rstate); if (camera == null) { camera = state.UserValues[cameraID] as Xen.Camera.Camera2D; if (camera == null) { camera = new Xen.Camera.Camera2D(true); state.UserValues[cameraID] = camera; } } state.PushCamera(camera); } else { this.clipTestActive = parent.clipTestActive | parent.ClipsChildren; } StencilTestState stencilState = new StencilTestState(); if (clipTestActive) { stencilState.Enabled = true; stencilState.ReferenceValue = clipDepth; stencilState.StencilFunction = CompareFunction.Equal; stencilState.StencilPassOperation = StencilOperation.Keep; } bool clearStencil = false; if (this.ClipsChildren) { clearStencil = clipDepth == 255; clipDepth--; if (!clipTestActive) { //check there actually is a stencil buffer #if DEBUG DepthFormat format = state.DrawTarget.SurfaceDepthFormat ?? DepthFormat.Unknown; if (format != DepthFormat.Depth24Stencil8) { throw new InvalidOperationException("ElementRect.ClipChildren requires the DrawTarget has a valid Depth Buffer with an 8bit Stencil Buffer"); } #endif stencilState.Enabled = true; stencilState.ReferenceValue = clipDepth; stencilState.StencilPassOperation = StencilOperation.Replace; } else { stencilState.StencilPassOperation = StencilOperation.Decrement; } } if ((scale.X != 0 && scale.Y != 0)) { Vector2 size = ElementSize; GetDisplayMatrix(out matrix, scale, ref size); state.PushWorldMatrixMultiply(ref matrix); BindShader(state, false); state.RenderState.AlphaBlend = blend; state.RenderState.StencilTest = stencilState; if (!UseSize) { size = new Vector2(1, 1); } else if (IsNormalised) { size *= scale; } PreDraw(size); DrawElement(state); List <Element> children = Children; if (children != null) { foreach (Element child in children) { if (((IDraw)child).CullTest(state)) { child.Draw(state, size, clipDepth); } } } if (clearStencil) { BindShader(state, true); stencilState = new StencilTestState(); stencilState.Enabled = true; stencilState.StencilFunction = CompareFunction.Never; stencilState.StencilFailOperation = StencilOperation.Zero; state.RenderState.StencilTest = stencilState; DrawElement(state); } state.PopWorldMatrix(); } if (parent == null) { state.PopRenderState(); state.PopCamera(); } if (device != null) { device.RenderState.MultiSampleAntiAlias = true; state.EndGetGraphicsDevice(); } }
private void Draw(DrawState state, Vector2 scale, byte clipDepth) { Element parent = this.parent; Matrix matrix; if (parent == null) { this.clipTestActive = false; state.RenderState.Push(); state.RenderState.CurrentRasterState.MultiSampleAntiAlias = false; state.RenderState.CurrentDepthState.DepthWriteEnabled = WriteToDepth; state.RenderState.CurrentDepthState.DepthTestEnabled = WriteToDepth; if (camera == null) { camera = state.Application.UserValues[cameraID] as Xen.Camera.Camera2D; if (camera == null) { camera = new Xen.Camera.Camera2D(true); state.Application.UserValues[cameraID] = camera; } } state.Camera.Push(camera); } else this.clipTestActive = parent.clipTestActive | parent.ClipsChildren; StencilState stencilState = new StencilState(); if (clipTestActive) { stencilState.Enabled = true; stencilState.ReferenceValue = clipDepth; stencilState.StencilFunction = CompareFunction.Equal; stencilState.StencilPassOperation = StencilOperation.Keep; } bool clearStencil = false; if (this.ClipsChildren) { clearStencil = clipDepth == 255; clipDepth--; if (!clipTestActive) { //check there actually is a stencil buffer #if DEBUG DepthFormat format = state.DrawTarget.SurfaceDepthFormat; if (format != DepthFormat.Depth24Stencil8) throw new InvalidOperationException("ElementRect.ClipChildren requires the DrawTarget has a valid Depth Buffer with an 8bit Stencil Buffer"); #endif stencilState.Enabled = true; stencilState.ReferenceValue = clipDepth; stencilState.StencilPassOperation = StencilOperation.Replace; } else stencilState.StencilPassOperation = StencilOperation.Decrement; } if ((scale.X != 0 && scale.Y != 0)) { Vector2 size = ElementSize; GetDisplayMatrix(out matrix, scale, ref size); using (state.WorldMatrix.PushMultiply(ref matrix)) { IShader shader = BindShader(state, false); if (shader != null) state.Shader.Push(shader); state.RenderState.CurrentBlendState = blend; state.RenderState.CurrentStencilState = stencilState; if (!UseSize) size = new Vector2(1, 1); else if (IsNormalised) size *= scale; PreDraw(size); DrawElement(state); List<Element> children = Children; if (children != null) foreach (Element child in children) if (((IDraw)child).CullTest(state)) child.Draw(state, size, clipDepth); if (shader != null) state.Shader.Pop(); if (clearStencil) { shader = BindShader(state, true); if (shader != null) state.Shader.Push(shader); stencilState = new StencilState(); stencilState.Enabled = true; stencilState.StencilFunction = CompareFunction.Never; stencilState.StencilFailOperation = StencilOperation.Zero; state.RenderState.CurrentStencilState = stencilState; DrawElement(state); if (shader != null) state.Shader.Pop(); } } } if (parent == null) { state.RenderState.Pop(); state.Camera.Pop(); } }