@@ -481,6 +481,54 @@ namespace geode {
481481#endif
482482}
483483
484+ namespace geode ::internal {
485+ template <class T , class = void >
486+ struct extract_modify_base { using type = void ; };
487+
488+ template <class T >
489+ struct extract_modify_base <T, std::void_t <decltype (T::m_fields)>> {
490+ private:
491+ template <class U >
492+ struct extract_base { using type = void ; };
493+
494+ template <class Derived , class Base >
495+ struct extract_base <modifier::FieldIntermediate<Derived, Base>> { using type = Base; };
496+ public:
497+ using type = typename extract_base<decltype (T::m_fields)>::type;
498+ };
499+
500+ template <class T >
501+ using ModifyBase = typename extract_modify_base<T>::type;
502+ }
503+
504+ namespace geode ::cast {
505+ /* *
506+ * A cast specialized to cast to modify classes. Static casts to the base class of the modify class first,
507+ * and then static casts to the modify class itself.
508+ * @example modify_cast<MyGJBaseGameLayer*>(PlayLayer::get());
509+ */
510+ template <class Target , class Original >
511+ constexpr Target modify_cast (Original original) {
512+
513+ using TargetBase = geode::internal::ModifyBase<std::remove_pointer_t <Target>>;
514+
515+ static_assert (std::is_pointer_v<Target> && !std::is_pointer_v<std::remove_pointer_t <Target>>, " Target class has to be a single pointer." );
516+ static_assert (std::is_pointer_v<Original> && !std::is_pointer_v<std::remove_pointer_t <Original>>, " Original class has to be a single pointer." );
517+ static_assert (
518+ (
519+ requires { std::remove_pointer_t <Target>::m_fields; !std::is_void_v<TargetBase>; } &&
520+ std::is_base_of_v<geode::Modify<std::remove_pointer_t <Target>, TargetBase>, std::remove_pointer_t <Target>>
521+ ),
522+ " The target class has to be a Modify class."
523+ );
524+ static_assert (
525+ !std::is_void_v<TargetBase> && requires { static_cast <TargetBase*>(original); },
526+ " The original class has to be castable to the class the modify class is modifying."
527+ );
528+ return static_cast <Target>(static_cast <TargetBase*>(original));
529+ }
530+ }
531+
484532/* *
485533 * Main class implementation, it has the structure
486534 *
0 commit comments