1 module des.gl.simple.object;
2 
3 import std.exception;
4 import std.stdio;
5 import std..string;
6 
7 public import des.gl.base;
8 
9 ///
10 abstract class GLSimpleObject : GLObject
11 {
12 private:
13     uint draw_count;
14     uint index_count;
15 
16     GLBuffer elem_buffer = null;
17 
18 protected:
19 
20     ///
21     void setDrawCount( uint cnt ) { draw_count = cnt; }
22 
23     ///
24     void setIndexCount( uint cnt ) { index_count = cnt; }
25 
26     ///
27     CommonGLShaderProgram shader;
28 
29     ///
30     bool warn_if_empty = true;
31 
32     ///
33     auto createArrayBuffer()
34     {
35         auto buf = newEMM!GLBuffer( GLBuffer.Target.ARRAY_BUFFER );
36         connect( buf.elementCountCB, &setDrawCount );
37         return buf;
38     }
39 
40     /+ ??? под вопросом +/
41     static struct APInfo
42     {
43         string name;
44         string attrib;
45         uint per_element;
46         GLType type;
47         size_t stride = 0;
48         size_t offset = 0;
49         bool required = true;
50 
51         this( string n, uint pe, GLType t, bool req=true )
52         {
53             name = n;
54             attrib = n;
55             per_element = pe;
56             type = t; 
57             required = req;
58         }
59 
60         this( string n, string a, uint pe, GLType t, size_t st, size_t of, bool req=true )
61         {
62             this( n, pe, t, req );
63             attrib = a;
64             stride = st;
65             offset = of;
66         }
67     }
68 
69     /+ ??? под вопросом +/
70     auto createArrayBuffersFromAttributeInfo( in APInfo[] infos... )
71     {
72         GLBuffer[string] ret;
73         foreach( info; infos )
74         {
75             auto loc = shader.getAttribLocation( info.attrib );
76 
77             if( loc < 0 )
78             {
79                 if( info.required )
80                     assert( 0, format( "no attrib '%s' in shader", info.attrib ) );
81                 else
82                 {
83                     logger.warn( "no attrib '%s' in shader", info.attrib );
84                     continue;
85                 }
86             }
87 
88             if( info.name !in ret )
89                 ret[info.name] = createArrayBuffer();
90                 
91             auto buf = ret[info.name];
92             setAttribPointer( buf, loc, info.per_element, info.type,
93                               info.stride, info.offset );
94         }
95         return ret;
96     }
97 
98     ///
99     auto createIndexBuffer()
100     {
101         auto buf = newEMM!GLBuffer( GLBuffer.Target.ELEMENT_ARRAY_BUFFER );
102         connect( buf.elementCountCB, &setIndexCount );
103         connect( buf.elementSizeCB, (uint sz){
104             enforce( sz == uint.sizeof, "set to index buffer not uint data" );
105         });
106         elem_buffer = buf;
107         return buf;
108     }
109 
110     ///
111     override void preDraw()
112     {
113         shader.use();
114         if( elem_buffer !is null )
115             elem_buffer.bind();
116         debug checkGL;
117     }
118 
119     ///
120     void drawArrays( DrawMode mode )
121     {
122         if( !visible ) return;
123         if( draw_count > 0 )
124             super.drawArrays( mode, cast(uint)draw_count );
125         else if( warn_if_empty )
126             logger.warn( "simple object draw empty object" );
127     }
128 
129     ///
130     void drawElements( DrawMode mode )
131     {
132         if( !visible ) return;
133         if( index_count > 0 && draw_count > 0 )
134             super.drawElements( mode, cast(uint)index_count );
135         else if( warn_if_empty )
136             logger.warn( "simple object draw empty object" );
137     }
138 
139 public:
140 
141     ///
142     this( string shader_source )
143     {
144         shader = newEMM!CommonGLShaderProgram( parseGLShaderSource( shader_source ) );
145     }
146 
147     ///
148     bool visible = true;
149 
150     ///
151     this( CommonGLShaderProgram sh )
152     in{ assert( sh !is null ); } body
153     { shader = sh; }
154 }