Skip to content

gatos.paint_sticker

tool Debug and rendering

Place, spray, tune, hide, and remove projected sticker decals drawn from uploaded images.

Use when
Putting your own artwork into the world — on a vehicle part, on terrain, or across ground clutter — rather than recoloring an existing material.
Availability
control_enabled plus paint_stickers_enabled, which itself requires paint_textures_enabled.

Input

FieldTypeRequirementDescription
operationstringRequiredplace, spray, set, remove, clear, list, or debug.
imagestring | nullOptional · nullUploaded image name from gatos.paint_texture. Required by place and spray, and by set when re-pointing a sticker at another image.
anchorstring | nullOptional · nullplace anchor frame: vessel (part-local metres) or body (geodetic degrees). Inferred from whichever of vessel_id or body is filled when omitted.
vessel_idstring | nullOptional · nullRaw vessel id for a vessel anchor.
part_iidintegerOptional · 0Anchor part or sub-part instance_id, from gatos.get_vessel(include:["parts"]).
positionnumber[3] | nullOptional · nullVessel anchor position [x,y,z] in part-local metres.
normalnumber[3] | nullOptional · nullVessel anchor outward surface normal [x,y,z]; finite and non-zero. Normalized game-side.
bodystring | nullOptional · nullRaw celestial body id for a body anchor.
latnumber | nullOptional · nullBody anchor geodetic latitude in degrees. Valid range: -90 to 90.
lonnumber | nullOptional · nullBody anchor geodetic longitude in degrees. Valid range: -360 to 360.
headingnumber | nullOptional · null (0)Body anchor compass heading in degrees; also the rotation payload for set. Any finite value.
rollnumber | nullOptional · null (0)Vessel anchor roll about the normal in degrees; also the rotation payload for set. On spray it is added to the upright orientation the picker chose rather than replacing it.
widthnumber | nullOptional · null (1)Decal width in metres. Valid range: greater than 0 through 1000.
heightnumber | nullOptional · null (1)Decal height in metres. Valid range: greater than 0 through 1000.
depthnumber | nullOptional · null (0.3 vessel, 1 body)Projection-box depth along the normal in metres. Valid range: greater than 0 through 100. Omitting it on spray lets the anchor kind the ray resolved pick the default.
alphanumber | nullOptional · null (1)Opacity. Valid range: 0 through 1.
brightnessnumber | nullOptional · null (1)Exposure multiplier. Valid range: greater than 0 through 8.
aimstringOptional · "camera"spray aim: camera (the main camera's forward axis, headless-friendly) or cursor (the mouse picking ray).
rangenumber | nullOptional · null (2000)spray ray length in metres. Valid range: greater than 0 through 1e6.
idintegerOptional · -1Sticker id from operation:"list". Required by set and remove.
valuenumber | nullOptional · nullFlag 0|1: sticker visibility for set, and the projection-box checker for debug.

Operation call shapes

Choose an operation below. Its required payload and a complete call stay together—there is no second table to cross-reference.

place

Canonical action: paint.sticker_place

Create a sticker at an exact anchor. A vessel anchor is stored in the part's local frame and follows the part; a body anchor is stored geodetically and rides the planet's rotation. The new sticker takes the lowest free id.

Arguments for this operation

{ operation: "place", image, anchor: "vessel", vessel_id, part_iid, position, normal, roll?, width?, height?, depth?, alpha?, brightness? } | { operation: "place", image, anchor: "body", body, lat, lon, heading?, width?, height?, depth?, alpha?, brightness? }

Example

gatos.paint_sticker({"operation":"place","image":"meow.png","anchor":"vessel","vessel_id":"Kitten-1","part_iid":7,"position":[0,0.5,-1.4],"normal":[0,1,0],"roll":15,"width":0.6,"height":0.3})

spray

Canonical action: paint.sticker_spray

Create a sticker on whatever the camera or cursor is pointing at. The ray hits a vehicle part first and the terrain behind it; nothing hit is ENOENT. Ground clutter cannot be aimed at, but the projection box still paints it.

Arguments for this operation

{ operation: "spray", image, aim?: "camera"|"cursor", range?, roll?, width?, height?, depth?, alpha?, brightness? }

Example

gatos.paint_sticker({"operation":"spray","image":"meow.png","width":2,"height":2})

set

Canonical action: paint.sticker_size | paint.sticker_depth | paint.sticker_rotation | paint.sticker_alpha | paint.sticker_brightness | paint.sticker_image | paint.sticker_visible

Change one knob on one sticker. Exactly one knob per call, which is what selects the canonical action; width and height must be given together. value carries visibility as 0|1 and keeps the entry when hiding it.

Arguments for this operation

{ operation: "set", id, and exactly one of (width + height) | depth | roll|heading | alpha | brightness | image | value }

Example

gatos.paint_sticker({"operation":"set","id":0,"alpha":0.4})

remove

Canonical action: paint.sticker_remove

Delete one sticker and free its id for reuse.

Arguments for this operation

{ operation: "remove", id }

Example

gatos.paint_sticker({"operation":"remove","id":0})

clear

Canonical action: paint.sticker_clear

Global teardown: every sticker removed, uploaded images kept. The render hook and GPU pipeline go away with the last live sticker.

Arguments for this operation

{ operation: "clear" }

Example

gatos.paint_sticker({"operation":"clear"})

list

Read the published sticker array, the subsystem runtime line, and the last place/spray result. Submits no command.

Arguments for this operation

{ operation: "list" }

Example

gatos.paint_sticker({"operation":"list"})

debug

Canonical action: paint.sticker_debug

Global development aid: draw every sticker as a magenta checker of its projection box instead of its image, which shows where the box actually is.

Arguments for this operation

{ operation: "debug", value: 0|1 }

Example

gatos.paint_sticker({"operation":"debug","value":1})

Call example

gatos.paint_sticker({"operation":"spray","image":"meow.png","width":2,"height":2})

Result

For list, the sticker array plus runtime health and the last placement line; every other operation returns the standard command envelope.

Errors

  • EINVAL for an unknown operation, a missing or out-of-range argument, a set call naming zero or more than one knob, a remove/set without an id, or a registry already at paint_stickers_max_count.
  • ENOENT when a spray ray hits nothing within range, when place names a vessel, part instance, or body that is not in the current system, or when set/remove names a sticker id that is gone.
  • EOPNOTSUPP when paint_stickers_enabled or paint_textures_enabled is false.

Operational notes

  • Images upload through gatos.paint_texture — there is no sticker-specific upload surface. Re-uploading the same name hot-swaps every sticker using it; deleting it makes them dormant.
  • Stickers are registry-keyed and vessel-agnostic: the sticker id rides the command ordinal, so they resolve before any vessel lookup. Only the vessel anchor of place names a vessel at all.
  • A vessel that despawns or a part that stages away makes its sticker dormant (live=0), not deleted, so it comes back when the anchor does. Only remove, clear, and mod unload delete entries.
  • Every successful place or spray emits a paint.sticker_placed event, so gatos.wait(event_type:"paint.sticker_placed") is the alternative to polling.
  • Nothing is persisted. Each sticker publishes a write-compatible spec line in the filesystem (/sim/paint/stickers/<id>/spec) that can be echoed back into place to recreate it.
  • The decal draws in the main viewport only, projects onto whatever opaque geometry falls inside its box including ground clutter, uses an approximation of the scene lighting, and is not drawn past paint_stickers_max_view_distance_m.