-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5c04718
commit 4658328
Showing
6 changed files
with
418 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#if Cpp_Relationships_Basics | ||
|
||
using Flecs.NET.Core; | ||
using static Flecs.NET.Bindings.Native; | ||
|
||
using World world = World.Create(args); | ||
|
||
// Entity used for Grows relationship | ||
Entity grows = world.Entity("Grows"); | ||
|
||
// Relationship objects | ||
Entity apples = world.Entity("Apples"); | ||
Entity pears = world.Entity("Pears"); | ||
|
||
// Create an entity with 3 relationships. Relationships are like regular components, | ||
// but combine two types/identifiers into an (relationship, object) pair. | ||
Entity bob = world.Entity("Bob") | ||
// Pairs can be constructed from a type and entity | ||
.Add<Eats>(apples) | ||
.Add<Eats>(pears) | ||
// Pairs can also be constructed from two entity ids | ||
.Add(grows, pears); | ||
|
||
// Has can be used with relationships as well | ||
Console.WriteLine($"Bob eats apples? {bob.Has<Eats>(apples)}"); | ||
|
||
// Wildcards can be used to match relationships | ||
Console.WriteLine($"Bob grows food? {bob.Has(grows, EcsWildcard)}"); | ||
|
||
// Print the type of the entity. Should output: | ||
// (Identifier,Name),(Eats,Apples),(Eats,Pears),(Grows,Pears) | ||
Console.WriteLine($"Bob's type: [{bob.Type().Str()}]"); | ||
|
||
// Relationships can be iterated for an entity. This iterates (Eats, *): | ||
bob.Each<Eats>((Entity second) => | ||
{ | ||
Console.WriteLine($"Bob eats {second.Name()}"); | ||
}); | ||
|
||
// Iterate by explicitly providing the pair. This iterates (*, Pears): | ||
bob.Each(EcsWildcard, pears, (Id id) => | ||
{ | ||
Console.WriteLine($"Bob {id.First().Name()} pears"); | ||
}); | ||
|
||
public struct Eats { } | ||
|
||
#endif | ||
|
||
// Output: | ||
// Bob eats apples? True | ||
// Bob grows food? True | ||
// Bob's type: [(Identifier,Name), (Eats,Apples), (Eats,Pears), (Grows,Pears)] | ||
// Bob eats Apples | ||
// Bob eats Pears | ||
// Bob Eats pears | ||
// Bob Grows pears |
109 changes: 109 additions & 0 deletions
109
src/Flecs.NET.Examples/Cpp/Relationships/EnumRelations.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// When an enumeration constant is added to an entity, it is added as a relationship | ||
// pair where the relationship is the enum type, and the target is the constant. For | ||
// example, this statement: | ||
// e.Add(Color.Red) | ||
// | ||
// adds this relationship: | ||
// (Color, Color.Red) | ||
// | ||
// Enums are registered as exclusive relationships, which means that adding an | ||
// enum constant will replace the previous constant for that enumeration: | ||
// e.Add(Color.Green) | ||
// | ||
// will replace Color.Red with Color.Green | ||
|
||
#if Cpp_Relationships_EnumRelations | ||
|
||
using Flecs.NET.Core; | ||
using static Flecs.NET.Bindings.Native; | ||
|
||
using World world = World.Create(args); | ||
|
||
// Create an entity with (Tile, Stone) and (TileStatus, Free) relationships | ||
Entity tile = world.Entity() | ||
.Add(Tile.Stone) | ||
.Add(TileStatus.Free); | ||
|
||
// (Tile, Tile.Stone), (TileStatus, TileStatus.Free) | ||
Console.WriteLine(tile.Type().Str()); | ||
|
||
// Replace (TileStatus, Free) with (TileStatus, Occupied) | ||
tile.Add(TileStatus.Occupied); | ||
|
||
// (Tile, Tile.Stone), (TileStatus, TileStatus.Occupied) | ||
Console.WriteLine(tile.Type().Str()); | ||
|
||
// Check if the entity has the Tile relationship and the Tile::Stone pair | ||
Console.WriteLine(tile.Has<Tile>()); // True | ||
Console.WriteLine(tile.Has(Tile.Stone)); // True | ||
|
||
// Get the current value of the enum | ||
ref readonly Tile v = ref tile.GetEnum<Tile>(); | ||
Console.WriteLine(v == Tile.Stone); // True | ||
|
||
// Create a few more entities that we can query | ||
world.Entity().Add(Tile.Grass).Add(TileStatus.Free); | ||
world.Entity().Add(Tile.Sand).Add(TileStatus.Occupied); | ||
|
||
// Iterate all entities with a Tile relationship | ||
using Filter filter1 = world.Filter( | ||
filter: world.FilterBuilder().With<Tile>(EcsWildcard) | ||
); | ||
|
||
filter1.Each((Iter it, int i) => | ||
{ | ||
Entity tileConstant = it.Pair(1).Second(); | ||
Console.WriteLine(tileConstant.Path()); | ||
}); | ||
|
||
// Outputs: | ||
// ::Tile::Stone | ||
// ::Tile::Grass | ||
// ::Tile::Sand | ||
|
||
// Iterate only occupied tiles | ||
using Filter filter2 = world.Filter( | ||
filter: world.FilterBuilder() | ||
.With<Tile>(EcsWildcard) | ||
.With(TileStatus.Occupied) | ||
); | ||
|
||
filter2.Each((Iter it, int i) => | ||
{ | ||
Entity tileConstant = it.Pair(1).Second(); | ||
Console.WriteLine(tileConstant.Path()); | ||
}); | ||
|
||
// Outputs: | ||
// ::Tile::Stone | ||
// ::Tile::Sand | ||
|
||
// Remove any instance of the TileStatus relationship | ||
tile.Remove<TileStatus>(); | ||
|
||
public enum Tile | ||
{ | ||
Grass, | ||
Sand, | ||
Stone | ||
} | ||
|
||
public enum TileStatus | ||
{ | ||
Free, | ||
Occupied, | ||
} | ||
|
||
#endif | ||
|
||
// Output: | ||
// (Tile,Tile.Stone), (TileStatus,TileStatus.Free) | ||
// (Tile,Tile.Stone), (TileStatus,TileStatus.Occupied) | ||
// True | ||
// True | ||
// True | ||
// ::Tile::Stone | ||
// ::Tile::Grass | ||
// ::Tile::Sand | ||
// ::Tile::Stone | ||
// ::Tile::Sand |
45 changes: 45 additions & 0 deletions
45
src/Flecs.NET.Examples/Cpp/Relationships/ExclusiveRelations.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#if Cpp_Relationships_ExclusiveRelations | ||
|
||
using Flecs.NET.Core; | ||
using static Flecs.NET.Bindings.Native; | ||
|
||
using World world = World.Create(args); | ||
|
||
// Register Platoon as exclusive relationship. This ensures that an entity | ||
// can only belong to a single Platoon. | ||
world.Component<Platoon>().Entity.Add(EcsExclusive); | ||
|
||
// Create two platoons | ||
Entity platoon1 = world.Entity(); | ||
Entity platoon2 = world.Entity(); | ||
|
||
// Create a unit | ||
Entity unit = world.Entity(); | ||
|
||
// Add unit to platoon 1 | ||
unit.Add<Platoon>(platoon1); | ||
|
||
// Log platoon of unit | ||
Console.WriteLine($"Unit in platoon 1: {unit.Has<Platoon>(platoon1)}"); | ||
Console.WriteLine($"Unit in platoon 2: {unit.Has<Platoon>(platoon2)}"); | ||
Console.WriteLine(); | ||
|
||
// Add unit to platoon 2. Because Platoon is an exclusive relationship, this | ||
// both removes (Platoon, platoon_1) and adds (Platoon, platoon_2) in a | ||
// single operation. | ||
unit.Add<Platoon>(platoon2); | ||
|
||
Console.WriteLine($"Unit in platoon 1: {unit.Has<Platoon>(platoon1)}"); | ||
Console.WriteLine($"Unit in platoon 2: {unit.Has<Platoon>(platoon2)}"); | ||
|
||
// Type for Platoon relationship | ||
public struct Platoon { } | ||
|
||
#endif | ||
|
||
// Output: | ||
// Unit in platoon 1: True | ||
// Unit in platoon 2: False | ||
// | ||
// Unit in platoon 1: False | ||
// Unit in platoon 2: True |
88 changes: 88 additions & 0 deletions
88
src/Flecs.NET.Examples/Cpp/Relationships/RelationComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// This example shows how relationships can be combined with components to attach | ||
// data to a relationship. | ||
|
||
#if Cpp_Relationships_RelationComponent | ||
|
||
using Flecs.NET.Core; | ||
using static Flecs.NET.Bindings.Native; | ||
|
||
using World world = World.Create(args); | ||
|
||
// When one element of a pair is a component and the other element is a tag, | ||
// the pair assumes the type of the component. | ||
Entity e1 = world.Entity().SetFirst<Requires, Gigawatts>(new Requires { Amount = 1.21 }); | ||
ref readonly Requires r = ref e1.GetFirst<Requires, Gigawatts>(); | ||
Console.WriteLine($"requires: {r.Amount}"); | ||
|
||
// The component can be either the first or second part of a pair: | ||
Entity e2 = world.Entity().SetSecond<Gigawatts, Requires>(new Requires { Amount = 1.21 }); | ||
r = ref e2.GetSecond<Gigawatts, Requires>(); | ||
Console.WriteLine($"requires: {r.Amount}"); | ||
|
||
// Note that <Requires, Gigawatts> and <Gigawatts, Requires> are two | ||
// different pairs, and can be added to an entity at the same time. | ||
|
||
// If both parts of a pair are components, the pair assumes the type of | ||
// the first element: | ||
Entity e3 = world.Entity().SetFirst<Expires, Position>(new Expires { Timeout = 0.5 }); | ||
ref readonly Expires e = ref e3.GetFirst<Expires, Position>(); | ||
Console.WriteLine($"expires: {e.Timeout}"); | ||
|
||
// You can prevent a pair from assuming the type of a component by adding | ||
// the Tag property to a relationship: | ||
world.Component<MustHave>().Entity.Add(EcsTag); | ||
|
||
// Even though Position is a component, <MustHave, Position> contains no | ||
// data because MustHave has the Tag property. | ||
world.Entity().Add<MustHave, Position>(); | ||
|
||
// The id::type_id method can be used to find the component type for a pair: | ||
Console.WriteLine(world.Pair<Requires, Gigawatts>().TypeId().Path()); | ||
Console.WriteLine(world.Pair<Gigawatts, Requires>().TypeId().Path()); | ||
Console.WriteLine(world.Pair<Expires, Position>().TypeId().Path()); | ||
Console.WriteLine(world.Pair<MustHave, Position>().TypeId().Path()); | ||
|
||
// When querying for a relationship component, add the pair type as template | ||
// argument to the builder: | ||
Query q = world.Query( | ||
filter: world.FilterBuilder() | ||
.Term<Requires>().Second<Gigawatts>() // set second part of pair for first term | ||
); | ||
|
||
// When iterating, always use the pair type: | ||
q.Each((Iter it, int i) => | ||
{ | ||
Column<Requires> rq = it.Field<Requires>(1); | ||
Console.WriteLine($"requires {rq[i].Amount} gigawatts"); | ||
}); | ||
|
||
public struct Requires | ||
{ | ||
public double Amount { get; set; } | ||
} | ||
|
||
public struct Expires | ||
{ | ||
public double Timeout { get; set; } | ||
} | ||
|
||
public struct Position | ||
{ | ||
public double X { get; set; } | ||
public double Y { get; set; } | ||
} | ||
|
||
public struct Gigawatts { } | ||
public struct MustHave { } | ||
|
||
#endif | ||
|
||
// Output: | ||
// requires: 1.21 | ||
// requires: 1.21 | ||
// expires: 0.5 | ||
// ::Requires | ||
// ::Requires | ||
// ::Expires | ||
// 0 | ||
// requires 1.21 gigawatts |
31 changes: 31 additions & 0 deletions
31
src/Flecs.NET.Examples/Cpp/Relationships/SymmetricRelations.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#if Cpp_Relationships_SymmetricRelations | ||
|
||
using Flecs.NET.Core; | ||
using static Flecs.NET.Bindings.Native; | ||
|
||
using World world = World.Create(args); | ||
|
||
// Register TradesWith as symmetric relationship. Symmetric relationships | ||
// go both ways, adding (R, B) to A will also add (R, A) to B. | ||
world.Component<TradesWith>().Entity.Add(EcsSymmetric); | ||
|
||
// Create two players | ||
Entity player1 = world.Entity(); | ||
Entity player2 = world.Entity(); | ||
|
||
// Add (TradesWith, player_2) to player_1. This also adds | ||
// (TradesWith, player_1) to player_2. | ||
player1.Add<TradesWith>(player2); | ||
|
||
// Log platoon of unit | ||
Console.WriteLine($"Player 1 trades with Player 2: {player1.Has<TradesWith>(player2)}"); | ||
Console.WriteLine($"Player 2 trades with Player 1: {player2.Has<TradesWith>(player1)}"); | ||
|
||
// Type for TradesWith relationship | ||
public struct TradesWith { } | ||
|
||
#endif | ||
|
||
// Output: | ||
// Player 1 trades with Player 2: True | ||
// Player 2 trades with Player 1: True |
Oops, something went wrong.