Commit 92b0ed04 authored by Vivien Kraus's avatar Vivien Kraus
Browse files

Include the layout engine

parent 0b492099
Pipeline #96755 passed with stages
in 3 minutes and 47 seconds
......@@ -64,10 +64,13 @@ AS_IF([test "x$with_gobject" != "xno"], [
])
])
AM_CONDITIONAL([WITH_GOBJECT], [test "x$WITH_GOBJECT" != "xno"])
AC_SEARCH_LIBS([atan2], [m])
AC_SEARCH_LIBS([sin], [m])
AC_SEARCH_LIBS([cos], [m])
# Checks for header files.
AC_HEADER_STDBOOL
AC_CHECK_HEADERS_ONCE([stdint.h limits.h sysexits.h])
AC_CHECK_HEADERS_ONCE([stdint.h limits.h sysexits.h math.h tgmath.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
......
......@@ -48,6 +48,7 @@ LIBTAROT_VERSION_INFO = 0:0:0
%reldir%/parser/libtarot-parser.la \
%reldir%/cli/libtarot-cli.la \
%reldir%/xml/libtarot-xml.la \
%reldir%/layout/libtarot-layout.la \
lib-library/libgnulibrary.la
if WITH_GOBJECT
......@@ -175,3 +176,4 @@ include %reldir%/lexer/Makefile.am
include %reldir%/parser/Makefile.am
include %reldir%/cli/Makefile.am
include %reldir%/xml/Makefile.am
include %reldir%/layout/Makefile.am
# Makefile.am
#
# Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
#
# 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
# <http://www.gnu.org/licenses/>.
# This library defines the placement of cards on a scene in order to
# render them. The goal is to have a simple function that takes as
# input the cards of our hand, the cards of the hands of our
# opponents, the cards of the trick, and return the positions, scales
# and angles of all cards.
noinst_LTLIBRARIES += %reldir%/libtarot-layout.la
tarotinclude_HEADERS += %reldir%/tarot/layout.h
EXTRA_DIST +=
%canon_reldir%_libtarot_layout_la_SOURCES = \
%reldir%/layout.c \
%reldir%/tarot/layout.h \
%reldir%/tarot/layout_private.h \
%reldir%/tarot/layout_private_impl.h
%canon_reldir%_libtarot_layout_la_CFLAGS = \
$(AM_CFLAGS)
%canon_reldir%_libtarot_layout_la_CXXFLAGS = \
$(AM_CXXFLAGS)
%canon_reldir%_libtarot_layout_la_CPPFLAGS = \
$(AM_CPPFLAGS)
%canon_reldir%_libtarot_layout_la_LDFLAGS = \
-no-undefined \
$(AM_LDADD)
AM_CPPFLAGS += \
-I $(srcdir)/%reldir% -I %reldir%
INDENTED += \
$(%canon_reldir%_libtarot_layout_la_SOURCES)
LIBTAROT_LAYOUT_LA = %reldir%/libtarot-layout.la
/**
* file tarot/layout.c
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <tarot/layout_private.h>
size_t
tarot_layout_position (double view_w, double view_h, double card_w,
double card_h, size_t n_my_cards, size_t n_adversaries,
const size_t * n_adv_cards, size_t n_center,
size_t max_dst, TarotPosition * dst)
{
return layout_position (view_w, view_h, card_w, card_h, n_my_cards,
n_adversaries, n_adv_cards, n_center, max_dst, dst);
}
#include <tarot/layout_private_impl.h>
/**
* file tarot/layout.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef H_TAROT_LAYOUT_INCLUDED
#define H_TAROT_LAYOUT_INCLUDED
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
struct TarotPosition
{
double x;
double y;
double z;
double scale;
double angle;
};
typedef struct TarotPosition TarotPosition;
/**
* tarot_layout_position:
*
* Compute the positions of the cards, in the following order: the
* hand of the main player, then the hands of the other players,
* then the trick, then the cards in the center. This is not the
* rendering order. The rendering order is increasing with the
* value of the z index.
*
* @view_w: the width of the view
* @view_h: the height of the view
* @card_w: the width of each card
* @card_h: the height of each card
* @n_my_cards: the number of cards in my hand
* @n_adversaries: the number of adversaries
* @n_adv_cards: (array length=n_adversaries): the number of cards
* for each adversary
* @n_center: the number of cards in the center (dog / discard, handful)
* @max_dst: the number of positions
* @dst: (array length=max_dst): where to store the positions
* Returns: the number of cards to position (n_my_cards + sum
* (n_adv_cards) + n_adversaries + 1 + n_center)
*/
size_t tarot_layout_position (double view_w, double view_h, double card_w,
double card_h, size_t n_my_cards,
size_t n_adversaries,
const size_t * n_adv_cards, size_t n_center,
size_t max_dst, TarotPosition * dst);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* not H_TAROT_LAYOUT_INCLUDED */
/**
* file tarot/layout_private.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef H_TAROT_LAYOUT_PRIVATE_INCLUDED
#define H_TAROT_LAYOUT_PRIVATE_INCLUDED
#ifdef HAVE_MATH_H
#include <math.h>
#endif /* HAVE_MATH_H */
#ifdef HAVE_TGMATH_H
#include <tgmath.h>
#endif /* HAVE_TGMATH_H */
#define ALPHA 0.25
#include <tarot/layout.h>
typedef struct
{
double view_w;
double view_h;
double card_w;
double card_h;
double main_hand_radius;
double main_hand_angle;
double main_hand_scale;
double foreground_hand_margin;
double foreground_hand_scale;
double adv_hand_scale;
double trick_scale;
double foreground_scale;
} TarotLayout;
static void compute_layout (TarotLayout * layout);
static void compute_position_main (const TarotLayout * layout, double i,
double n, TarotPosition * position);
static void compute_position_adv (const TarotLayout * layout, double i_player,
double n_player, double i_card,
double n_cards, TarotPosition * position);
static void compute_position_trick (const TarotLayout * layout, double i,
double n, TarotPosition * position);
static void compute_position_foreground (const TarotLayout * layout, double i,
double n, TarotPosition * position);
static size_t compute_positions_main (const TarotLayout * layout, size_t n,
size_t max, TarotPosition * position);
static size_t compute_positions_adversary (const TarotLayout * layout,
double i_player, double n_player,
size_t n_cards, size_t max,
TarotPosition * position);
static size_t compute_positions_adversaries (const TarotLayout * layout,
size_t n_adversaries,
const size_t * n_cards,
size_t max,
TarotPosition * position);
static size_t compute_positions_trick (const TarotLayout * layout,
size_t n_adversaries, size_t max,
TarotPosition * position);
static size_t compute_positions_foreground (const TarotLayout * layout,
size_t n, size_t max,
TarotPosition * position);
static size_t compute_positions (const TarotLayout * layout, size_t n_main,
size_t n_adversaries,
const size_t * n_adv_cards,
size_t n_foreground, size_t max_dst,
TarotPosition * dst);
static size_t layout_position (double view_w, double view_h, double card_w,
double card_h, size_t n_my_cards,
size_t n_adversaries,
const size_t * n_adv_cards, size_t n_center,
size_t max_dst, TarotPosition * dst);
#endif /* not H_TAROT_LAYOUT_PRIVATE_INCLUDED */
/**
* file tarot/layout_private_impl.h
*
* Copyright (C) 2018 Vivien Kraus <vivien@planete-kraus.eu>
*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef H_TAROT_LAYOUT_PRIVATE_IMPL_INCLUDED
#define H_TAROT_LAYOUT_PRIVATE_IMPL_INCLUDED
#include <tarot/layout_private.h>
#define MINI(a, b) ((a) < (b) ? (a) : (b))
#define MAXI(a, b) ((a) > (b) ? (a) : (b))
static inline void
compute_layout (TarotLayout * layout)
{
const double alphah = ALPHA * MINI (layout->view_h, layout->view_w);
const double R =
(layout->view_w * layout->view_w + alphah * alphah) / (4 * alphah);
const double main_extension = atan2 (layout->view_w, 2 * R - alphah);
const double card_ratio = layout->card_w / layout->card_h;
const double main_card_h = MINI (layout->view_h / 2, layout->view_w / 2);
const double main_card_w = card_ratio * main_card_h;
const double main_margin = atan2 (main_card_w / 2, R);
const double main_angle = main_extension - main_margin;
const double foreground_card_h_wide = layout->view_h / 2;
const double foreground_card_w_tall = layout->view_w / 2;
const double foreground_card_w_wide = foreground_card_h_wide * card_ratio;
const double foreground_card_w =
MINI (foreground_card_w_tall, foreground_card_w_wide);
const double foreground_margin = foreground_card_w / 2;
const double main_scale = main_card_w / layout->card_w;
const double adv_card_w = foreground_card_w / 6;
const double adv_scale = adv_card_w / layout->card_w;
const double trick_card_w = foreground_card_w / 4;
const double trick_scale = trick_card_w / layout->card_w;
const double foreground_scale = foreground_card_w / layout->card_w;
layout->main_hand_radius = R;
layout->main_hand_angle = main_angle;
layout->foreground_hand_margin = foreground_margin;
layout->main_hand_scale = main_scale;
layout->adv_hand_scale = adv_scale;
layout->trick_scale = trick_scale;
layout->foreground_scale = foreground_scale;
}
static inline void
compute_position_main (const TarotLayout * layout, double i, double n,
TarotPosition * position)
{
const int pointed = 0;
const int selected = 0;
const float pc = (i + 1.0) / (n + 1.0);
const float theta = -(2 * pc - 1) * layout->main_hand_angle;
const float sc = layout->main_hand_scale;
const float r_selected = layout->main_hand_radius - (layout->view_h / 4);
const float r_not_selected = r_selected - (layout->view_h / 8);
const float r = (selected ? r_selected : r_not_selected);
const float x_center = -r * sin (theta);
const float y_center = r * cos (theta) - layout->main_hand_radius;
position->angle = theta;
position->x = x_center;
position->y = y_center;
position->z = 2 + pc;
position->scale = sc;
if (pointed)
{
position->z = 3;
}
}
static inline void
compute_position_adv (const TarotLayout * layout, double i_player,
double n_players, double i_card, double n_cards,
TarotPosition * position)
{
const int pointed = 0;
const int selected = 0;
const double player_pc = (i_player + 1.0) / (n_players + 1.0);
const double player_angle = M_PI * (1 - player_pc);
const double x_player = layout->view_w / 2 * cos (player_angle);
const double y_player = layout->view_h / 2 * sin (player_angle);
const double pc = (i_card + 1.0) / (n_cards + 1.0);
const double card_angle = M_PI * pc;
const double absolute_angle = player_angle - card_angle;
const double card_h = layout->adv_hand_scale * layout->card_h;
const double dx = (card_h / 2) * sin (absolute_angle);
const double dy = -(card_h / 2) * cos (absolute_angle);
position->x = x_player + dx;
position->y = y_player + dy;
position->z = player_pc * pc - 1;
position->angle = absolute_angle;
position->scale = layout->adv_hand_scale;
if (selected)
{
position->scale *= 1.25;
}
if (pointed)
{
position->z = 3;
}
}
/* n is the number of adversaries, not the number of cards in the
trick */
static inline void
compute_position_trick (const TarotLayout * layout, double i, double n,
TarotPosition * position)
{
const int selected = 0;
const int pointed = 0;
const double y_center = layout->view_h / 4;
const double adv_pc = i / (n + 1.0);
const double angle_adv = M_PI * (1 - adv_pc);
const double angle_main = -M_PI / 2;
const double theta = (i == 0 ? angle_main : angle_adv);
const double radius_w = layout->view_w / 6;
const double card_h = layout->trick_scale * layout->card_h;
const double radius_h = card_h;
position->x = radius_w * cos (theta);
position->y = radius_h * sin (theta) + y_center;
position->z = adv_pc;
position->angle = 0;
position->scale = layout->trick_scale;
if (selected)
{
position->scale *= 1.25;
}
if (pointed)
{
position->z = 3;
}
}
static inline void
compute_position_foreground (const TarotLayout * layout, double i, double n,
TarotPosition * position)
{
const int selected = 0;
const int pointed = 0;
const float margin = layout->foreground_hand_margin;
const float pc = (i + 1.0) / (n + 1.0);
position->x = (2 * pc - 1) * (layout->view_w - margin);
position->y = 0;
position->z = pc + 1;
position->angle = 0;
position->scale = layout->foreground_scale;
if (selected)
{
position->scale *= 1.25;
}
if (pointed)
{
position->z = 3;
}
}
static inline size_t
compute_positions_main (const TarotLayout * layout, size_t n, size_t max,
TarotPosition * position)
{
size_t i_int;
double i_flt;
double n_flt = n;
for (i_int = 0, i_flt = 0.0; i_int < n && i_int < max; i_int++, i_flt++)
{
compute_position_main (layout, i_flt, n_flt, &(position[i_int]));
}
return i_int;
}
static inline size_t
compute_positions_adversary (const TarotLayout * layout, double i_player,
double n_players, size_t n_cards, size_t max,
TarotPosition * position)
{
size_t i_int;
double i_flt;
double n_flt = n_cards;
for (i_int = 0, i_flt = 0.0; i_int < n_cards && i_int < max;
i_int++, i_flt++)
{
compute_position_adv (layout, i_player, n_players, i_flt, n_flt,
&(position[i_int]));
}
return i_int;
}
static inline size_t
compute_positions_adversaries (const TarotLayout * layout,
size_t n_adversaries, const size_t * n_cards,
size_t max, TarotPosition * position)
{
size_t i_int;
double i_flt;
double n_flt = n_adversaries;
size_t ret = 0;
for (i_int = 0, i_flt = 0.0; i_int < n_adversaries && ret < max;
i_int++, i_flt++)
{
ret +=
compute_positions_adversary (layout, i_flt, n_flt, n_cards[i_int],
max - ret, &(position[ret]));
}
return ret;
}
static inline size_t
compute_positions_trick (const TarotLayout * layout, size_t n_adversaries,
size_t max, TarotPosition * position)
{
size_t i_int;
double i_flt;
double n_flt = n_adversaries;
for (i_int = 0, i_flt = 0.0; i_int < n_adversaries && i_int < max;
i_int++, i_flt++)
{
compute_position_trick (layout, i_flt, n_flt, &(position[i_int]));
}
return i_int;
}
static inline size_t
compute_positions_foreground (const TarotLayout * layout, size_t n,
size_t max, TarotPosition * position)
{
size_t i_int;
double i_flt;
double n_flt = n;
for (i_int = 0, i_flt = 0.0; i_int < n && i_int < max; i_int++, i_flt++)
{
compute_position_foreground (layout, i_flt, n_flt, &(position[i_int]));
}
return i_int;
}
static inline size_t
compute_positions (const TarotLayout * layout, size_t n_main,
size_t n_adversaries, const size_t * n_adv_cards,
size_t n_foreground, size_t max, TarotPosition * dst)
{
size_t ret = 0;
ret += compute_positions_main (layout, n_main, max - ret, &(dst[ret]));
ret +=
compute_positions_adversaries (layout, n_adversaries, n_adv_cards,
max - ret, &(dst[ret]));
ret +=
compute_positions_trick (layout, n_adversaries, max - ret, &(dst[ret]));
ret +=
compute_positions_foreground (layout, n_foreground, max - ret,
&(dst[ret]));
return ret;
}
static inline size_t
layout_position (double view_w, double view_h, double card_w, double card_h,
size_t n_my_cards, size_t n_adversaries,
const size_t * n_adv_cards, size_t n_center, size_t max_dst,
TarotPosition * dst)
{
TarotLayout layout;
layout.view_w = view_w;
layout.view_h = view_h;
layout.card_w = card_w;
layout.card_h = card_h;
compute_layout (&layout);
return compute_positions (&layout, n_my_cards, n_adversaries, n_adv_cards,
n_center, max_dst, dst);
}
#endif /* not H_TAROT_LAYOUT_PRIVATE_IMPL_INCLUDED */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment