Vuo  2.0.0
VuoLayer.c
Go to the documentation of this file.
1 
10 #include "type.h"
11 #include "VuoLayer.h"
12 #include "VuoAnchor.h"
13 #include "VuoImageBlur.h"
14 #include "VuoImageText.h"
15 #include "VuoSceneText.h"
16 
18 #ifdef VUO_COMPILER
20  "title" : "Layer",
21  "description" : "A 2D Layer: visible (image), or virtual (group).",
22  "keywords" : [ ],
23  "version" : "1.0.0",
24  "dependencies" : [
25  "VuoAnchor",
26  "VuoColor",
27  "VuoImageBlur",
28  "VuoImageText",
29  "VuoPoint2d",
30  "VuoRectangle",
31  "VuoSceneObject",
32  "VuoSceneText",
33  "VuoTransform2d",
34  "VuoWindowReference",
35  "VuoList_VuoColor",
36  "VuoList_VuoLayer",
37  "VuoList_VuoSceneObject"
38  ]
39  });
40 #endif
41 
43 
48 {
49  VuoLayer o;
51  return o;
52 }
53 
64 VuoLayer VuoLayer_make(VuoText name, VuoImage image, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal alpha)
65 {
66  VuoLayer o;
67  VuoPoint3d center3d = VuoPoint3d_make(center.x, center.y, 0);
68  VuoPoint3d rotation3d = VuoPoint3d_make(0, 0, rotation);
69  o.sceneObject = VuoSceneObject_makeImage(image, center3d, rotation3d, width, alpha);
70  o.sceneObject.name = name;
71  return o;
72 }
73 
83 {
84  VuoLayer o;
85  VuoPoint3d center3d = VuoPoint3d_make(transform.translation.x, transform.translation.y, 0);
86  // VuoSceneObject_makeImage wants rotation in degrees
87  VuoPoint3d rotation3d = VuoPoint3d_make(0, 0, transform.rotation * 57.295779513f);
88  o.sceneObject = VuoSceneObject_makeImage(image, center3d, rotation3d, 2, alpha);
89  o.sceneObject.transform.scale = VuoPoint3d_make(transform.scale.x, transform.scale.y, 1);
90  o.sceneObject.name = name;
91  return o;
92 }
93 
105 VuoLayer VuoLayer_makeRealSize(VuoText name, VuoImage image, VuoPoint2d center, VuoReal alpha, VuoBoolean preservePhysicalSize)
106 {
107  VuoLayer l = VuoLayer_make(name,image,center,0,0,alpha);
108  l.sceneObject.isRealSize = true;
109  l.sceneObject.preservePhysicalSize = preservePhysicalSize;
110  return l;
111 }
112 
129 static VuoLayer VuoLayer_makeWithShadowInternal(VuoText name, VuoImage image, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal alpha, VuoBoolean preservePhysicalSize, VuoColor shadowColor, VuoReal shadowBlur, VuoReal shadowAngle, VuoReal shadowDistance, VuoBoolean isRealSize)
130 {
131  if (!image)
132  return VuoLayer_makeEmpty();
133 
134  // Create a pair of layers, one for the main layer and one for the shadow, and put them in a group.
135  // Apply the transformation to the individual layers, rather than to the group, so that
136  // VuoRenderedLayers_getTransformedLayer() can work with the individual layers.
137 
138  float rotationInRadians = rotation * M_PI/180.;
139  VuoTransform groupTransform = VuoTransform_makeFrom2d( VuoTransform2d_make(center, rotationInRadians, VuoPoint2d_make(width,width)) );
140  float matrix[16];
141  VuoTransform_getMatrix(groupTransform, matrix);
142 
143  VuoPoint3d center3d = VuoPoint3d_make(0,0,0);
144  VuoPoint3d layerCenter3d = VuoTransform_transformPoint(matrix, center3d);
145  VuoPoint2d layerCenter = VuoPoint2d_make(layerCenter3d.x, layerCenter3d.y);
146  VuoLayer layer = VuoLayer_make(name, image, layerCenter, rotation, width, alpha);
147  layer.sceneObject.isRealSize = isRealSize;
148  layer.sceneObject.preservePhysicalSize = preservePhysicalSize;
149 
151  VuoRetain(colors);
152  VuoListAppendValue_VuoColor(colors, shadowColor);
153  VuoImage recoloredImage = VuoImage_mapColors(image, colors, 1);
154  VuoRetain(recoloredImage);
155  VuoRelease(colors);
156 
158  VuoRetain(ib);
159  VuoImage blurredImage = VuoImageBlur_blur(ib, recoloredImage, NULL, VuoBlurShape_Gaussian, shadowBlur, 1, TRUE);
160  VuoRelease(ib);
161  float shadowAngleInRadians = shadowAngle * M_PI/180.;
162  VuoPoint3d shadowOffset3d = VuoPoint3d_make(shadowDistance * cos(shadowAngleInRadians),
163  shadowDistance * sin(shadowAngleInRadians),
164  0);
165  VuoPoint3d shadowCenter3d = VuoTransform_transformPoint(matrix, shadowOffset3d);
166  VuoPoint2d shadowCenter = VuoPoint2d_make(shadowCenter3d.x, shadowCenter3d.y);
167  VuoReal shadowWidth = width * blurredImage->pixelsWide/image->pixelsWide;
168  VuoLayer shadow = VuoLayer_make(NULL, blurredImage, shadowCenter, rotation, shadowWidth, alpha);
169  shadow.sceneObject.isRealSize = isRealSize;
170  shadow.sceneObject.preservePhysicalSize = preservePhysicalSize;
171 
173  VuoRetain(layers);
174  VuoListAppendValue_VuoLayer(layers, shadow);
175  VuoListAppendValue_VuoLayer(layers, layer);
176 
177  VuoRelease(recoloredImage);
178 
180  VuoRelease(layers);
181 
182  return group;
183 }
184 
199 VuoLayer VuoLayer_makeWithShadow(VuoText name, VuoImage image, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal alpha, VuoColor shadowColor, VuoReal shadowBlur, VuoReal shadowAngle, VuoReal shadowDistance)
200 {
201  return VuoLayer_makeWithShadowInternal(name,image,center,rotation,width,alpha,false,shadowColor,shadowBlur,shadowAngle,shadowDistance,false);
202 }
203 
219 VuoLayer VuoLayer_makeRealSizeWithShadow(VuoText name, VuoImage image, VuoPoint2d center, VuoReal alpha, VuoBoolean preservePhysicalSize, VuoColor shadowColor, VuoReal shadowBlur, VuoReal shadowAngle, VuoReal shadowDistance)
220 {
221  return VuoLayer_makeWithShadowInternal(name,image,center,0,1,alpha,preservePhysicalSize,shadowColor,shadowBlur,shadowAngle,shadowDistance,true);
222 }
223 
234 VuoLayer VuoLayer_makeColor(VuoText name, VuoColor color, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height)
235 {
236  VuoLayer o;
239  VuoPoint3d_make(center.x, center.y, 0),
240  VuoPoint3d_make(0, 0, rotation),
241  width,
242  height
243  );
244  o.sceneObject.name = name;
245  return o;
246 }
247 
259 VuoLayer VuoLayer_makeOval(VuoText name, VuoColor color, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height, VuoReal sharpness)
260 {
261  VuoLayer o;
262  // Since VuoShader_makeUnlitCircleShader() produces a shader that fills half the size (to leave enough room for sharpness=0),
263  // make the layer twice the specified size.
265  VuoShader_makeUnlitCircleShader(color, sharpness),
266  VuoPoint3d_make(center.x, center.y, 0),
267  VuoPoint3d_make(0, 0, rotation),
268  width*2,
269  height*2
270  );
271  o.sceneObject.name = name;
272  return o;
273 }
274 
288 VuoLayer VuoLayer_makeCheckmark(VuoText name, VuoColor fillColor, VuoColor outlineColor, VuoReal outlineThickness, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height)
289 {
290  VuoLayer o;
291 
293  VuoShader_makeUnlitCheckmarkShader(fillColor, outlineColor, outlineThickness),
294  VuoPoint3d_make(center.x, center.y, 0),
295  VuoPoint3d_make(0, 0, rotation),
296  width,
297  height );
298  o.sceneObject.name = name;
299  return o;
300 }
301 
314 VuoLayer VuoLayer_makeRoundedRectangle(VuoText name, VuoColor color, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height, VuoReal sharpness, VuoReal roundness)
315 {
316  VuoLayer o;
317 
319  VuoShader_makeUnlitRoundedRectangleShader(color, sharpness, roundness, width/height),
320  VuoPoint3d_make(center.x, center.y, 0),
321  VuoPoint3d_make(0, 0, rotation),
322  width * 2,
323  height * 2
324  );
325  o.sceneObject.name = name;
326 
327  return o;
328 }
329 
343 VuoLayer VuoLayer_makeLinearGradient(VuoText name, VuoList_VuoColor colors, VuoPoint2d start, VuoPoint2d end, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height, VuoReal noiseAmount)
344 {
346  VuoShader_setLinearGradientShaderValues(shader, colors, start, end, 1, noiseAmount);
347  VuoLayer o;
349  shader,
350  VuoPoint3d_make(center.x, center.y, 0),
351  VuoPoint3d_make(0, 0, rotation),
352  width,
353  height
354  );
355  o.sceneObject.name = name;
356  return o;
357 }
358 
372 VuoLayer VuoLayer_makeRadialGradient(VuoText name, VuoList_VuoColor colors, VuoPoint2d gradientCenter, VuoReal radius, VuoPoint2d center, VuoReal rotation, VuoReal width, VuoReal height, VuoReal noiseAmount)
373 {
375  VuoShader_setRadialGradientShaderValues(shader, colors, gradientCenter, radius, width, height, noiseAmount);
376  VuoLayer o;
378  shader,
379  VuoPoint3d_make(center.x, center.y, 0),
380  VuoPoint3d_make(0, 0, rotation),
381  width,
382  height
383  );
384  o.sceneObject.name = name;
385  return o;
386 }
387 
392 {
393  VuoLayer o;
395 
396  unsigned long childLayerCount = VuoListGetCount_VuoLayer(childLayers);
397  for (unsigned long i = 1; i <= childLayerCount; ++i)
398  VuoListAppendValue_VuoSceneObject(o.sceneObject.childObjects, VuoListGetValue_VuoLayer(childLayers, i).sceneObject);
399 
400  return o;
401 }
402 
408 {
410  VuoLocal(group);
411  VuoListAppendValue_VuoLayer(group, layer1);
412  VuoListAppendValue_VuoLayer(group, layer2);
413  return VuoLayer_makeGroup(group, transform);
414 }
415 
421 {
423  VuoLocal(group);
424  VuoListAppendValue_VuoLayer(group, layer1);
425  VuoListAppendValue_VuoLayer(group, layer2);
426  VuoListAppendValue_VuoLayer(group, layer3);
427  return VuoLayer_makeGroup(group, transform);
428 }
429 
434 {
435  unsigned long childLayerCount = VuoListGetCount_VuoSceneObject(layer.sceneObject.childObjects);
436  if (childLayerCount == 0)
437  return NULL;
438 
439  VuoList_VuoLayer childLayers = VuoListCreateWithCount_VuoLayer(childLayerCount, VuoLayer_makeEmpty());
440  VuoLayer *childLayersData = VuoListGetData_VuoLayer(childLayers);
441  VuoSceneObject *objects = VuoListGetData_VuoSceneObject(layer.sceneObject.childObjects);
442  for (unsigned int i = 0; i < childLayerCount; ++i)
443  {
444  childLayersData[i] = (VuoLayer){objects[i]};
445  VuoLayer_retain(childLayersData[i]);
446  }
447  return childLayers;
448 }
449 
453 static VuoRectangle VuoLayer_getBoundingRectangleWithSceneObject(VuoSceneObject so, VuoInteger viewportWidth, VuoInteger viewportHeight, float backingScaleFactor)
454 {
455  VuoRectangle b = VuoRectangle_make(NAN,NAN,0,0);
456 
457  float matrix[16];
458 
459  if (so.type == VuoSceneObjectSubType_Text)
460  {
461  if (so.scaleWithScene)
462  viewportWidth = VuoGraphicsWindowDefaultWidth * backingScaleFactor;
463 
464  if (viewportWidth > 0)
465  {
466  b = VuoImage_getTextRectangle(so.text, so.font, backingScaleFactor, 1, 0, so.wrapWidth, true);
467  b.size = VuoPoint2d_multiply(b.size, 2./viewportWidth);
468 
469  if (so.mesh)
470  {
471  VuoPoint2d anchorOffset = VuoAnchor_getOffset(VuoSceneText_getAnchor(so));
472  b.center.x += anchorOffset.x * b.size.x;
473  b.center.y += anchorOffset.y * b.size.y;
474  }
475 
476  VuoTransform_getMatrix(so.transform, matrix);
477  b = VuoTransform_transformRectangle(matrix, b);
478  }
479  else
480  {
481  b = VuoImage_getTextRectangle(so.text, so.font, backingScaleFactor, 1, 0, INFINITY, false);
482  b.center = (VuoPoint2d){so.transform.translation.x, so.transform.translation.y};
484  }
485  }
486 
487  if (so.shader)
488  {
489  VuoImage image = VuoShader_getUniform_VuoImage(so.shader, "texture");
490  if (image && so.isRealSize)
491  {
492  VuoPoint2d mesh0 = (VuoPoint2d){so.mesh->submeshes[0].positions[0].x, so.mesh->submeshes[0].positions[0].y};
493  VuoTransform_getBillboardMatrix(image->pixelsWide, image->pixelsHigh, image->scaleFactor, so.preservePhysicalSize, so.transform.translation.x, so.transform.translation.y, viewportWidth, viewportHeight, backingScaleFactor, mesh0, matrix);
494  }
495  else
496  VuoTransform_getMatrix(so.transform, matrix);
497 
498  b = VuoTransform_transformRectangle(matrix, VuoRectangle_make(0,0,so.shader->objectScale,so.shader->objectScale));
499  }
500  else
501  VuoTransform_getMatrix(so.transform, matrix);
502 
503  if (so.childObjects)
504  {
505  unsigned long childObjectCount = VuoListGetCount_VuoSceneObject(so.childObjects);
506  for (unsigned long i = 1; i <= childObjectCount; ++i)
507  {
508  VuoSceneObject child = VuoListGetValue_VuoSceneObject(so.childObjects, i);
509  VuoRectangle childBoundingBox = VuoLayer_getBoundingRectangleWithSceneObject(child, viewportWidth, viewportHeight, backingScaleFactor);
510  childBoundingBox = VuoTransform_transformRectangle(matrix, childBoundingBox);
511  if (!isnan(childBoundingBox.center.x))
512  {
513  if (!isnan(b.center.x))
514  b = VuoRectangle_union(b, childBoundingBox);
515  else
516  b = childBoundingBox;
517  }
518  }
519  }
520 
521  return b;
522 }
523 
530 VuoLayer VuoLayer_setAnchor(VuoLayer child, VuoAnchor anchor, VuoInteger viewportWidth, VuoInteger viewportHeight, float backingScaleFactor)
531 {
533  return child;
534 
535  VuoTransform childTransform = child.sceneObject.transform;
536  child.sceneObject.transform = VuoTransform_makeIdentity();
537 
538  VuoRectangle rect = VuoLayer_getBoundingRectangle(child, viewportWidth, viewportHeight, backingScaleFactor);
539 
540  VuoPoint3d childTranslation = childTransform.translation;
541  VuoPoint2d boundsCenter = rect.center;
542  VuoPoint3d parentTranslation = VuoPoint3d_make(childTranslation.x - boundsCenter.x, childTranslation.y - boundsCenter.y, 0);
543 
544  if (VuoAnchor_getHorizontal(anchor) == VuoHorizontalAlignment_Left)
545  boundsCenter.x += rect.size.x * .5f;
546  else if (VuoAnchor_getHorizontal(anchor) == VuoHorizontalAlignment_Right)
547  boundsCenter.x -= rect.size.x * .5f;
548 
549  if (VuoAnchor_getVertical(anchor) == VuoVerticalAlignment_Top)
550  boundsCenter.y -= rect.size.y * .5f;
551  else if (VuoAnchor_getVertical(anchor) == VuoVerticalAlignment_Bottom)
552  boundsCenter.y += rect.size.y * .5f;
553 
554  child.sceneObject.transform.translation = VuoPoint3d_make(boundsCenter.x, boundsCenter.y, 0);
555 
556  VuoTransform parentTransform = childTransform;
557  parentTransform.translation = parentTranslation;
558 
559  VuoLayer parent;
561 
562  parent.sceneObject.name = child.sceneObject.name;
563  child.sceneObject.name = VuoText_make(VuoText_format("%s (Child)", parent.sceneObject.name));
564 
565  VuoListAppendValue_VuoSceneObject(parent.sceneObject.childObjects, child.sceneObject);
566 
567  return parent;
568 }
569 
573 VuoRectangle VuoLayer_getBoundingRectangle(VuoLayer layer, VuoInteger viewportWidth, VuoInteger viewportHeight, float backingScaleFactor)
574 {
575  return VuoLayer_getBoundingRectangleWithSceneObject(layer.sceneObject, viewportWidth, viewportHeight, backingScaleFactor);
576 }
577 
582 {
584 }
585 
591 {
592  VuoLayer o;
594  return o;
595 }
596 
602 {
603  return VuoSceneObject_getJson(value.sceneObject);
604 }
605 
610 char * VuoLayer_getSummary(const VuoLayer value)
611 {
613 }