1 module rpui.widgets.panel.render_system; 2 3 import rpui.theme; 4 import rpui.widgets.panel.widget; 5 import rpui.widgets.panel.transforms_system; 6 7 import gapi.texture; 8 import gapi.vec; 9 import gapi.geometry; 10 import rpui.primitives; 11 import rpui.render.components; 12 import rpui.render.components_factory; 13 import rpui.render.renderer; 14 15 enum SplitColor { 16 darkInner, 17 darkOuter, 18 lightInner, 19 lightOuter, 20 } 21 22 struct RenderData { 23 vec4[Panel.Background] backgroundColors; 24 vec4[SplitColor] splitColors; 25 Texture2DCoords headerOpenMarkTexCoords; 26 Texture2DCoords headerCloseMarkTexCoords; 27 vec2 headerMarkSize; 28 vec2 headerMarkPosition; 29 30 Geometry background; 31 Geometry splitInner; 32 Geometry splitOuter; 33 StatefulChain horizontalScrollButton; 34 StatefulChain verticalScrollButton; 35 StatefulTexAtlasTextureQuad headerBackground; 36 TextureQuad headerMark; 37 StatefulUiText headerText; 38 } 39 40 final class PanelRenderSystem : RenderSystem { 41 private Panel widget; 42 private Theme theme; 43 private RenderTransforms* transforms; 44 private RenderData* renderData; 45 46 this(Panel widget, RenderData* renderData, RenderTransforms* transforms) { 47 this.widget = widget; 48 this.theme = widget.view.theme; 49 this.transforms = transforms; 50 this.renderData = renderData; 51 } 52 53 override void onRender() { 54 renderBackground(); 55 renderHeader(); 56 57 if (!widget.isOpen) { 58 renderSplit(); 59 return; 60 } 61 62 widget.renderChildren(); 63 renderSplit(); 64 renderScrollButtons(); 65 } 66 67 private void renderBackground() { 68 if (widget.background == Panel.Background.transparent) { 69 return; 70 } 71 72 renderColorQuad( 73 theme, 74 renderData.background, 75 renderData.backgroundColors[widget.background], 76 transforms.background 77 ); 78 } 79 80 private void renderScrollButtons() { 81 if (widget.horizontalScrollButton.visible) { 82 renderHorizontalChain( 83 theme, 84 renderData.horizontalScrollButton.parts, 85 renderData.horizontalScrollButton.texCoords[widget.horizontalScrollButton.state], 86 transforms.horizontalScrollButton 87 ); 88 } 89 90 if (widget.verticalScrollButton.visible) { 91 renderVerticalChain( 92 theme, 93 renderData.verticalScrollButton.parts, 94 renderData.verticalScrollButton.texCoords[widget.verticalScrollButton.state], 95 transforms.verticalScrollButton 96 ); 97 } 98 } 99 100 private void renderSplit() { 101 if (!widget.showSplit) 102 return; 103 104 const innerColor = widget.darkSplit 105 ? renderData.splitColors[SplitColor.darkInner] 106 : renderData.splitColors[SplitColor.lightInner]; 107 108 const outerColor = widget.darkSplit 109 ? renderData.splitColors[SplitColor.darkOuter] 110 : renderData.splitColors[SplitColor.lightOuter]; 111 112 renderColorQuad( 113 theme, 114 renderData.splitInner, 115 innerColor, 116 transforms.splitInner 117 ); 118 119 renderColorQuad( 120 theme, 121 renderData.splitOuter, 122 outerColor, 123 transforms.splitOuter 124 ); 125 } 126 127 private void renderHeader() { 128 if (widget.userCanHide) { 129 renderTexAtlasQuad( 130 theme, 131 renderData.headerBackground.geometry, 132 renderData.headerBackground.texture, 133 renderData.headerBackground.texCoords[widget.headerState].normilizedTexCoords, 134 transforms.headerBackground 135 ); 136 137 Texture2DCoords markTexCoords; 138 139 if (widget.isOpen) { 140 markTexCoords = renderData.headerOpenMarkTexCoords; 141 } else { 142 markTexCoords = renderData.headerCloseMarkTexCoords; 143 } 144 145 renderTexAtlasQuad( 146 theme, 147 renderData.headerMark.geometry, 148 renderData.headerMark.texture, 149 markTexCoords, 150 transforms.headerMark 151 ); 152 } 153 154 renderUiText( 155 theme, 156 renderData.headerText.render, 157 renderData.headerText.attrs[widget.headerState], 158 transforms.headerText, 159 ); 160 } 161 }