Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
en:toolworks:docs:apparatus:iterating [2021/06/17 19:29] – vladius | en:toolworks:docs:apparatus:iterating [2022/06/05 15:26] (current) – Пофиксил ссылки, чтобы они указывали на существующую страницу. jispar | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Iterating ====== | ====== Iterating ====== | ||
- | In order to implement your actual Mechanic logic you have to be able to process all of the [[en: | + | In order to implement your actual Mechanic logic you have to be able to process all of the [[en: |
- | Chains are iterated with the help of Cursors. Those are very much like container iterators. Multiple Cursors are available but this is more of a multi-threading future-proofing. For now, you should really use a single default Cursor only. | + | Chains are iterated with the help of Cursors. Those are very much like container iterators. |
===== C++ Workflow ===== | ===== C++ Workflow ===== | ||
+ | |||
+ | Iterating a Chain is done through a special type of object called //Cursor//. | ||
+ | You can have as many of those, but usually one is enough: | ||
+ | |||
+ | <code cpp> | ||
+ | FChain:: | ||
+ | </ | ||
+ | |||
+ | The solid-variant would logically be like so: | ||
+ | |||
+ | <code cpp> | ||
+ | FSolidChain:: | ||
+ | </ | ||
+ | |||
+ | When you got the Cursor needed, you can construct a simple while loop like so: | ||
+ | |||
+ | <code cpp> | ||
+ | while (Cursor.Provide()) | ||
+ | { | ||
+ | auto Trait = Cursor.GetTrait< | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | are no more slots available ('' | ||
+ | |||
+ | With a solid Cursor you can also get a direct (copy-free) reference to a Trait (with a '' | ||
+ | |||
+ | <code cpp> | ||
+ | while (SolidCursor.Provide()) | ||
+ | { | ||
+ | auto& Trait = SolidCursor.GetTraitRef< | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Please note, that the Chain gets disposed automatically when all | ||
+ | of the iterating Cursors have finished providing (iterating) the slots. | ||
+ | To suppress this behavior use explicit '' | ||
+ | for a custom lifetime organization: | ||
+ | |||
+ | <code cpp> | ||
+ | Chain-> | ||
+ | FChain:: | ||
+ | while (Cursor.Provide()) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | // Do some other stuff with the chain. | ||
+ | // It's now guaranteed to not be disposed. | ||
+ | ... | ||
+ | Chain-> | ||
+ | </ | ||
+ | |||
+ | ==== Embedded Cursors ==== | ||
+ | |||
+ | Apparatus provides a way to iterate the chains via embedded (self-allocated) cursors. | ||
+ | This is mainly utilized internally, by the Blueprints and generally should be | ||
+ | avoided within your C++ code. | ||
Your basic loop is quite simple. It's just a '' | Your basic loop is quite simple. It's just a '' | ||
Line 24: | Line 84: | ||
MyPosition-> | MyPosition-> | ||
... | ... | ||
+ | MyVelocity.VelocityX = 0; | ||
+ | MyVelocity.VelocityY = 0; | ||
+ | Subject.SetTrait(MyVelocity); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | When the Chain Cursor is gone past the last available Subject/ | ||
+ | |||
+ | ==== Direct Iterating ==== | ||
+ | |||
+ | If you want to iterate the Chunks directly you can utilize the Chunks Proxies. | ||
+ | You will basically need to iterate all of the Proxies collected | ||
+ | through the corresponding [[appi> | ||
+ | within each Chunk iterate all of its Subjects-containing Slots. | ||
+ | |||
+ | An example is as such:< | ||
+ | TArray< | ||
+ | Mechanism-> | ||
+ | for (int32 i = 0; i < ChunkProxies.Num(); | ||
+ | { | ||
+ | auto& ChunkProxy = ChunkProxies[i]; | ||
+ | for (int32 j = 0; j < ChunkProxy.Num(); | ||
+ | { | ||
+ | // Perform the necessary logic... | ||
+ | ChunkProxy.TraitRefAt< | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Please note however, that this approach is totally manual, and doesn' | ||
+ | |||
+ | If you're also performing some topology-changing logic within your loops your Subjects can change their Chunks and Slots in an arbitrary way, so perhaps you also have to be checking for Slots to be (non-)stale. | ||
+ | |||
+ | You would do it like so:<code cpp> | ||
+ | for (int32 j = 0; j < ChunkProxy.Num(); | ||
+ | { | ||
+ | if (ChunkProxy.IsStaleAt(j)) continue; // Skip the Subject if it's either moved or despawned... | ||
+ | ChunkProxy.SubjectAt(j).SetTrait(FSpeedBoostTrait{10.0f}); | ||
} | } | ||
</ | </ | ||
+ | Iterating the Chunks directly (via Proxies) can introduce a certain performance boost as compared to normal iterating and [[en: |