private void renderControl( ref dfRenderData buffer, dfControl control, uint checksum, float opacity ) { // Don't render controls that are not currently active if( !control.enabled || !control.gameObject.activeSelf ) return; // Don't render controls that are invisible. Keeping a running // accumulator for opacity allows us to know a control's final // calculated opacity var effectiveOpacity = opacity * control.Opacity; if( effectiveOpacity <= 0.001f ) { return; } // If this control has a dfRenderGroup component on it, then pass off all // responsibility for rendering that control to the component. var renderGroup = GetRenderGroupForControl( control, true ); if( renderGroup != null && renderGroup != this && renderGroup.enabled ) { renderGroups.Add( renderGroup ); renderGroup.Render( renderCamera, control, groupOccluders, groupControls, checksum, effectiveOpacity ); return; } // Don't render controls that have the IsVisible flag set to FALSE. Note that this is tested // *after* checking for the presence of a dfRenderGroup component, since that component (if // present) will need to update its own internal state if the control's IsVisible property // has changed. if( !control.GetIsVisibleRaw() ) return; // Grab the current clip region information off the stack var clipInfo = clipStack.Peek(); // Update the checksum to include the current control checksum = dfChecksumUtil.Calculate( checksum, control.Version ); // Retrieve the control's bounds, which will be used in intersection testing // and triangle clipping. var bounds = control.GetBounds(); var screenRect = control.GetScreenRect(); var occluder = getControlOccluder( ref screenRect, control ); // Indicates whether the control was not rendered because it fell outside // of the currently-active clipping region var wasClipped = false; if( !( control is IDFMultiRender ) ) { // Ask the control to render itself and return a buffer of the // information needed to render it as a Mesh var controlData = control.Render(); if( controlData != null ) { processRenderData( ref buffer, controlData, ref bounds, ref screenRect, checksum, clipInfo, ref wasClipped ); } } else { // Ask the control to render itself and return as many dfRenderData buffers // as needed to render all elements of the control as a Mesh var childBuffers = ( (IDFMultiRender)control ).RenderMultiple(); if( childBuffers != null ) { var buffers = childBuffers.Items; var bufferCount = childBuffers.Count; for( int i = 0; i < bufferCount; i++ ) { var childBuffer = buffers[ i ]; if( childBuffer != null ) { processRenderData( ref buffer, childBuffer, ref bounds, ref screenRect, checksum, clipInfo, ref wasClipped ); } } } } // Allow control to keep track of its clipping state control.setClippingState( wasClipped ); // Keep track of which controls are rendered, and where they appear on-screen groupOccluders.Add( occluder ); groupControls.Add( control ); // If the control has the "Clip child controls" option set, push // its clip region information onto the stack so that all controls // lower in the hierarchy are clipped against that region. if( control.ClipChildren ) { if( !Application.isPlaying || clipType == dfClippingMethod.Software ) { clipInfo = dfTriangleClippingRegion.Obtain( clipInfo, control ); clipStack.Push( clipInfo ); } else if( this.clipInfo.IsEmpty ) { setClipRegion( control, ref screenRect ); } } // Dereference raw child control list for direct access var childControls = control.Controls.Items; var childCount = control.Controls.Count; // Ensure lists contain enough space for child controls groupControls.EnsureCapacity( groupControls.Count + childCount ); groupOccluders.EnsureCapacity( groupOccluders.Count + childCount ); // Render all child controls for( int i = 0; i < childCount; i++ ) { renderControl( ref buffer, childControls[ i ], checksum, effectiveOpacity ); } // No longer need the current control's clip region information if( control.ClipChildren ) { if( !Application.isPlaying || clipType == dfClippingMethod.Software ) { clipStack.Pop().Release(); } } }
private void renderControl(ref dfRenderData buffer, dfControl control, uint checksum, float opacity) { // Don't render controls that are not currently active if (!control.enabled || !control.gameObject.activeSelf) { return; } // Don't render controls that are invisible. Keeping a running // accumulator for opacity allows us to know a control's final // calculated opacity var effectiveOpacity = opacity * control.Opacity; if (effectiveOpacity <= 0.001f) { return; } // If this control has a dfRenderGroup component on it, then pass off all // responsibility for rendering that control to the component. var renderGroup = GetRenderGroupForControl(control, true); if (renderGroup != null && renderGroup != this && renderGroup.enabled) { renderGroups.Add(renderGroup); renderGroup.Render(renderCamera, control, groupOccluders, groupControls, checksum, effectiveOpacity); return; } // Don't render controls that have the IsVisible flag set to FALSE. Note that this is tested // *after* checking for the presence of a dfRenderGroup component, since that component (if // present) will need to update its own internal state if the control's IsVisible property // has changed. if (!control.GetIsVisibleRaw()) { return; } // Grab the current clip region information off the stack var clipInfo = clipStack.Peek(); // Update the checksum to include the current control checksum = dfChecksumUtil.Calculate(checksum, control.Version); // Retrieve the control's bounds, which will be used in intersection testing // and triangle clipping. var bounds = control.GetBounds(); var screenRect = control.GetScreenRect(); var occluder = getControlOccluder(ref screenRect, control); // Indicates whether the control was not rendered because it fell outside // of the currently-active clipping region var wasClipped = false; if (!(control is IDFMultiRender)) { // Ask the control to render itself and return a buffer of the // information needed to render it as a Mesh var controlData = control.Render(); if (controlData != null) { processRenderData(ref buffer, controlData, ref bounds, ref screenRect, checksum, clipInfo, ref wasClipped); } } else { // Ask the control to render itself and return as many dfRenderData buffers // as needed to render all elements of the control as a Mesh var childBuffers = ((IDFMultiRender)control).RenderMultiple(); if (childBuffers != null) { var buffers = childBuffers.Items; var bufferCount = childBuffers.Count; for (int i = 0; i < bufferCount; i++) { var childBuffer = buffers[i]; if (childBuffer != null) { processRenderData(ref buffer, childBuffer, ref bounds, ref screenRect, checksum, clipInfo, ref wasClipped); } } } } // Allow control to keep track of its clipping state control.setClippingState(wasClipped); // Keep track of which controls are rendered, and where they appear on-screen groupOccluders.Add(occluder); groupControls.Add(control); // If the control has the "Clip child controls" option set, push // its clip region information onto the stack so that all controls // lower in the hierarchy are clipped against that region. if (control.ClipChildren) { if (!Application.isPlaying || clipType == dfClippingMethod.Software) { clipInfo = dfTriangleClippingRegion.Obtain(clipInfo, control); clipStack.Push(clipInfo); } else if (this.clipInfo.IsEmpty) { setClipRegion(control, ref screenRect); } } // Dereference raw child control list for direct access var childControls = control.Controls.Items; var childCount = control.Controls.Count; // Ensure lists contain enough space for child controls groupControls.EnsureCapacity(groupControls.Count + childCount); groupOccluders.EnsureCapacity(groupOccluders.Count + childCount); // Render all child controls for (int i = 0; i < childCount; i++) { renderControl(ref buffer, childControls[i], checksum, effectiveOpacity); } // No longer need the current control's clip region information if (control.ClipChildren) { if (!Application.isPlaying || clipType == dfClippingMethod.Software) { clipStack.Pop().Release(); } } }