Location>code7788 >text

A general C++ ECS system implementation (event conditional action system)

Popularity:878 ℃/2025-04-19 13:51:18

AI prompt words

using eca_cond = bool(*)(...);
 using eca_action = void(*)(...);

 class eca_info
 {
 public:
     eca_cond m_cond;
     eca_action m_action;
     void* m_handler_owner;
 };

 using eca_infos = std::vector<eca_info>;

 void listen(const std::string& key, eca_action action, void* handler_owner = nullptr);
 void listen(const std::string& key, eca_cond cond, eca_action action, void* handler_owner = nullptr);
 const eca_infos& get_infos(const std::string& key);

 template<typename... Args>
 inline void trigger(const std::string& key, Args ...args)
 {
     auto infos get_infos(key);
     for (auto& info : infos)
     {
         if (info.m_cond && !info.m_cond(...args))
         {
             continue;
         }

         if (info.handler_owner)
         {
             // Call object method
             (info.handler_owner)->info.m_action()...args);
         }
         else
         {
             // Call global functions
             info.m_action(...args);
         }
     }
 }

 Complete the above functions

Modified ECA system:

#pragma once

 #include <cstdint>
 #include <string>
 #include <vector>
 #include <unordered_map>

 // Define the types of conditions and actions
 using eca_cond = bool(*)(...);
 using eca_action = void(*)(...);

 // Event information structure, including the owner of the condition, action and event handler
 class eca_info {
 public:
     eca_cond m_cond; // Conditional function
     eca_action m_action; // Action function
     void* m_handler_owner; // owner of event handler, used for object method calls
 };

 // Use vectors to store event information to manage multiple events
 using eca_infos = std::vector<eca_info>;

 // Simulated global storage, used to save the event information list corresponding to different keys
 using eca_map = std::unordered_map<std::string, eca_infos>;
 inline eca_map& get_eca_map()
 {
     static eca_map eca_map_;
     return eca_map_;
 }

 // Listen to events and register actions
 void listen(const std::string& key, eca_action action, void* handler_owner = nullptr)
 {
     get_eca_map()[key].push_back({nullptr, action, handler_owner});
 }

 // Listen to events, registration conditions and actions
 void listen(const std::string& key, eca_cond cond, eca_action action, void* handler_owner = nullptr)
 {
     get_eca_map()[key].push_back({cond, action, handler_owner});
 }

 // Get the list of event information corresponding to a specific event key
 const eca_infos& get_infos(const std::string& key)
 {
     static const eca_infos empty; // empty list is used for cases not found
     auto map = get_eca_map();
     return (key) ? map[key] : empty;
 }

 // Trigger event
 template<typename... Args>
 inline void trigger(const std::string& key, Args... args) {
     auto& infos = get_infos(key); // Get all information about the corresponding event
     for (auto& info : infos) {
         // If a condition function exists and the condition is not satisfied, skip this action
         if (info.m_cond && !info.m_cond(args...)) {
             continue;
         }

         // Determine whether there is an owner of the event handler (object method call)
         if (info.m_handler_owner)
         {
             // Call the object method, assuming that the action function is a member function of the object
             // Note: tweaks may be required here to correctly call member functions
             (static_cast<void(*)(void*, Args...)>(info.m_action))(info.m_handler_owner, args...);
         }
         else
         {
             // Call global or static functions
             info.m_action(args...);
         }
     }
 }