> ## Documentation Index
> Fetch the complete documentation index at: https://docs.summerengine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Painted_location (Painted 25d world skill)

> painted_location.gd from the Painted 25d world skill in the Summer Engine skill library. Build a 2D or 2.5D game as a painted world: a 3D blockout under one fixed camera, an AI paint-over projected onto it, sprite characters.

> [!NOTE]
>
> Part of the [`painted-25d-world` skill](/skills/painted-25d-world). The skill links here when your agent needs the detail.

```gdscript painted_location.gd theme={null}
extends Node3D
## One painted frame: a PaintCamera, the blockout under Painted, and the paint-over projected onto it from
## that camera. With no `paint` set it shows the plain blockout (play it and capture that frame for the paint-over).
## Children: PaintCamera (Camera3D, orthographic, KEEP_WIDTH), Painted (Node3D with every block).

const PROJECTION := preload("res://painted/paint_projection.gdshader")

## The paint-over for this frame (4K, imported lossless).
@export var paint: Texture2D
## Rooms: frame the whole painting like a stage. Outdoors: follow the player.
@export var frame_whole := false

@onready var paint_cam: Camera3D = $PaintCamera
var paint_size := Vector2.ZERO
## Average colour along the painting's border: the clear colour while the player is here.
var edge_color := Color(0.1, 0.1, 0.1)

func _ready() -> void:
	if paint == null:
		return
	paint_size = Vector2(paint_cam.size, paint_cam.size * paint.get_height() / float(paint.get_width()))
	var mat := ShaderMaterial.new()
	mat.shader = PROJECTION
	mat.set_shader_parameter("paint", paint)
	mat.set_shader_parameter("paint_origin", paint_cam.global_position)
	mat.set_shader_parameter("paint_right", paint_cam.global_basis.x)
	mat.set_shader_parameter("paint_up", paint_cam.global_basis.y)
	mat.set_shader_parameter("paint_size", paint_size)
	for mi in $Painted.find_children("*", "MeshInstance3D", true, false):
		# door slabs and steps stick out of the walls in the blockout; the painting already shows them
		if mi.name.containsn("door") or mi.name.containsn("steps"):
			mi.visible = false
			continue
		(mi as MeshInstance3D).material_override = mat
		(mi as MeshInstance3D).cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF
	edge_color = _edge_color()

## Where p sits in this frame's picture plane, in metres from the frame centre.
func plane(p: Vector3) -> Vector2:
	var d := p - paint_cam.global_position
	return Vector2(d.dot(paint_cam.global_basis.x), d.dot(paint_cam.global_basis.y))

func _edge_color() -> Color:
	var img := paint.get_image()
	if img == null:
		return edge_color
	if img.is_compressed():
		img.decompress()
	var w := img.get_width() - 1
	var h := img.get_height() - 1
	var sum := Color(0, 0, 0, 0)
	for i in 32:
		var t := i / 31.0
		for p in [Vector2i(int(t * w), 0), Vector2i(int(t * w), h), Vector2i(0, int(t * h)), Vector2i(w, int(t * h))]:
			sum += img.get_pixelv(p)
	return Color(sum.r / 128.0, sum.g / 128.0, sum.b / 128.0)
```

***

Source: [`library/skills/painted-25d-world/_building-blocks/painted_location.gd`](https://github.com/SummerEngine/summer/blob/main/library/skills/painted-25d-world/_building-blocks/painted_location.gd), rendered from `summer-engine@4.5.0` on npm.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.