+2006-08-29 Matthew Allum <mallum@openedhand.com>
+
+ * clutter/clutter-fixed.h:
+ Add basic fixed point utility defines and type.
+
+ * clutter/Makefile.am:
+ * clutter/clutter-actor.c:
+ * clutter/clutter-actor.h:
+ * clutter/clutter-group.c:
+ * clutter/clutter-stage.c:
+ * examples/super-oh.c: (main):
+ Add scale API and functionality.
+ Rework group sizing. Now group size requests have no effect
+ but can be scaled.
+
2006-08-29 Jorn Baayen <jorn@openedhand.com>
* clutter/clutter-behaviour.c: (_clutter_behaviour_finalize),
source_h = \
$(srcdir)/clutter-keysyms.h \
$(srcdir)/clutter-util.h \
+ $(srcdir)/clutter-fixed.h \
$(srcdir)/clutter-media.h \
$(srcdir)/clutter-event.h \
$(srcdir)/clutter-color.h \
ClutterActor *parent_actor; /* This should always be a group */
gchar *name;
-
+
+ ClutterFixed scale_x, scale_y;
+
guint32 id; /* Unique ID */
};
klass = CLUTTER_ACTOR_GET_CLASS (self);
-#if 0
- if (self->priv->has_clip)
- {
- ClutterGeometry *clip = &(self->priv->clip);
- gint absx, absy;
- ClutterActor *stage = clutter_stage_get_default ();
-
- clutter_actor_get_abs_position (self, &absx, &absy);
-
- CLUTTER_DBG("clip +%i+%i, %ix%i\n",
- absx + clip->x,
- clutter_actor_get_height (stage)
- - (absy + clip->y) - clip->height,
- clip->width,
- clip->height);
-
- glEnable (GL_SCISSOR_TEST);
-
- glScissor (absx + clip->x,
- clutter_actor_get_height (stage)
- - (absy + clip->y) - clip->height,
- clip->width,
- clip->height);
- }
-#endif
-
glPushMatrix();
glLoadName (clutter_actor_get_id (self));
- /* FIXME: Less clunky ? */
if (self->priv->rzang)
{
if (self->priv->z)
glTranslatef ( 0.0, 0.0, (float)self->priv->z);
+ if (self->priv->scale_x != CFX_ONE || self->priv->scale_y != CFX_ONE)
+ {
+ glScaled (CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_x),
+ CLUTTER_FIXED_TO_DOUBLE (self->priv->scale_y),
+ 1.0);
+ }
+
if (self->priv->has_clip)
{
ClutterGeometry *clip = &(self->priv->clip);
klass = CLUTTER_ACTOR_GET_CLASS (self);
- /* FIXME: Kludgy see allocate co-ords */
if (klass->request_coords)
klass->request_coords (self, box);
height_change = (self->priv->coords.y2 - self->priv->coords.y1
!= box->y2 - box->y1);
- self->priv->coords.x1 = box->x1;
- self->priv->coords.y1 = box->y1;
- self->priv->coords.x2 = box->x2;
- self->priv->coords.y2 = box->y2;
-
- if (CLUTTER_ACTOR_IS_VISIBLE (self))
- clutter_actor_queue_redraw (self);
-
- /* FIXME: Below really needed ? If so should add to other _set calls.
- */
- if (x_change)
- g_object_notify (G_OBJECT (self), "x");
-
- if (y_change)
- g_object_notify (G_OBJECT (self), "y");
-
- if (width_change)
- g_object_notify (G_OBJECT (self), "width");
-
- if (height_change)
- g_object_notify (G_OBJECT (self), "height");
+ if (x_change || y_change || width_change || height_change)
+ {
+ self->priv->coords.x1 = box->x1;
+ self->priv->coords.y1 = box->y1;
+ self->priv->coords.x2 = box->x2;
+ self->priv->coords.y2 = box->y2;
+
+ if (CLUTTER_ACTOR_IS_VISIBLE (self))
+ clutter_actor_queue_redraw (self);
+
+ if (x_change)
+ g_object_notify (G_OBJECT (self), "x");
+
+ if (y_change)
+ g_object_notify (G_OBJECT (self), "y");
+
+ if (width_change)
+ g_object_notify (G_OBJECT (self), "width");
+
+ if (height_change)
+ g_object_notify (G_OBJECT (self), "height");
+ }
}
/**
self->priv->has_clip = FALSE;
self->priv->opacity = 0xff;
self->priv->id = __id++;
+ self->priv->scale_x = CFX_ONE;
+ self->priv->scale_y = CFX_ONE;
clutter_actor_set_position (self, 0, 0);
clutter_actor_set_size (self, 0, 0);
*/
void
clutter_actor_get_coords (ClutterActor *self,
- gint *x1,
- gint *y1,
- gint *x2,
- gint *y2)
+ gint *x1,
+ gint *y1,
+ gint *x2,
+ gint *y2)
{
ClutterActorBox box;
*/
void
clutter_actor_set_position (ClutterActor *self,
- gint x,
- gint y)
+ gint x,
+ gint y)
{
ClutterActorBox box;
*/
void
clutter_actor_set_size (ClutterActor *self,
- gint width,
- gint height)
+ gint width,
+ gint height)
{
ClutterActorBox box;
*/
void
clutter_actor_get_abs_position (ClutterActor *self,
- gint *x,
- gint *y)
+ gint *x,
+ gint *y)
{
ClutterActorBox box;
ClutterActor *parent;
parent = self->priv->parent_actor;
/* FIXME: must be nicer way to get 0,0 for stage ? */
- if (parent && !CLUTTER_IS_STAGE (parent))
- clutter_actor_get_abs_position (parent, &px, &py);
+ if (parent)
+ {
+ ClutterFixed parent_scale_x, parent_scale_y, fx, fy;
+
+ clutter_actor_get_scalex(parent, &parent_scale_x, &parent_scale_y);
+
+ if (parent_scale_x != CFX_ONE || parent_scale_y != CFX_ONE)
+ {
+ fx = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(box.x1),parent_scale_x);
+ fy = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(box.y1),parent_scale_y);
+
+ box.x1 = CLUTTER_FIXED_INT(fx);
+ box.y1 = CLUTTER_FIXED_INT(fy);
+ }
+
+ if (!CLUTTER_IS_STAGE (parent))
+ clutter_actor_get_abs_position (parent, &px, &py);
+ }
if (x)
*x = px + box.x1;
}
/**
+ * clutter_actor_get_abs_size
+ * @self: A #ClutterActor
+ * @x: Location to store width if non NULL.
+ * @y: Location to store height if non NULL.
+ *
+ * Gets the absolute size of an actor taking into account
+ * an scaling factors
+ */
+void
+clutter_actor_get_abs_size (ClutterActor *self,
+ guint *width,
+ guint *height)
+{
+ ClutterActorBox box;
+ ClutterActor *parent;
+
+ clutter_actor_allocate_coords (self, &box);
+
+ if (width)
+ *width = box.x2 - box.x1;
+ if (height)
+ *height = box.y2 - box.y1;
+
+ parent = self;
+
+ do
+ {
+ if (parent->priv->scale_x != CFX_ONE || parent->priv->scale_y != CFX_ONE)
+ {
+ ClutterFixed fx, fy;
+
+ if (width)
+ {
+ fx = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(*width),
+ parent->priv->scale_x);
+ *width = CLUTTER_FIXED_INT(fx);
+ }
+
+ if (height)
+ {
+ fy = CLUTTER_FIXED_MUL(CLUTTER_INT_TO_FIXED(*height),
+ parent->priv->scale_x);
+ *height = CLUTTER_FIXED_INT(fy);
+ }
+ }
+ }
+ while ((parent = clutter_actor_get_parent(parent)) != NULL);
+}
+
+
+/**
* clutter_actor_get_width
* @self: A #ClutterActor
*
}
/**
+ * clutter_actor_set_scalex:
+ * @self: A #ClutterActor
+ * @scale_x: #ClutterFixed factor to scale actor by horizontally.
+ * @scale_y: #ClutterFixed factor to scale actor by vertically.
+ *
+ * Scale an actor.
+ */
+void
+clutter_actor_set_scalex (ClutterActor *self,
+ ClutterFixed scale_x,
+ ClutterFixed scale_y)
+{
+ g_return_if_fail (CLUTTER_IS_ACTOR (self));
+
+ self->priv->scale_x = scale_x;
+ self->priv->scale_y = scale_y;
+
+ if (CLUTTER_ACTOR_IS_VISIBLE (self))
+ clutter_actor_queue_redraw (self);
+}
+
+/**
+ * clutter_actor_set_scale:
+ * @self: A #ClutterActor
+ * @scale_x: double
+ * @scale_y: double
+ */
+void
+clutter_actor_set_scale (ClutterActor *self,
+ double scale_x,
+ double scale_y)
+{
+ g_return_if_fail (CLUTTER_IS_ACTOR (self));
+
+ clutter_actor_set_scalex (self,
+ CLUTTER_FLOAT_TO_FIXED (scale_x),
+ CLUTTER_FLOAT_TO_FIXED (scale_y));
+}
+
+/**
+ * clutter_actor_get_scalex
+ * @self: A #ClutterActor
+ * @scale_x: FIXME
+ * @scale_y: FIXME
+ *
+ * FIXME
+ */
+void
+clutter_actor_get_scalex (ClutterActor *self,
+ ClutterFixed *scale_x,
+ ClutterFixed *scale_y)
+{
+ if (scale_x)
+ *scale_x = self->priv->scale_x;
+
+ if (scale_y)
+ *scale_y = self->priv->scale_y;
+}
+
+/**
+ * clutter_actor_get_scale
+ * @self: A #ClutterActor
+ * @scale_x: FIXME
+ * @scale_y: FIXME
+ *
+ * FIXME
+ */
+void
+clutter_actor_get_scale (ClutterActor *self,
+ double *scale_x,
+ double *scale_y)
+{
+ if (scale_x)
+ *scale_x = CLUTTER_FIXED_TO_FLOAT(self->priv->scale_x);
+
+ if (scale_y)
+ *scale_y = CLUTTER_FIXED_TO_FLOAT(self->priv->scale_y);
+}
+
+
+/**
* clutter_actor_set_opacity:
* @self: A #ClutterActor
* @opacity: New opacity value for actor.
#include <glib-object.h>
+#include "clutter-fixed.h"
+
G_BEGIN_DECLS
#define CLUTTER_TYPE_GEOMETRY (clutter_geometry_get_type ())
#define CLUTTER_CALLBACK(f) ((ClutterCallback) (f))
struct _ClutterGeometry
-{
+{
+ /* FIXME:
+ * It is likely gonna save a load of pain if we make
+ * x,y unsigned...
+ */
gint x;
gint y;
guint width;
gint depth);
gint clutter_actor_get_depth (ClutterActor *self);
+void
+clutter_actor_set_scalex (ClutterActor *self,
+ ClutterFixed scale_x,
+ ClutterFixed scale_y);
+
+void
+clutter_actor_set_scale (ClutterActor *self,
+ double scale_x,
+ double scale_y);
+
+void
+clutter_actor_get_scalex (ClutterActor *self,
+ ClutterFixed *scale_x,
+ ClutterFixed *scale_y);
+
+void
+clutter_actor_get_scale (ClutterActor *self,
+ double *scale_x,
+ double *scale_y);
+
+void
+clutter_actor_get_abs_size (ClutterActor *self,
+ guint *width,
+ guint *height);
G_END_DECLS
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _HAVE_CLUTTER_FIXED_H
+#define _HAVE_CLUTTER_FIXED_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef gint32 ClutterFixed;
+
+#define CFX_Q 16 /* Decimal part size in bits */
+#define CFX_ONE (1 << CFX_Q) /* 1 */
+#define CFX_MAX 0x7fffffff
+#define CFX_MIN 0x80000000
+
+#define CLUTTER_FIXED_TO_FLOAT(x) ((float)((x)/65536.0))
+
+#define CLUTTER_FIXED_TO_DOUBLE(x) ((double)((x)/65536.0))
+
+#define CLUTTER_FLOAT_TO_FIXED(x) \
+ ( (ABS(x) > 32767.0) ? \
+ (((x)/(x))*0x7fffffff) \
+ : ((long)((x) * 65536.0 + ((x) < 0 ? -0.5 : 0.5))) )
+
+#define CLUTTER_INT_TO_FIXED(x) ((x) << CFX_Q)
+
+#define CLUTTER_FIXED_INT(x) ((x) >> CFX_Q)
+
+#define CLUTTER_FIXED_FRACTION(x) ((x) & ((1 << CFX_Q) - 1))
+
+#define CLUTTER_FIXED_FLOOR(x) \
+ (((x) >= 0) ? ((x) >> CFX_Q) : ~((~(x)) >> CFX_Q))
+
+#define CLUTTER_FIXED_CEIL(x) CLUTTER_FIXED_FLOOR(x + 0xffff)
+
+#define CLUTTER_FIXED_MUL(x,y) ((x) >> 8) * ((y) >> 8)
+
+#define CLUTTER_FIXED_DIV(x,y) ((((x) << 8)/(y)) << 8)
+
+G_END_DECLS
+
+#endif
clutter_group_request_coords (ClutterActor *self,
ClutterActorBox *box)
{
- ClutterGroup *group = CLUTTER_GROUP(self);
- guint cwidth, cheight, width ,height;
ClutterActorBox cbox;
clutter_actor_allocate_coords (self, &cbox);
- cwidth = cbox.x2 - cbox.x1;
- cheight = cbox.y2 - cbox.y1;
-
- /* g_print("cbox x2: %i x1 %i\n", cbox.x2, cbox.x1); */
-
- width = box->x2 - box->x1;
- height = box->y2 - box->y1;
-
- /* FIXME: below needs work */
- if (cwidth != width || cheight != height)
- {
- GList *child_item;
-
- for (child_item = group->priv->children;
- child_item != NULL;
- child_item = child_item->next)
- {
- ClutterActor *child = child_item->data;
- ClutterActorBox tbox;
- gint nx, ny;
- gint twidth, theight, nwidth, nheight;
-
- g_assert (child != NULL);
-
- clutter_actor_allocate_coords (child, &tbox);
-
- twidth = tbox.x2 - tbox.x1;
- theight = tbox.y2 - tbox.y1;
-
- /* g_print("getting ps %ix%i\n", tbox.x1, tbox.y1); */
-
- nwidth = ( width * twidth ) / cwidth;
- nheight = ( height * theight ) / cheight;
-
- nx = ( nwidth * tbox.x1 ) / twidth ;
-
- /* g_print("n: %i t %i x1: %i\n", nwidth, twidth, tbox.x1); */
-
- ny = ( nheight * tbox.y1 ) / theight;
-
- /* g_print("n: %i t %i x1: %i\n", nheight, theight, tbox.y1); */
-
- clutter_actor_set_position (child, nx, ny);
- clutter_actor_set_size (child, nwidth, height);
-
- /* g_print("size to +%i+%x %ix%i\n", nx, ny, nwidth, nheight); */
- }
- }
+ /* Sizing requests fail, use scale() instead */
+ box->x1 = cbox.x1;
+ box->y1 = cbox.y1;
+ box->x2 = cbox.x2;
+ box->y2 = cbox.y2;
}
static void
{
ClutterActor *child = CLUTTER_ACTOR(child_item->data);
- /* if (CLUTTER_ACTOR_IS_VISIBLE (child)) */
+ if (CLUTTER_ACTOR_IS_VISIBLE (child))
{
ClutterActorBox cbox;
clutter_actor_allocate_coords (child, &cbox);
- /*
- if (box->x1 == 0 || cbox.x1 < box->x1)
- box->x1 = cbox.x1;
-
- if (box->y1 == 0 || cbox.y1 < box->y1)
- box->y1 = cbox.y1;
- */
+ /* Ignore any children with offscreen ( negaive )
+ * positions
+ */
if (box->x2 == 0 || cbox.x2 > box->x2)
box->x2 = cbox.x2;
ClutterActor *actor)
{
ClutterActor *parent;
+
+ /* FIXME: add() needs to be somehow overidden */
g_return_if_fail (CLUTTER_IS_GROUP (self));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
clutter_group_sort_depth_order (self);
+ /* If were scaled, we scale the actor too */
+
g_signal_emit (self, group_signals[ADD], 0, actor);
g_object_unref (actor);
priv->xwin,
box->x1,
box->y1);
+
}
static void
priv = texture->priv;
-
-
qwidth = x2-x1;
qheight = y2-y1;
/* Create a texture from pixbuf, then clone in to same resources */
if (i == 0)
- oh->hand[i] = clutter_texture_new_from_pixbuf (pixbuf);
- else
- oh->hand[i] = clutter_clone_texture_new (CLUTTER_TEXTURE(oh->hand[0]));
+ oh->hand[i] = clutter_texture_new_from_pixbuf (pixbuf);
+ else
+ oh->hand[i] = clutter_clone_texture_new (CLUTTER_TEXTURE(oh->hand[0]));
/* Place around a circle */
w = clutter_actor_get_width (oh->hand[0]);
clutter_group_add (CLUTTER_GROUP (oh->group), oh->hand[i]);
}
+ clutter_actor_set_scale (oh->group, .1, 0.1);
+
+#if 0
+ {
+ guint w, h;
+ clutter_actor_get_abs_size (CLUTTER_ACTOR(oh->hand[0]), &w, &h);
+ g_print ("%ix%i\n", w, h);
+ g_print ("%ix%i\n",
+ clutter_actor_get_width(oh->hand[0]),
+ clutter_actor_get_height(oh->hand[0]));
+ }
+#endif
+
/* Add the group to the stage */
clutter_group_add (CLUTTER_GROUP (stage), CLUTTER_ACTOR(oh->group));