8b2d0f9c16a886a752c31c03515a937a3d29ae63
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / rendering / material-api.cpp
1 /*
2  * Copyright (c) 2015 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
19 // CLASS HEADER
20 #include "material-api.h"
21
22 // EXTERNAL INCLUDES
23 #include <dali/public-api/object/type-registry.h>
24
25 // INTERNAL INCLUDES
26 #include <v8-utils.h>
27 #include <rendering/material-wrapper.h>
28 #include <rendering/shader-wrapper.h>
29 #include <rendering/shader-api.h>
30 #include <rendering/sampler-wrapper.h>
31 #include <rendering/sampler-api.h>
32 #include <image/image-wrapper.h>
33
34 namespace Dali
35 {
36
37 namespace V8Plugin
38 {
39
40 /**
41  * ## Material API
42  *
43  * Material is a handle to an object that specifies the visual properties of the renderer.
44  *
45  * @class Material
46  * @extends Handle
47  */
48
49 Material MaterialApi::GetMaterial( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
50 {
51   v8::HandleScope handleScope( isolate );
52
53   v8::Local<v8::Object> object = args.This();
54   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
55   void* ptr = field->Value();
56
57   MaterialWrapper* wrapper = static_cast< MaterialWrapper *>(ptr);
58   return wrapper->GetMaterial();
59 }
60
61 Material MaterialApi::GetMaterialFromParams( int paramIndex,
62                                                bool& found,
63                                                v8::Isolate* isolate,
64                                                const v8::FunctionCallbackInfo< v8::Value >& args )
65 {
66   found = false;
67
68   v8::HandleScope handleScope( isolate );
69   BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::MATERIAL, isolate, args );
70   if( wrappedObject )
71   {
72     found = true;
73     MaterialWrapper* wrapper = static_cast< MaterialWrapper *>(wrappedObject);
74     return wrapper->GetMaterial();
75   }
76   else
77   {
78     return Material();
79   }
80 }
81
82 /**
83  * Create a new material object.
84  *
85  * @constructor
86  * @method Material
87  * @for Material
88  * @param {Object} shader The shader used by the material
89  * @return {Object} Material
90  */
91 Material MaterialApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
92 {
93   v8::Isolate* isolate = args.GetIsolate();
94   v8::HandleScope handleScope( isolate );
95
96   bool found( false );
97   Shader shader = ShaderApi::GetShaderFromParams( 0, found, isolate, args );
98   if( found )
99   {
100     return Material::New( shader );
101   }
102   else
103   {
104     DALI_SCRIPT_EXCEPTION( isolate, "missing shader from param 0" );
105     return Material();
106   }
107 }
108
109 /**
110  * Set the Shader used by this material
111  *
112  * @method setShader
113  * @for Material
114  * @param {Object} shader Handle to the shader
115  */
116 void MaterialApi::SetShader( const v8::FunctionCallbackInfo< v8::Value >& args )
117 {
118   v8::Isolate* isolate = args.GetIsolate();
119   v8::HandleScope handleScope( isolate );
120
121   Material material = GetMaterial( isolate, args );
122
123   bool found( false );
124   Shader shader = ShaderApi::GetShaderFromParams( 0, found, isolate, args );
125   if( !found )
126   {
127     DALI_SCRIPT_EXCEPTION( isolate, "invalid shader parameter" );
128   }
129   else
130   {
131     return material.SetShader( shader );
132   }
133 }
134
135 /**
136  * Get the Shader used by this material
137  *
138  * @method getShader
139  * @for Material
140  * @return {Object} Shader
141  */
142 void MaterialApi::GetShader( const v8::FunctionCallbackInfo< v8::Value >& args )
143 {
144   v8::Isolate* isolate = args.GetIsolate();
145   v8::HandleScope handleScope( isolate );
146
147   Material material = GetMaterial( isolate, args );
148   Shader shader = material.GetShader();
149
150   // Wrap the shader
151   v8::Local<v8::Object> localObject = ShaderWrapper::WrapShader( isolate, shader );
152   args.GetReturnValue().Set( localObject );
153 }
154
155 /**
156  * Add a new texture to be used by the material
157  *
158  * @method addTexture
159  * @for Material
160  * @param {Object} image The image used by this sampler
161  * @param {String} uniformName The string with the name of the uniform
162  * @param {Object} sampler The sampler to add to this material
163  * @return {integer} The index of the texture in the array of textures or -1 if texture can not be added
164  */
165 void MaterialApi::AddTexture( const v8::FunctionCallbackInfo< v8::Value >& args )
166 {
167   v8::Isolate* isolate = args.GetIsolate();
168   v8::HandleScope handleScope( isolate );
169
170   Material material = GetMaterial( isolate, args );
171
172   bool found( false );
173   Image image = V8Utils::GetImageParameter( PARAMETER_0, found, isolate, args );
174   if( !found )
175   {
176     DALI_SCRIPT_EXCEPTION( isolate, "missing image from param 0" );
177     return;
178   }
179
180   found = false;
181   std::string uniformName = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args );
182   if( !found )
183   {
184     DALI_SCRIPT_EXCEPTION( isolate, "missing uniform name from param 1" );
185     return;
186   }
187
188   found = false;
189   Sampler sampler = SamplerApi::GetSamplerFromParams( PARAMETER_2, found, isolate, args );
190   if( !found )
191   {
192     args.GetReturnValue().Set( v8::Integer::New( isolate, material.AddTexture( image, uniformName ) ) );
193   }
194   else
195   {
196     args.GetReturnValue().Set( v8::Integer::New( isolate, material.AddTexture( image, uniformName, sampler ) ) );
197   }
198 }
199
200 /**
201  * Removes a texture from the material
202  *
203  * @method removeTexture
204  * @for Material
205  * @param {integer} index The index of the texture in the array of textures
206  */
207 void MaterialApi::RemoveTexture( const v8::FunctionCallbackInfo< v8::Value >& args )
208 {
209   v8::Isolate* isolate = args.GetIsolate();
210   v8::HandleScope handleScope( isolate );
211
212   Material material = GetMaterial( isolate, args );
213
214   bool found( false );
215   int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
216   if( !found )
217   {
218     DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
219   }
220   else
221   {
222     material.RemoveTexture( index );
223   }
224 }
225
226 /**
227  * Sets the image to be used by a given texture
228  * @method setTextureImage
229  * @for Material
230  * @param {integer} index The index of the texture in the array of textures
231  * @param {Object} image The image used by this sampler
232  */
233 void MaterialApi::SetTextureImage( const v8::FunctionCallbackInfo< v8::Value >& args )
234 {
235   v8::Isolate* isolate = args.GetIsolate();
236   v8::HandleScope handleScope( isolate );
237
238   Material material = GetMaterial( isolate, args );
239
240   bool found( false );
241   int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
242   if( !found )
243   {
244     DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
245     return;
246   }
247
248   found = false;
249   Image image = V8Utils::GetImageParameter( PARAMETER_1, found, isolate, args );
250   if( !found )
251   {
252     DALI_SCRIPT_EXCEPTION( isolate, "missing image from param 1" );
253   }
254   else
255   {
256     material.SetTextureImage(index, image);
257   }
258 }
259
260 /**
261  * Set the sampler used by a given texture
262  * @method setTextureSampler
263  * @for Material
264  * @param {integer} index The index of the texture in the array of textures
265  * @param {Object} sampler The new sampler
266  */
267 void MaterialApi::SetTextureSampler( const v8::FunctionCallbackInfo< v8::Value >& args )
268 {
269   v8::Isolate* isolate = args.GetIsolate();
270   v8::HandleScope handleScope( isolate );
271
272   Material material = GetMaterial( isolate, args );
273
274   bool found( false );
275   int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
276   if( !found )
277   {
278     DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
279     return;
280   }
281
282   found = false;
283   Sampler sampler = SamplerApi::GetSamplerFromParams( PARAMETER_1, found, isolate, args );
284   if( !found )
285   {
286     DALI_SCRIPT_EXCEPTION( isolate, "missing sampler from param 1" );
287   }
288   else
289   {
290     material.SetTextureSampler(index, sampler);
291   }
292 }
293
294 /**
295  * Set the uniform name of a given texture
296  * @method setTextureUniformName
297  * @for Material
298  * @param {integer} index The index of the texture in the array of textures
299  * @param {string} uniformName The new uniform name
300  */
301 void MaterialApi::SetTextureUniformName( const v8::FunctionCallbackInfo< v8::Value >& args )
302 {
303   v8::Isolate* isolate = args.GetIsolate();
304   v8::HandleScope handleScope( isolate );
305
306   Material material = GetMaterial( isolate, args );
307
308   bool found( false );
309   int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
310   if( !found )
311   {
312     DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
313     return;
314   }
315
316   found = false;
317   std::string uniformName = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args );
318   if( !found )
319   {
320     DALI_SCRIPT_EXCEPTION( isolate, "invalid uniform name parameter" );
321   }
322   else
323   {
324     material.SetTextureUniformName(index, uniformName);
325   }
326 }
327
328 /**
329  * Establish if a given texture will affect the transparency of the material ( true by default )
330  * @method setTextureAffectsTransparency
331  * @for Material
332  * @param {integer} index The index of the texture in the array of textures
333  * @param {string} affectsTransparency True if the texture affects transparency, false otherwise
334  */
335 void MaterialApi::SetTextureAffectsTransparency( const v8::FunctionCallbackInfo< v8::Value >& args )
336 {
337   v8::Isolate* isolate = args.GetIsolate();
338   v8::HandleScope handleScope( isolate );
339
340   Material material = GetMaterial( isolate, args );
341
342   bool found( false );
343   int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
344   if( !found )
345   {
346     DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
347     return;
348   }
349
350   found = false;
351   bool affectsTransparency = V8Utils::GetBooleanParameter( PARAMETER_1, found, isolate, args );
352   if( !found )
353   {
354     DALI_SCRIPT_EXCEPTION( isolate, "invalid affectsTransparency parameter" );
355   }
356   else
357   {
358     material.SetTextureAffectsTransparency(index, affectsTransparency);
359   }
360 }
361
362 /**
363  * Retrive the index of a texture given its uniform name
364  * @method getTextureIndex
365  * @for Material
366  * @param {string} uniformName The uniform name
367  * @return {integer} The index in the array of textures or -1 if the texture is not found
368  */
369 void MaterialApi::GetTextureIndex( const v8::FunctionCallbackInfo< v8::Value >& args )
370 {
371   v8::Isolate* isolate = args.GetIsolate();
372   v8::HandleScope handleScope( isolate );
373
374   Material material = GetMaterial( isolate, args );
375
376   bool found( false );
377   std::string uniformName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
378   if( !found )
379   {
380     DALI_SCRIPT_EXCEPTION( isolate, "invalid uniform name parameter" );
381   }
382   else
383   {
384     args.GetReturnValue().Set( v8::Integer::New( isolate, material.GetTextureIndex(uniformName) ) );
385   }
386 }
387
388 /**
389  * Retrieve the number of textures used by the material
390  *
391  * @method getNumberOfTextures
392  * @for Material
393  * @return {integer} The number of textures
394  */
395 void MaterialApi::GetNumberOfTextures( const v8::FunctionCallbackInfo< v8::Value >& args )
396 {
397   v8::Isolate* isolate = args.GetIsolate();
398   v8::HandleScope handleScope( isolate );
399
400   Material material = GetMaterial( isolate, args );
401
402   args.GetReturnValue().Set( v8::Integer::New( isolate, material.GetNumberOfTextures() ) );
403 }
404
405 /**
406  * Set the culling mode for this material
407  *
408  * @method setFaceCullingMode
409  * @for Material
410  * @param {integer} cullingMode The culling mode for this material
411  * @example
412  *      // face culling mode is one of the following
413  *      dali.MATERIAL_NONE                           // None of the faces should be culled
414  *      dali.MATERIAL_CULL_BACK                      // Cull back face, back face should never be shown
415  *      dali.MATERIAL_CULL_FRONT                     // Cull front face, back face should never be shown
416  *      dali.MATERIAL_CULL_BACK_AND_FRONT            // Cull back and front faces, if the geometry is composed of triangles none of the faces will be shown
417  *
418  *      material.setFaceCullingMode( dali.MATERIAL_NONE );
419  */
420 void MaterialApi::SetFaceCullingMode( const v8::FunctionCallbackInfo< v8::Value >& args )
421 {
422   v8::Isolate* isolate = args.GetIsolate();
423   v8::HandleScope handleScope( isolate );
424
425   Material material = GetMaterial( isolate, args );
426
427   bool found( false );
428   int mode = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0);
429   if( !found )
430   {
431     DALI_SCRIPT_EXCEPTION( isolate, "invalid cullingMode parameter" );
432   }
433   else
434   {
435     material.SetFaceCullingMode( static_cast<Material::FaceCullingMode>(mode) );
436   }
437 }
438
439 /**
440  * Set the blending mode.
441  *
442  * If blending is disabled (BLENDING_OFF) fade in and fade out animations do not work.
443  *
444  * @for Material
445  * @method setBlendMode
446  * @param { integer } mode The blending mode.
447  * @example
448  *      // blend mode is one of the following
449  *      dali.BLENDING_OFF       // Blending is disabled.
450  *      dali.BLENDING_AUTO      // Blending is enabled if there is alpha channel.
451  *      dali.BLENDING_ON        // Blending is enabled.
452  *
453  *      material.setBlendMode( dali.BLENDING_AUTO );
454  */
455 void MaterialApi::SetBlendMode( const v8::FunctionCallbackInfo< v8::Value >& args )
456 {
457   v8::Isolate* isolate = args.GetIsolate();
458   v8::HandleScope handleScope( isolate );
459
460   Material material = GetMaterial( isolate, args );
461
462   bool found( false );
463   int mode = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 );
464   if( !found )
465   {
466     DALI_SCRIPT_EXCEPTION( isolate, "invalid blendMode parameter" );
467   }
468   else
469   {
470     material.SetBlendMode( static_cast<Dali::BlendingMode::Type>( mode ) );
471   }
472 }
473
474 /**
475  * Retrieves the blending mode.
476  *
477  * @for Material
478  * @method getBlendMode
479  * @return { integer } blendMode
480  * @example returns one of the following:
481  *
482  *        dali.BLENDING_OFF       // Blending is disabled.
483  *        dali.BLENDING_AUTO      // Blending is enabled if there is alpha channel.
484  *        dali.BLENDING_ON        // Blending is enabled.
485  */
486 void MaterialApi::GetBlendMode( const v8::FunctionCallbackInfo<v8::Value>& args )
487 {
488   v8::Isolate* isolate = args.GetIsolate();
489   v8::HandleScope handleScope( isolate );
490
491   Material material = GetMaterial( isolate, args );
492
493   args.GetReturnValue().Set( v8::Integer::New( isolate, material.GetBlendMode() ) );
494 }
495
496 /**
497  * Specify the pixel arithmetic used when the actor is blended.
498  *
499  * @for Material
500  * @method setBlendFunc
501  * @param {integer} srcFactorRgb Source Blending RGB
502  * @param {integer} destFactorRgb Destination Blending RGB
503  * @param {integer} srcFactorAlpha Source Blending Alpha
504  * @param {integer} destFactorAlpha Destinatino Blending Alpha
505  * @example
506  *    //blending constants
507  *    dali.BLEND_FACTOR_ZERO
508  *    dali.BLEND_FACTOR_ONE
509  *    dali.BLEND_FACTOR_SRC_COLOR
510  *    dali.BLEND_FACTOR_ONE_MINUS_SRC_COLOR
511  *    dali.BLEND_FACTOR_SRC_ALPHA
512  *    dali.BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
513  *    dali.BLEND_FACTOR_DST_ALPHA
514  *    dali.BLEND_FACTOR_ONE_MINUS_DST_ALPHA
515  *    dali.BLEND_FACTOR_DST_COLOR
516  *    dali.BLEND_FACTOR_ONE_MINUS_DST_COLOR
517  *    dali.BLEND_FACTOR_SRC_ALPHA_SATURATE
518  *    dali.BLEND_FACTOR_CONSTANT_COLOR
519  *    dali.BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR
520  *    dali.BLEND_FACTOR_CONSTANT_ALPHA
521  *    dali.BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA
522  *
523  *    material.setBlendFunc( dali.BLEND_FACTOR_CONSTANT_COLOR, dali.BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
524  *                           dali.BLEND_FACTOR_CONSTANT_ALPHA, dali.BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA );
525  */
526 void MaterialApi::SetBlendFunc( const v8::FunctionCallbackInfo< v8::Value >& args )
527 {
528   v8::Isolate* isolate = args.GetIsolate();
529   v8::HandleScope handleScope( isolate );
530
531   Material material = GetMaterial( isolate, args );
532
533   int params[4];
534   bool foundAllParams(false);
535   V8Utils::ReadIntegerArguments( foundAllParams, &params[0], 4, args, 0 );
536   if( foundAllParams )
537   {
538     material.SetBlendFunc( static_cast< Dali::BlendingFactor::Type>(params[0]),
539                            static_cast< Dali::BlendingFactor::Type>(params[1]),
540                            static_cast< Dali::BlendingFactor::Type>(params[2]),
541                            static_cast< Dali::BlendingFactor::Type>(params[3]) );
542   }
543   else
544   {
545     DALI_SCRIPT_EXCEPTION( isolate, "invalid blendFunc parameter");
546   }
547 }
548
549 /**
550  * Query the pixel arithmetic used when the actor is blended.
551  *
552  * @for Material
553  * @method getBlendFunc
554  * @return {Object} Blend properties
555  * @example Blend properties object has 4 fields
556  *
557  *      blendProperties.sourceRgb // source rgb enum
558  *      blendProperties.destinationRgb // destination rgb enum
559  *      blendProperties.sourceAlpha source // alpha enum
560  *      blendProperties.destinationAlpha // destination alpha enum
561  */
562 void MaterialApi::GetBlendFunc( const v8::FunctionCallbackInfo< v8::Value >& args )
563 {
564   // Pass by reference doesn't work in Javascript
565   // For now just return a vector 4...
566
567   BlendingFactor::Type srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha;
568   v8::Isolate* isolate = args.GetIsolate();
569   v8::HandleScope handleScope( isolate );
570
571   Material material = GetMaterial( isolate, args );
572
573   material.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
574
575   v8::Local<v8::Object> blendProperties = v8::Object::New( isolate );
576
577   blendProperties->Set( v8::String::NewFromUtf8( isolate, "sourceRgb" ),        v8::Integer::New( isolate, srcFactorRgb) );
578   blendProperties->Set( v8::String::NewFromUtf8( isolate, "destinationRgb" ),   v8::Integer::New( isolate, destFactorRgb ) );
579   blendProperties->Set( v8::String::NewFromUtf8( isolate, "sourceAlpha" ),      v8::Integer::New( isolate, srcFactorAlpha  ) );
580   blendProperties->Set( v8::String::NewFromUtf8( isolate, "destinationAlpha" ), v8::Integer::New( isolate, destFactorAlpha ) );
581
582   args.GetReturnValue().Set( blendProperties );
583 }
584
585 /**
586  * Specify the equation used when the actor is blended.
587  *
588  * @for Material
589  * @method setBlendEquation
590  * @param { integer } equationRgb The equation used for combining red, green, and blue components.
591  * @param { integer } equationAlpha The equation used for combining the alpha component.
592  * @example
593  *      // blend equation is one of the following
594  *      dali.BLEND_EQUATION_ADD
595  *      dali.BLEND_EQUATION_SUBTRACT
596  *      dali.BLEND_EQUATION_REVERSE_SUBTRACT
597  *
598  *      material.setBlendEquation( dali.BLEND_EQUATION_ADD, dali.BLEND_EQUATION_REVERSE_SUBTRACT );
599  */
600 void MaterialApi::SetBlendEquation( const v8::FunctionCallbackInfo< v8::Value >& args )
601 {
602   v8::Isolate* isolate = args.GetIsolate();
603   v8::HandleScope handleScope( isolate );
604
605   Material material = GetMaterial( isolate, args );
606
607   int params[2];
608   bool foundAllParams(false);
609   V8Utils::ReadIntegerArguments( foundAllParams, &params[0], 2, args, 0 );
610   if( foundAllParams )
611   {
612     material.SetBlendEquation( static_cast< BlendingEquation::Type>(params[0]), static_cast< BlendingEquation::Type>(params[1]) );
613   }
614   else
615   {
616     DALI_SCRIPT_EXCEPTION( isolate, "invalid BlendEquation parameter");
617   }
618 }
619
620 /**
621  * Query the equation used when the actor is blended.
622  *
623  * @for Material
624  * @method getBlendEquation
625  * @return {Object} Blend equations
626  * @example Blend equations object has 2 fields
627  *
628  *      blendEquations.equationRgb // equation used for combining rgb components
629  *      blendEquations.equationAlpha // equation used for combining alpha components
630  */
631 void MaterialApi::GetBlendEquation( const v8::FunctionCallbackInfo< v8::Value >& args )
632 {
633   // Pass by reference doesn't work in Javascript
634   // For now just return a vector 2...
635
636   BlendingEquation::Type equationRgb, equationAlpha;
637   v8::Isolate* isolate = args.GetIsolate();
638   v8::HandleScope handleScope( isolate );
639
640   Material material = GetMaterial( isolate, args );
641
642   material.GetBlendEquation( equationRgb, equationAlpha );
643
644   v8::Local<v8::Object> blendEquations = v8::Object::New( isolate );
645
646   blendEquations->Set( v8::String::NewFromUtf8( isolate, "equationRgb" ),   v8::Integer::New( isolate, equationRgb) );
647   blendEquations->Set( v8::String::NewFromUtf8( isolate, "equationAlpha" ), v8::Integer::New( isolate, equationAlpha ) );
648
649   args.GetReturnValue().Set( blendEquations );
650 }
651
652 } // namespace V8Plugin
653
654 } // namespace Dali