Dali 3D User Interface Engine
shader-effect-impl.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 
24 // INTERNAL INCLUDES
34 #include "dali-shaders.h"
35 
36 using std::string;
37 
38 namespace Dali
39 {
40 
41 namespace Internal
42 {
43 
44 namespace
45 {
46 
47 // Properties
48 
49 // Name Type writable animatable constraint-input enum for index-checking
51 DALI_PROPERTY( "gridDensity", FLOAT, true, false, false, Dali::ShaderEffect::Property::GRID_DENSITY )
52 DALI_PROPERTY( "image", MAP, true, false, false, Dali::ShaderEffect::Property::IMAGE )
53 DALI_PROPERTY( "program", MAP, true, false, false, Dali::ShaderEffect::Property::PROGRAM )
54 DALI_PROPERTY( "geometryHints", STRING, true, false, false, Dali::ShaderEffect::Property::GEOMETRY_HINTS )
56 
58 {
60 
61  return Dali::ShaderEffect(internal.Get());
62 }
63 
65 
67 {
68  const char* vertexShaderPrefix;
69  const char* fragmentShaderPrefix;
70  const char* vertexShaderPostfix;
71  const char* fragmentShaderPostfix;
72 };
73 
75 {
76  CustomImagePrefixVertex, CustomImagePrefixFragment,
77  CustomImagePostfixVertex, CustomImagePostfixFragment
78 };
79 
85 std::string WrapVertexShader( const std::string& vertexPrefix, const std::string& vertexBody )
86 {
87  std::string vertexSource = vertexPrefix + customImageShaderWrappers.vertexShaderPrefix;
88 
89  // Append the custom vertex shader code if supplied, otherwise append the default
90  if ( vertexBody.length() > 0 )
91  {
92  vertexSource.append( vertexBody );
93  }
94  else
95  {
96  vertexSource.append( customImageShaderWrappers.vertexShaderPostfix );
97  }
98 
99  return vertexSource;
100 }
101 
107 std::string WrapFragmentShader( const std::string& fragmentPrefix, const std::string& fragmentBody )
108 {
109  std::string fragmentSource = fragmentPrefix + customImageShaderWrappers.fragmentShaderPrefix;
110 
111  // Append the custom fragment shader code if supplied, otherwise append the default
112  if ( fragmentBody.length() > 0 )
113  {
114  fragmentSource.append( fragmentBody );
115  }
116  else
117  {
118  fragmentSource.append( customImageShaderWrappers.fragmentShaderPostfix );
119  }
120 
121  return fragmentSource;
122 }
123 
124 std::string GetStringProperty(const std::string& field, const Property::Value& property)
125 {
126  std::string retval;
127  const Property::Map* map = property.GetMap();
128  if( map )
129  {
130  const Property::Value* value = map->Find( field );
131  if( value )
132  {
133  value->Get( retval );
134  }
135  }
136 
137  return retval;
138 }
139 
141 {
142  int convertedHints = Dali::Shader::HINT_NONE;
144  {
146  }
148  {
150  }
152  {
153  convertedHints |= Dali::Shader::HINT_MODIFIES_GEOMETRY;
154  }
155 
156  return Dali::Shader::ShaderHints( convertedHints );
157 }
158 
159 } // unnamed namespace
160 
162 {
163  ShaderEffectPtr shaderEffect( new ShaderEffect( hints ) );
164  shaderEffect->RegisterObject();
165  return shaderEffect;
166 }
167 
169 : mGridDensity( Dali::ShaderEffect::DEFAULT_GRID_DENSITY ),
170  mGeometryHints( hints )
171 {
172 }
173 
175 {
176  // Guard to allow handle destruction after Core has been destroyed
178 }
179 
181 {
182  // if images are the same, do nothing
183  if ( mEffectImage == image )
184  {
185  return;
186  }
187 
188  if ( mEffectImage && mConnectedActors.size() > 0 )
189  {
190  // unset previous image
191  GetImplementation( mEffectImage ).Disconnect();
192  }
193 
194  // in case image is empty this will reset our image handle
195  mEffectImage = image;
196 
197  if( image )
198  {
199  // tell image that we're using it
200  if (mConnectedActors.size() > 0)
201  {
202  GetImplementation( mEffectImage ).Connect();
203  }
204  }
205 
206  //inform connected actors the image has been unset
207  for(std::vector< ActorPtr >::iterator it = mConnectedActors.begin(); it != mConnectedActors.end(); ++it )
208  {
209  ImageActor* imageActor = dynamic_cast< ImageActor* >( it->Get() );
210  if( imageActor )
211  {
212  imageActor->EffectImageUpdated();
213  }
214  }
215 }
216 
217 void ShaderEffect::SetUniform( const std::string& name, Property::Value value, UniformCoordinateType uniformCoordinateType )
218 {
219  // Register the property if it does not exist
220  mShader->RegisterProperty( name, value );
221 }
222 
223 void ShaderEffect::SetPrograms( const string& vertexSource, const string& fragmentSource )
224 {
225  SetPrograms( "", "", vertexSource, fragmentSource );
226 }
227 
228 void ShaderEffect::SetPrograms( const std::string& vertexPrefix, const std::string& fragmentPrefix,
229  const std::string& vertexSource, const std::string& fragmentSource )
230 {
231  mShader = Shader::New( WrapVertexShader( vertexPrefix, vertexSource ),
232  WrapFragmentShader( fragmentPrefix, fragmentSource ),
234 }
235 
237 {
238  Vector2 gridSize( 1.f, 1.f );
239 
240  if( mGridDensity > 0 )
241  {
243  {
244  gridSize.x = ceil( size.width / mGridDensity );
245  }
247  {
248  gridSize.y = ceil( size.height / mGridDensity );
249  }
250  }
251 
252  return gridSize;
253 }
254 
256 {
257  if( !actor )
258  {
259  return;
260  }
261 
262  std::vector< ActorPtr >::const_iterator it = std::find( mConnectedActors.begin(), mConnectedActors.end(), actor );
263  if( it == mConnectedActors.end() )
264  {
265  mConnectedActors.push_back( actor );
266  }
267 
268  if( mEffectImage && mConnectedActors.size() == 1 )
269  {
270  GetImplementation( mEffectImage ).Connect();
271  }
272 }
274 {
275  if( !actor )
276  {
277  return;
278  }
279 
281  std::vector< ActorPtr >::iterator match( std::remove( mConnectedActors.begin(), mConnectedActors.end(), actor ) );
282  mConnectedActors.erase( match, mConnectedActors.end() );
283 
284  if (mEffectImage && mConnectedActors.size() == 0)
285  {
286  GetImplementation(mEffectImage).Disconnect();
287  }
288 }
289 
290 unsigned int ShaderEffect::GetPropertyCount() const
291 {
293 }
294 
296 {
297  if ( index < DEFAULT_PROPERTY_COUNT )
298  {
299  return GetDefaultPropertyName( index );
300  }
301  else
302  {
303  return mShader->GetPropertyName( index );
304  }
305 }
306 
307 Property::Index ShaderEffect::GetPropertyIndex( const std::string& name ) const
308 {
310  if( index == Property::INVALID_INDEX )
311  {
312  return mShader->GetPropertyIndex( name );
313  }
314  else
315  {
316  return index;
317  }
318 }
319 
321 {
322  if ( index < DEFAULT_PROPERTY_COUNT )
323  {
324  return IsDefaultPropertyWritable( index );
325  }
326  else
327  {
328  return mShader->IsPropertyWritable( index );
329  }
330 }
331 
333 {
334  if ( index < DEFAULT_PROPERTY_COUNT )
335  {
336  return IsDefaultPropertyAnimatable( index );
337  }
338  else
339  {
340  return mShader->IsPropertyAnimatable( index );
341  }
342 }
343 
345 {
346  if ( index < DEFAULT_PROPERTY_COUNT )
347  {
348  return IsDefaultPropertyAConstraintInput( index );
349  }
350  else
351  {
352  return mShader->IsPropertyAConstraintInput( index );
353  }
354 }
355 
357 {
358  if ( index < DEFAULT_PROPERTY_COUNT )
359  {
360  return GetDefaultPropertyType( index );
361  }
362  return mShader->GetPropertyType( index );
363 }
364 
365 void ShaderEffect::SetProperty( Property::Index index, const Property::Value& propertyValue )
366 {
367  if ( index < DEFAULT_PROPERTY_COUNT )
368  {
369  SetDefaultProperty( index, propertyValue );
370  }
371  else
372  {
373  mShader->SetProperty( index, propertyValue );
374  }
375 }
376 
378 {
379  if ( index < DEFAULT_PROPERTY_COUNT )
380  {
381  return GetDefaultProperty( index );
382  }
383  return mShader->GetProperty( index );
384 }
385 
387 {
388  mShader->GetPropertyIndices( indices );
389  GetDefaultPropertyIndices( indices );
390 }
391 
392 Property::Index ShaderEffect::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
393 {
394  return mShader->RegisterProperty( name, propertyValue );
395 }
396 
397 Property::Index ShaderEffect::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
398 {
399  return mShader->RegisterProperty( name, propertyValue, accessMode );
400 }
401 
403  int componentIndex,
404  const Dali::PropertyCondition& condition )
405 {
406  return mShader->AddPropertyNotification( index, componentIndex, condition );
407 }
408 
410 {
411  mShader->RemovePropertyNotification( propertyNotification );
412 }
413 
415 {
417 }
418 
420 {
421  return DEFAULT_PROPERTY_COUNT;
422 }
423 
425 {
426  indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
427 
428  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
429  {
430  indices.PushBack( i );
431  }
432 }
433 
435 {
436  if( index < DEFAULT_PROPERTY_COUNT )
437  {
438  return DEFAULT_PROPERTY_DETAILS[index].name;
439  }
440 
441  return NULL;
442 }
443 
445 {
447 
448  // Look for name in default properties
449  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
450  {
451  const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
452  if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
453  {
454  index = i;
455  break;
456  }
457  }
458 
459  return index;
460 }
461 
463 {
464  return DEFAULT_PROPERTY_DETAILS[ index ].writable;
465 }
466 
468 {
469  return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
470 }
471 
473 {
474  return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
475 }
476 
478 {
479  if( index < DEFAULT_PROPERTY_COUNT )
480  {
481  return DEFAULT_PROPERTY_DETAILS[index].type;
482  }
483 
484  // index out of range...return Property::NONE
485  return Property::NONE;
486 }
487 
489 {
490  switch ( index )
491  {
493  {
494  propertyValue.Get( mGridDensity );
497  {
498  //inform all the connected actors
499  for(std::vector< ActorPtr >::iterator it = mConnectedActors.begin(); it != mConnectedActors.end(); ++it )
500  {
501  (*it)->RelayoutRequest();
502  }
503  }
504  break;
505  }
506 
508  {
509  Dali::Image img(Scripting::NewImage( propertyValue ));
510  if(img)
511  {
512  SetEffectImage( img );
513  }
514  else
515  {
516  DALI_LOG_WARNING("Cannot create image from property value for ShaderEffect image\n");
517  }
518  break;
519  }
520 
522  {
523  std::string vertexPrefix = GetStringProperty("vertexPrefix", propertyValue);
524  std::string fragmentPrefix = GetStringProperty("fragmentPrefix", propertyValue);
525  std::string vertex = GetStringProperty("vertex", propertyValue);
526  std::string fragment = GetStringProperty("fragment", propertyValue);
527 
528  SetPrograms( vertexPrefix, fragmentPrefix, vertex, fragment );
529  break;
530  }
531 
533  {
535  std::string s = propertyValue.Get<std::string>();
536  if(s == "HINT_NONE")
537  {
539  }
540  else if(s == "HINT_GRID_X")
541  {
543  }
544  else if(s == "HINT_GRID_Y")
545  {
547  }
548  else if(s == "HINT_GRID")
549  {
551  }
552  else if(s == "HINT_DEPTH_BUFFER")
553  {
555  }
556  else if(s == "HINT_BLENDING")
557  {
559  }
560  else if(s == "HINT_DOESNT_MODIFY_GEOMETRY")
561  {
563  }
564  else
565  {
566  DALI_ASSERT_ALWAYS(!"Geometry hint unknown" );
567  }
568  break;
569  }
570 
571  default:
572  {
573  // nothing to do
574  break;
575  }
576  }
577 }
578 
580 {
581  // none of our properties are readable so return empty
582  return Property::Value();
583 }
584 
586 {
587  return mShader->GetSceneObject();
588 }
589 
591 {
592  return mShader->GetSceneObjectAnimatableProperty( index );
593 }
594 
596 {
597  return mShader->GetSceneObjectInputProperty( index );
598 }
599 
601 {
602  return mShader->GetPropertyComponentIndex( index );
603 }
604 
605 } // namespace Internal
606 
607 } // namespace Dali
Dali Docs Home
Read more about Dali