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