Image.cpp
Go to the documentation of this file.
1 #include "Image.hpp"
2 
3 #include "../Defs.hpp"
4 
5 namespace iv
6 {
7 
8 Image::Image( Instance * inst ) :
9  Elem( inst ),
10  SlotChild( this ),
11  TranslucentElem( this ),
12  cm( inst, this, "Image", ClientMarker::Status() ),
13  attr_filename( &this->cm, "/ivorium_graphics/empty.png" ),
14  shading( &this->cm ),
15  texture( inst, ResourcePath() ),
16  shader( inst ),
17  square( inst )
18 {
19  this->cm.inherits( this->Elem::cm, this->SlotChild::cm, this->TranslucentElem::cm );
20  this->cm.owns( this->texture.cm, this->shader.cm, this->square.cm );
21 }
22 
24 {
25  static iv::TableId DebugTable = TableId::create( "Image" );
26 
27  auto row = view->Table( DebugTable ).Row( this );
28 
29  row.Column( "filename", this->attr_filename.Get() );
30 
31  row.Column( "fittingStage", this->shading.fittingStage );
32 
33  row.Column( "pixelizeStage", this->shading.pixelizeStage )
34  .Hint( "size", this->shading.pixelizeSize.Get() )
35  .Hint( "offset", this->shading.pixelizeOffset.Get() );
36 
37  row.Column( "resizeStage", this->shading.resizeStage )
38  .Hint( "anchor", this->shading.resizeAnchor.Get() );
39 
40  row.Column( "filteringStage", this->shading.filteringStage )
41  .Hint( "filteringAlphaThreshold", this->shading.filteringAlphaThreshold.Get() )
42  .Hint( "filteringAlphaWidth", this->shading.filteringAlphaWidth.Get() );
43 
44  row.Column( "alpha", this->shading.alpha.Get() );
45 
46  row.Column( "colorTransform", this->shading.colorTransform.Get() );
47 }
48 
50 {
51  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "First pass." );
52 
53  if( this->attr_filename.dirty() )
54  {
55  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "Refresh preferred_size (filename changed)." );
56 
57  er->Notify_FirstPass_Refresh( this );
58 
59  // read texture
60  this->texture.path( this->attr_filename.Get() );
61  this->attr_filename.clear_dirty();
62 
63  // update prefsize
64  if( this->texture.get() )
65  {
66  int2 prefsize = this->texture->metadata().size;
67  float density = this->texture->metadata().density;
68  this->preferredSize.Set( float3( prefsize.x / density, prefsize.y / density, 0 ) );
69  }
70  else
71  {
72  this->preferredSize.Set( float3( 0, 0, 0 ) );
73  }
74  }
75 
76  // queue render
77  if( this->shading.alpha.Get() != 0.0f )
78  {
79  GLuint shader_id = this->shader.get() ? this->shader->program_id() : 0;
80  GLuint texture_id = this->texture.get() ? this->texture->gl_texture()->texture_id() : 0;
81 
82  if( shader_id && texture_id )
83  {
84  if( this->attr_translucent.Get() )
85  {
86  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "Queue render pass (translucent)." );
87  er->AddRenderable_Translucent( this, shader_id, texture_id );
88  }
89  else
90  {
91  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "Queue render pass (solid)." );
92  er->AddRenderable_Solid( this, shader_id, texture_id );
93  }
94  }
95  else
96  {
97  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "Render skipped (shader or texture are not loaded yet)." );
98  }
99  }
100  else
101  {
102  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "Render skipped (alpha == 0)." );
103  }
104 }
105 
107 {
108 }
109 
110 void Image::render( CameraState const & camera, std::optional< float > draw_order_depth )
111 {
112  this->cm.log( SRC_INFO, Defs::Log::ElementRenderPass, "Render ", this->attr_filename.Get(), "." );
113 
114  float3 size = this->size.Get();
115 
116  this->shader->Render(
117  this->cm,
118 
119  camera,
120  draw_order_depth,
121 
122  this->modelTransform.Get(),
123  this->scissor.Get(),
124 
125  this->attr_preblend.Get(),
126  this->attr_translucent.Get(),
127 
128  this->square->gl_mesh(),
129  float3( size.x, size.y, 0.0f ),
130  float2( 1.0f, 1.0f ),
131 
132  this->texture->gl_texture(),
133  this->texture->metadata().density,
134  this->texture->metadata().msdf_pixelRange,
135 
136  this->shading
137  );
138 }
139 
140 float Image::texcoord_frame_transform_px( float coord_image_px, float tex_size, float image_size )
141 {
142  float coord_tex_px;
143  if( coord_image_px < image_size * 0.5 )
144  {// left half
145  if( coord_image_px < tex_size / 2.0f )
146  coord_tex_px = coord_image_px;
147  else
148  coord_tex_px = tex_size / 2.0f;
149  }
150  else
151  {// right half
152  if( image_size - coord_image_px < tex_size / 2.0f )
153  coord_tex_px = tex_size - ( image_size - coord_image_px );
154  else
155  coord_tex_px = tex_size / 2.0f;
156  }
157 
158  return coord_tex_px;
159 }
160 
162 {
163  if( !this->texture.get() )
164  return false;
165 
166  if( !this->texture->metadata().hitmap )
167  return true;
168 
169  float2 size( this->size.Get().x, this->size.Get().y );
170  float2 texsize( this->texture->metadata().size );
171  float dpi = this->texture->metadata().density;
172 
173  int2 texpos;
175  {
176  texpos = local_pos / size * texsize;
177  }
179  {
180  auto resizeAnchor = this->shading.resizeAnchor.Get();
181  texpos = local_pos - resizeAnchor * size + resizeAnchor * texsize / dpi;
182  texpos.x = sig_mod( texpos.x, texsize.x / dpi ) * dpi;
183  texpos.y = sig_mod( texpos.y, texsize.y / dpi ) * dpi;
184  }
186  {
187  texpos = int2( Image::texcoord_frame_transform_px( local_pos.x, texsize.x / dpi, size.x ) * dpi, Image::texcoord_frame_transform_px( local_pos.y, texsize.y / dpi, size.y ) * dpi );
188  }
189  else // FlatShader::ResizeStage::Fixed
190  {
191  auto resizeAnchor = this->shading.resizeAnchor.Get();
192  texpos = ( local_pos - resizeAnchor * size + resizeAnchor * texsize / dpi ) * dpi;
193  }
194 
195 
197  "pixel_text:", Context::Endl(),
198  " texsize=", texsize, Context::Endl(),
199  " texpos=", texpos );
200 
201  return this->texture->hittest( texpos.x, texsize.y - texpos.y - 1 );
202 }
203 
204 Image * Image::enabled( bool val )
205 {
206  this->Elem::enabled( val );
207  return this;
208 }
209 
211 {
212  this->TranslucentElem::preblend( val );
213  return this;
214 }
215 
217 {
218  this->TranslucentElem::translucent( val );
219  return this;
220 }
221 
223 {
224  this->attr_filename.Set( val );
225  return this;
226 }
227 
229 {
230  this->shading.fittingStage = v;
231  return this;
232 }
233 
235 {
236  this->shading.pixelizeStage = v;
237  return this;
238 }
239 
241 {
242  this->shading.pixelizeSize.Set( v );
243  return this;
244 }
245 
247 {
248  this->shading.pixelizeOffset.Set( v );
249  return this;
250 }
251 
253 {
254  this->shading.resizeStage = v;
255  return this;
256 }
257 
259 {
260  this->shading.resizeAnchor.Set( v );
261  return this;
262 }
263 
265 {
266  this->shading.filteringStage = v;
267  return this;
268 }
269 
271 {
273  return this;
274 }
275 
277 {
278  this->shading.filteringAlphaWidth.Set( v );
279  return this;
280 }
281 
282 Image * Image::alpha( float v )
283 {
284  this->shading.alpha.Set( v );
285  return this;
286 }
287 
289 {
290  this->shading.colorTransform.Set( v );
291  return this;
292 }
293 
294 }