# `tecs.gfx.clips` Target-pixel clip regions and the component that selects one. A clip region is one rectangle in render-target pixels. An entity carrying `Clip` keeps the fragments that land inside the region it names and loses the ones that do not, whatever placed them there: a panel occupies a part of the window whether its contents are positioned by the camera, in screen pixels, or in virtual coordinates, and one rectangle is right for all three. ```nupp tecs.gfx.clips.setRegion(1, {x = 16, y = 16, width = 320, height = 180}) world:spawn( tecs.ecs.Transform2D(64, 64, 0, 1, 0, 32, 32), tecs.gfx.Tint(1, 1, 1, 1), tecs.gfx.Clip(1), tecs.gfx.Renderable2D ) ``` Region zero is not a region and cannot be set. It is what an entity says when it wants no clipping at all, and it is what `Clip` defaults to. Nesting belongs to whoever hands the indices out. A region is one rectangle, so a panel inside a panel is set up as the intersection of the two rather than as two regions an entity sits in at once. The table is process-wide, in the same way component identity is, because one process drives one renderer. # Reach `culls` and `contains` answer against the table this module holds, so a game, an input layer, and a debug tool all test the same rectangles. Extraction packs the selected region's pixel bounds into each clipped instance, and the fragment shader rejects pixels outside them. Region changes invalidate retained render data as well as updating the CPU clipping tests. ## Types ### `Clip` _struct_ ```nupp struct Clip index: integer end ``` `@derive(nupp.derive.Debug, nupp.derive.Serde)` Restricts an entity's fragments to one clip region. A component rather than a field on every renderable, because presence is the opt-in and absence is the common case. #### Fields ##### `index` ```nupp index: integer ``` Caller-writable. Selects a region set with `setRegion`, from one to `MAX - 1`. Zero, the default, means no clipping. ### `Region` _type_ ```nupp type Region = { x: number, y: number, width: number, height: number } ``` Defines one clip rectangle in render-target pixels, measured from the top left corner. ## Functions ### `clearRegion` _function_ ```nupp function clearRegion(index: integer): nil ``` Stops one region clipping anything. The region goes back to what it was before anyone set it, so an entity still pointing at it draws whole rather than disappearing. Whoever hands indices out and takes them back therefore leaves nothing behind that silently removes content. #### Arguments | Name | Type | Description | | --- | --- | --- | | `index` | `integer` | the region to clear, from one to `MAX - 1`; clearing one nobody set is not an error | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the index is zero or outside the table ### `contains` _function_ ```nupp function contains(index: integer, x: number, y: number): boolean ``` Returns whether one target pixel survives a region. #### Arguments | Name | Type | Description | | --- | --- | --- | | `index` | `integer` | the region to test against; zero keeps every pixel | | `x` | `number` | the pixels from the target's left edge | | `y` | `number` | the pixels from the target's top edge | #### Returns | Type | Description | | --- | --- | | `boolean` | whether a fragment at that pixel is kept | ### `culls` _function_ ```nupp function culls(index: integer, minX: number, minY: number, maxX: number, maxY: number): boolean ``` Returns whether a region removes every fragment of one target-pixel bound. The cull half of clipping: a quad whose bound misses its region entirely contributes nothing, so a caller may drop it before it reaches the backend. A bound that only partly overlaps is kept whole, because the region decides the rest per fragment. #### Arguments | Name | Type | Description | | --- | --- | --- | | `index` | `integer` | the region to test against; zero culls nothing | | `minX` | `number` | the bound's left edge in target pixels | | `minY` | `number` | the bound's top edge in target pixels | | `maxX` | `number` | the bound's right edge in target pixels | | `maxY` | `number` | the bound's bottom edge in target pixels | #### Returns | Type | Description | | --- | --- | | `boolean` | whether the bound lies entirely outside the region | ### `regionOf` _function_ ```nupp function regionOf(index: integer): number, number, number, number ``` Returns one region's bounds in target pixels. #### Arguments | Name | Type | Description | | --- | --- | --- | | `index` | `integer` | the region to read; zero, and anything outside the table, answers the bounds of a region that clips nothing | #### Returns | Type | Description | | --- | --- | | `number` | the left edge, then the top, then the right, then the bottom | | `number` | | | `number` | | | `number` | | ### `revision` _function_ ```nupp function revision(): integer ``` Returns the region table's revision. #### Returns | Type | Description | | --- | --- | | `integer` | a count starting at zero that only rises, so a consumer holding a packed copy can tell whether its copy is still the answer | ### `setRegion` _function_ ```nupp function setRegion(index: integer, region: Region): nil ``` Points one region at a rectangle in target pixels. Replaces whatever the region held rather than intersecting with it, so a caller reusing an index across frames writes the whole rectangle each time. #### Arguments | Name | Type | Description | | --- | --- | --- | | `index` | `integer` | the region to set, from one to `MAX - 1` | | `region` | `Region` | the rectangle in target pixels, measured from the top left | #### Returns | Type | Description | | --- | --- | | `nil` | | #### Raises - when the index is zero or outside the table, or when the rectangle has a negative width or height ## Values ### `ClipComponent` _variable_ ```nupp const ClipComponent: ecs.ComponentDefinition ``` The process-wide `Clip` component definition. ### `MAX` _variable_ ```nupp const MAX: integer ``` The number of clip slots the table holds. Regions run from one to `MAX - 1`, because zero is the entity saying it wants no clipping. Extraction copies selected bounds into the instance; this limit bounds the CPU registry.