Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions UE4SS/include/GUI/LiveView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ namespace RC::GUI

private:
auto collapse_all_except(void* except_id) -> void;
auto search() -> void;
auto search_by_name() -> void;
auto search(bool apply_filters_when_not_searching = false) -> void;
auto make_filtered_set(bool ignore_name = false) -> void;
auto select_object(size_t index, const FUObjectItem* object_item, UObject* object, AffectsHistory = AffectsHistory::Yes) -> void;
auto select_property(size_t index, FProperty* property, AffectsHistory affects_history) -> void;
auto get_selected_object_or_property() -> const ObjectOrProperty&;
Expand Down
59 changes: 39 additions & 20 deletions UE4SS/include/GUI/LiveView/Filter/SearchFilter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@
// 5. In the same file, find the 'LiveView::render' function and find the 'if (ImGui::BeginPopupContextItem("##search-options"))' if-statement.
// 6. Add a checkbox (or whatever) to control your search filter inside the if-statement.

// Whether to track the reason why objects get filtered out.
#ifndef RC_LIVE_VIEW_DEBUG_FILTER_RESULTS
#define RC_LIVE_VIEW_DEBUG_FILTER_RESULTS 0
#endif

#ifndef RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE
#if RC_LIVE_VIEW_DEBUG_FILTER_RESULTS
#define RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(FilteredOut, Reason) {Reason, FilteredOut}
#else
#define RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(FilteredOut, ...) FilteredOut
#endif
#endif

#ifndef RC_LIVE_VIEW_WAS_FILTERED
#if RC_LIVE_VIEW_DEBUG_FILTER_RESULTS
#define RC_LIVE_VIEW_WAS_FILTERED(Result) Result.was_filtered
#else
#define RC_LIVE_VIEW_WAS_FILTERED(Result) Result
#endif
#endif

namespace RC::GUI::Filter
{
using namespace Unreal;
Expand All @@ -37,6 +58,16 @@ namespace RC::GUI::Filter
s_highlighted_properties.emplace(property);
}

#if RC_LIVE_VIEW_DEBUG_FILTER_RESULTS
struct FilterResult
{
StringType reason{};
bool was_filtered{true};
};
#else
using FilterResult = bool;
#endif

template <typename...>
struct Types
{
Expand All @@ -53,20 +84,20 @@ namespace RC::GUI::Filter
};

template <typename T>
auto eval_pre_search_filters(T&, UObject* object) -> bool
auto eval_pre_search_filters(T&, UObject* object) -> FilterResult
{
if constexpr (CanPreEval<T>)
{
return T::pre_eval(object);
}
else
{
return false;
return RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(false, {});
}
}

template <typename T, typename... Ts>
auto eval_pre_search_filters(Types<T, Ts...>&, UObject* object) -> bool
auto eval_pre_search_filters(Types<T, Ts...>&, UObject* object) -> FilterResult
{
auto eval_next_filters = [&] {
Types<Ts...> next_filters{};
Expand All @@ -77,7 +108,7 @@ namespace RC::GUI::Filter
{
if (T::pre_eval(object))
{
return true;
return RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(true, fmt::format(STR("{}"), T::s_debug_name));
}
else
{
Expand All @@ -91,20 +122,20 @@ namespace RC::GUI::Filter
}

template <typename T>
auto eval_post_search_filters(T&, UObject* object) -> bool
auto eval_post_search_filters(T&, UObject* object) -> FilterResult
{
if constexpr (CanPostEval<T>)
{
return T::post_eval(object);
}
else
{
return false;
return RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(false, {});
}
}

template <typename T, typename... Ts>
auto eval_post_search_filters(Types<T, Ts...>&, UObject* object) -> bool
auto eval_post_search_filters(Types<T, Ts...>&, UObject* object) -> FilterResult
{
auto eval_next_filters = [&] {
Types<Ts...> next_filters{};
Expand All @@ -115,7 +146,7 @@ namespace RC::GUI::Filter
{
if (T::post_eval(object))
{
return true;
return RC_LIVE_VIEW_MAKE_FILTER_RETURN_VALUE(true, fmt::format(STR("{}"), T::s_debug_name));
}
else
{
Expand All @@ -128,18 +159,6 @@ namespace RC::GUI::Filter
}
}

#define APPLY_PRE_SEARCH_FILTERS(Filters) \
if (eval_pre_search_filters(Filters, object)) \
{ \
return true; \
}

#define APPLY_POST_SEARCH_FILTERS(Filters) \
if (eval_post_search_filters(Filters, object)) \
{ \
return true; \
}

static auto is_instance(UObject* object, bool care_about_cdo = true) -> bool
{
const auto cdo = care_about_cdo ? !object->HasAnyFlags(static_cast<EObjectFlags>(RF_ClassDefaultObject | RF_ArchetypeObject)) : true;
Expand Down
Loading