/* gcompris - scale.c
*
* Copyright (C) 2006, 2008 Miguel de Izarra
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include "gcompris/gcompris.h"
#include // for strcmp
#define SOUNDLISTFILE PACKAGE
static GcomprisBoard *gcomprisBoard = NULL;
static gboolean board_paused = TRUE;
static void start_board (GcomprisBoard *agcomprisBoard);
static void pause_board (gboolean pause);
static void end_board (void);
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
static void config_start(GcomprisBoard *agcomprisBoard,
GcomprisProfile *aProfile);
static void config_stop();
static void set_level (guint level);
static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str);
static void process_ok(void);
static int gamewon;
static void game_won(void);
static GooCanvasItem *boardRootItem = NULL;
static GooCanvasItem *group_g, *group_d, *group_m;
static GooCanvasItem *sign;
static GooCanvasItem *bras;
static GooCanvasItem *answer_item;
static GString *answer_string = NULL;
static void scale_destroy_all_items(void);
static void scale_next_level(void);
#define MODE_COUNT 0 // No conversions
#define MODE_WEIGHT 1 // kg <-> g conversions
#define DEFAULT_MODE MODE_COUNT
static gint board_mode = DEFAULT_MODE;
static gint bonus_item = GC_BONUS_SMILEY;
#define ITEM_X_MIN 125
#define ITEM_X_MAX 500
#define ITEM_Y_MIN 400
#define ITEM_Y_MAX 500
#define ITEM_W 45
#define ITEM_H 70
#define PLATE_Y 33.0
#define PLATE_Y_DELTA 15.0
#define PLATE_W 190.0
#define BRAS_X 55.0
#define BRAS_Y -6.0
#define PLATE_SIZE 4 // number of place in the plate
typedef struct
{
GooCanvasItem *item;
double x, y;
int plate; // 0 not place, 1 in plate_g, -1 in plate_d
int plate_index; // position in the plate
int weight;
} ScaleItem;
static GList *item_list = NULL;
static int objet_weight = 0;
static gboolean ask_for_answer = FALSE;
static gdouble balance_left_y;
static gdouble balance_right_y;
static gdouble balance_left_x;
static gdouble balance_right_x;
static gdouble last_delta=0;
static gint drag_mode;
static const char *imageList[] = {
"scale/chocolate_cake.png",
"scale/pear.png",
"scale/orange.png",
"scale/suggar_box.png",
"scale/flowerpot.png",
"scale/glass.png"
};
static const int imageListCount = G_N_ELEMENTS(imageList);
static int scale_drag_event(GooCanvasItem *w,
GooCanvasItem *target,
GdkEvent *event,
ScaleItem *item);
/* Description of this plugin */
static BoardPlugin menu_bp =
{
NULL,
NULL,
"Scale",
"Balance the scales properly",
"Miguel de Izarra ",
NULL,
NULL,
NULL,
NULL,
start_board,
pause_board,
end_board,
is_our_board,
key_press,
NULL,
set_level,
NULL,
NULL,
config_start,
config_stop
};
/*
* Main entry point mandatory for each Gcompris's game
* ---------------------------------------------------
*
*/
GET_BPLUGIN_INFO(scale)
/*
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
*
*/
static void pause_board (gboolean pause)
{
if(gcomprisBoard==NULL)
return;
if(gamewon == TRUE && pause == FALSE) /* the game is won */
{
game_won();
}
board_paused = pause;
}
static void
start_board (GcomprisBoard *agcomprisBoard)
{
if(agcomprisBoard!=NULL)
{
gcomprisBoard=agcomprisBoard;
gcomprisBoard->level=1;
gcomprisBoard->sublevel=1;
gc_bar_set(GC_BAR_LEVEL|GC_BAR_CONFIG);
gc_bar_location(-1, -1, 0.7);
if (strcmp(gcomprisBoard->mode, "count") == 0)
board_mode = MODE_COUNT;
else if (strcmp(gcomprisBoard->mode, "weight") == 0)
board_mode = MODE_WEIGHT;
else
board_mode = DEFAULT_MODE;
gcomprisBoard->maxlevel = (board_mode == MODE_COUNT) ? 4 : 5;
gcomprisBoard->number_of_sublevel = (board_mode == MODE_COUNT) ? 5 : 3;
bonus_item = (board_mode == MODE_COUNT) ? GC_BONUS_SMILEY : GC_BONUS_TUX;
gamewon = FALSE;
pause_board(FALSE);
GHashTable *config = gc_db_get_board_conf();
gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode");
if (drag_mode_str && (strcmp (drag_mode_str, "NULL") != 0))
drag_mode = g_ascii_strtod(drag_mode_str, NULL);
else
drag_mode = GC_DRAG_MODE_DEFAULT;
gc_set_background(goo_canvas_get_root_item(gcomprisBoard->canvas),
"scale/tabepice.jpg");
gc_drag_start(goo_canvas_get_root_item(gcomprisBoard->canvas),
(GcDragFunc)scale_drag_event, drag_mode);
gc_score_start(SCORESTYLE_NOTE,
BOARDWIDTH - 220,
450 ,
gcomprisBoard->number_of_sublevel);
scale_next_level();
}
}
static void
end_board ()
{
if(gcomprisBoard!=NULL)
{
gc_drag_stop(goo_canvas_get_root_item(gcomprisBoard->canvas));
pause_board(TRUE);
scale_destroy_all_items();
gc_score_end();
}
gcomprisBoard = NULL;
}
/* ======================================= */
static void
set_level (guint level)
{
if(gcomprisBoard!=NULL)
{
gcomprisBoard->level=level;
gcomprisBoard->sublevel=1;
scale_next_level();
}
}
/* ======================================= */
gboolean is_our_board (GcomprisBoard *gcomprisBoard)
{
if (gcomprisBoard)
if(g_ascii_strcasecmp(gcomprisBoard->type, "scale")==0)
{
/* Set the plugin entry */
gcomprisBoard->plugin=&menu_bp;
return TRUE;
}
return FALSE;
}
/* ======================================= */
static gint
key_press(guint keyval, gchar *commit_str, gchar *preedit_str)
{
if(!gcomprisBoard)
return FALSE;
/* Add some filter for control and shift key */
switch (keyval)
{
/* Avoid all this keys to be interpreted by this game */
case GDK_Shift_L:
case GDK_Shift_R:
case GDK_Control_L:
case GDK_Control_R:
case GDK_Caps_Lock:
case GDK_Shift_Lock:
case GDK_Meta_L:
case GDK_Meta_R:
case GDK_Alt_L:
case GDK_Alt_R:
case GDK_Super_L:
case GDK_Super_R:
case GDK_Hyper_L:
case GDK_Hyper_R:
case GDK_Num_Lock:
return FALSE;
case GDK_KP_Enter:
case GDK_Return:
process_ok();
return TRUE;
case GDK_Right:
case GDK_Left:
break;
case GDK_BackSpace:
if(answer_string)
g_string_truncate(answer_string, answer_string->len -1);
break;
}
if(answer_string)
{
gchar *tmpstr;
gchar c = commit_str ? commit_str[0] : 0;
/* Limit the user entry to 5 digits */
if(c>='0' && c<='9' && answer_string->len < 5)
answer_string = g_string_append_c(answer_string, c);
if (board_mode == MODE_WEIGHT)
tmpstr = g_strdup_printf(_("Weight in g = %s"), answer_string->str);
else
tmpstr = g_strdup_printf(_("Weight = %s"), answer_string->str);
g_object_set(answer_item,
"text", tmpstr,
NULL);
g_free(tmpstr);
}
return TRUE;
}
// plate = 1 plate g (left)
// plate = -1 plate d (right)
// plate = 0 plate g - plate d
int
get_weight_plate(int plate)
{
GList *list;
ScaleItem *item;
int result=0;
for(list = item_list; list; list=list->next)
{
item = list->data;
if(item->plate == plate || plate==0)
{
result += item->weight * item->plate;
}
}
if(plate==-1)
result = -result;
return result;
}
void
scale_anim_plate(void)
{
double delta_y;
double angle;
double scale;
int diff;
// in MODE_WEIGHT the granularity is gramm, so we use a different factor
scale = (board_mode == MODE_WEIGHT) ? 2000.0 : 10.0;
diff = get_weight_plate(0);
delta_y = CLAMP(PLATE_Y_DELTA / scale * diff,
-PLATE_Y_DELTA, PLATE_Y_DELTA);
if(get_weight_plate(1) == 0)
delta_y = -PLATE_Y_DELTA;
/* Update the sign */
if (diff == 0)
g_object_set(sign, "text", "=", NULL);
else if (diff < 0)
g_object_set(sign, "text", "<", NULL);
else
g_object_set(sign, "text", ">", NULL);
if(last_delta != delta_y)
{
goo_canvas_item_translate(group_g, 0, -last_delta);
goo_canvas_item_translate(group_d, 0, last_delta);
last_delta = delta_y;
angle = tan(delta_y / 138) * 180 / M_PI;
goo_canvas_item_translate(group_g, 0, delta_y);
goo_canvas_item_translate(group_d, 0, -delta_y);
gc_item_rotate_with_center(bras, -angle, 138, 84);
}
if(diff == 0 && ask_for_answer)
{
double x_offset = BOARDWIDTH/2;
double y_offset = BOARDHEIGHT*0.7;
GooCanvasItem *item = goo_canvas_svg_new (boardRootItem,
gc_skin_rsvg_get(),
"svg-id", "#BUTTON_TEXT",
NULL);
SET_ITEM_LOCATION_CENTER(item,
x_offset / 2,
y_offset);
goo_canvas_item_scale(item, 2, 1);
answer_item = goo_canvas_text_new(boardRootItem,
"",
x_offset,
y_offset,
-1,
GTK_ANCHOR_CENTER,
"font", gc_skin_font_board_title_bold,
"fill-color", "white",
NULL);
answer_string = g_string_new(NULL);
key_press(0, NULL, NULL);
}
else if(diff == 0)
process_ok();
}
// if plate = 1 , move to plate g (left)
// if plate = -1, move to plate d (right)
// if plate = 0 , move to the item list
void
scale_item_move_to(ScaleItem *item, int plate)
{
ScaleItem *scale;
GList *list;
gboolean found;
int index;
if(plate != 0)
{
if(item->plate)
item->plate_index = -1;
else
gc_sound_play_ogg ("sounds/eraser1.wav", NULL);
// find the first free place in the plate
for(index=0; index < 2 * PLATE_SIZE; index++)
{
found = FALSE;
for(list = item_list; list; list = list->next)
{
scale = list->data;
if(scale->plate_index == index && scale->plate == plate)
found=TRUE;
}
if(!found)
{ // move to the plate
gdouble x = (plate == 1 ? balance_left_x : balance_right_x);
gdouble y = (plate == 1
? balance_left_y + last_delta
: balance_right_y - last_delta);
item->plate = plate;
item->plate_index = index;
/* Reparent */
g_object_ref(item->item);
goo_canvas_item_remove(item->item);
goo_canvas_item_add_child ((plate == 1 ? group_g : group_d),
item->item, -1);
g_object_unref(item->item);
gc_item_absolute_move(item->item,
x + (index % PLATE_SIZE) * ITEM_W,
y + PLATE_Y - ITEM_H + 5 - (index >= PLATE_SIZE ? ITEM_H : 0));
break;
}
}
if(found) // can't find place
plate=0;
}
if(plate==0)
{ // move the item to the list
if(item->plate)
gc_sound_play_ogg ("sounds/eraser1.wav", NULL);
item->plate = 0;
/* Reparent */
g_object_ref(item->item);
goo_canvas_item_remove(item->item);
goo_canvas_item_add_child (group_m,
item->item, -1);
g_object_unref(item->item);
gc_item_absolute_move(item->item,
item->x,
item->y);
goo_canvas_item_raise(item->item, NULL);
}
scale_anim_plate();
if (!gamewon)
gc_item_focus_init(item->item, NULL);
}
static gboolean
scale_item_event (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
ScaleItem *scale)
{
if(answer_string)
return FALSE;
if(event->type == GDK_BUTTON_PRESS && event->button==3)
scale_item_move_to(scale, 0);
return FALSE;
}
static int
scale_drag_event(GooCanvasItem *w,
GooCanvasItem *target,
GdkEvent *event,
ScaleItem *scale)
{
double x, y;
double item_x, item_y;
if(answer_string) // disable, waiting a answer
return FALSE;
switch(event->type)
{
case GDK_BUTTON_PRESS:
gc_drag_offset_save(event);
goo_canvas_item_raise(goo_canvas_item_get_parent(scale->item),
NULL);
goo_canvas_item_raise(scale->item, NULL);
break;
case GDK_MOTION_NOTIFY:
gc_drag_item_move(event, NULL);
break;
case GDK_BUTTON_RELEASE:
{
int plate;
item_x = event->button.x;
item_y = event->button.y;
goo_canvas_convert_from_item_space(goo_canvas_item_get_canvas(w),
scale->item, &item_x, &item_y);
x = item_x;
y = item_y;
goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(w),
group_g, &x, &y);
if( -ITEM_W < x
&& x < PLATE_W + ITEM_W
&& abs(y - PLATE_Y) < ITEM_H)
plate = 1;
else
{
x = item_x;
y = item_y;
goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(w),
group_d, &x, &y);
if( -ITEM_W < x
&& x < PLATE_W + ITEM_W
&& abs(y - PLATE_Y) < ITEM_H)
plate = -1;
else
plate=0;
}
scale_item_move_to(scale, plate);
}
break;
default:
break;
}
return FALSE;
}
// show_weight:
// 0 -> no unit,
// 1 -> display g, 1000 -> display kg,
// 10000 -> random (weighted 1:2)
static ScaleItem *
scale_list_add_weight(GooCanvasItem *group,
gint weight, int show_weight)
{
ScaleItem *new_item;
GdkPixbuf *pixmap;
gchar *weight_text;
double x, y;
GList *last;
last = g_list_last(item_list);
if(last)
{
new_item = last->data;
x = new_item->x + ITEM_W;
y = new_item->y;
if(x > ITEM_X_MAX)
{
x = ITEM_X_MIN;
y += ITEM_H;
if(y > ITEM_Y_MAX)
g_warning("No more place for new item");
}
}
else
{
x = ITEM_X_MIN;
y = ITEM_Y_MIN;
}
new_item = g_new0(ScaleItem, 1);
new_item->x = x;
new_item->y = y;
new_item->weight = weight;
/* If selected, display multiples of 500g as 'g' or 'kg' randomly */
if (show_weight > 9999) {
if ((weight % 500) == 0)
show_weight = g_random_int_range(1,3000);
else
show_weight = 1;
}
if (show_weight < 1000) {
weight_text = g_strdup_printf("%d%s", weight, show_weight ? "\n g" : "");
} else {
int thousand = weight / 1000;
int hundred = (weight % 1000) / 100;
weight_text = g_strdup_printf("%c %c\n kg", '0' + thousand, '0' + hundred);
}
pixmap = gc_pixmap_load("scale/masse.png");
new_item->item = goo_canvas_group_new(group, NULL);
goo_canvas_image_new(new_item->item,
pixmap,
0, 0,
NULL);
goo_canvas_text_new(new_item->item,
weight_text,
18,
35,
-1,
GTK_ANCHOR_CENTER,
"font", "sans 10",
"fill_color_rgba", 0x000000FFL,
NULL);
goo_canvas_item_translate(new_item->item,
new_item->x,
new_item->y);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
#else
g_object_unref(pixmap);
#endif
g_free(weight_text);
gc_item_focus_init(new_item->item, NULL);
g_signal_connect(new_item->item, "button_press_event",
(GCallback)gc_drag_event, new_item);
g_signal_connect(new_item->item, "button_release_event",
(GCallback)gc_drag_event, new_item);
g_signal_connect(new_item->item, "button_press_event",
(GCallback) scale_item_event, new_item);
item_list = g_list_append(item_list, new_item);
return new_item;
}
// show_weight:
// 0 -> no display,
// 1 -> display g,
// 1000 -> display kg, 10000 -> random (weighted 1:2)
static ScaleItem *
scale_list_add_object(GooCanvasItem *group,
GdkPixbuf *pixmap,
int weight, int plate,
int show_weight)
{
GooCanvasItem *item;
ScaleItem * new_item;
item = goo_canvas_image_new(group,
pixmap,
PLATE_SIZE * ITEM_W * .5
- gdk_pixbuf_get_width(pixmap)/2,
PLATE_Y + 5 - gdk_pixbuf_get_height(pixmap),
NULL);
goo_canvas_item_lower(item, NULL);
if(show_weight)
{ // display the object weight
double x,y;
gchar * text;
x = PLATE_SIZE * ITEM_W * .5;
y = PLATE_Y - 20.0;
if (board_mode == MODE_WEIGHT) {
if (show_weight > 9999) {
if ((weight % 500) == 0)
show_weight = g_random_int_range(1,3000);
else
show_weight = 1;
}
if (show_weight < 1000)
text = g_strdup_printf("%d g", objet_weight);
else
text = g_strdup_printf("%.1f kg", objet_weight / 1000.0);
} else {
text = g_strdup_printf("%d", objet_weight);
}
goo_canvas_text_new(group,
text,
x + 1.0,
y + 1.0,
-1,
GTK_ANCHOR_CENTER,
"font", gc_skin_font_board_title_bold,
"fill_color_rgba", gc_skin_color_shadow,
NULL);
goo_canvas_text_new(group,
text,
x,
y,
-1,
GTK_ANCHOR_CENTER,
"font", gc_skin_font_board_title_bold,
"fill_color_rgba", gc_skin_color_content,
NULL);
g_free(text);
}
new_item = g_new0(ScaleItem, 1);
new_item->weight = weight;
new_item->plate = plate;
new_item->plate_index = -1;
new_item->item = item;
item_list = g_list_append(item_list, new_item);
return new_item;
}
// test if adding elements in table can produce total
static gboolean
test_addition(int total, int *table, int len)
{
int i;
if(total == 0)
return TRUE;
for(i=0; ilevel)
{
case 1:
case 2:
objet_weight = g_random_int_range(5,20);
for(i=0; i<10; i++)
list_weight[i] = default_list_weight[i];
show_weight = gcomprisBoard->level == 1;
break;
case 3:
case 4:
while(1)
{
for(i=0; i< 5; i++)
do
tmp[i] = default_list_weight[g_random_int_range(0,10)];
while(tmp[i]==0);
objet_weight=0;
for(i=0; i<5; i++)
objet_weight += g_random_int_range(-1,2) * tmp[i];
objet_weight = abs(objet_weight);
if(!test_addition(objet_weight, tmp, 5))
break;
}
for(i=0; i<5; i++)
list_weight[i] = tmp[i];
show_weight = gcomprisBoard->level == 3;
break;
}
ask_for_answer = !show_weight;
for(i=0; list_weight[i] ; i++)
scale_list_add_weight(group_m, list_weight[i], 0);
pixmap = gc_pixmap_load(imageList[g_random_int_range(0,imageListCount)]);
scale_list_add_object(group_d, pixmap, objet_weight, -1, show_weight);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
#else
g_object_unref(pixmap);
#endif
}
// Defines a set of available weight-items and possible values for the "unknown" object
struct weight_set {
const int list_weight[10];
int range_min;
int range_max;
};
static struct weight_set weight1 = {
.list_weight = { 100,200,400,500,800,1000 },
.range_min = 500,
.range_max = 2000,
};
static struct weight_set weight2 = {
.list_weight = { 100,100,200,500,1000,1500,2000,2500,3000 },
.range_min = 200,
.range_max = 9000,
};
static struct weight_set weight3 = {
.list_weight = { 100,200,300,600,900,1200,1500 },
.range_min = 500,
.range_max = 3000,
};
static struct weight_set weight4 = {
.list_weight = { 100,100,200,200,200,500,500,1000 },
.range_min = 300,
.range_max = 2500,
};
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static void scale_prepare_level_weight()
{
GdkPixbuf *pixmap;
int show_weight_objet = 1;
int show_weight_mass = 1;
// A level may use the following weight-sets
struct weight_set *set1[] = { &weight1, &weight2, &weight3, &weight4 };
struct weight_set *set2[] = { &weight1, &weight2, &weight4 };
struct weight_set *set3[] = { &weight1, &weight2, &weight3, &weight4 };
struct weight_set *set4[] = { &weight1, &weight2, &weight4 };
struct weight_set *set5[] = { &weight1, &weight4 };
struct weight_set *set = &weight1;
const int *list_weight = NULL;
int i, tmp[6] = { 0 };
group_m = goo_canvas_group_new(boardRootItem, NULL);
switch(gcomprisBoard->level)
{
case 1:
set = set1[g_random_int_range(0,ARRAY_SIZE(set1))];
objet_weight = g_random_int_range(set->range_min / 100, set->range_max / 100) * 100;
list_weight = set->list_weight;
show_weight_objet = 1;
show_weight_mass = 1;
break;
case 2:
set = set2[g_random_int_range(0,ARRAY_SIZE(set2))];
objet_weight = g_random_int_range(set->range_min / 100, set->range_max / 100) * 100;
list_weight = set->list_weight;
show_weight_objet = 10000;
show_weight_mass = 10000;
break;
case 3:
set = set3[g_random_int_range(0,ARRAY_SIZE(set3))];
objet_weight = g_random_int_range(set->range_min / 100, set->range_max / 100) * 100;
list_weight = set->list_weight;
show_weight_objet = 0;
show_weight_mass = 1;
break;
case 4:
set = set4[g_random_int_range(0,ARRAY_SIZE(set4))];
objet_weight = g_random_int_range(set->range_min / 100, set->range_max / 100) * 100;
list_weight = set->list_weight;
show_weight_objet = 0;
show_weight_mass = 10000;
break;
case 5:
set = set5[g_random_int_range(0,ARRAY_SIZE(set5))];
objet_weight = g_random_int_range(set->range_min / 100, set->range_max / 100) * 100;
list_weight = set->list_weight;
while(1)
{
for(i=0; i< 5; i++)
do
tmp[i] = list_weight[g_random_int_range(0,10)];
while(tmp[i]==0);
objet_weight=0;
for(i=0; i<5; i++)
objet_weight += g_random_int_range(-1,2) * tmp[i];
objet_weight = abs(objet_weight);
if(!test_addition(objet_weight, tmp, 5))
break;
}
list_weight = tmp;
show_weight_objet = 0;
show_weight_mass = 10000;
break;
}
ask_for_answer = !show_weight_objet;
for(i=0; list_weight[i] ; i++)
scale_list_add_weight(group_m, list_weight[i], show_weight_mass);
pixmap = gc_pixmap_load(imageList[g_random_int_range(0,imageListCount)]);
scale_list_add_object(group_d, pixmap, objet_weight,-1, show_weight_objet);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
#else
g_object_unref(pixmap);
#endif
}
static void
scale_next_level()
{
GdkPixbuf *pixmap, *pixmap2;
gdouble balance_x;
gc_bar_set_level(gcomprisBoard);
scale_destroy_all_items();
gamewon = FALSE;
gc_score_set(gcomprisBoard->sublevel);
// create the scale
pixmap = gc_pixmap_load("scale/balance.png");
balance_x = (BOARDWIDTH - gdk_pixbuf_get_width(pixmap))/2;
balance_left_y = balance_right_y = \
(BOARDHEIGHT - gdk_pixbuf_get_height(pixmap))/2;
boardRootItem = \
goo_canvas_group_new (goo_canvas_get_root_item(gcomprisBoard->canvas),
NULL);
pixmap2 = gc_pixmap_load("scale/bras.png");
bras = goo_canvas_image_new(boardRootItem,
pixmap2,
BOARDWIDTH/2 - gdk_pixbuf_get_width(pixmap2)/2,
balance_left_y - 10,
NULL);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap2);
#else
g_object_unref(pixmap2);
#endif
goo_canvas_image_new(boardRootItem,
pixmap,
balance_x,
balance_left_y,
NULL);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
#else
g_object_unref(pixmap);
#endif
/* Set a sign on the scale in case it's not easy to determine
on which side it balances */
sign = goo_canvas_text_new(boardRootItem,
"=",
BOARDWIDTH/2 + 2,
balance_left_y + 80,
-1,
GTK_ANCHOR_CENTER,
"font", gc_skin_font_board_medium,
"fill-color", "white",
NULL);
/* create left plate */
group_g = goo_canvas_group_new (boardRootItem,
NULL);
balance_left_x = balance_x - 40;
goo_canvas_item_translate(group_g,
balance_left_x,
balance_left_y);
pixmap = gc_pixmap_load("scale/plateau.png");
goo_canvas_image_new(group_g,
pixmap,
0,
PLATE_Y,
NULL);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
#else
g_object_unref(pixmap);
#endif
/* create right plate */
group_d = goo_canvas_group_new(boardRootItem, NULL);
balance_right_x = BOARDWIDTH/2 + 40;
goo_canvas_item_translate(group_d,
balance_right_x,
balance_right_y);
pixmap = gc_pixmap_load("scale/plateau.png");
pixmap2 = gdk_pixbuf_flip(pixmap, TRUE);
goo_canvas_image_new(group_d,
pixmap2,
0,
PLATE_Y,
NULL);
#if GDK_PIXBUF_MAJOR <= 2 && GDK_PIXBUF_MINOR <= 24
gdk_pixbuf_unref(pixmap);
gdk_pixbuf_unref(pixmap2);
#else
g_object_unref(pixmap);
g_object_unref(pixmap2);
#endif
/* display some hint */
if(gcomprisBoard->level > 2 || board_mode == MODE_WEIGHT)
goo_canvas_text_new(boardRootItem,
_("Take care, you can drop weights on both sides of the scale."),
BOARDWIDTH/2,
ITEM_Y_MIN - 20,
-1,
GTK_ANCHOR_CENTER,
"font", gc_skin_font_board_medium,
"fill-color", "darkblue",
NULL);
if (board_mode == MODE_COUNT)
scale_prepare_level();
else
scale_prepare_level_weight();
last_delta=0;
scale_anim_plate();
}
static void scale_destroy_all_items()
{
GList *list;
if(item_list)
{
for(list = item_list; list ; list = list->next)
g_free(list->data);
g_list_free(item_list);
item_list = NULL;
}
if(answer_string)
{
g_string_free(answer_string, TRUE);
answer_string = NULL;
}
if(boardRootItem)
goo_canvas_item_remove(boardRootItem);
boardRootItem = NULL;
}
static void game_won()
{
gcomprisBoard->sublevel++;
if(gcomprisBoard->sublevel > gcomprisBoard->number_of_sublevel) {
/* Try the next level */
gcomprisBoard->sublevel=1;
gcomprisBoard->level++;
if(gcomprisBoard->level > gcomprisBoard->maxlevel)
gcomprisBoard->level = gcomprisBoard->maxlevel;
gc_sound_play_ogg ("sounds/bonus.wav", NULL);
}
scale_next_level();
}
/* ==================================== */
static void process_ok()
{
gboolean good_answer = TRUE;
if(board_paused)
return;
if(answer_string)
{
gint answer_weight ;
answer_weight = g_strtod(answer_string->str, NULL);
good_answer = answer_weight == objet_weight;
}
if(get_weight_plate(0)== 0 && good_answer)
{
gamewon = TRUE;
scale_destroy_all_items();
gc_bonus_display(gamewon, bonus_item);
}
else
gc_bonus_display(gamewon, bonus_item);
}
/* ************************************* */
/* * Configuration * */
/* ************************************* */
/* ======================= */
/* = config_start = */
/* ======================= */
static GcomprisProfile *profile_conf;
static GcomprisBoard *board_conf;
static void save_table (gpointer key,
gpointer value,
gpointer user_data)
{
gc_db_set_board_conf ( profile_conf,
board_conf,
(gchar *) key,
(gchar *) value);
}
static gboolean
conf_ok(GHashTable *table)
{
if (!table){
if (gcomprisBoard)
pause_board(FALSE);
return TRUE;
}
g_hash_table_foreach(table, (GHFunc) save_table, NULL);
if (gcomprisBoard){
GHashTable *config;
if (profile_conf)
config = gc_db_get_board_conf();
else
config = table;
gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode");
if (drag_mode_str && (g_ascii_strcasecmp (drag_mode_str, "NULL") != 0))
drag_mode = (gint ) g_ascii_strtod(drag_mode_str, NULL);
else
drag_mode = 0;
if (profile_conf)
g_hash_table_destroy(config);
gc_drag_change_mode(drag_mode);
scale_next_level();
pause_board(FALSE);
}
board_conf = NULL;
profile_conf = NULL;
return TRUE;
}
static void
config_start(GcomprisBoard *agcomprisBoard,
GcomprisProfile *aProfile)
{
board_conf = agcomprisBoard;
profile_conf = aProfile;
if (gcomprisBoard)
pause_board(TRUE);
gchar * label = g_strdup_printf(_("%s configuration\n for profile %s"),
agcomprisBoard->name,
aProfile? aProfile->name : "");
GcomprisBoardConf *bconf;
bconf = gc_board_config_window_display( label,
conf_ok);
g_free(label);
/* init the combo to previously saved value */
GHashTable *config = gc_db_get_conf( profile_conf, board_conf);
gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode");
gint drag_previous;
if (drag_mode_str && (strcmp (drag_mode_str, "NULL") != 0))
drag_previous = (gint ) g_ascii_strtod(drag_mode_str, NULL);
else
drag_previous = 0;
gc_board_config_combo_drag(bconf, drag_previous);
}
/* ======================= */
/* = config_stop = */
/* ======================= */
static void config_stop()
{
}