star-2d

Contour structuring for efficient 2D geometric queries
git clone git://git.meso-star.fr/star-2d.git
Log | Files | Refs | README | LICENSE

s2d_scene.c (4804B)


      1 /* Copyright (C) 2016-2021, 2023 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "s2d.h"
     17 #include "s2d_device_c.h"
     18 #include "s2d_scene_c.h"
     19 #include "s2d_scene_view_c.h"
     20 #include "s2d_shape_c.h"
     21 
     22 #include <rsys/list.h>
     23 #include <rsys/mem_allocator.h>
     24 
     25 /*******************************************************************************
     26  * Helper functions
     27  ******************************************************************************/
     28 static void
     29 scene_release(ref_T* ref)
     30 {
     31   struct s2d_scene* scn;
     32   struct s2d_device* dev;
     33   struct list_node* node;
     34   struct list_node* tmp;
     35 
     36   ASSERT(ref);
     37   scn = CONTAINER_OF(ref, struct s2d_scene, ref);
     38   dev = scn->dev;
     39 
     40   LIST_FOR_EACH_SAFE(node, tmp, &scn->scnviews) {
     41     scene_view_destroy(CONTAINER_OF(node, struct s2d_scene_view, node));
     42   }
     43   S2D(scene_clear(scn));
     44   htable_shape_release(&scn->shapes);
     45   MEM_RM(dev->allocator, scn);
     46   S2D(device_ref_put(dev));
     47 }
     48 
     49 /*******************************************************************************
     50  * Exported s2d_scene functions
     51  ******************************************************************************/
     52 res_T
     53 s2d_scene_create(struct s2d_device* dev, struct s2d_scene** out_scn)
     54 {
     55   struct s2d_scene* scn = NULL;
     56   res_T res = RES_OK;
     57 
     58   if(!dev || !out_scn) {
     59     res = RES_BAD_ARG;
     60     goto error;
     61   }
     62 
     63   scn = (struct s2d_scene*)MEM_CALLOC
     64     (dev->allocator, 1, sizeof(struct s2d_scene));
     65   if(!scn) {
     66     res = RES_MEM_ERR;
     67     goto error;
     68   }
     69   htable_shape_init(dev->allocator, &scn->shapes);
     70   SIG_INIT(&scn->sig_shape_detach);
     71   list_init(&scn->scnviews);
     72   ref_init(&scn->ref);
     73   S2D(device_ref_get(dev));
     74   scn->dev = dev;
     75 
     76 exit:
     77   if(out_scn) *out_scn = scn;
     78   return res;
     79 error:
     80   if(scn) {
     81     S2D(scene_ref_put(scn));
     82     scn = NULL;
     83   }
     84   goto exit;
     85 }
     86 
     87 res_T
     88 s2d_scene_ref_get(struct s2d_scene* scn)
     89 {
     90   if(!scn) return RES_BAD_ARG;
     91   ref_get(&scn->ref);
     92   return RES_OK;
     93 }
     94 
     95 res_T
     96 s2d_scene_ref_put(struct s2d_scene* scn)
     97 {
     98   if(!scn) return RES_BAD_ARG;
     99   ref_put(&scn->ref, scene_release);
    100   return RES_OK;
    101 }
    102 
    103 res_T
    104 s2d_scene_attach_shape(struct s2d_scene* scn, struct s2d_shape* shape)
    105 {
    106   unsigned shape_id;
    107   res_T res = RES_OK;
    108 
    109   if(!scn || !shape) {
    110     return RES_BAD_ARG;
    111   }
    112 
    113   S2D(shape_get_id(shape, &shape_id));
    114   if(htable_shape_find(&scn->shapes, &shape_id) != NULL) {
    115     log_warning(scn->dev,
    116       "%s: the shape is already attached to the scene.\n", FUNC_NAME);
    117     return RES_OK;
    118   }
    119 
    120   res = htable_shape_set(&scn->shapes, &shape_id, &shape);
    121   if(res != RES_OK) {
    122     log_error(scn->dev,
    123       "%s: cannot attach the shape to the scene.\n", FUNC_NAME);
    124     return RES_OK;
    125   }
    126   S2D(shape_ref_get(shape));
    127   return RES_OK;
    128 }
    129 
    130 res_T
    131 s2d_scene_detach_shape(struct s2d_scene* scn, struct s2d_shape* shape)
    132 {
    133   size_t n;
    134   unsigned shape_id;
    135 
    136   if(!scn || !shape) return RES_BAD_ARG;
    137 
    138   S2D(shape_get_id(shape, &shape_id));
    139   if(htable_shape_find(&scn->shapes, &shape_id) == NULL) {
    140     log_error(scn->dev,
    141       "%s: the shape is not attached to the scene.\n", FUNC_NAME);
    142     return RES_BAD_ARG;
    143   }
    144 
    145   n = htable_shape_erase(&scn->shapes, &shape_id);
    146   ASSERT(n == 1); (void)n;
    147 
    148   SIG_BROADCAST(&scn->sig_shape_detach, scene_shape_cb_T, ARG2(scn, shape));
    149 
    150   S2D(shape_ref_put(shape));
    151   return RES_OK;
    152 }
    153 
    154 res_T
    155 s2d_scene_clear(struct s2d_scene* scn)
    156 {
    157   struct htable_shape_iterator it, end;
    158 
    159   if(!scn) return RES_BAD_ARG;
    160 
    161   htable_shape_begin(&scn->shapes, &it);
    162   htable_shape_end(&scn->shapes, &end);
    163   while(!htable_shape_iterator_eq(&it, &end)) {
    164     struct s2d_shape** pshape = htable_shape_iterator_data_get(&it);
    165     struct s2d_shape* shape = *pshape;
    166     SIG_BROADCAST(&scn->sig_shape_detach, scene_shape_cb_T, ARG2(scn, shape));
    167     S2D(shape_ref_put(shape));
    168     htable_shape_iterator_next(&it);
    169   }
    170   htable_shape_clear(&scn->shapes);
    171 
    172   return RES_OK;
    173 }
    174 
    175 res_T
    176 s2d_scene_get_device(struct s2d_scene* scn, struct s2d_device** dev)
    177 {
    178   if(!scn || !dev) return RES_BAD_ARG;
    179   *dev = scn->dev;
    180   return RES_OK;
    181 }
    182 
    183 res_T
    184 s2d_scene_get_shapes_count(struct s2d_scene* scn, size_t* nshapes)
    185 {
    186   if(!scn || !nshapes) return RES_BAD_ARG;
    187   *nshapes = htable_shape_size_get(&scn->shapes);
    188   return RES_OK;
    189 }
    190