clutter布局之json[0722]
clutter布局可以使用一种源自json的语言
这样对程序日后的调整就方便了许多,下面给出两端源自官网的代码
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <clutter/clutter.h>
static ClutterScript *script = NULL;
static guint merge_id = 0;
static const gchar *test_unmerge =
"["
" {"
" \"id\" : \"main-stage\","
" \"type\" : \"ClutterStage\","
" \"children\" : [ \"blue-button\" ]"
" },"
" {"
" \"id\" : \"blue-button\","
" \"type\" : \"ClutterRectangle\","
" \"color\" : \"#0000ffff\","
" \"x\" : 350,"
" \"y\" : 50,"
" \"width\" : 100,"
" \"height\" : 100,"
" \"visible\" : true,"
" \"reactive\" : true"
" }"
"]";
static const gchar *test_behaviour =
"["
" {"
" \"id\" : \"main-timeline\","
" \"type\" : \"ClutterTimeline\","
" \"duration\" : 5000,"
" \"loop\" : true"
" },"
" {"
" \"id\" : \"path-behaviour\","
" \"type\" : \"ClutterBehaviourPath\","
" \"knots\" : [ [ 50, 50 ],[100,100]],"
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"ramp_inc\""
" }"
" },"
" {"
" \"id\" : \"rotate-behaviour\","
" \"type\" : \"ClutterBehaviourRotate\","
" \"angle-start\" : 0.0,"
" \"angle-end\" : 360.0,"
" \"axis\" : \"y-axis\","
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"sine\""
" }"
" },"
" {"
" \"id\" : \"fade-behaviour\","
" \"type\" : \"ClutterBehaviourOpacity\","
" \"opacity-start\" : 255,"
" \"opacity-end\" : 0,"
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"ramp-inc\""
" }"
" }"
"]";
static gboolean
blue_button_press (ClutterActor *actor,
ClutterButtonEvent *event,
gpointer data)
{
g_print ("[*] Pressed `%s'\n", clutter_get_script_id (G_OBJECT (actor)));
g_print ("[*] Unmerging objects with merge id: %d\n", merge_id);
clutter_script_unmerge_objects (script, merge_id);
return TRUE;
}
static gboolean
red_button_press (ClutterActor *actor,
ClutterButtonEvent *event,
gpointer data)
{
GObject *timeline;
g_print ("[*] Pressed `%s'\n", clutter_get_script_id (G_OBJECT (actor)));
timeline = clutter_script_get_object (script, "main-timeline");
g_assert (CLUTTER_IS_TIMELINE (timeline));
if (!clutter_timeline_is_playing (CLUTTER_TIMELINE (timeline)))
clutter_timeline_start (CLUTTER_TIMELINE (timeline));
else
clutter_timeline_pause (CLUTTER_TIMELINE (timeline));
return TRUE;
}
int
main (int argc, char *argv[])
{
GObject *stage, *blue_button, *red_button;
GError *error = NULL;
gint res;
clutter_init (&argc, &argv);
script = clutter_script_new ();
g_assert (CLUTTER_IS_SCRIPT (script));
clutter_script_load_from_data (script, test_behaviour, -1, &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
clutter_script_load_from_file (script, "test-script.json", &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
merge_id = clutter_script_load_from_data (script, test_unmerge, -1, &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
res = clutter_script_get_objects (script,
"main-stage", &stage,
"red-button", &red_button,
"blue-button", &blue_button,
NULL);
g_assert (res == 3);
clutter_actor_show (CLUTTER_ACTOR (stage));
g_signal_connect (red_button,
"button-press-event",
G_CALLBACK (red_button_press),
NULL);
g_signal_connect (blue_button,
"button-press-event",
G_CALLBACK (blue_button_press),
NULL);
clutter_main ();
g_object_unref (script);
return EXIT_SUCCESS;
}
上面这段为c的代码,下面给出外置布局文件的代码
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
{
"Scene" : {
"id" : "main-stage",
"type" : "ClutterStage",
"title" : "ClutterScript test",
"color" : "white",
"children" : [
{
"id" : "red-button",
"type" : "ClutterRectangle",
"color" : "#ff0000ff",
"x" : 50, "y" : 50, "width" : 100, "height" : 100,
"reactive" : true,
"rotation" : [
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
],
"behaviours" : [ "fade-behaviour", "path-behaviour" ],
},
{
"id" : "green-button",
"type" : "ClutterRectangle",
"color" : "#00ff00ff",
"border-width" : 5,
"border-color" : "#00cc00ff",
"x" : 200,
"y" : 50,
"width" : 100,
"height" : 100,
"reactive" : true,
},
{
"id" : "red-hand",
"type" : "ClutterTexture",
"filename" : "star.png",
"x" : 100,
"y" : 100,
"width" : "20mm",
"keep-aspect-ratio" : true,
"anchor-x" : 5,
"anchor-y" : 5,
"opacity" : 100,
"behaviours" : [ "rotate-behaviour", "fade-behaviour" ]
},
{
"id" : "red-hand-clone",
"type" : "ClutterCloneTexture",
"parent-texture" : "red-hand",
"x" : 250,
"y" : 150,
"opacity" : 100,
},
{
"id" : "label",
"type" : "ClutterLabel",
"x" : 50,
"y" : 200,
"width" : 400,
"text" : "Clutter\tScript测试",
"font-name" : "Sans 24px",
"color" : "black",
"alignment" : "center",
"wrap" : false,
"ellipsize" : "none",
"rotation" : [
{ "z-axis" : [ 45.0, [ 0,0 ] ] }
]
}
]
}
}
实际使用中发现使用json布局文件除了一般的布局之外还可以关联behavior等属性,这样就免除了
反复unref的麻烦,只需在最后unref掉script即可。
虽然官方手册中提到可以在布局文件中声明signal,但实际使用中发现这样做总是提示找不到相应的处理函数
[即使声明了G_MODULE_EXPORT也不行]或是提示段错误。
但无论怎样,这对于代码的简化还是很有帮助的。
这样对程序日后的调整就方便了许多,下面给出两端源自官网的代码
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <clutter/clutter.h>
static ClutterScript *script = NULL;
static guint merge_id = 0;
static const gchar *test_unmerge =
"["
" {"
" \"id\" : \"main-stage\","
" \"type\" : \"ClutterStage\","
" \"children\" : [ \"blue-button\" ]"
" },"
" {"
" \"id\" : \"blue-button\","
" \"type\" : \"ClutterRectangle\","
" \"color\" : \"#0000ffff\","
" \"x\" : 350,"
" \"y\" : 50,"
" \"width\" : 100,"
" \"height\" : 100,"
" \"visible\" : true,"
" \"reactive\" : true"
" }"
"]";
static const gchar *test_behaviour =
"["
" {"
" \"id\" : \"main-timeline\","
" \"type\" : \"ClutterTimeline\","
" \"duration\" : 5000,"
" \"loop\" : true"
" },"
" {"
" \"id\" : \"path-behaviour\","
" \"type\" : \"ClutterBehaviourPath\","
" \"knots\" : [ [ 50, 50 ],[100,100]],"
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"ramp_inc\""
" }"
" },"
" {"
" \"id\" : \"rotate-behaviour\","
" \"type\" : \"ClutterBehaviourRotate\","
" \"angle-start\" : 0.0,"
" \"angle-end\" : 360.0,"
" \"axis\" : \"y-axis\","
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"sine\""
" }"
" },"
" {"
" \"id\" : \"fade-behaviour\","
" \"type\" : \"ClutterBehaviourOpacity\","
" \"opacity-start\" : 255,"
" \"opacity-end\" : 0,"
" \"alpha\" : {"
" \"timeline\" : \"main-timeline\","
" \"function\" : \"ramp-inc\""
" }"
" }"
"]";
static gboolean
blue_button_press (ClutterActor *actor,
ClutterButtonEvent *event,
gpointer data)
{
g_print ("[*] Pressed `%s'\n", clutter_get_script_id (G_OBJECT (actor)));
g_print ("[*] Unmerging objects with merge id: %d\n", merge_id);
clutter_script_unmerge_objects (script, merge_id);
return TRUE;
}
static gboolean
red_button_press (ClutterActor *actor,
ClutterButtonEvent *event,
gpointer data)
{
GObject *timeline;
g_print ("[*] Pressed `%s'\n", clutter_get_script_id (G_OBJECT (actor)));
timeline = clutter_script_get_object (script, "main-timeline");
g_assert (CLUTTER_IS_TIMELINE (timeline));
if (!clutter_timeline_is_playing (CLUTTER_TIMELINE (timeline)))
clutter_timeline_start (CLUTTER_TIMELINE (timeline));
else
clutter_timeline_pause (CLUTTER_TIMELINE (timeline));
return TRUE;
}
int
main (int argc, char *argv[])
{
GObject *stage, *blue_button, *red_button;
GError *error = NULL;
gint res;
clutter_init (&argc, &argv);
script = clutter_script_new ();
g_assert (CLUTTER_IS_SCRIPT (script));
clutter_script_load_from_data (script, test_behaviour, -1, &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
clutter_script_load_from_file (script, "test-script.json", &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
merge_id = clutter_script_load_from_data (script, test_unmerge, -1, &error);
if (error)
{
g_print ("*** Error:\n"
"*** %s\n", error->message);
g_error_free (error);
g_object_unref (script);
return EXIT_FAILURE;
}
res = clutter_script_get_objects (script,
"main-stage", &stage,
"red-button", &red_button,
"blue-button", &blue_button,
NULL);
g_assert (res == 3);
clutter_actor_show (CLUTTER_ACTOR (stage));
g_signal_connect (red_button,
"button-press-event",
G_CALLBACK (red_button_press),
NULL);
g_signal_connect (blue_button,
"button-press-event",
G_CALLBACK (blue_button_press),
NULL);
clutter_main ();
g_object_unref (script);
return EXIT_SUCCESS;
}
上面这段为c的代码,下面给出外置布局文件的代码
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
"Scene" : {
"id" : "main-stage",
"type" : "ClutterStage",
"title" : "ClutterScript test",
"color" : "white",
"children" : [
{
"id" : "red-button",
"type" : "ClutterRectangle",
"color" : "#ff0000ff",
"x" : 50, "y" : 50, "width" : 100, "height" : 100,
"reactive" : true,
"rotation" : [
{ "z-axis" : [ 45.0, [ 75, 75 ] ] }
],
"behaviours" : [ "fade-behaviour", "path-behaviour" ],
},
{
"id" : "green-button",
"type" : "ClutterRectangle",
"color" : "#00ff00ff",
"border-width" : 5,
"border-color" : "#00cc00ff",
"x" : 200,
"y" : 50,
"width" : 100,
"height" : 100,
"reactive" : true,
},
{
"id" : "red-hand",
"type" : "ClutterTexture",
"filename" : "star.png",
"x" : 100,
"y" : 100,
"width" : "20mm",
"keep-aspect-ratio" : true,
"anchor-x" : 5,
"anchor-y" : 5,
"opacity" : 100,
"behaviours" : [ "rotate-behaviour", "fade-behaviour" ]
},
{
"id" : "red-hand-clone",
"type" : "ClutterCloneTexture",
"parent-texture" : "red-hand",
"x" : 250,
"y" : 150,
"opacity" : 100,
},
{
"id" : "label",
"type" : "ClutterLabel",
"x" : 50,
"y" : 200,
"width" : 400,
"text" : "Clutter\tScript测试",
"font-name" : "Sans 24px",
"color" : "black",
"alignment" : "center",
"wrap" : false,
"ellipsize" : "none",
"rotation" : [
{ "z-axis" : [ 45.0, [ 0,0 ] ] }
]
}
]
}
}
实际使用中发现使用json布局文件除了一般的布局之外还可以关联behavior等属性,这样就免除了
反复unref的麻烦,只需在最后unref掉script即可。
虽然官方手册中提到可以在布局文件中声明signal,但实际使用中发现这样做总是提示找不到相应的处理函数
[即使声明了G_MODULE_EXPORT也不行]或是提示段错误。
但无论怎样,这对于代码的简化还是很有帮助的。