2007-12-10 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-actor.c:
	(clutter_actor_set_property),
	(clutter_actor_get_property),
	(clutter_actor_class_init): Add the rotation-* properties,
	controlling the rotation angle and center on each axis. (#614)

	(parse_rotation_array), (parse_rotation),
	(clutter_actor_parse_custom_node),
	(clutter_actor_set_custom_property),
	(clutter_scriptable_iface_init): Add a new "rotation" custom
	property for expressing the rotation along each axis in a
	compact way:

	  "rotation" : [
	    { "x-axis" : [ <angle>, [ <y>, <z> ] ] },
	    { "y-axis" : [ <angle>, [ <x>, <z> ] ] },
	    { "z-axis" : [ <angle>, [ <x>, <y> ] ] }
	  ]

	(clutter_geometry_get_type),(clutter_vertex_get_type),
	(clutter_actor_box_get_type): Use the I_() macro instead of
	directly calling g_intern_static_string().
	
	* clutter/clutter-entry.c (clutter_entry_request_coords):
	* clutter/clutter-label.c (clutter_label_ensure_layout),
	(clutter_label_request_coords): Use CLUTTER_UNITS_FROM_DEVICE()
	instead of CLUTTER_UNITS_FROM_INT(), as "device" means "pixels".

	* clutter/clutter-private.h: Add the I_() macro for intern
	static strings.

	* tests/test-script.json: Test the newly added "rotation"
	custom property.
This commit is contained in:
Emmanuele Bassi 2007-12-10 11:01:10 +00:00
parent aed212384a
commit 0f535537c2
6 changed files with 518 additions and 68 deletions

View File

@ -1,3 +1,39 @@
2007-12-10 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-actor.c:
(clutter_actor_set_property),
(clutter_actor_get_property),
(clutter_actor_class_init): Add the rotation-* properties,
controlling the rotation angle and center on each axis. (#614)
(parse_rotation_array), (parse_rotation),
(clutter_actor_parse_custom_node),
(clutter_actor_set_custom_property),
(clutter_scriptable_iface_init): Add a new "rotation" custom
property for expressing the rotation along each axis in a
compact way:
"rotation" : [
{ "x-axis" : [ <angle>, [ <y>, <z> ] ] },
{ "y-axis" : [ <angle>, [ <x>, <z> ] ] },
{ "z-axis" : [ <angle>, [ <x>, <y> ] ] }
]
(clutter_geometry_get_type),(clutter_vertex_get_type),
(clutter_actor_box_get_type): Use the I_() macro instead of
directly calling g_intern_static_string().
* clutter/clutter-entry.c (clutter_entry_request_coords):
* clutter/clutter-label.c (clutter_label_ensure_layout),
(clutter_label_request_coords): Use CLUTTER_UNITS_FROM_DEVICE()
instead of CLUTTER_UNITS_FROM_INT(), as "device" means "pixels".
* clutter/clutter-private.h: Add the I_() macro for intern
static strings.
* tests/test-script.json: Test the newly added "rotation"
custom property.
2007-12-10 Tomas Frydrych <tf@openedhand.com> 2007-12-10 Tomas Frydrych <tf@openedhand.com>
* tests/Makefile.am: * tests/Makefile.am:

View File

@ -32,8 +32,7 @@
* be a #ClutterActor, either by using one of the classes provided by * be a #ClutterActor, either by using one of the classes provided by
* Clutter, or by implementing a new #ClutterActor subclass. * Clutter, or by implementing a new #ClutterActor subclass.
* *
* * Notes on actor transformation matrix * Actor Transformations
*
* The OpenGL modelview matrix for the actor is constructed from the actor * The OpenGL modelview matrix for the actor is constructed from the actor
* settings by the following order of operations: * settings by the following order of operations:
* <orderedlist> * <orderedlist>
@ -50,7 +49,7 @@
* </listitem> * </listitem>
* </orderedlist> * </orderedlist>
* *
* Notes on clutter actor events: * Event handling
* <orderedlist> * <orderedlist>
* <listitem><para>Actors emit pointer events if set reactive, see * <listitem><para>Actors emit pointer events if set reactive, see
* clutter_actor_set_reactive()</para></listitem> * clutter_actor_set_reactive()</para></listitem>
@ -165,7 +164,7 @@ struct _ClutterActorPrivate
ClutterGeometry clip; /* FIXME: Should be Units */ ClutterGeometry clip; /* FIXME: Should be Units */
guint has_clip : 1; guint has_clip : 1;
ClutterFixed rxang, ryang, rzang; /* Rotation*/ ClutterFixed rxang, ryang, rzang; /* Rotation*/
ClutterUnit rzx, rzy, rxy, rxz, ryx, ryz; /* FIXME: Should be Units */ ClutterUnit rzx, rzy, rxy, rxz, ryx, ryz;
ClutterUnit z; ClutterUnit z;
guint8 opacity; guint8 opacity;
ClutterActor *parent_actor; ClutterActor *parent_actor;
@ -180,19 +179,31 @@ struct _ClutterActorPrivate
enum enum
{ {
PROP_0, PROP_0,
PROP_NAME,
PROP_X, PROP_X,
PROP_Y, PROP_Y,
PROP_WIDTH, PROP_WIDTH,
PROP_HEIGHT, PROP_HEIGHT,
PROP_DEPTH, PROP_DEPTH,
PROP_CLIP, PROP_CLIP,
PROP_HAS_CLIP, PROP_HAS_CLIP,
PROP_OPACITY, PROP_OPACITY,
PROP_NAME,
PROP_VISIBLE, PROP_VISIBLE,
PROP_REACTIVE,
PROP_SCALE_X, PROP_SCALE_X,
PROP_SCALE_Y, PROP_SCALE_Y,
PROP_REACTIVE
PROP_ROTATION_ANGLE_X,
PROP_ROTATION_ANGLE_Y,
PROP_ROTATION_ANGLE_Z,
PROP_ROTATION_CENTER_X,
PROP_ROTATION_CENTER_Y,
PROP_ROTATION_CENTER_Z
}; };
enum enum
@ -1107,6 +1118,63 @@ clutter_actor_set_property (GObject *object,
case PROP_REACTIVE: case PROP_REACTIVE:
clutter_actor_set_reactive (actor, g_value_get_boolean (value)); clutter_actor_set_reactive (actor, g_value_get_boolean (value));
break; break;
case PROP_ROTATION_ANGLE_X:
clutter_actor_set_rotation (actor,
CLUTTER_X_AXIS,
g_value_get_double (value),
0, priv->rxy, priv->rxz);
break;
case PROP_ROTATION_ANGLE_Y:
clutter_actor_set_rotation (actor,
CLUTTER_Y_AXIS,
g_value_get_double (value),
priv->ryx, 0, priv->ryz);
break;
case PROP_ROTATION_ANGLE_Z:
clutter_actor_set_rotation (actor,
CLUTTER_Z_AXIS,
g_value_get_double (value),
priv->rzx, priv->rzy, 0);
break;
case PROP_ROTATION_CENTER_X:
{
ClutterVertex *center;
center = g_value_get_boxed (value);
clutter_actor_set_rotationx (actor,
CLUTTER_X_AXIS,
priv->rxang,
0,
CLUTTER_UNITS_TO_DEVICE (center->y),
CLUTTER_UNITS_TO_DEVICE (center->z));
}
break;
case PROP_ROTATION_CENTER_Y:
{
ClutterVertex *center;
center = g_value_get_boxed (value);
clutter_actor_set_rotationx (actor,
CLUTTER_X_AXIS,
priv->ryang,
CLUTTER_UNITS_TO_DEVICE (center->x),
0,
CLUTTER_UNITS_TO_DEVICE (center->z));
}
break;
case PROP_ROTATION_CENTER_Z:
{
ClutterVertex *center;
center = g_value_get_boxed (value);
clutter_actor_set_rotationx (actor,
CLUTTER_X_AXIS,
priv->rzang,
CLUTTER_UNITS_TO_DEVICE (center->x),
CLUTTER_UNITS_TO_DEVICE (center->y),
0);
}
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1168,6 +1236,45 @@ clutter_actor_get_property (GObject *object,
g_value_set_boolean (value, g_value_set_boolean (value,
(CLUTTER_ACTOR_IS_REACTIVE (actor) != FALSE)); (CLUTTER_ACTOR_IS_REACTIVE (actor) != FALSE));
break; break;
case PROP_ROTATION_ANGLE_X:
g_value_set_double (value, CLUTTER_FIXED_TO_DOUBLE (priv->rxang));
break;
case PROP_ROTATION_ANGLE_Y:
g_value_set_double (value, CLUTTER_FIXED_TO_DOUBLE (priv->ryang));
break;
case PROP_ROTATION_ANGLE_Z:
g_value_set_double (value, CLUTTER_FIXED_TO_DOUBLE (priv->rzang));
break;
case PROP_ROTATION_CENTER_X:
{
ClutterVertex center = { 0, };
center.y = priv->rxy;
center.z = priv->rxz;
g_value_set_boxed (value, &center);
}
break;
case PROP_ROTATION_CENTER_Y:
{
ClutterVertex center = { 0, };
center.x = priv->ryx;
center.z = priv->ryz;
g_value_set_boxed (value, &center);
}
break;
case PROP_ROTATION_CENTER_Z:
{
ClutterVertex center = { 0, };
center.x = priv->rzx;
center.y = priv->rzy;
g_value_set_boxed (value, &center);
}
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -1368,7 +1475,6 @@ clutter_actor_class_init (ClutterActorClass *klass)
"Name of the actor", "Name of the actor",
NULL, NULL,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
* ClutterActor::scale-x: * ClutterActor::scale-x:
* *
@ -1386,7 +1492,6 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_MAXDOUBLE, G_MAXDOUBLE,
1.0, 1.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/** /**
* ClutterActor::scale-y: * ClutterActor::scale-y:
* *
@ -1404,7 +1509,102 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_MAXDOUBLE, G_MAXDOUBLE,
1.0, 1.0,
CLUTTER_PARAM_READWRITE)); CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-angle-x:
*
* The rotation angle on the X axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_ANGLE_X,
g_param_spec_double ("rotation-angle-x",
"Rotation Angle X",
"The rotation angle on the X axis",
0.0,
G_MAXDOUBLE,
0.0,
CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-angle-y:
*
* The rotation angle on the Y axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_ANGLE_Y,
g_param_spec_double ("rotation-angle-y",
"Rotation Angle Y",
"The rotation angle on the Y axis",
0.0,
G_MAXDOUBLE,
0.0,
CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-angle-z:
*
* The rotation angle on the Z axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_ANGLE_Z,
g_param_spec_double ("rotation-angle-z",
"Rotation Angle Z",
"The rotation angle on the Z axis",
0.0,
G_MAXDOUBLE,
0.0,
CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-center-x:
*
* The rotation center on the X axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_CENTER_X,
g_param_spec_boxed ("rotation-center-x",
"Rotation Center X",
"The rotation center on the X axis",
CLUTTER_TYPE_VERTEX,
CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-center-y:
*
* The rotation center on the Y axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_CENTER_Y,
g_param_spec_boxed ("rotation-center-y",
"Rotation Center Y",
"The rotation center on the Y axis",
CLUTTER_TYPE_VERTEX,
CLUTTER_PARAM_READWRITE));
/**
* ClutterActor::rotation-center-z:
*
* The rotation center on the Z axis.
*
* Since: 0.6
*/
g_object_class_install_property
(object_class,
PROP_ROTATION_CENTER_Z,
g_param_spec_boxed ("rotation-center-z",
"Rotation Center Z",
"The rotation center on the Z axis",
CLUTTER_TYPE_VERTEX,
CLUTTER_PARAM_READWRITE));
/** /**
* ClutterActor::destroy: * ClutterActor::destroy:
@ -1862,10 +2062,10 @@ clutter_actor_get_geometry (ClutterActor *self,
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
geometry->x = CLUTTER_UNITS_TO_INT (box.x1); geometry->x = CLUTTER_UNITS_TO_DEVICE (box.x1);
geometry->y = CLUTTER_UNITS_TO_INT (box.y1); geometry->y = CLUTTER_UNITS_TO_DEVICE (box.y1);
geometry->width = CLUTTER_UNITS_TO_INT (box.x2 - box.x1); geometry->width = CLUTTER_UNITS_TO_DEVICE (box.x2 - box.x1);
geometry->height = CLUTTER_UNITS_TO_INT (box.y2 - box.y1); geometry->height = CLUTTER_UNITS_TO_DEVICE (box.y2 - box.y1);
} }
/** /**
@ -1893,16 +2093,16 @@ clutter_actor_get_coords (ClutterActor *self,
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
if (x_1) if (x_1)
*x_1 = CLUTTER_UNITS_TO_INT (box.x1); *x_1 = CLUTTER_UNITS_TO_DEVICE (box.x1);
if (y_1) if (y_1)
*y_1 = CLUTTER_UNITS_TO_INT (box.y1); *y_1 = CLUTTER_UNITS_TO_DEVICE (box.y1);
if (x_2) if (x_2)
*x_2 = CLUTTER_UNITS_TO_INT (box.x2); *x_2 = CLUTTER_UNITS_TO_DEVICE (box.x2);
if (y_2) if (y_2)
*y_2 = CLUTTER_UNITS_TO_INT (box.y2); *y_2 = CLUTTER_UNITS_TO_DEVICE (box.y2);
} }
/** /**
@ -2103,10 +2303,10 @@ clutter_actor_get_size (ClutterActor *self,
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
if (width) if (width)
*width = CLUTTER_UNITS_TO_INT (box.x2 - box.x1); *width = CLUTTER_UNITS_TO_DEVICE (box.x2 - box.x1);
if (height) if (height)
*height = CLUTTER_UNITS_TO_INT (box.y2 - box.y1); *height = CLUTTER_UNITS_TO_DEVICE (box.y2 - box.y1);
} }
/** /**
@ -2160,10 +2360,10 @@ clutter_actor_get_position (ClutterActor *self,
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
if (x) if (x)
*x = CLUTTER_UNITS_TO_INT (box.x1); *x = CLUTTER_UNITS_TO_DEVICE (box.x1);
if (y) if (y)
*y = CLUTTER_UNITS_TO_INT (box.y1); *y = CLUTTER_UNITS_TO_DEVICE (box.y1);
} }
/** /**
@ -2246,9 +2446,9 @@ clutter_actor_get_abs_position (ClutterActor *self,
clutter_actor_get_abs_position_units (self, &xu, &yu); clutter_actor_get_abs_position_units (self, &xu, &yu);
if (x) if (x)
*x = CLUTTER_UNITS_TO_INT (xu); *x = CLUTTER_UNITS_TO_DEVICE (xu);
if (y) if (y)
*y = CLUTTER_UNITS_TO_INT (yu); *y = CLUTTER_UNITS_TO_DEVICE (yu);
} }
/* /*
@ -2322,8 +2522,8 @@ clutter_actor_get_abs_size (ClutterActor *self,
gint32 wu, hu; gint32 wu, hu;
clutter_actor_get_abs_size_units (self, &wu, &hu); clutter_actor_get_abs_size_units (self, &wu, &hu);
*width = CLUTTER_UNITS_TO_INT (wu); *width = CLUTTER_UNITS_TO_DEVICE (wu);
*height = CLUTTER_UNITS_TO_INT (hu); *height = CLUTTER_UNITS_TO_DEVICE (hu);
} }
@ -2344,7 +2544,7 @@ clutter_actor_get_width (ClutterActor *self)
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
return CLUTTER_UNITS_TO_INT (box.x2 - box.x1); return CLUTTER_UNITS_TO_DEVICE (box.x2 - box.x1);
} }
/** /**
@ -2386,7 +2586,7 @@ clutter_actor_get_height (ClutterActor *self)
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
return CLUTTER_UNITS_TO_INT (box.y2 - box.y1); return CLUTTER_UNITS_TO_DEVICE (box.y2 - box.y1);
} }
/** /**
@ -2581,7 +2781,7 @@ clutter_actor_get_x (ClutterActor *self)
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
return CLUTTER_UNITS_TO_INT (box.x1); return CLUTTER_UNITS_TO_DEVICE (box.x1);
} }
/** /**
@ -2625,7 +2825,7 @@ clutter_actor_get_y (ClutterActor *self)
clutter_actor_query_coords (self, &box); clutter_actor_query_coords (self, &box);
return CLUTTER_UNITS_TO_INT (box.y1); return CLUTTER_UNITS_TO_DEVICE (box.y1);
} }
/** /**
@ -3959,6 +4159,158 @@ out:
return retval; return retval;
} }
typedef struct {
ClutterRotateAxis axis;
gdouble angle;
ClutterUnit center_x;
ClutterUnit center_y;
ClutterUnit center_z;
} RotationInfo;
static gboolean
parse_rotation_array (ClutterActor *actor,
JsonNode *node,
RotationInfo *info)
{
JsonArray *array = json_node_get_array (node);
JsonNode *element;
if (json_array_get_length (array) != 2)
return FALSE;
/* angle */
element = json_array_get_element (array, 0);
if (JSON_NODE_TYPE (element) == JSON_NODE_VALUE)
info->angle = json_node_get_double (element);
else
return FALSE;
/* center */
element = json_array_get_element (array, 1);
if (JSON_NODE_TYPE (element) == JSON_NODE_ARRAY)
{
JsonArray *array = json_node_get_array (element);
if (json_array_get_length (array) != 2)
return FALSE;
switch (info->axis)
{
case CLUTTER_X_AXIS:
info->center_y = parse_units (actor, PARSE_Y,
json_array_get_element (array, 0));
info->center_z = parse_units (actor, PARSE_Y,
json_array_get_element (array, 1));
return TRUE;
case CLUTTER_Y_AXIS:
info->center_x = parse_units (actor, PARSE_X,
json_array_get_element (array, 0));
info->center_z = parse_units (actor, PARSE_X,
json_array_get_element (array, 1));
return TRUE;
case CLUTTER_Z_AXIS:
info->center_x = parse_units (actor, PARSE_X,
json_array_get_element (array, 0));
info->center_y = parse_units (actor, PARSE_Y,
json_array_get_element (array, 1));
return TRUE;
}
}
return FALSE;
}
static gboolean
parse_rotation (ClutterActor *actor,
JsonNode *node,
RotationInfo *info)
{
JsonArray *array;
guint len, i;
gboolean retval = FALSE;
if (JSON_NODE_TYPE (node) != JSON_NODE_ARRAY)
{
g_warning ("Invalid node of type `%s' found, expecting an array",
json_node_type_name (node));
return FALSE;
}
array = json_node_get_array (node);
len = json_array_get_length (array);
for (i = 0; i < len; i++)
{
JsonNode *element = json_array_get_element (array, i);
JsonObject *object;
JsonNode *member;
if (JSON_NODE_TYPE (element) != JSON_NODE_OBJECT)
{
g_warning ("Invalid node of type `%s' found, expecting an object",
json_node_type_name (element));
return FALSE;
}
object = json_node_get_object (element);
if (json_object_has_member (object, "x-axis"))
{
member = json_object_get_member (object, "x-axis");
info->axis = CLUTTER_X_AXIS;
if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE)
{
info->angle = json_node_get_double (member);
retval = TRUE;
}
else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY)
retval = parse_rotation_array (actor, member, info);
else
retval = FALSE;
}
else if (json_object_has_member (object, "y-axis"))
{
member = json_object_get_member (object, "y-axis");
info->axis = CLUTTER_Y_AXIS;
if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE)
{
info->angle = json_node_get_double (member);
retval = TRUE;
}
else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY)
retval = parse_rotation_array (actor, member, info);
else
retval = FALSE;
}
else if (json_object_has_member (object, "z-axis"))
{
member = json_object_get_member (object, "z-axis");
info->axis = CLUTTER_Z_AXIS;
if (JSON_NODE_TYPE (member) == JSON_NODE_VALUE)
{
info->angle = json_node_get_double (member);
retval = TRUE;
}
else if (JSON_NODE_TYPE (member) == JSON_NODE_ARRAY)
retval = parse_rotation_array (actor, member, info);
else
retval = FALSE;
}
}
return retval;
}
static gboolean static gboolean
clutter_actor_parse_custom_node (ClutterScriptable *scriptable, clutter_actor_parse_custom_node (ClutterScriptable *scriptable,
ClutterScript *script, ClutterScript *script,
@ -3994,14 +4346,57 @@ clutter_actor_parse_custom_node (ClutterScriptable *scriptable,
retval = TRUE; retval = TRUE;
} }
else if (strcmp (name, "rotation") == 0)
{
RotationInfo *info;
info = g_slice_new0 (RotationInfo);
retval = parse_rotation (actor, node, info);
if (retval)
{
g_value_init (value, G_TYPE_POINTER);
g_value_set_pointer (value, info);
}
else
g_slice_free (RotationInfo, info);
}
return retval; return retval;
} }
static void
clutter_actor_set_custom_property (ClutterScriptable *scriptable,
ClutterScript *script,
const gchar *name,
const GValue *value)
{
if (strcmp (name, "rotation") == 0)
{
RotationInfo *info;
if (!G_VALUE_HOLDS (value, G_TYPE_POINTER))
return;
info = g_value_get_pointer (value);
clutter_actor_set_rotation (CLUTTER_ACTOR (scriptable),
info->axis, info->angle,
CLUTTER_UNITS_TO_DEVICE (info->center_x),
CLUTTER_UNITS_TO_DEVICE (info->center_y),
CLUTTER_UNITS_TO_DEVICE (info->center_z));
g_slice_free (RotationInfo, info);
}
else
g_object_set_property (G_OBJECT (scriptable), name, value);
}
static void static void
clutter_scriptable_iface_init (ClutterScriptableIface *iface) clutter_scriptable_iface_init (ClutterScriptableIface *iface)
{ {
iface->parse_custom_node = clutter_actor_parse_custom_node; iface->parse_custom_node = clutter_actor_parse_custom_node;
iface->set_custom_property = clutter_actor_set_custom_property;
} }
/** /**
@ -4217,7 +4612,7 @@ clutter_geometry_get_type (void)
if (G_UNLIKELY (our_type == 0)) if (G_UNLIKELY (our_type == 0))
our_type = our_type =
g_boxed_type_register_static (g_intern_static_string ("ClutterGeometry"), g_boxed_type_register_static (I_("ClutterGeometry"),
(GBoxedCopyFunc) clutter_geometry_copy, (GBoxedCopyFunc) clutter_geometry_copy,
(GBoxedFreeFunc) clutter_geometry_free); (GBoxedFreeFunc) clutter_geometry_free);
@ -4252,7 +4647,7 @@ clutter_vertex_get_type (void)
if (G_UNLIKELY (our_type == 0)) if (G_UNLIKELY (our_type == 0))
our_type = our_type =
g_boxed_type_register_static (g_intern_static_string ("ClutterVertex"), g_boxed_type_register_static (I_("ClutterVertex"),
(GBoxedCopyFunc) clutter_vertex_copy, (GBoxedCopyFunc) clutter_vertex_copy,
(GBoxedFreeFunc) clutter_vertex_free); (GBoxedFreeFunc) clutter_vertex_free);
@ -4286,7 +4681,7 @@ clutter_actor_box_get_type (void)
if (G_UNLIKELY (our_type == 0)) if (G_UNLIKELY (our_type == 0))
our_type = our_type =
g_boxed_type_register_static (g_intern_static_string ("ClutterActorBox"), g_boxed_type_register_static (I_("ClutterActorBox"),
(GBoxedCopyFunc) clutter_actor_box_copy, (GBoxedCopyFunc) clutter_actor_box_copy,
(GBoxedFreeFunc) clutter_actor_box_free); (GBoxedFreeFunc) clutter_actor_box_free);
return our_type; return our_type;
@ -4295,11 +4690,19 @@ clutter_actor_box_get_type (void)
/******************************************************************************/ /******************************************************************************/
typedef struct _BoxedFloat BoxedFloat; typedef struct _BoxedFloat BoxedFloat;
struct _BoxedFloat struct _BoxedFloat
{ {
gfloat value; gfloat value;
}; };
static void
boxed_float_free (gpointer data)
{
if (G_LIKELY (data))
g_slice_free (BoxedFloat, data);
}
struct _ShaderData struct _ShaderData
{ {
ClutterShader *shader; ClutterShader *shader;
@ -4320,57 +4723,60 @@ destroy_shader_data (ClutterActor *self)
if (shader_data->shader) if (shader_data->shader)
{ {
g_object_unref (shader_data->shader); g_object_unref (shader_data->shader);
shader_data->shader = NULL;
} }
shader_data->shader = NULL;
if (shader_data->float1f_hash) if (shader_data->float1f_hash)
{ {
g_hash_table_destroy (shader_data->float1f_hash); g_hash_table_destroy (shader_data->float1f_hash);
shader_data->float1f_hash = NULL; shader_data->float1f_hash = NULL;
} }
g_free (shader_data); g_free (shader_data);
actor_priv->shader_data = NULL; actor_priv->shader_data = NULL;
} }
gboolean clutter_actor_apply_shader (ClutterActor *self, gboolean
ClutterShader *shader) clutter_actor_apply_shader (ClutterActor *self,
ClutterShader *shader)
{ {
ClutterActorPrivate *actor_priv; ClutterActorPrivate *actor_priv;
ShaderData *shader_data; ShaderData *shader_data;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
g_return_val_if_fail (shader == NULL || CLUTTER_IS_SHADER (shader), FALSE);
actor_priv = self->priv; actor_priv = self->priv;
shader_data = actor_priv->shader_data; shader_data = actor_priv->shader_data;
if (shader_data == NULL) if (!shader_data)
{ {
actor_priv->shader_data = shader_data = g_new0 (ShaderData, 1); actor_priv->shader_data = shader_data = g_new0 (ShaderData, 1);
shader_data->float1f_hash = g_hash_table_new_full ( shader_data->float1f_hash =
g_str_hash, g_str_equal, g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free); g_free,
boxed_float_free);
} }
if (shader_data->shader) if (shader_data->shader)
{ {
g_object_unref (shader_data->shader); g_object_unref (shader_data->shader);
}
if (shader)
{
shader_data->shader = g_object_ref (shader);
}
else
{
shader_data->shader = NULL; shader_data->shader = NULL;
} }
if (shader)
shader_data->shader = g_object_ref (shader);
return TRUE; return TRUE;
} }
static void static void
each_param (gpointer key, set_each_param (gpointer key,
gpointer value, gpointer value,
gpointer user_data) gpointer user_data)
{ {
ClutterShader *shader = CLUTTER_SHADER (user_data); ClutterShader *shader = CLUTTER_SHADER (user_data);
BoxedFloat *box = value; BoxedFloat *box = value;
clutter_shader_set_uniform_1f (shader, key, box->value); clutter_shader_set_uniform_1f (shader, key, box->value);
} }
@ -4378,15 +4784,15 @@ static void
clutter_actor_shader_pre_paint (ClutterActor *actor, clutter_actor_shader_pre_paint (ClutterActor *actor,
gboolean repeat) gboolean repeat)
{ {
ClutterActorPrivate *actor_priv; ClutterActorPrivate *priv;
ShaderData *shader_data; ShaderData *shader_data;
ClutterShader *shader; ClutterShader *shader;
ClutterMainContext *context; ClutterMainContext *context;
g_return_if_fail (CLUTTER_IS_ACTOR (actor)); g_return_if_fail (CLUTTER_IS_ACTOR (actor));
actor_priv = actor->priv; priv = actor->priv;
shader_data = actor_priv->shader_data; shader_data = priv->shader_data;
if (!shader_data) if (!shader_data)
return; return;
@ -4398,27 +4804,25 @@ clutter_actor_shader_pre_paint (ClutterActor *actor,
{ {
clutter_shader_enable (shader); clutter_shader_enable (shader);
g_hash_table_foreach (shader_data->float1f_hash, each_param, shader); g_hash_table_foreach (shader_data->float1f_hash, set_each_param, shader);
if (!repeat) if (!repeat)
{ context->shaders = g_slist_prepend (context->shaders, actor);
context->shaders = g_slist_prepend (context->shaders, actor);
}
} }
} }
static void static void
clutter_actor_shader_post_paint (ClutterActor *actor) clutter_actor_shader_post_paint (ClutterActor *actor)
{ {
ClutterActorPrivate *actor_priv; ClutterActorPrivate *priv;
ShaderData *shader_data; ShaderData *shader_data;
ClutterShader *shader; ClutterShader *shader;
ClutterMainContext *context; ClutterMainContext *context;
g_return_if_fail (CLUTTER_IS_ACTOR (actor)); g_return_if_fail (CLUTTER_IS_ACTOR (actor));
actor_priv = actor->priv; priv = actor->priv;
shader_data = actor_priv->shader_data; shader_data = priv->shader_data;
if (!shader_data) if (!shader_data)
return; return;
@ -4447,19 +4851,20 @@ clutter_actor_set_shader_param (ClutterActor *actor,
const gchar *param, const gchar *param,
gfloat value) gfloat value)
{ {
ClutterActorPrivate *actor_priv; ClutterActorPrivate *priv;
ShaderData *shader_data; ShaderData *shader_data;
BoxedFloat *box; BoxedFloat *box;
g_return_if_fail (CLUTTER_IS_ACTOR (actor)); g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (param != NULL);
actor_priv = actor->priv; priv = actor->priv;
shader_data = actor_priv->shader_data; shader_data = priv->shader_data;
if (!shader_data) if (!shader_data)
return; return;
box = g_malloc (sizeof (BoxedFloat)); box = g_slice_new (BoxedFloat);
box->value = value; box->value = value;
g_hash_table_insert (shader_data->float1f_hash, g_strdup (param), box); g_hash_table_insert (shader_data->float1f_hash, g_strdup (param), box);
} }

View File

@ -482,7 +482,7 @@ clutter_entry_request_coords (ClutterActor *self,
ClutterEntryPrivate *priv = entry->priv; ClutterEntryPrivate *priv = entry->priv;
gint width; gint width;
width = CLUTTER_UNITS_TO_INT (box->x2 - box->x1); width = CLUTTER_UNITS_TO_DEVICE (box->x2 - box->x1);
if (priv->width != width) if (priv->width != width)
{ {

View File

@ -170,7 +170,7 @@ clutter_label_ensure_layout (ClutterLabel *label)
priv = label->priv; priv = label->priv;
/* use the last size requested, if any */ /* use the last size requested, if any */
width = CLUTTER_UNITS_TO_INT (priv->allocation.x2 - priv->allocation.x1); width = CLUTTER_UNITS_TO_DEVICE (priv->allocation.x2 - priv->allocation.x1);
if (!priv->layout) if (!priv->layout)
{ {
@ -342,7 +342,7 @@ clutter_label_request_coords (ClutterActor *self,
gint width; gint width;
PangoRectangle logical; PangoRectangle logical;
width = CLUTTER_UNITS_TO_INT (box->x2 - box->x1) * PANGO_SCALE; width = CLUTTER_UNITS_TO_DEVICE (box->x2 - box->x1) * PANGO_SCALE;
pango_layout_set_width (priv->layout, -1); pango_layout_set_width (priv->layout, -1);
pango_layout_get_extents (priv->layout, NULL, &logical); pango_layout_get_extents (priv->layout, NULL, &logical);

View File

@ -110,6 +110,8 @@ ClutterMainContext *clutter_context_get_default (void);
#define CLUTTER_PARAM_READWRITE \ #define CLUTTER_PARAM_READWRITE \
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |G_PARAM_STATIC_BLURB
#define I_(str) (g_intern_static_string ((str)))
/* vfuncs implemnted by backend */ /* vfuncs implemnted by backend */
GType _clutter_backend_impl_get_type (void); GType _clutter_backend_impl_get_type (void);

View File

@ -14,6 +14,9 @@
"x" : 50, "y" : 50, "width" : 100, "height" : 100, "x" : 50, "y" : 50, "width" : 100, "height" : 100,
"visible" : true, "visible" : true,
"reactive" : true, "reactive" : true,
"rotation" : [
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
],
"behaviours" : [ "fade-behaviour", "path-behaviour" ], "behaviours" : [ "fade-behaviour", "path-behaviour" ],
}, },
{ {
@ -66,6 +69,10 @@
"wrap" : false, "wrap" : false,
"ellipsize" : "none", "ellipsize" : "none",
"visible" : true "visible" : true
"rotation" : [
{ "y-axis" : [ 60.0, [ 275, 100 ] ] },
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
],
} }
"blue-button", "blue-button",
] ]