Align.cpp
Go to the documentation of this file.
1 #include "Align.hpp"
2 
3 namespace iv
4 {
5 
6 Align::Align( Instance * inst ) :
7  OneChildElem< SlotChild >( inst ),
8  SlotChild( this ),
9  cm( inst, this, "Align", ClientMarker::Status() ),
10  attr_dontExpand( &this->cm, false ),
11  attr_keepAspect( &this->cm, false ),
12  attr_resizeScales( &this->cm, false ),
13  attr_innerAnchor( &this->cm, float3( 0.5, 0.5, 0.5 ) )
14 {
16 }
17 
19 {
20  static iv::TableId DebugTable = TableId::create( "Align" );
21 
22  auto row = view->Table( DebugTable ).Row( this );
23 
24  row.Column( "dontExpand", this->attr_dontExpand.Get() );
25  row.Column( "keepAspect", this->attr_keepAspect.Get() );
26  row.Column( "resizeScales", this->attr_resizeScales.Get() );
27  row.Column( "innerAnchor", this->attr_innerAnchor.Get() );
28  row.Column( "insize", this->insize );
29  row.Column( "inpos", this->inpos );
30  row.Column( "inscale", this->inscale );
31 }
32 
34 {
35  // first pass on child and refresh preferred size
36  if( this->child.Get() )
37  {
38  if( this->child.dirty() || this->expectedSize.dirty() )
39  {
40  this->expectedSize.clear_dirty();
41  this->child.Get()->expectedSize.Set( this->expectedSize.Get() );
42  }
43 
44  this->child.Get()->elem()->first_pass( er );
45 
46  if( this->child.dirty() || this->child.Get()->preferredSize.dirty() )
47  {
48  //this->child.Get()->preferred_size.clear_dirty();
49  this->preferredSize.Set( this->child.Get()->preferredSize.Get() );
50  }
51  }
52  else
53  {
54  if( this->child.dirty() )
55  {
56  this->preferredSize.Set( float3( 0, 0, 0 ) );
57  }
58  }
59 
60  if( this->child.Get() )
61  if( this->child.dirty() || this->child.Get()->preferredSize.dirty() || this->size.dirty() || this->modelTransform.dirty()
62  || this->attr_dontExpand.dirty() || this->attr_keepAspect.dirty() || this->attr_innerAnchor.dirty() || this->scissor.dirty() )
63  er->QueueSecondPass( this );
64 }
65 
66 void Align::inner_layout( float3 & out_size, float3 & out_position, float3 & out_scale ) const
67 {
68  // prepare size computation
69  float3 prefsize = this->preferredSize.Get();
70  float3 size = this->size.Get();
71  float3 scale( 1, 1, 1 );
72 
73  // apply dont_expand
74  if( this->attr_dontExpand.Get() )
75  {
76  if( prefsize.x && size.x > prefsize.x )
77  size.x = prefsize.x;
78  if( prefsize.y && size.y > prefsize.y )
79  size.y = prefsize.y;
80  if( prefsize.z && size.z > prefsize.z )
81  size.z = prefsize.z;
82  }
83 
84  // apply keep_aspect
85  if( this->attr_keepAspect.Get() )
86  {
87  float scale = std::numeric_limits< float >::infinity();
88  if( prefsize.x )
89  scale = std::min( scale, size.x / prefsize.x );
90  if( prefsize.y )
91  scale = std::min( scale, size.y / prefsize.y );
92  if( prefsize.z )
93  scale = std::min( scale, size.z / prefsize.z );
94 
95  if( prefsize.x )
96  size.x = prefsize.x * scale;
97  if( prefsize.y )
98  size.y = prefsize.y * scale;
99  if( prefsize.z )
100  size.z = prefsize.z * scale;
101  }
102 
103  // compute inner offset
104  float3 position = this->size.Get() - size;
105  position *= this->attr_innerAnchor.Get();
106 
107  // apply resize_scales
108  if( this->attr_resizeScales.Get() )
109  {
110  if( prefsize.x != 0 )
111  scale.x = size.x / prefsize.x;
112  if( prefsize.y != 0 )
113  scale.y = size.y / prefsize.y;
114  if( prefsize.z != 0 )
115  scale.z = size.z / prefsize.z;
116  size = prefsize;
117  }
118 
119  // return values
120  out_size = size;
121  out_position = position;
122  out_scale = scale;
123 }
124 
126 {
127  // delay any refreshes if there is no child
128  if( !this->child.Get() )
129  return;
130 
131  // refresh internal geometry
132  bool refresh = false;
133  if( this->size.dirty() || this->attr_dontExpand.dirty() || this->attr_keepAspect.dirty()
134  || this->attr_innerAnchor.dirty() || this->attr_resizeScales.dirty() || this->child.Get()->preferredSize.dirty() )
135  {
136  er->Notify_SecondPass_Refresh( this );
137  refresh = true;
138 
139  //
140  this->inner_layout( this->insize, this->inpos, this->inscale );
141 
142  //
143  this->child.Get()->preferredSize.clear_dirty();
144  this->size.clear_dirty();
149  }
150 
151  // reassign values
152  if( refresh || this->child.dirty() || this->modelTransform.dirty() || this->scissor.dirty() )
153  {
154  this->child.clear_dirty();
155  this->modelTransform.clear_dirty();
156  this->scissor.clear_dirty();
157 
158  this->child.Get()->elem()->modelTransform.Set( this->modelTransform.Get() * glm::translate( float4x4( 1 ), inpos ) * glm::scale( float4x4( 1 ), this->inscale ) );
159  this->child.Get()->elem()->scissor.Set( this->scissor.Get() );
160  this->child.Get()->size.Set( insize );
161  this->child.Get()->elem()->second_pass( er );
162  }
163 }
164 
165 Align * Align::enabled( bool val )
166 {
167  this->Elem::enabled( val );
168  return this;
169 }
170 
172 {
173  this->attr_dontExpand.Set( val );
174  return this;
175 }
176 
178 {
179  this->attr_keepAspect.Set( val );
180  return this;
181 }
182 
184 {
185  this->attr_innerAnchor.Set( val );
186  return this;
187 }
188 
190 {
191  this->attr_resizeScales.Set( val );
192  return this;
193 }
194 
195 }