#ifndef SEAD_METHODTREE_H_ #define SEAD_METHODTREE_H_ #include #include #include #include #include #include #include namespace sead { class CriticalSection; template class IDelegate2; class MethodTreeNode : public IDisposer, public TTreeNode, public INamable { SEAD_RTTI_BASE(MethodTreeNode) public: enum PauseFlag { cPause_None = 0, cPause_Self = 1, cPause_Child = 2, cPause_Both = 3, }; using PauseEventDelegate = IDelegate2; // NON_MATCHING: stores for mPauseFlag, mPauseEventDelegate, mUserID explicit MethodTreeNode(CriticalSection* cs) : TTreeNode(this) { mCriticalSection = cs; mPauseEventDelegate = nullptr; mUserID = nullptr; mDelegateHolder.construct(sead::Delegate()); setPauseFlag(cPause_Both); } ~MethodTreeNode() override { detachAll(); } template void bind(const Delegate& delegate, const char* name) { lock_(); mDelegateHolder.construct(delegate); unlock_(); if (name) setName(name); } void call(); void detachAll(); void pushBackChild(MethodTreeNode* node); void pushFrontChild(MethodTreeNode* node); void setPauseFlag(PauseFlag flag) { lock_(); if (mPauseEventDelegate) mPauseEventDelegate->invoke(this, flag); mPauseFlag = flag; unlock_(); } private: void attachMutexRec_(CriticalSection* m) const; void callRec_(); void lock_(); void unlock_(); StorageFor mDelegateHolder; mutable CriticalSection* mCriticalSection; [[maybe_unused]] u32 mPriority; BitFlag32 mPauseFlag; PauseEventDelegate* mPauseEventDelegate; void* mUserID; }; } // namespace sead #endif // SEAD_METHODTREE_H_