@@ -264,4 +264,172 @@ namespace pg
264264
265265 changed = true ;
266266 }
267+
268+ // ---------------------------------------------------------------------------
269+ // RoundedRect2DObject serialize / deserialize
270+ // ---------------------------------------------------------------------------
271+
272+ template <>
273+ void serialize (Archive& archive, const RoundedRect2DObject& value)
274+ {
275+ LOG_THIS (DOM);
276+
277+ archive.startSerialization (RoundedRect2DObject::getType ());
278+
279+ serialize (archive, " cornerRadius" , value.cornerRadius );
280+ serialize (archive, " colors" , value.colors );
281+
282+ archive.endSerialization ();
283+ }
284+
285+ template <>
286+ RoundedRect2DObject deserialize (const UnserializedObject& serializedString)
287+ {
288+ LOG_THIS (DOM);
289+
290+ if (serializedString.isNull ())
291+ {
292+ LOG_ERROR (DOM, " Element is null" );
293+ return RoundedRect2DObject{};
294+ }
295+
296+ LOG_INFO (DOM, " Deserializing a RoundedRect2DObject" );
297+
298+ auto cornerRadius = deserialize<float >(serializedString[" cornerRadius" ]);
299+ auto colors = deserialize<constant::Vector4D>(serializedString[" colors" ]);
300+
301+ return RoundedRect2DObject{cornerRadius, colors};
302+ }
303+
304+ // ---------------------------------------------------------------------------
305+ // RoundedRect2DObjectSystem
306+ // ---------------------------------------------------------------------------
307+
308+ void RoundedRect2DObjectSystem::init ()
309+ {
310+ LOG_THIS_MEMBER (DOM);
311+
312+ Material mat;
313+
314+ mat.shader = masterRenderer->getShader (" RoundedRect" );
315+
316+ mat.nbTextures = 0 ;
317+
318+ mat.uniformMap .emplace (" sWidth" , " ScreenWidth" );
319+ mat.uniformMap .emplace (" sHeight" , " ScreenHeight" );
320+
321+ // Instance layout: worldPos(3), size(2), rotation(1), color(4), cornerRadius(1) = 11 floats
322+ mat.setSimpleMesh ({3 , 2 , 1 , 4 , 1 });
323+
324+ materialId = masterRenderer->registerMaterial (mat);
325+
326+ auto group = registerGroup<PositionComponent, RoundedRect2DObject>();
327+
328+ group->addOnGroup ([this ](EntityRef entity) {
329+ LOG_MILE (" Rounded Rect 2D System" , " Add entity " << entity->id << " to rounded rect group!" );
330+ updateQueue.push (entity->id );
331+ changed = true ;
332+ });
333+
334+ group->removeOfGroup ([this ](EntitySystem* ecsRef, _unique_id id) {
335+ LOG_MILE (" Rounded Rect 2D System" , " Remove entity " << id << " from rounded rect group!" );
336+ auto entity = ecsRef->getEntity (id);
337+ ecsRef->detach <RoundedRect2DRenderCall>(entity);
338+ changed = true ;
339+ });
340+ }
341+
342+ void RoundedRect2DObjectSystem::execute ()
343+ {
344+ if (not changed)
345+ return ;
346+
347+ while (not updateQueue.empty ())
348+ {
349+ auto entityId = updateQueue.front ();
350+
351+ auto entity = ecsRef->getEntity (entityId);
352+
353+ if (not entity)
354+ {
355+ updateQueue.pop ();
356+ continue ;
357+ }
358+
359+ auto ui = entity->get <PositionComponent>();
360+ auto obj = entity->get <RoundedRect2DObject>();
361+
362+ if (entity->has <RoundedRect2DRenderCall>())
363+ {
364+ entity->get <RoundedRect2DRenderCall>()->call = createRenderCall (ui, obj);
365+ }
366+ else
367+ {
368+ ecsRef->_attach <RoundedRect2DRenderCall>(entity, createRenderCall (ui, obj));
369+ }
370+
371+ updateQueue.pop ();
372+ }
373+
374+ renderCallList.clear ();
375+
376+ const auto & renderCallView = view<RoundedRect2DRenderCall>();
377+
378+ renderCallList.reserve (renderCallView.nbComponents ());
379+
380+ for (const auto & renderCall : renderCallView)
381+ {
382+ renderCallList.push_back (renderCall->call );
383+ }
384+
385+ finishChanges ();
386+ }
387+
388+ RenderCall RoundedRect2DObjectSystem::createRenderCall (CompRef<PositionComponent> ui, CompRef<RoundedRect2DObject> obj)
389+ {
390+ LOG_THIS_MEMBER (DOM);
391+
392+ RenderCall call;
393+
394+ call.processPositionComponent (ui);
395+
396+ call.setOpacity (OpacityType::Additive);
397+
398+ call.setRenderStage (renderStage);
399+
400+ call.setMaterial (materialId);
401+
402+ call.setViewport (obj->viewport );
403+
404+ // 11 floats: x, y, z, width, height, rotation, r, g, b, a, cornerRadius
405+ call.data .resize (11 );
406+
407+ call.data [0 ] = ui->x ;
408+ call.data [1 ] = ui->y ;
409+ call.data [2 ] = ui->z ;
410+ call.data [3 ] = ui->width ;
411+ call.data [4 ] = ui->height ;
412+ call.data [5 ] = ui->rotation ;
413+ call.data [6 ] = obj->colors .x ;
414+ call.data [7 ] = obj->colors .y ;
415+ call.data [8 ] = obj->colors .z ;
416+ call.data [9 ] = obj->colors .w ;
417+ call.data [10 ] = obj->cornerRadius ;
418+
419+ return call;
420+ }
421+
422+ void RoundedRect2DObjectSystem::onEvent (const EntityChangedEvent& event)
423+ {
424+ LOG_THIS_MEMBER (DOM);
425+
426+ auto entity = ecsRef->getEntity (event.id );
427+
428+ if (not entity or not entity->has <RoundedRect2DObject>())
429+ return ;
430+
431+ updateQueue.push (event.id );
432+
433+ changed = true ;
434+ }
267435}
0 commit comments