diff --git a/docs/maps/camera.md b/docs/maps/camera.md
new file mode 100644
index 00000000..ac25c843
--- /dev/null
+++ b/docs/maps/camera.md
@@ -0,0 +1,86 @@
+{.section-title.accent.text-primary}
+# Working with camera
+
+## Focusable Zones
+
+It is possible to define special regions on the map that can make the camera zoom and center on themselves. We call them "Focusable Zones". When player gets inside, his camera view will be altered - focused, zoomed and locked on defined zone, like this:
+
+
+

+
+
+### Adding new **Focusable Zone**:
+
+1. Make sure you are editing an **Object Layer**
+
+
+

+
+
+2. Select **Insert Rectangle** tool
+
+
+

+
+
+3. Define new object wherever you want. For example, you can make your chilling room event cosier!
+
+
+

+
+
+4. Edit this new object and click on **Add Property**, like this:
+
+
+

+
+
+5. Add a **bool** property of name *focusable*:
+
+
+

+
+
+6. Make sure it's checked! :)
+
+
+

+
+
+All should be set up now and your new **Focusable Zone** should be working fine!
+
+### Defining custom zoom margin:
+
+If you want, you can add an additional property to control how much should the camera zoom onto focusable zone.
+
+1. Like before, click on **Add Property**
+
+
+

+
+
+2. Add a **float** property of name *zoom_margin*:
+
+
+

+
+
+2. Define how much (in percentage value) should the zoom be decreased:
+
+
+

+
+
+ For example, if you define your zone as a 300x200 rectangle, setting this property to 0.5 *(50%)* means the camera will try to fit within the viewport the entire zone + margin of 50% of its dimensions, so 450x300.
+
+ - No margin defined
+
+
+

+
+
+ - Margin set to **0.35**
+
+
+

+
\ No newline at end of file
diff --git a/docs/maps/images/camera/0_focusable_zone.png b/docs/maps/images/camera/0_focusable_zone.png
new file mode 100644
index 00000000..8b54f11f
Binary files /dev/null and b/docs/maps/images/camera/0_focusable_zone.png differ
diff --git a/docs/maps/images/camera/1_object_layer.png b/docs/maps/images/camera/1_object_layer.png
new file mode 100644
index 00000000..6f57d0ae
Binary files /dev/null and b/docs/maps/images/camera/1_object_layer.png differ
diff --git a/docs/maps/images/camera/2_rectangle_zone.png b/docs/maps/images/camera/2_rectangle_zone.png
new file mode 100644
index 00000000..9b0b9cda
Binary files /dev/null and b/docs/maps/images/camera/2_rectangle_zone.png differ
diff --git a/docs/maps/images/camera/3_define_new_zone.png b/docs/maps/images/camera/3_define_new_zone.png
new file mode 100644
index 00000000..226028eb
Binary files /dev/null and b/docs/maps/images/camera/3_define_new_zone.png differ
diff --git a/docs/maps/images/camera/4_click_add_property.png b/docs/maps/images/camera/4_click_add_property.png
new file mode 100644
index 00000000..9aa96a2f
Binary files /dev/null and b/docs/maps/images/camera/4_click_add_property.png differ
diff --git a/docs/maps/images/camera/5_add_focusable_prop.png b/docs/maps/images/camera/5_add_focusable_prop.png
new file mode 100644
index 00000000..3ba1b955
Binary files /dev/null and b/docs/maps/images/camera/5_add_focusable_prop.png differ
diff --git a/docs/maps/images/camera/6_make_sure_checked.png b/docs/maps/images/camera/6_make_sure_checked.png
new file mode 100644
index 00000000..7fbcdb89
Binary files /dev/null and b/docs/maps/images/camera/6_make_sure_checked.png differ
diff --git a/docs/maps/images/camera/7_add_zoom_margin.png b/docs/maps/images/camera/7_add_zoom_margin.png
new file mode 100644
index 00000000..8e3f5256
Binary files /dev/null and b/docs/maps/images/camera/7_add_zoom_margin.png differ
diff --git a/docs/maps/images/camera/8_optional_zoom_margin_defined.png b/docs/maps/images/camera/8_optional_zoom_margin_defined.png
new file mode 100644
index 00000000..8b41d7d0
Binary files /dev/null and b/docs/maps/images/camera/8_optional_zoom_margin_defined.png differ
diff --git a/docs/maps/images/camera/no_margin.png b/docs/maps/images/camera/no_margin.png
new file mode 100644
index 00000000..b8c9dd18
Binary files /dev/null and b/docs/maps/images/camera/no_margin.png differ
diff --git a/docs/maps/images/camera/with_margin.png b/docs/maps/images/camera/with_margin.png
new file mode 100644
index 00000000..ffd057ea
Binary files /dev/null and b/docs/maps/images/camera/with_margin.png differ
diff --git a/docs/maps/menu.php b/docs/maps/menu.php
index 0bf0a7f9..10a2f4c5 100644
--- a/docs/maps/menu.php
+++ b/docs/maps/menu.php
@@ -51,6 +51,12 @@ return [
'markdown' => 'maps.website-in-map',
'editUrl' => 'https://github.com/thecodingmachine/workadventure/edit/develop/docs/maps/website-in-map.md',
],
+ [
+ 'title' => 'Camera',
+ 'url' => '/map-building/camera.md',
+ 'markdown' => 'maps.camera',
+ 'editUrl' => 'https://github.com/thecodingmachine/workadventure/edit/develop/docs/maps/camera.md',
+ ],
[
'title' => 'Variables',
'url' => '/map-building/variables.md',
diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts
index 8635b25b..5ebca15b 100644
--- a/front/src/Phaser/Game/GameScene.ts
+++ b/front/src/Phaser/Game/GameScene.ts
@@ -793,7 +793,10 @@ export class GameScene extends DirtyScene {
const focusable = zone.properties?.find((property) => property.name === "focusable");
if (focusable && focusable.value === true) {
const zoomMargin = zone.properties?.find((property) => property.name === "zoom_margin");
- this.cameraManager.enterFocusMode(zone, Number(zoomMargin?.value));
+ this.cameraManager.enterFocusMode(
+ zone,
+ zoomMargin ? Math.max(0, Number(zoomMargin.value)) : undefined
+ );
break;
}
}
diff --git a/maps/tests/focusable_zone_map.json b/maps/tests/focusable_zone_map.json
index 469b8c6d..8a9aa6af 100644
--- a/maps/tests/focusable_zone_map.json
+++ b/maps/tests/focusable_zone_map.json
@@ -150,15 +150,10 @@
"y":0
},
{
- "height":128,
+ "height":146.081567555252,
"id":9,
"name":"chillZone",
"properties":[
- {
- "name":"display_name",
- "type":"string",
- "value":"Chilling Room"
- },
{
"name":"focusable",
"type":"bool",
@@ -167,14 +162,14 @@
{
"name":"zoom_margin",
"type":"float",
- "value":0.5
+ "value":3
}],
"rotation":0,
"type":"zone",
"visible":true,
"width":192,
"x":32,
- "y":96
+ "y":77.9184324447482
},
{
"height":416,
@@ -194,7 +189,7 @@
{
"name":"zoom_margin",
"type":"float",
- "value":0
+ "value":0.35
}],
"rotation":0,
"type":"zone",
@@ -203,26 +198,6 @@
"x":736,
"y":32
},
- {
- "height":66.6667,
- "id":12,
- "name":"",
- "rotation":0,
- "text":
- {
- "fontfamily":"Sans Serif",
- "halign":"center",
- "pixelsize":11,
- "text":"Step inside to focus on the chilling zone",
- "valign":"center",
- "wrap":true
- },
- "type":"",
- "visible":true,
- "width":155.104,
- "x":52.6352863978128,
- "y":125.784444486216
- },
{
"height":66.6667,
"id":13,
@@ -286,7 +261,7 @@
"y":0
}],
"nextlayerid":39,
- "nextobjectid":14,
+ "nextobjectid":18,
"orientation":"orthogonal",
"properties":[
{