s2d_shape.c (6319B)
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_c.h" 18 #include "s2d_device_c.h" 19 #include "s2d_line_segments.h" 20 #include "s2d_shape_c.h" 21 22 #include <rsys/mem_allocator.h> 23 24 /******************************************************************************* 25 * Helper functions 26 ******************************************************************************/ 27 static void 28 shape_release(ref_T* ref) 29 { 30 struct s2d_shape* shape; 31 struct s2d_device* dev; 32 ASSERT(ref); 33 shape = CONTAINER_OF(ref, struct s2d_shape, ref); 34 dev = shape->dev; 35 36 /* The shape should not be attached */ 37 ASSERT(is_list_empty(&shape->scene_attachment)); 38 line_segments_ref_put(shape->lines); 39 flist_name_del(&dev->names, shape->id); 40 MEM_RM(dev->allocator, shape); 41 S2D(device_ref_put(dev)); 42 } 43 44 /******************************************************************************* 45 * Exported s2d_shape functions 46 ******************************************************************************/ 47 res_T 48 s2d_shape_create_line_segments 49 (struct s2d_device* dev, struct s2d_shape** out_shape) 50 { 51 struct s2d_shape* shape = NULL; 52 res_T res = RES_OK; 53 if(!dev || !out_shape) { 54 res = RES_BAD_ARG; 55 goto error; 56 } 57 58 shape = (struct s2d_shape*) 59 MEM_CALLOC(dev->allocator, 1, sizeof(struct s2d_shape)); 60 if(!shape) { 61 res = RES_MEM_ERR; 62 goto error; 63 } 64 list_init(&shape->scene_attachment); 65 S2D(device_ref_get(dev)); 66 shape->dev = dev; 67 ref_init(&shape->ref); 68 shape->id = flist_name_add(&dev->names); 69 shape->is_enabled = 1; 70 shape->flip_contour = 0; 71 72 res = line_segments_create(dev, &shape->lines); 73 if(res != RES_OK) goto error; 74 75 exit: 76 if(out_shape) *out_shape = shape; 77 return res; 78 error: 79 if(shape) { 80 S2D(shape_ref_put(shape)); 81 shape = NULL; 82 } 83 goto exit; 84 } 85 86 res_T 87 s2d_shape_ref_get(struct s2d_shape* shape) 88 { 89 if(!shape) return RES_BAD_ARG; 90 ref_get(&shape->ref); 91 return RES_OK; 92 } 93 94 res_T 95 s2d_shape_ref_put(struct s2d_shape* shape) 96 { 97 if(!shape) return RES_BAD_ARG; 98 ref_put(&shape->ref, shape_release); 99 return RES_OK; 100 } 101 102 res_T 103 s2d_shape_get_id(const struct s2d_shape* shape, unsigned* id) 104 { 105 if(!shape || !id) return RES_BAD_ARG; 106 *id = shape->id.index; 107 return RES_OK; 108 } 109 110 res_T 111 s2d_shape_enable(struct s2d_shape* shape, const char enable) 112 { 113 if(!shape) return RES_BAD_ARG; 114 shape->is_enabled = enable; 115 return RES_OK; 116 } 117 118 res_T 119 s2d_shape_is_enabled(const struct s2d_shape* shape, char* is_enabled) 120 { 121 if(!shape || !is_enabled) return RES_BAD_ARG; 122 *is_enabled = shape->is_enabled; 123 return RES_OK; 124 } 125 126 res_T 127 s2d_shape_is_attached(const struct s2d_shape* shape, char* is_attached) 128 { 129 if(!shape || !is_attached) return RES_BAD_ARG; 130 *is_attached = !is_list_empty(&shape->scene_attachment); 131 return RES_OK; 132 } 133 134 res_T 135 s2d_shape_flip_contour(struct s2d_shape* shape) 136 { 137 if(!shape) return RES_BAD_ARG; 138 shape->flip_contour ^= 1; 139 return RES_OK; 140 } 141 142 res_T 143 s2d_line_segments_setup_indexed_vertices 144 (struct s2d_shape* shape, 145 const unsigned nsegments, 146 void (*get_indices) 147 (const unsigned isegment, unsigned ids[2], void* ctx), 148 const unsigned nverts, 149 struct s2d_vertex_data attribs[], 150 const unsigned nattribs, 151 void* data) 152 { 153 if(!shape) return RES_BAD_ARG; 154 return line_segments_setup_indexed_vertices 155 (shape->lines, nsegments, get_indices, nverts, attribs, nattribs, data); 156 } 157 158 res_T 159 s2d_line_segments_copy(const struct s2d_shape* src, struct s2d_shape* dst) 160 { 161 if(!src || !dst) return RES_BAD_ARG; 162 if(src == dst) return RES_OK; 163 dst->flip_contour = src->flip_contour; 164 dst->is_enabled = src->is_enabled; 165 line_segments_copy_indexed_vertices(src->lines, dst->lines); 166 return RES_OK; 167 } 168 169 res_T 170 s2d_line_segments_get_vertices_count 171 (const struct s2d_shape* shape, unsigned* nverts) 172 { 173 if(!shape || !nverts) return RES_BAD_ARG; 174 *nverts = (unsigned)line_segments_get_nverts(shape->lines); 175 return RES_OK; 176 } 177 178 res_T 179 s2d_line_segments_get_vertex_attrib 180 (const struct s2d_shape* shape, 181 const unsigned ivert, 182 const enum s2d_attrib_usage usage, 183 struct s2d_attrib* attrib) 184 { 185 const float* data; 186 unsigned i, dim; 187 188 if(!shape 189 || (unsigned)usage >= S2D_ATTRIBS_COUNT__ 190 || !shape->lines->attribs[usage] 191 || !attrib 192 || ivert >= (unsigned)line_segments_get_nverts(shape->lines)) 193 return RES_BAD_ARG; 194 195 attrib->usage = usage; 196 attrib->type = shape->lines->attribs_type[usage]; 197 198 dim = s2d_type_get_dimension(attrib->type); 199 data = line_segments_get_attr(shape->lines, usage) + ivert * dim; 200 FOR_EACH(i, 0, dim) attrib->value[i] = data[i]; 201 return RES_OK; 202 } 203 204 res_T 205 s2d_line_segments_get_segments_count 206 (const struct s2d_shape* shape, unsigned* nsegments) 207 { 208 if(!shape || !nsegments) return RES_BAD_ARG; 209 *nsegments = (unsigned)line_segments_get_nsegments(shape->lines); 210 return RES_OK; 211 } 212 213 res_T 214 s2d_line_segments_get_segment_indices 215 (const struct s2d_shape* shape, 216 const unsigned isegment, 217 unsigned ids[2]) 218 { 219 const unsigned* data; 220 if(!shape 221 || !ids 222 || isegment >= (unsigned)line_segments_get_nsegments(shape->lines)) 223 return RES_BAD_ARG; 224 225 data = line_segments_get_ids(shape->lines) + isegment * 2/*#ids per segment*/; 226 ids[0] = data[0]; 227 ids[1] = data[1]; 228 return RES_OK; 229 } 230 231 res_T 232 s2d_line_segments_set_hit_filter_function 233 (struct s2d_shape* shape, 234 s2d_hit_filter_function_T func, 235 void* data) 236 { 237 if(!shape) return RES_BAD_ARG; 238 shape->lines->filter.func = func; 239 shape->lines->filter.data = data; 240 return RES_OK; 241 } 242 243 res_T 244 s2d_line_segments_get_hit_filter_data(struct s2d_shape* shape, void** data) 245 { 246 if(!shape || !data) return RES_BAD_ARG; 247 *data = shape->lines->filter.data; 248 return RES_OK; 249 } 250