Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/igood/igranges
C++ Ranges for Unreal
https://github.com/igood/igranges
cpp20 linq ranges ue5-plugin unreal-engine-plugin
Last synced: 3 months ago
JSON representation
C++ Ranges for Unreal
- Host: GitHub
- URL: https://github.com/igood/igranges
- Owner: IGood
- License: mit
- Created: 2024-08-29T06:34:44.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2024-10-12T09:11:58.000Z (3 months ago)
- Last Synced: 2024-10-12T16:20:22.906Z (3 months ago)
- Topics: cpp20, linq, ranges, ue5-plugin, unreal-engine-plugin
- Language: C++
- Homepage:
- Size: 166 KB
- Stars: 5
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# ![Logo](Resources/Icon128.png) for Unreal
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](/LICENSE)**IGRanges** is an Unreal Engine 5 plugin that leverages the [Ranges library (C++20)](https://en.cppreference.com/w/cpp/ranges) to provide [LINQ (C#)](https://learn.microsoft.com/en-us/dotnet/csharp/linq/) style code patterns.
Unreal's container types (e.g. `TArray`) do not support Ranges out of the box (yet?), so this plugin first adds the necessary customization point objects to make them compatible.\
Beyond that, a handful of common mapping & filtering operations have been implemented in ways that are familiar to programmers acquainted with UE & LINQ.----
## C++20 Ranges, But Think LINQ
A quick primer for Ranges from [cppreference.com](https://en.cppreference.com/w/cpp/ranges):
> The ranges library is an extension and generalization of the algorithms and iterator libraries that makes them more powerful by making them composable and less error-prone.\
The library creates and manipulates range views, lightweight objects that indirectly represent iterable sequences (ranges).### 👩💻 Example A:
The following example "pipes" an array of integers through views to generate a sequence that is a modified subset of the original values.#### 👩💻 Example A.1:
```cpp
int myInts[] = { 0, 1, 2, 3, 4, 5 };
auto even = [](int i) { return i % 2 == 0; };
auto square = [](int i) { return i * i; };
// the "pipe" syntax of composing the views:
for (int i : myInts | std::views::filter(even) | std::views::transform(square))
std::cout << i << ' ';
// Output: 0 4 16
```This example is very *C++*-looking. It's not very *UE*-looking & it doesn't read quite as clearly as LINQ.\
If we were to rewrite it in a UE style with IGRanges, then it might look something like this:#### 👩💻 Example A.2:
```cpp
TArray MyInts = { 0, 1, 2, 3, 4, 5 };
auto IsEven = [](int i) { return i % 2 == 0; };
auto Square = [](int i) { return i * i; };
FString Result;
for (int32 i : MyInts | Where(IsEven) | Select(Square))
{
Result.AppendInt(i);
Result += TEXT(", ");
}
UE_LOG(LogTemp, Log, TEXT("Result{%s}"), *Result);
// Output: Result{0, 4, 16,}
```Or, depending on style preferences, it might look something like this:
#### 👩💻 Example A.3:
```cpp
TArray MyInts = { 0, 1, 2, 3, 4, 5 };
auto Sqevens = MyInts
| Where([](int i) { return i % 2 == 0; })
| Select([](int i) { return i * i; });
FString Result;
for (int32 i : Sqevens)
{
Result.AppendInt(i);
Result += TEXT(", ");
}
```### 👩💻 Example B:
A better demonstration of IGRanges is shown in the following example.\
The declarative syntax can make it easier to understand the intent of the code.\
In this case, we have a collection of pointers to Actors (some of which might be null) & we want to get the World from one of them.ImperativeDeclarative
```cpp
TArray MaybeActors = ...;
UWorld* World = nullptr;
for (const AActor* Actor : MaybeActors)
{
if (Actor != nullptr)
{
World = Actor->GetWorld();
break;
}
}
if (World != nullptr) ...
``````cpp
TArray MaybeActors = ...;
UWorld* World = MaybeActors
| NonNull()
| Select(&AActor::GetWorld)
| FirstOrDefault();
if (World != nullptr) ...```
### 👩💻 Example C:
Filtering & collecting elements also becomes very easy with IGRanges.
ImperativeDeclarative
```cpp
TArray SomeObjects = ...;
TArray Foos;
for (UObject* Obj : SomeObjects)
{
if (UFoo* Foo = Cast(Obj))
{
Foos.Add(Foo);
}
}
``````cpp
TArray SomeObjects = ...;
TArray Foos = SomeObjects | OfType() | ToArray();```
----
### ✨ Features
- `Where`, `WhereNot`, `SafeWhere`, `SafeWhereNot`
- `NonNull`, `NonNullRef`
- `Select`, `SelectNonNull`
- `Cast`, `CastExact`, `CastChecked`, `CastCheckedRef`
- `OfType`, `OfTypeRef`, `OfTypeExact`, `OfTypeExactRef`, `OfType`, `OfTypeRef`
- `FirstOrDefault`
- `Count`
- `Sum`
- `Accumulate`
- `ToArray`
- `ToSet`
- `All`, `Any`, `None`
- `Selectors::CDO`
- `Filters::IsChildOf`, `Filters::IsChildOf`----
### 🔗 Related Links
- [Ranges library (C++20)](https://en.cppreference.com/w/cpp/ranges)
- [\ | Microsoft Learn](https://learn.microsoft.com/en-us/cpp/standard-library/ranges)
- [Language Integrated Query (LINQ) - C# | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/csharp/linq/)