Slot.cpp
Go to the documentation of this file.
1 #include "Slot.hpp"
2 #include "../Defs.hpp"
3 #include "Camera.hpp"
4 
6 
7 namespace iv
8 {
9 
10 //--------------------- ProtectedSlot --------------------------------
12  Elem( inst ),
13  SlotChild( this ),
14  cm( inst, this, "ProtectedSlot" ),
15  root( inst )
16 {
17  this->cm.inherits( this->Elem::cm, this->SlotChild::cm );
18  this->cm.owns( this->root.cm );
19 
20  this->root.input_setParent( this );
21  this->root.elem_setParent( this );
22 }
23 
24 void ProtectedSlot::elem_eachChild( std::function< void( Elem * ) > const & f )
25 {
26  f( &this->root );
27 }
28 
30 {
31 }
32 
33 void ProtectedSlot::input_eachChild( std::function< void( InputNode * ) > const & f )
34 {
35  this->Elem::input_eachChild( f );
36 
37  f( &this->root );
38 }
39 
41 {
42  this->Elem::input_childDisconnect( child );
43 }
44 
46 {
47  if( this->expectedSize.dirty() )
48  {
49  this->expectedSize.clear_dirty();
50  this->root.expectedSize.Set( this->expectedSize.Get() );
51  }
52 
53  this->root.elem()->first_pass( er );
54 
55  if( this->root.preferredSize.dirty() )
57  this->preferredSize.Set( this->root.preferredSize.Get() );
58 }
59 
61 {
62  bool changed = false;
63 
64  if( this->modelTransform.dirty() )
66  this->root.elem()->modelTransform.Set( this->modelTransform.Get() ),
67  changed = true;
68 
69  if( this->size.dirty() )
70  this->size.clear_dirty(),
71  this->root.size.Set( this->size.Get() ),
72  changed = true;
73 
74  if( this->scissor.dirty() )
75  this->scissor.clear_dirty(),
76  this->root.elem()->scissor.Set( this->scissor.Get() ),
77  changed = true;
78 
79  if( changed )
80  this->root.elem()->second_pass( er );
81 }
82 
83 
84 
85 //--------------------- SlotChild ----------------------
87  Pickable( elem ),
88  cm( elem->instance(), this, "SlotChild", ClientMarker::Status() ),
89  expectedSize( &this->cm, float3( std::numeric_limits< float >::infinity(), std::numeric_limits< float >::infinity(), std::numeric_limits< float >::infinity() ) ),
90  preferredSize( &this->cm, float3( 0, 0, 0 ) ),
91  size( &this->cm, float3( 0, 0, 0 ) )
92 {
93  this->cm.inherits( this->Pickable::cm );
94 }
95 
97 {
98  return this->elem()->instance();
99 }
100 
102 {
103  static iv::TableId DebugTable = TableId::create( "SlotChild" );
104 
105  auto row = view->Table( DebugTable ).Row( this );
106 
107  row.Column( "expectedSize", this->expectedSize.Get() );
108  row.Column( "preferredSize", this->preferredSize.Get() );
109  row.Column( "size", this->size.Get() );
110 }
111 
112 bool SlotChild::picking_test( int2 input_pos )
113 {
114  // check that it was drawn last frame
115  if( !this->elem()->elem_getRoot() )
116  return false;
117 
118  // bounding box picking
119  float3 size = this->size.Get();
120  float2 local_pos = this->elem()->FromScreenPlaneToLocalPlane( input_pos );
121  bool is_in = local_pos.x >= 0.0 && local_pos.y >= 0.0 && local_pos.x <= size.x && local_pos.y <= size.y;
122  if( !is_in )
123  {
125  "picking_test:", Context::Endl(),
126  " input_pos=", input_pos, Context::Endl(),
127  " inner_size=", size, Context::Endl(),
128  " local_pos=", local_pos, Context::Endl(),
129  " is_in=", is_in );
130  return false;
131  }
132 
133  // scissor test
134  ShaderScissor const & scissor = this->elem()->scissor.Get();
135  if( scissor.enabled )
136  {
137  Camera * camera = this->elem()->elem_getRoot();
138  if( camera )
139  {
140  float2 scissor_pos = camera->FromViewportPlaneToLocalPlane( scissor.model, input_pos );
141  bool is_in_scissor = scissor_pos.x >= 0.0 && scissor_pos.y >= 0.0 && scissor_pos.x <= scissor.size.x && scissor_pos.y <= scissor.size.y;
142  if( !is_in_scissor )
143  {
145  "picking_test:", Context::Endl(),
146  " input_pos=", input_pos, Context::Endl(),
147  " inner_size=", size, Context::Endl(),
148  " local_pos=", local_pos, Context::Endl(),
149  " is_in=", is_in, Context::Endl(),
150  " is_in_scissor=", is_in_scissor );
151  return false;
152  }
153  }
154  }
155 
156  // pixel precise picking
157  bool is_pixel_picked = this->picking_test_pixel_perfect( local_pos );
159  "picking_test:", Context::Endl(),
160  " input_pos=", input_pos, Context::Endl(),
161  " inner_size=", size, Context::Endl(),
162  " local_pos=", local_pos, Context::Endl(),
163  " is_in=", is_in, Context::Endl(),
164  " is_pixel_picked=", is_pixel_picked );
165  return is_pixel_picked;
166 }
167 
168 //--------------------- Slot --------------------------------
169 Slot::Slot( Instance * inst ) :
170  VectorChildrenElem< SlotChild >( inst ),
171  SlotChild( this ),
172  cm( inst, this, "Slot", ClientMarker::Status() )
173 {
175 }
176 
178 {
179  static iv::TableId DebugTable = TableId::create( "Slot" );
180 
181  auto row = view->Table( DebugTable ).Row( this );
182 
183  row.Column( "children", this->children.size() );
184 }
185 
187 {
188  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass, "First pass." );
189 
190  bool prefsize_changed = this->children_dirty;
191  bool expectedSize_changed = this->expectedSize.clear_dirty();
192 
193  for( SlotChild * child : this->children )
194  {
195  // expected size to child
196  if( expectedSize_changed )
197  child->expectedSize.Set( this->expectedSize.Get() );
198 
199  // first pass
200  child->elem()->first_pass( er );
201 
202  // preferred size change detect
203  prefsize_changed = prefsize_changed || child->preferredSize.dirty();
204  }
205 
206  if( prefsize_changed )
207  {
208  er->Notify_FirstPass_Refresh( this );
209 
210  float3 prefsize_new( 0 );
211  for( SlotChild * child : this->children )
212  {
213  prefsize_new = glm::max( prefsize_new, child->preferredSize.Get() );
214  child->preferredSize.clear_dirty();
215  }
216 
217  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass_Refresh, "Refresh preferred_size from ", this->children.size(), " children to ", prefsize_new , "." );
218  this->preferredSize.Set( prefsize_new );
219  }
220 
221  if( this->children_dirty || this->size.dirty() || this->modelTransform.dirty() )
222  {
223  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass_Refresh, "Queue second pass." );
224  er->QueueSecondPass( this );
225  }
226 }
227 
229 {
230  this->cm.log( SRC_INFO, Defs::Log::ElementSecondPass, "Second pass." );
231 
232  if( this->children_dirty || this->size.dirty() || this->modelTransform.dirty() || this->scissor.dirty() )
233  {
234  this->cm.log( SRC_INFO, Defs::Log::ElementFirstPass_Refresh, "Refresh size and model_transform." );
235 
236  //
237  this->children_dirty = false;
238  this->size.clear_dirty();
239  this->modelTransform.clear_dirty();
240  this->scissor.clear_dirty();
241 
242  //
243  for( auto it = this->children.rbegin(); it != this->children.rend(); ++it )
244  {
245  auto child = *it;
246  child->elem()->modelTransform.Set( this->modelTransform.Get() );
247  child->elem()->scissor.Set( this->scissor.Get() );
248  child->size.Set( this->size.Get() );
249  child->elem()->second_pass( er );
250  }
251  }
252 }
253 
254 }