Skip to content

Game.Simulation.Flow.Layer

Assembly: Assembly-CSharp
Namespace: Game.Simulation.Flow

Type: struct

Base: System.ValueType, implements System.IDisposable

Summary:
Represents a single "layer" of cut elements used by the simulation flow system. Layer stores CutElement and CutElementRef entries in Unity UnsafeList containers, manages free lists for reuse, and tracks usage counts. It provides low-level add/free operations, group merging, linking management, and (de)serialization helpers to save/load layer state into contiguous native arrays. Because it uses Unity.Collections low-level containers (UnsafeList / NativeList / NativeArray), callers must manage allocator lifetimes and call Dispose to release native memory.


Fields

  • public UnsafeList<CutElement> m_Elements
    Stores the underlying array of CutElement instances. This UnsafeList represents the allocated slots (capacity). Individual elements may be active or part of a free list. The list's Length is used as the current capacity and is resized automatically when adding beyond capacity.

  • public UnsafeList<CutElementRef> m_ElementRefs
    Stores the underlying array of CutElementRef instances. Works the same way as m_Elements but for references/links between layers.

  • private int m_UsedElementCount
    Count of currently active (in-use) CutElement entries. Useful to quickly check if the layer is empty or for statistics.

  • private int m_UsedElementRefCount
    Count of currently active CutElementRef entries.

  • private int m_FreeElementIndex
    Head index of the free list for m_Elements. -1 indicates no free entries. Freed element slots are pushed onto this list for reuse.

  • private int m_FreeElementRefIndex
    Head index of the free list for m_ElementRefs. -1 indicates none available.

Properties

  • public bool isEmpty { get; }
    Returns true when m_UsedElementCount == 0. Quick check to determine whether the layer contains any active elements.

  • public int usedElementCount { get; }
    Returns the current number of active CutElement entries (m_UsedElementCount).

  • public int usedElementRefCount { get; }
    Returns the current number of active CutElementRef entries (m_UsedElementRefCount).

Constructors

  • public Layer(int initialLength, Allocator allocator)
    Creates a layer with initial capacity initialLength using the provided Unity.Collections.Allocator. Both m_Elements and m_ElementRefs are allocated and their slots initialized into a free list (each slot's m_NextIndex is chained). If initialLength is zero, free list heads are set to -1. The lists are created with NativeArrayOptions.ClearMemory so slots start zeroed.

Methods

  • public bool ContainsCutElement(Identifier id)
    Checks whether the given Identifier references a valid, created CutElement in this layer: index must not be -1, element must be marked as created and have a matching version. Returns true when the referenced element exists and matches the version.

  • public bool ContainsCutElementForConnection(Identifier id, Connection connection, bool admissible)
    Greater validation compared to ContainsCutElement — additionally checks that the element matches the provided connection fields (edge, start/end node) and the admissible flag. Also validates index bounds (index < m_Elements.Length).

  • public ref CutElement GetCutElement(int index)
    Returns a by-ref access to the CutElement at the given index using UnsafeList.ElementAt. Caller is responsible for ensuring the index is valid before calling.

  • public int AddCutElement(in CutElement element)
    Adds a new CutElement into the layer. If there is a free slot (m_FreeElementIndex != -1), it reuses that slot; otherwise it resizes m_Elements (Length++) and uses the new slot. The element is copied into the slot and m_UsedElementCount is incremented. Returns the index of the added element.

  • public void FreeCutElement(int index)
    Frees the element at index: resets its flags to None, pushes the slot onto the element free-list (m_FreeElementIndex), and decrements m_UsedElementCount. The element's m_NextIndex is set to the previous free head.

  • public ref CutElementRef GetCutElementRef(int index)
    Returns a by-ref access to the CutElementRef at the specified index. Caller must ensure index validity.

  • public int AddCutElementRef(in CutElementRef elementRef)
    Adds a CutElementRef, reusing a free slot when available or growing m_ElementRefs otherwise. Increments m_UsedElementRefCount. Returns the index of the inserted ref.

  • public void FreeCutElementRef(int index)
    Frees the CutElementRef at index by resetting its m_Layer and m_Index to -1, pushing the slot on the ref free-list, and decrementing m_UsedElementRefCount.

  • public void MergeGroups(int elementId1, int elementId2)
    Merges the group of elementId2 into the group of elementId1. This method relinks the internal m_NextIndex chain and updates m_Group for all elements in elementId2's group so they point to elementId1's group. No-op if both elements are already in the same group.

  • public void RemoveElementLink(int elementIndex, int upperLayerIndex, int upperLayerElementIndex)
    Removes a link from the specified element's linked-elements list that points to a CutElementRef identifying (upperLayerIndex, upperLayerElementIndex). Traverses the link chain, unlinks the found CutElementRef, and frees that CutElementRef slot.

  • public static Layer Load(LayerState state, NativeArray<CutElement> layerElements, ref int elementIndex, NativeArray<CutElementRef> layerElementRefs, ref int elementRefIndex)
    Deserializes a Layer from a LayerState and slices of contiguous arrays of CutElement and CutElementRef. It creates temporary UnsafeList instances (Allocator.Temp) and copies the slices into them using AddRange, advances elementIndex and elementRefIndex by the lengths consumed, and returns a Layer populated with the loaded lists and bookkeeping values taken from state. Note: the created UnsafeLists use Allocator.Temp in this implementation — exercise care with lifetime; Allocator.Temp is only valid for a short duration (same frame).

  • private unsafe static void AddRange<T>(ref UnsafeList<T> unsafeList, NativeSlice<T> slice) where T : unmanaged
    Low-level helper that adds the contents of a NativeSlice into an UnsafeList via unsafe pointer copy. Used by Load to fill temporary UnsafeLists.

  • public void Save(NativeList<LayerState> layerStates, NativeList<CutElement> layerElements, NativeList<CutElementRef> layerElementRefs)
    Serializes the layer state and appends it to the provided NativeLists. LayerState captures lengths, usage counts, and free list heads. Element and element-ref contents are appended using AddRange helpers.

  • private unsafe static void AddRange<T>(NativeList<T> list, UnsafeList<T> unsafeList) where T : unmanaged
    Low-level helper to append an UnsafeList's memory contents into a NativeList via pointer copy.

  • public void Dispose()
    Disposes m_Elements and m_ElementRefs native containers to release native memory. Must be called when the Layer is no longer needed to avoid memory leaks. After Dispose, the UnsafeLists become invalid.

Usage Example

// Example: create a persistent layer, add an element, then dispose
var layer = new Layer(16, Allocator.Persistent);

CutElement element = default;
// Initialize element fields (m_Group, m_Flags, etc.) as required by your mod
int index = layer.AddCutElement(in element);

// Access element by ref and modify
ref CutElement eRef = ref layer.GetCutElement(index);
eRef.m_Flags |= CutElementFlags.SomeFlag; // example

// When done with this layer:
layer.Dispose();

Notes and tips: - This struct uses Unity.Collections UnsafeList and Native containers. Respect allocator semantics: Allocator.Temp is only valid inside a single frame, Allocator.Persistent must be disposed explicitly, and Allocator.TempJob has limited lifetime as well. - Many methods return or accept refs into the UnsafeList; ensure indices are valid before calling GetCutElement / GetCutElementRef to avoid undefined behavior. - Layer is not thread-safe for concurrent writes. If using in jobs, adhere to Unity's native container job safety requirements and scheduling (JobHandles) or make copies per job. - Be cautious with Load: it currently constructs the returned Layer with UnsafeLists created using Allocator.Temp — if you need persistent layers, copy data into lists allocated with Allocator.Persistent or allocate differently.