ajwillia-ms pushed a commit to branch master.

http://git.enlightenment.org/tools/examples.git/commit/?id=fc7503113a18ff5da384fce24214dde7c17c7941

commit fc7503113a18ff5da384fce24214dde7c17c7941
Author: Andy Williams <a...@andywilliams.me>
Date:   Fri Dec 1 22:27:35 2017 +0000

    apps: Add first pass Game of Life :)
---
 apps/c/life/meson.build        |  13 ++++
 apps/c/life/src/life_board.c   | 162 +++++++++++++++++++++++++++++++++++++++++
 apps/c/life/src/life_main.c    |  90 +++++++++++++++++++++++
 apps/c/life/src/life_private.h |  25 +++++++
 apps/c/life/src/life_render.c  |  93 +++++++++++++++++++++++
 apps/c/life/src/meson.build    |  14 ++++
 6 files changed, 397 insertions(+)

diff --git a/apps/c/life/meson.build b/apps/c/life/meson.build
new file mode 100644
index 0000000..06c1dc7
--- /dev/null
+++ b/apps/c/life/meson.build
@@ -0,0 +1,13 @@
+project(
+  'efl-example-life', 'c',
+  version : '0.0.1',
+  default_options: [ 'c_std=gnu99', 'warning_level=2' ],
+  meson_version : '>= 0.38.0')
+
+eina = dependency('eina', version : '>=1.20.99')
+efl = dependency('efl-ui', version : '>=1.20.99')
+elm = dependency('elementary', version : '>=1.20.99')
+
+inc = include_directories('.')
+subdir('src')
+
diff --git a/apps/c/life/src/life_board.c b/apps/c/life/src/life_board.c
new file mode 100644
index 0000000..40884d4
--- /dev/null
+++ b/apps/c/life/src/life_board.c
@@ -0,0 +1,162 @@
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Elementary.h>
+#include <Efl_Ui.h>
+
+#include "life_private.h"
+
+static int gen = 0;
+
+int *life_board, *life_board_prev;
+static int *_life_board_1, *_life_board_2;
+static Efl_Loop_Timer *_life_timer;
+
+static void
+_life_tick(void *data, const Efl_Event *event EINA_UNUSED)
+{
+   Efl_Ui_Win *win = data;
+
+   life_board_nextgen();
+   life_render_refresh(win);
+}
+
+static void
+_life_cell_on(int x, int y)
+{
+   _life_board_1[life_render_index_for_position(x, y)] = 1;
+}
+
+static void
+_life_board_setup()
+{
+   // glide
+   _life_cell_on(16, 1);
+   _life_cell_on(17, 2);
+   _life_cell_on(18, 2);
+   _life_cell_on(16, 3);
+   _life_cell_on(17, 3);
+
+   // oscilate
+   _life_cell_on(22, 15);
+   _life_cell_on(23, 15);
+   _life_cell_on(24, 15);
+
+   // block
+   _life_cell_on(32, 15);
+   _life_cell_on(33, 15);
+   _life_cell_on(32, 16);
+   _life_cell_on(33, 16);
+}
+
+void
+life_board_init()
+{
+   _life_board_1 = calloc(1, sizeof(int) * LIFE_BOARD_WIDTH * 
LIFE_BOARD_HEIGHT);
+   _life_board_2 = calloc(1, sizeof(int) * LIFE_BOARD_WIDTH * 
LIFE_BOARD_HEIGHT);
+
+   _life_board_setup();
+
+   life_board = _life_board_1;
+   life_board_prev = _life_board_2;
+}
+
+void
+life_board_run(Efl_Ui_Win *win)
+{
+   _life_timer = efl_add(EFL_LOOP_TIMER_CLASS, NULL,
+                         efl_loop_timer_interval_set(efl_added, 0.1));
+
+   efl_event_callback_add(_life_timer, EFL_LOOP_TIMER_EVENT_TICK, _life_tick, 
win);
+}
+
+int
+life_board_sum_around(int x, int y)
+{
+   int sum = 0;
+   int i, max;
+
+   max = LIFE_BOARD_WIDTH * LIFE_BOARD_HEIGHT;
+
+   i = life_render_index_for_position(x - 1, (y - 1));
+   if (i >= 0)
+     sum += life_board[i];
+   i++;
+   if (i >= 0)
+     sum += life_board[i];
+   i++;
+   if (i >= 0)
+     sum += life_board[i];
+
+   i = life_render_index_for_position(x - 1, y);
+   if (i >= 0)
+     sum += life_board[i];
+   i += 2;
+   if (i < max)
+     sum += life_board[i];
+
+   i = life_render_index_for_position(x - 1, (y + 1));
+   if (i < max)
+     sum += life_board[i];
+   i++;
+   if (i < max)
+     sum += life_board[i];
+   i++;
+   if (i < max)
+     sum += life_board[i];
+
+   return sum;
+}
+
+void
+life_board_nextgen()
+{
+   int *work;
+   int x, y, i, n;
+   gen++;
+
+   if (life_board == _life_board_1)
+     work = _life_board_2;
+   else
+     work = _life_board_1;
+
+   for (y = 0; y < LIFE_BOARD_HEIGHT; y++)
+     for (x = 0; x < LIFE_BOARD_WIDTH; x++)
+       {
+          i = life_render_index_for_position(x, y);
+
+          n = life_board_sum_around(x, y);
+          if (life_board[i])
+            {
+               if (n > 3 || n < 2)
+                 work[i] = 0;
+               else
+                 work[i] = 1;
+            }
+          else
+            {
+               if (n == 3)
+                 work[i] = 1;
+               else
+                 work[i] = 0;
+            }
+       }
+
+   life_board_prev = life_board;
+   life_board = work;
+}
+
+void
+life_board_pause_toggle(Efl_Ui_Win *win)
+{
+   if (_life_timer)
+     {
+        efl_del(_life_timer);
+        _life_timer = NULL;
+     }
+   else
+     {
+        life_board_run(win);
+     }
+}
+
diff --git a/apps/c/life/src/life_main.c b/apps/c/life/src/life_main.c
new file mode 100644
index 0000000..63f97f8
--- /dev/null
+++ b/apps/c/life/src/life_main.c
@@ -0,0 +1,90 @@
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Elementary.h>
+#include <Efl_Ui.h>
+
+#include "life_private.h"
+
+static void
+_life_win_resize(void *data EINA_UNUSED, const Efl_Event *event)
+{
+   Efl_Ui_Win *win = event->object;
+
+   life_render_layout(win);
+}
+
+static void
+_life_win_touch(void *data EINA_UNUSED, const Efl_Event *event)
+{
+   int cellx, celly, i;
+   Efl_Input_Pointer *ev;
+   Efl_Ui_Win *win;
+   Eina_Position2D position;
+
+   ev = event->info;
+   win = event->object;
+
+   position = efl_input_pointer_position_get(ev);
+   life_render_cell_for_coords(win, position, &cellx, &celly);
+
+   i = life_render_index_for_position(cellx, celly);
+   life_board[i] = !life_board[i];
+   life_render_cell(win, cellx, celly);
+}
+
+static void
+_life_win_key_down(void *data EINA_UNUSED, const Efl_Event *event)
+{
+   Efl_Input_Key *ev;
+   Efl_Ui_Win *win;
+
+   ev = event->info;
+   win = event->object;
+
+   if (!strcmp(efl_input_key_get(ev), "space"))
+     life_board_pause_toggle(win);
+}
+
+static Evas_Object *
+_life_win_setup(void)
+{
+   Efl_Ui_Win *win;
+   Evas_Coord w;
+   Evas_Coord h;
+
+   win = efl_add(EFL_UI_WIN_CLASS, NULL,
+                 efl_ui_win_type_set(efl_added, EFL_UI_WIN_BASIC),
+                 efl_text_set(efl_added, "EFL Life"),
+                 efl_ui_win_autodel_set(efl_added, EINA_TRUE));
+   if (!win) return NULL;
+
+   // TODO
+   elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+   w = 10 * LIFE_BOARD_WIDTH * efl_ui_scale_get(win);
+   h = 10 * LIFE_BOARD_HEIGHT * efl_ui_scale_get(win);
+
+   life_board_init();
+   life_render_init(win);
+   life_render_refresh(win);
+
+   efl_event_callback_add(win, EFL_GFX_EVENT_RESIZE, _life_win_resize, NULL);
+   efl_event_callback_add(win, EFL_EVENT_POINTER_DOWN, _life_win_touch, NULL);
+   efl_event_callback_add(win, EFL_EVENT_KEY_DOWN, _life_win_key_down, NULL);
+
+   efl_gfx_size_set(win, EINA_SIZE2D(w, h));
+
+   return win;
+}
+
+EAPI_MAIN void
+efl_main(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED)
+{
+   Efl_Ui_Win *win;
+
+   if (!(win = _life_win_setup()))
+     efl_exit(1);
+
+   life_board_run(win);
+}
+EFL_MAIN()
diff --git a/apps/c/life/src/life_private.h b/apps/c/life/src/life_private.h
new file mode 100644
index 0000000..724c76b
--- /dev/null
+++ b/apps/c/life/src/life_private.h
@@ -0,0 +1,25 @@
+#ifndef LIFE_PRIVATE_H_
+# define LIFE_PRIVATE_H_
+
+#include <Elementary.h>
+#include <Efl_Ui.h>
+
+#define LIFE_BOARD_WIDTH 47
+#define LIFE_BOARD_HEIGHT 31
+
+extern int *life_board, *life_board_prev;
+
+void life_board_init(void);
+
+void life_board_nextgen(void);
+void life_board_run(Efl_Ui_Win *win);
+void life_board_pause_toggle(Efl_Ui_Win *win);
+
+void life_render_init(Efl_Ui_Win *win);
+void life_render_cell_for_coords(Efl_Ui_Win *win, Eina_Position2D coord, int 
*x, int *y);
+int life_render_index_for_position(int x, int y);
+void life_render_layout(Efl_Ui_Win *win);
+void life_render_cell(Efl_Ui_Win *win, int x, int y);
+void life_render_refresh(Efl_Ui_Win *win);
+
+#endif
diff --git a/apps/c/life/src/life_render.c b/apps/c/life/src/life_render.c
new file mode 100644
index 0000000..9fd2da8
--- /dev/null
+++ b/apps/c/life/src/life_render.c
@@ -0,0 +1,93 @@
+#define EFL_EO_API_SUPPORT 1
+#define EFL_BETA_API_SUPPORT 1
+
+#include <Elementary.h>
+#include <Efl_Ui.h>
+
+#include "life_private.h"
+
+Efl_Canvas_Rectangle **_life_cells;
+
+void
+life_render_init(Efl_Ui_Win *win)
+{
+   int x, y;
+
+   _life_cells = calloc(1, sizeof(Efl_Canvas_Rectangle *) * LIFE_BOARD_WIDTH * 
LIFE_BOARD_HEIGHT);
+
+   for (y = 0; y < LIFE_BOARD_HEIGHT; y++)
+     for (x = 0; x < LIFE_BOARD_WIDTH; x++)
+       efl_add(EFL_CANVAS_RECTANGLE_CLASS, win,
+               _life_cells[life_render_index_for_position(x, y)] = efl_added);
+
+   life_render_layout(win);
+}
+
+void
+life_render_cell_for_coords(Efl_Ui_Win *win, Eina_Position2D coord,
+                            int *x, int *y)
+{
+   Eina_Size2D size;
+
+   size = efl_gfx_size_get(win);
+
+   if (x)
+     *x = coord.x / ((double) size.w / LIFE_BOARD_WIDTH);
+   if (y)
+     *y = coord.y / ((double) size.h / LIFE_BOARD_HEIGHT);
+}
+
+int
+life_render_index_for_position(int x, int y)
+{
+   return y * LIFE_BOARD_WIDTH + x;
+}
+
+void
+life_render_layout(Efl_Ui_Win *win)
+{
+   Eina_Size2D size;
+   double cw, ch;
+   Evas_Object *rect;
+   int x, y;
+
+   size = efl_gfx_size_get(win);
+   cw = (double) size.w / LIFE_BOARD_WIDTH;
+   ch = (double) size.h / LIFE_BOARD_HEIGHT;
+
+   for (y = 0; y < LIFE_BOARD_HEIGHT; y++)
+     for (x = 0; x < LIFE_BOARD_WIDTH; x++)
+       {
+          rect = _life_cells[life_render_index_for_position(x, y)];
+
+          // the little +1 here will avoid tearing as we layout non-multiple 
sizes
+          efl_gfx_size_set(rect, EINA_SIZE2D(cw + 1, ch + 1));
+          efl_gfx_position_set(rect, EINA_POSITION2D(x * cw, y * ch));
+       }
+}
+
+void
+life_render_cell(Efl_Ui_Win *win EINA_UNUSED, int x, int y)
+{
+   Evas_Object *rect;
+   int i;
+
+   i = life_render_index_for_position(x, y);
+   rect = _life_cells[i];
+
+   if (life_board[i])
+     efl_gfx_color_set(rect, 0, 0, 0, 255);
+   else
+     efl_gfx_color_set(rect, 255, 255, 255, 255);
+}
+
+void
+life_render_refresh(Efl_Ui_Win *win EINA_UNUSED)
+{
+   int x, y;
+
+   for (y = 0; y < LIFE_BOARD_HEIGHT; y++)
+     for (x = 0; x < LIFE_BOARD_WIDTH; x++)
+       life_render_cell(win, x, y);
+}
+
diff --git a/apps/c/life/src/meson.build b/apps/c/life/src/meson.build
new file mode 100644
index 0000000..fc95182
--- /dev/null
+++ b/apps/c/life/src/meson.build
@@ -0,0 +1,14 @@
+src = files([
+  'life_render.c',
+  'life_board.c',
+  'life_main.c',
+])
+
+deps = [eina, efl, elm]
+
+executable('efl_example_life', src,
+  dependencies : deps,
+  include_directories : inc,
+  install : true
+)
+

-- 


Reply via email to