#pragma once #include #include "group.h" #include #include "lib_begin.h" namespace cgv { namespace base { class CGV_API traverse_policy; /** The action class is used in tree traversals together with the traverser. It implements the interface needed to perform an action on an arbitrary object. */ class CGV_API action { protected: bool default_result_begin; bool default_result_end; public: /// construct with default return values for the begin and end method action(bool _default_result_begin, bool _default_result_end); /// sets the value that is returned, whenever no result is obtained from the traversed methods void set_default_results(bool _default_result); /// sets the value that is returned for on_begin events void set_default_result_begin(bool _default_result_begin); /// sets the value that is returned for on_end events void set_default_result_end(bool _default_result_end); /// make the passed object current virtual void select(base_ptr p); /// check if the current object implements the interface needed for this action virtual bool implements_action() const; /// return the traverse_policy of the current object if available or 0 otherwise virtual traverse_policy* get_policy() const; /// perform the enter part of the action on the current object virtual bool begin(); /// perform the leave part of the action on the current object virtual bool end(); /// check whether the action has registered a single begin method or both begin and end methods virtual bool has_begin_only() const; }; template struct extract_policy_struct { static void extract_policy(X*, traverse_policy* &tp) { tp = 0; } }; template struct extract_policy_struct { static void extract_policy(X* x, traverse_policy* &tp) { tp = static_cast(x); } }; /** base class for all actions that use methods of class X*/ template class base_method_action : public action { protected: traverse_policy* tp; X* x; public: /// construct from default return values that are passed on to the base class base_method_action(bool _default_result_begin, bool _default_result_end) : action(_default_result_begin, _default_result_end), tp(0), x(0) {} /// implement the select method and store pointers of type X* and traverse_policy* void select(base_ptr p) { x = p->get_interface(); extract_policy_struct::value,X>::extract_policy(x, tp); } /// simply return whether the stored pointer of type X* is not 0 bool implements_action() const { return x != 0; } /// simply return the stored pointer of type traverse_policy* traverse_policy* get_policy() const { return tp; } }; /** base class for all method actions that take a single argument of type T1 in their signature*/ template class method_action : public base_method_action { protected: T1 v1; public: /// construct action from signature and default return values method_action(T1 _v1, bool _default_result_begin, bool _default_result_end) : base_method_action(_default_result_begin, _default_result_end), v1(_v1) {} /// set a new signature with which the methods of the traversed nodes are called void set_signature(T1 _v1) { v1 = _v1; } /// call a void method given a default return value bool call_method(void (X::*mp)(T1), bool default_result) { if (this->x && mp) (this->x->*mp)(v1); return default_result; } /// call a bool method given a default return value bool call_method(bool (X::*mp)(T1), bool default_result) { if (this->x && mp) return (this->x->*mp)(v1); return default_result; } }; /** complete implementation of method actions that only call one method when entering a node*/ template class single_method_action : public method_action { protected: R (X::*on_begin)(T1); public: /// construct from signature, method pointer and default result values single_method_action(T1 _v1, R (X::*_on_begin)(T1), bool _default_result_begin = false, bool _default_result_end = false) : method_action(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin) {} /// uses call_method of base class method_action to call the method refered to by the stored method pointer bool begin() { return this->call_method(on_begin, this->default_result_begin); } /// check whether the action has registered a single begin method or both begin and end methods bool has_begin_only() const { return true; } }; /** complete implementation of method actions that call a begin and end method when entering and leaving a node*/ template class matched_method_action : public method_action { protected: R1 (X::*on_begin)(T1); R2 (X::*on_end)(T1); public: /// construct from signature, method pointers and default result values matched_method_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin, bool _default_result_end) : method_action(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin), on_end(_on_end) {} /// uses call_method of base class method_action to call the method refered to by the stored method pointer bool begin() { return this->call_method(on_begin, this->default_result_begin); } /// uses call_method of base class method_action to call the method refered to by the stored method pointer bool end() { return this->call_method(on_end, this->default_result_end); } }; /// helper function to construct an action from a signature and one method that is called when a node is entered template single_method_action make_action(T1 _v1, R (X::*_on_begin)(T1), bool _default_result_begin = false, bool _default_result_end = false) { return single_method_action(_v1, _on_begin, _default_result_begin, _default_result_end); } /// helper function to construct an action from a signature and two methods that are called when a node is entered and when it is left again template matched_method_action make_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin = false, bool _default_result_end = false) { return matched_method_action(_v1, _on_begin, _on_end, _default_result_begin, _default_result_end); } /** base class for all method actions that take a single argument of type T1 in their signature*/ template class method_action_2 : public base_method_action { protected: T1 v1; T2 v2; public: /// construct action from signature and default return values method_action_2(T1 _v1, T2 _v2, bool _default_result_begin, bool _default_result_end) : base_method_action(_default_result_begin, _default_result_end), v1(_v1), v2(_v2) {} /// set a new signature with which the methods of the traversed nodes are called void set_signature(T1 _v1, T2 _v2) { v1 = _v1; v2 = _v2; } /// call a void method given a default return value bool call_method(void (X::*mp)(T1, T2), bool default_result) { if (this->x && mp) (this->x->*mp)(v1,v2); return default_result; } /// call a bool method given a default return value bool call_method(bool (X::*mp)(T1, T2), bool default_result) { if (this->x && mp) return (this->x->*mp)(v1, v2); return default_result; } }; /** complete implementation of method actions that only call one method when entering a node*/ template class single_method_action_2 : public method_action_2 { protected: R (X::*on_begin)(T1,T2); public: /// construct from signature, method pointer and default result values single_method_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2), bool _default_result_begin = false, bool _default_result_end = false) : method_action_2(_v1, _v2, _default_result_begin, _default_result_end), on_begin(_on_begin) {} /// uses call_method of base class method_action to call the method refered to by the stored method pointer bool begin() { return this->call_method(on_begin, this->default_result_begin); } /// check whether the action has registered a single begin method or both begin and end methods bool has_begin_only() const { return true; } }; /// helper function to construct an action from a signature and one method that is called when a node is entered template single_method_action_2 make_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2), bool _default_result_begin = false, bool _default_result_end = false) { return single_method_action_2(_v1, _v2, _on_begin, _default_result_begin, _default_result_end); } } } #include